{"version":3,"file":"Cesium.js","sources":["../../../Source/Core/appendForwardSlash.js","../../../Source/Core/defined.js","../../../Source/Core/DeveloperError.js","../../../Source/Core/Check.js","../../../Source/Core/defaultValue.js","../../../Source/ThirdParty/mersenne-twister.js","../../../Source/Core/Math.js","../../../Source/Core/Cartesian3.js","../../../Source/Core/scaleToGeodeticSurface.js","../../../Source/Core/Cartographic.js","../../../Source/Core/Ellipsoid.js","../../../Source/Core/GeographicProjection.js","../../../Source/Core/Intersect.js","../../../Source/Core/Interval.js","../../../Source/Core/Matrix3.js","../../../Source/Core/Cartesian4.js","../../../Source/Core/RuntimeError.js","../../../Source/Core/Matrix4.js","../../../Source/Core/Rectangle.js","../../../Source/Core/BoundingSphere.js","../../../Source/ThirdParty/Uri.js","../../../Source/Core/getAbsoluteUri.js","../../../Source/ThirdParty/when.js","../../../Source/Core/clone.js","../../../Source/Core/combine.js","../../../Source/Core/getBaseUri.js","../../../Source/Core/getExtensionFromUri.js","../../../Source/Core/isBlobUri.js","../../../Source/Core/isCrossOriginUrl.js","../../../Source/Core/isDataUri.js","../../../Source/Core/loadAndExecuteScript.js","../../../Source/Core/objectToQuery.js","../../../Source/Core/queryToObject.js","../../../Source/Core/RequestState.js","../../../Source/Core/RequestType.js","../../../Source/Core/Request.js","../../../Source/Core/parseResponseHeaders.js","../../../Source/Core/RequestErrorEvent.js","../../../Source/Core/Event.js","../../../Source/Core/Heap.js","../../../Source/Core/RequestScheduler.js","../../../Source/Core/TrustedServers.js","../../../Source/Core/Resource.js","../../../Source/Core/buildModuleUrl.js","../../../Source/Core/Cartesian2.js","../../../Source/Core/GeographicTilingScheme.js","../../../Source/Core/ApproximateTerrainHeights.js","../../../Source/ThirdParty/purify.js","../../../Source/Core/Credit.js","../../../Source/Core/HeightmapEncoding.js","../../../Source/Core/AxisAlignedBoundingBox.js","../../../Source/Core/EllipsoidalOccluder.js","../../../Source/Core/QuadraticRealPolynomial.js","../../../Source/Core/CubicRealPolynomial.js","../../../Source/Core/QuarticRealPolynomial.js","../../../Source/Core/Ray.js","../../../Source/Core/IntersectionTests.js","../../../Source/Core/Plane.js","../../../Source/Core/binarySearch.js","../../../Source/Core/EarthOrientationParametersSample.js","../../../Source/ThirdParty/sprintf.js","../../../Source/Core/GregorianDate.js","../../../Source/Core/isLeapYear.js","../../../Source/Core/LeapSecond.js","../../../Source/Core/TimeConstants.js","../../../Source/Core/TimeStandard.js","../../../Source/Core/JulianDate.js","../../../Source/Core/EarthOrientationParameters.js","../../../Source/Core/HeadingPitchRoll.js","../../../Source/Core/Iau2006XysSample.js","../../../Source/Core/Iau2006XysData.js","../../../Source/Core/Fullscreen.js","../../../Source/Core/FeatureDetection.js","../../../Source/Core/Quaternion.js","../../../Source/Core/Transforms.js","../../../Source/Core/EllipsoidTangentPlane.js","../../../Source/Core/OrientedBoundingBox.js","../../../Source/Core/AttributeCompression.js","../../../Source/Core/WebGLConstants.js","../../../Source/Core/ComponentDatatype.js","../../../Source/Core/TerrainQuantization.js","../../../Source/Core/TerrainEncoding.js","../../../Source/Core/WebMercatorProjection.js","../../../Source/Core/HeightmapTessellator.js","../../../Source/Core/destroyObject.js","../../../Source/Core/TaskProcessor.js","../../../Source/Core/TerrainData.js","../../../Source/Core/TerrainMesh.js","../../../Source/Core/IndexDatatype.js","../../../Source/Core/TerrainProvider.js","../../../Source/Core/HeightmapTerrainData.js","../../../Source/Core/TileAvailability.js","../../../Source/Core/formatError.js","../../../Source/Core/TileProviderError.js","../../../Source/Core/WebMercatorTilingScheme.js","../../../Source/Core/ArcGISTiledElevationTerrainProvider.js","../../../Source/Core/ArcType.js","../../../Source/Core/arrayFill.js","../../../Source/Core/arrayRemoveDuplicates.js","../../../Source/Core/arraySlice.js","../../../Source/Core/AssociativeArray.js","../../../Source/Core/barycentricCoordinates.js","../../../Source/Core/BingMapsGeocoderService.js","../../../Source/Core/BoundingRectangle.js","../../../Source/Core/GeometryType.js","../../../Source/Core/Matrix2.js","../../../Source/Core/PrimitiveType.js","../../../Source/Core/Geometry.js","../../../Source/Core/GeometryAttribute.js","../../../Source/Core/GeometryAttributes.js","../../../Source/Core/GeometryOffsetAttribute.js","../../../Source/Core/VertexFormat.js","../../../Source/Core/BoxGeometry.js","../../../Source/Core/BoxOutlineGeometry.js","../../../Source/Core/cancelAnimationFrame.js","../../../Source/Core/CartographicGeocoderService.js","../../../Source/Core/Spline.js","../../../Source/Core/LinearSpline.js","../../../Source/Core/TridiagonalSystemSolver.js","../../../Source/Core/HermiteSpline.js","../../../Source/Core/CatmullRomSpline.js","../../../Source/Core/getStringFromTypedArray.js","../../../Source/Core/getJsonFromTypedArray.js","../../../Source/Core/Intersections2D.js","../../../Source/Core/QuantizedMeshTerrainData.js","../../../Source/Core/CesiumTerrainProvider.js","../../../Source/Core/EllipseGeometryLibrary.js","../../../Source/Core/GeometryInstance.js","../../../Source/Core/EncodedCartesian3.js","../../../Source/Core/Tipsify.js","../../../Source/Core/GeometryPipeline.js","../../../Source/Core/EllipseGeometry.js","../../../Source/Core/CircleGeometry.js","../../../Source/Core/EllipseOutlineGeometry.js","../../../Source/Core/CircleOutlineGeometry.js","../../../Source/Core/ClockRange.js","../../../Source/Core/ClockStep.js","../../../Source/Core/getTimestamp.js","../../../Source/Core/Clock.js","../../../Source/Core/Color.js","../../../Source/Core/ColorGeometryInstanceAttribute.js","../../../Source/Core/CompressedTextureBuffer.js","../../../Source/Core/CoplanarPolygonGeometryLibrary.js","../../../Source/Core/EllipsoidRhumbLine.js","../../../Source/ThirdParty/earcut-2.2.1.js","../../../Source/Core/WindingOrder.js","../../../Source/Core/PolygonPipeline.js","../../../Source/Core/Queue.js","../../../Source/Core/PolygonGeometryLibrary.js","../../../Source/Core/CoplanarPolygonGeometry.js","../../../Source/Core/CoplanarPolygonOutlineGeometry.js","../../../Source/Core/CornerType.js","../../../Source/Core/EllipsoidGeodesic.js","../../../Source/Core/PolylinePipeline.js","../../../Source/Core/PolylineVolumeGeometryLibrary.js","../../../Source/Core/CorridorGeometryLibrary.js","../../../Source/Core/CorridorGeometry.js","../../../Source/Core/CorridorOutlineGeometry.js","../../../Source/Core/createGuid.js","../../../Source/Core/Ion.js","../../../Source/Core/IonResource.js","../../../Source/Core/createWorldTerrain.js","../../../Source/Core/CullingVolume.js","../../../Source/Core/CylinderGeometryLibrary.js","../../../Source/Core/CylinderGeometry.js","../../../Source/Core/CylinderOutlineGeometry.js","../../../Source/Core/decodeGoogleEarthEnterpriseData.js","../../../Source/Core/decodeVectorPolylinePositions.js","../../../Source/Core/DefaultProxy.js","../../../Source/Core/oneTimeWarning.js","../../../Source/Core/deprecationWarning.js","../../../Source/Core/DistanceDisplayCondition.js","../../../Source/Core/DistanceDisplayConditionGeometryInstanceAttribute.js","../../../Source/Core/DoubleEndedPriorityQueue.js","../../../Source/Core/DoublyLinkedList.js","../../../Source/ThirdParty/Tween.js","../../../Source/Core/EasingFunction.js","../../../Source/Core/EllipsoidGeometry.js","../../../Source/Core/EllipsoidOutlineGeometry.js","../../../Source/Core/EllipsoidTerrainProvider.js","../../../Source/Core/EventHelper.js","../../../Source/Core/ExtrapolationType.js","../../../Source/Core/OrthographicOffCenterFrustum.js","../../../Source/Core/OrthographicFrustum.js","../../../Source/Core/PerspectiveOffCenterFrustum.js","../../../Source/Core/PerspectiveFrustum.js","../../../Source/Core/FrustumGeometry.js","../../../Source/Core/FrustumOutlineGeometry.js","../../../Source/Core/GeocoderService.js","../../../Source/Core/GeocodeType.js","../../../Source/Core/GeometryFactory.js","../../../Source/Core/GeometryInstanceAttribute.js","../../../Source/Core/getFilenameFromUri.js","../../../Source/Core/getImagePixels.js","../../../Source/Core/getMagic.js","../../../Source/ThirdParty/protobuf-minimal.js","../../../Source/Core/isBitSet.js","../../../Source/Core/GoogleEarthEnterpriseTileInformation.js","../../../Source/Core/GoogleEarthEnterpriseMetadata.js","../../../Source/Core/GoogleEarthEnterpriseTerrainData.js","../../../Source/Core/GoogleEarthEnterpriseTerrainProvider.js","../../../Source/Core/GroundPolylineGeometry.js","../../../Source/Core/HeadingPitchRange.js","../../../Source/Core/HermitePolynomialApproximation.js","../../../Source/Core/IauOrientationParameters.js","../../../Source/Core/Iau2000Orientation.js","../../../Source/Core/IauOrientationAxes.js","../../../Source/Core/InterpolationAlgorithm.js","../../../Source/Core/PeliasGeocoderService.js","../../../Source/Core/IonGeocoderService.js","../../../Source/Core/TimeInterval.js","../../../Source/Core/Iso8601.js","../../../Source/Core/KeyboardEventModifier.js","../../../Source/Core/LagrangePolynomialApproximation.js","../../../Source/Core/LinearApproximation.js","../../../Source/Core/loadCRN.js","../../../Source/Core/loadImageFromTypedArray.js","../../../Source/Renderer/PixelDatatype.js","../../../Source/Core/PixelFormat.js","../../../Source/Core/loadKTX.js","../../../Source/Core/ManagedArray.js","../../../Source/Core/MapProjection.js","../../../Source/Core/mergeSort.js","../../../Source/Core/NearFarScalar.js","../../../Source/Core/Visibility.js","../../../Source/Core/Occluder.js","../../../Source/Core/OffsetGeometryInstanceAttribute.js","../../../Source/Core/OpenCageGeocoderService.js","../../../Source/Core/Packable.js","../../../Source/Core/PackableForInterpolation.js","../../../Source/ThirdParty/measureText.js","../../../Source/Core/writeTextToCanvas.js","../../../Source/Core/PinBuilder.js","../../../Source/Core/PlaneGeometry.js","../../../Source/Core/PlaneOutlineGeometry.js","../../../Source/Core/pointInsideTriangle.js","../../../Source/Core/PolygonGeometry.js","../../../Source/Core/PolygonHierarchy.js","../../../Source/Core/PolygonOutlineGeometry.js","../../../Source/Core/PolylineGeometry.js","../../../Source/Core/PolylineVolumeGeometry.js","../../../Source/Core/PolylineVolumeOutlineGeometry.js","../../../Source/Core/Proxy.js","../../../Source/Core/QuaternionSpline.js","../../../Source/ThirdParty/rbush.js","../../../Source/Core/RectangleCollisionChecker.js","../../../Source/Core/RectangleGeometryLibrary.js","../../../Source/Core/RectangleGeometry.js","../../../Source/Core/RectangleOutlineGeometry.js","../../../Source/Core/ReferenceFrame.js","../../../Source/Core/requestAnimationFrame.js","../../../Source/Core/sampleTerrain.js","../../../Source/Core/sampleTerrainMostDetailed.js","../../../Source/Core/ScreenSpaceEventType.js","../../../Source/Core/ScreenSpaceEventHandler.js","../../../Source/Core/ShowGeometryInstanceAttribute.js","../../../Source/Core/Simon1994PlanetaryPositions.js","../../../Source/Core/SimplePolylineGeometry.js","../../../Source/Core/SphereGeometry.js","../../../Source/Core/SphereOutlineGeometry.js","../../../Source/Core/Spherical.js","../../../Source/Core/subdivideArray.js","../../../Source/Core/TileEdge.js","../../../Source/Core/TilingScheme.js","../../../Source/Core/TimeIntervalCollection.js","../../../Source/Core/TranslationRotationScale.js","../../../Source/Core/VideoSynchronizer.js","../../../Source/Core/VRTheWorldTerrainProvider.js","../../../Source/Core/WallGeometryLibrary.js","../../../Source/Core/WallGeometry.js","../../../Source/Core/WallOutlineGeometry.js","../../../Source/Core/webGLConstantToGlslType.js","../../../Source/Core/WeightSpline.js","../../../Source/Core/wrapFunction.js","../../../Source/DataSources/ConstantProperty.js","../../../Source/DataSources/createPropertyDescriptor.js","../../../Source/DataSources/BillboardGraphics.js","../../../Source/Scene/HeightReference.js","../../../Source/Scene/HorizontalOrigin.js","../../../Source/Scene/VerticalOrigin.js","../../../Source/DataSources/BoundingSphereState.js","../../../Source/DataSources/Property.js","../../../Source/DataSources/BillboardVisualizer.js","../../../Source/Shaders/Appearances/AllMaterialAppearanceFS.js","../../../Source/Shaders/Appearances/AllMaterialAppearanceVS.js","../../../Source/Shaders/Appearances/BasicMaterialAppearanceFS.js","../../../Source/Shaders/Appearances/BasicMaterialAppearanceVS.js","../../../Source/Shaders/Appearances/TexturedMaterialAppearanceFS.js","../../../Source/Shaders/Appearances/TexturedMaterialAppearanceVS.js","../../../Source/Scene/BlendEquation.js","../../../Source/Scene/BlendFunction.js","../../../Source/Scene/BlendingState.js","../../../Source/Scene/CullFace.js","../../../Source/Scene/Appearance.js","../../../Source/Renderer/ContextLimits.js","../../../Source/Renderer/CubeMapFace.js","../../../Source/Renderer/MipmapHint.js","../../../Source/Renderer/TextureMagnificationFilter.js","../../../Source/Renderer/TextureMinificationFilter.js","../../../Source/Renderer/TextureWrap.js","../../../Source/Renderer/Sampler.js","../../../Source/Renderer/CubeMap.js","../../../Source/Renderer/Texture.js","../../../Source/Shaders/Materials/AspectRampMaterial.js","../../../Source/Shaders/Materials/BumpMapMaterial.js","../../../Source/Shaders/Materials/CheckerboardMaterial.js","../../../Source/Shaders/Materials/DotMaterial.js","../../../Source/Shaders/Materials/ElevationBandMaterial.js","../../../Source/Shaders/Materials/ElevationContourMaterial.js","../../../Source/Shaders/Materials/ElevationRampMaterial.js","../../../Source/Shaders/Materials/FadeMaterial.js","../../../Source/Shaders/Materials/GridMaterial.js","../../../Source/Shaders/Materials/NormalMapMaterial.js","../../../Source/Shaders/Materials/PolylineArrowMaterial.js","../../../Source/Shaders/Materials/PolylineDashMaterial.js","../../../Source/Shaders/Materials/PolylineGlowMaterial.js","../../../Source/Shaders/Materials/PolylineOutlineMaterial.js","../../../Source/Shaders/Materials/RimLightingMaterial.js","../../../Source/Shaders/Materials/SlopeRampMaterial.js","../../../Source/Shaders/Materials/StripeMaterial.js","../../../Source/Shaders/Materials/Water.js","../../../Source/Scene/Material.js","../../../Source/Scene/MaterialAppearance.js","../../../Source/Shaders/Appearances/PerInstanceColorAppearanceFS.js","../../../Source/Shaders/Appearances/PerInstanceColorAppearanceVS.js","../../../Source/Shaders/Appearances/PerInstanceFlatColorAppearanceFS.js","../../../Source/Shaders/Appearances/PerInstanceFlatColorAppearanceVS.js","../../../Source/Scene/PerInstanceColorAppearance.js","../../../Source/DataSources/ColorMaterialProperty.js","../../../Source/Renderer/DrawCommand.js","../../../Source/Renderer/Pass.js","../../../Source/Renderer/freezeRenderState.js","../../../Source/Renderer/RenderState.js","../../../Source/Renderer/AutomaticUniforms.js","../../../Source/Renderer/createUniform.js","../../../Source/Renderer/createUniformArray.js","../../../Source/Renderer/ShaderProgram.js","../../../Source/Renderer/modernizeShader.js","../../../Source/Shaders/Builtin/Constants/degreesPerRadian.js","../../../Source/Shaders/Builtin/Constants/depthRange.js","../../../Source/Shaders/Builtin/Constants/epsilon1.js","../../../Source/Shaders/Builtin/Constants/epsilon2.js","../../../Source/Shaders/Builtin/Constants/epsilon3.js","../../../Source/Shaders/Builtin/Constants/epsilon4.js","../../../Source/Shaders/Builtin/Constants/epsilon5.js","../../../Source/Shaders/Builtin/Constants/epsilon6.js","../../../Source/Shaders/Builtin/Constants/epsilon7.js","../../../Source/Shaders/Builtin/Constants/infinity.js","../../../Source/Shaders/Builtin/Constants/oneOverPi.js","../../../Source/Shaders/Builtin/Constants/oneOverTwoPi.js","../../../Source/Shaders/Builtin/Constants/passCesium3DTile.js","../../../Source/Shaders/Builtin/Constants/passCesium3DTileClassification.js","../../../Source/Shaders/Builtin/Constants/passCesium3DTileClassificationIgnoreShow.js","../../../Source/Shaders/Builtin/Constants/passClassification.js","../../../Source/Shaders/Builtin/Constants/passCompute.js","../../../Source/Shaders/Builtin/Constants/passEnvironment.js","../../../Source/Shaders/Builtin/Constants/passGlobe.js","../../../Source/Shaders/Builtin/Constants/passOpaque.js","../../../Source/Shaders/Builtin/Constants/passOverlay.js","../../../Source/Shaders/Builtin/Constants/passTerrainClassification.js","../../../Source/Shaders/Builtin/Constants/passTranslucent.js","../../../Source/Shaders/Builtin/Constants/pi.js","../../../Source/Shaders/Builtin/Constants/piOverFour.js","../../../Source/Shaders/Builtin/Constants/piOverSix.js","../../../Source/Shaders/Builtin/Constants/piOverThree.js","../../../Source/Shaders/Builtin/Constants/piOverTwo.js","../../../Source/Shaders/Builtin/Constants/radiansPerDegree.js","../../../Source/Shaders/Builtin/Constants/sceneMode2D.js","../../../Source/Shaders/Builtin/Constants/sceneMode3D.js","../../../Source/Shaders/Builtin/Constants/sceneModeColumbusView.js","../../../Source/Shaders/Builtin/Constants/sceneModeMorphing.js","../../../Source/Shaders/Builtin/Constants/solarRadius.js","../../../Source/Shaders/Builtin/Constants/threePiOver2.js","../../../Source/Shaders/Builtin/Constants/twoPi.js","../../../Source/Shaders/Builtin/Constants/webMercatorMaxLatitude.js","../../../Source/Shaders/Builtin/Structs/depthRangeStruct.js","../../../Source/Shaders/Builtin/Structs/material.js","../../../Source/Shaders/Builtin/Structs/materialInput.js","../../../Source/Shaders/Builtin/Structs/ray.js","../../../Source/Shaders/Builtin/Structs/raySegment.js","../../../Source/Shaders/Builtin/Structs/shadowParameters.js","../../../Source/Shaders/Builtin/Functions/acesTonemapping.js","../../../Source/Shaders/Builtin/Functions/alphaWeight.js","../../../Source/Shaders/Builtin/Functions/antialias.js","../../../Source/Shaders/Builtin/Functions/approximateSphericalCoordinates.js","../../../Source/Shaders/Builtin/Functions/backFacing.js","../../../Source/Shaders/Builtin/Functions/branchFreeTernary.js","../../../Source/Shaders/Builtin/Functions/cascadeColor.js","../../../Source/Shaders/Builtin/Functions/cascadeDistance.js","../../../Source/Shaders/Builtin/Functions/cascadeMatrix.js","../../../Source/Shaders/Builtin/Functions/cascadeWeights.js","../../../Source/Shaders/Builtin/Functions/columbusViewMorph.js","../../../Source/Shaders/Builtin/Functions/computePosition.js","../../../Source/Shaders/Builtin/Functions/cosineAndSine.js","../../../Source/Shaders/Builtin/Functions/decompressTextureCoordinates.js","../../../Source/Shaders/Builtin/Functions/depthClamp.js","../../../Source/Shaders/Builtin/Functions/eastNorthUpToEyeCoordinates.js","../../../Source/Shaders/Builtin/Functions/ellipsoidContainsPoint.js","../../../Source/Shaders/Builtin/Functions/ellipsoidWgs84TextureCoordinates.js","../../../Source/Shaders/Builtin/Functions/equalsEpsilon.js","../../../Source/Shaders/Builtin/Functions/eyeOffset.js","../../../Source/Shaders/Builtin/Functions/eyeToWindowCoordinates.js","../../../Source/Shaders/Builtin/Functions/fastApproximateAtan.js","../../../Source/Shaders/Builtin/Functions/fog.js","../../../Source/Shaders/Builtin/Functions/gammaCorrect.js","../../../Source/Shaders/Builtin/Functions/geodeticSurfaceNormal.js","../../../Source/Shaders/Builtin/Functions/getDefaultMaterial.js","../../../Source/Shaders/Builtin/Functions/getLambertDiffuse.js","../../../Source/Shaders/Builtin/Functions/getSpecular.js","../../../Source/Shaders/Builtin/Functions/getWaterNoise.js","../../../Source/Shaders/Builtin/Functions/HSBToRGB.js","../../../Source/Shaders/Builtin/Functions/HSLToRGB.js","../../../Source/Shaders/Builtin/Functions/hue.js","../../../Source/Shaders/Builtin/Functions/inverseGamma.js","../../../Source/Shaders/Builtin/Functions/isEmpty.js","../../../Source/Shaders/Builtin/Functions/isFull.js","../../../Source/Shaders/Builtin/Functions/latitudeToWebMercatorFraction.js","../../../Source/Shaders/Builtin/Functions/lineDistance.js","../../../Source/Shaders/Builtin/Functions/luminance.js","../../../Source/Shaders/Builtin/Functions/metersPerPixel.js","../../../Source/Shaders/Builtin/Functions/modelToWindowCoordinates.js","../../../Source/Shaders/Builtin/Functions/multiplyWithColorBalance.js","../../../Source/Shaders/Builtin/Functions/nearFarScalar.js","../../../Source/Shaders/Builtin/Functions/octDecode.js","../../../Source/Shaders/Builtin/Functions/packDepth.js","../../../Source/Shaders/Builtin/Functions/phong.js","../../../Source/Shaders/Builtin/Functions/planeDistance.js","../../../Source/Shaders/Builtin/Functions/pointAlongRay.js","../../../Source/Shaders/Builtin/Functions/rayEllipsoidIntersectionInterval.js","../../../Source/Shaders/Builtin/Functions/readDepth.js","../../../Source/Shaders/Builtin/Functions/readNonPerspective.js","../../../Source/Shaders/Builtin/Functions/reverseLogDepth.js","../../../Source/Shaders/Builtin/Functions/RGBToHSB.js","../../../Source/Shaders/Builtin/Functions/RGBToHSL.js","../../../Source/Shaders/Builtin/Functions/RGBToXYZ.js","../../../Source/Shaders/Builtin/Functions/sampleOctahedralProjection.js","../../../Source/Shaders/Builtin/Functions/saturation.js","../../../Source/Shaders/Builtin/Functions/shadowDepthCompare.js","../../../Source/Shaders/Builtin/Functions/shadowVisibility.js","../../../Source/Shaders/Builtin/Functions/signNotZero.js","../../../Source/Shaders/Builtin/Functions/sphericalHarmonics.js","../../../Source/Shaders/Builtin/Functions/tangentToEyeSpaceMatrix.js","../../../Source/Shaders/Builtin/Functions/transformPlane.js","../../../Source/Shaders/Builtin/Functions/translateRelativeToEye.js","../../../Source/Shaders/Builtin/Functions/translucentPhong.js","../../../Source/Shaders/Builtin/Functions/transpose.js","../../../Source/Shaders/Builtin/Functions/unpackDepth.js","../../../Source/Shaders/Builtin/Functions/unpackFloat.js","../../../Source/Shaders/Builtin/Functions/vertexLogDepth.js","../../../Source/Shaders/Builtin/Functions/windowToEyeCoordinates.js","../../../Source/Shaders/Builtin/Functions/writeDepthClamp.js","../../../Source/Shaders/Builtin/Functions/writeLogDepth.js","../../../Source/Shaders/Builtin/Functions/writeNonPerspective.js","../../../Source/Shaders/Builtin/Functions/XYZToRGB.js","../../../Source/Shaders/Builtin/CzmBuiltins.js","../../../Source/Renderer/ShaderSource.js","../../../Source/Shaders/ShadowVolumeAppearanceVS.js","../../../Source/Shaders/ShadowVolumeFS.js","../../../Source/Scene/ClassificationType.js","../../../Source/Scene/DepthFunction.js","../../../Source/Renderer/BufferUsage.js","../../../Source/Renderer/Buffer.js","../../../Source/Renderer/VertexArray.js","../../../Source/Scene/BatchTable.js","../../../Source/Scene/PrimitivePipeline.js","../../../Source/Scene/PrimitiveState.js","../../../Source/Scene/SceneMode.js","../../../Source/Scene/ShadowMode.js","../../../Source/Scene/Primitive.js","../../../Source/Shaders/ShadowVolumeAppearanceFS.js","../../../Source/Scene/ShadowVolumeAppearance.js","../../../Source/Scene/StencilFunction.js","../../../Source/Scene/StencilOperation.js","../../../Source/Scene/StencilConstants.js","../../../Source/Scene/ClassificationPrimitive.js","../../../Source/Scene/GroundPrimitive.js","../../../Source/DataSources/MaterialProperty.js","../../../Source/DataSources/DynamicGeometryUpdater.js","../../../Source/Shaders/PolylineShadowVolumeFS.js","../../../Source/Shaders/PolylineShadowVolumeMorphFS.js","../../../Source/Shaders/PolylineShadowVolumeMorphVS.js","../../../Source/Shaders/PolylineShadowVolumeVS.js","../../../Source/Shaders/Appearances/PolylineColorAppearanceVS.js","../../../Source/Shaders/PolylineCommon.js","../../../Source/Scene/PolylineColorAppearance.js","../../../Source/Shaders/Appearances/PolylineMaterialAppearanceVS.js","../../../Source/Shaders/PolylineFS.js","../../../Source/Scene/PolylineMaterialAppearance.js","../../../Source/Scene/GroundPolylinePrimitive.js","../../../Source/DataSources/ImageMaterialProperty.js","../../../Source/DataSources/createMaterialPropertyDescriptor.js","../../../Source/DataSources/BoxGraphics.js","../../../Source/DataSources/PositionProperty.js","../../../Source/DataSources/ConstantPositionProperty.js","../../../Source/DataSources/CorridorGraphics.js","../../../Source/DataSources/createRawPropertyDescriptor.js","../../../Source/DataSources/CylinderGraphics.js","../../../Source/DataSources/EllipseGraphics.js","../../../Source/DataSources/EllipsoidGraphics.js","../../../Source/DataSources/LabelGraphics.js","../../../Source/DataSources/NodeTransformationProperty.js","../../../Source/DataSources/PropertyBag.js","../../../Source/DataSources/ModelGraphics.js","../../../Source/DataSources/Cesium3DTilesetGraphics.js","../../../Source/DataSources/PathGraphics.js","../../../Source/DataSources/PlaneGraphics.js","../../../Source/DataSources/PointGraphics.js","../../../Source/DataSources/PolygonGraphics.js","../../../Source/DataSources/PolylineGraphics.js","../../../Source/DataSources/PolylineVolumeGraphics.js","../../../Source/DataSources/RectangleGraphics.js","../../../Source/DataSources/WallGraphics.js","../../../Source/DataSources/Entity.js","../../../Source/DataSources/GeometryUpdater.js","../../../Source/DataSources/CallbackProperty.js","../../../Source/DataSources/TerrainOffsetProperty.js","../../../Source/DataSources/heightReferenceOnEntityPropertyChanged.js","../../../Source/DataSources/BoxGeometryUpdater.js","../../../Source/Renderer/ClearCommand.js","../../../Source/Scene/Axis.js","../../../Source/Scene/AttributeType.js","../../../Source/Scene/Cesium3DTileColorBlendMode.js","../../../Source/Scene/getBinaryAccessor.js","../../../Source/Scene/Cesium3DTileBatchTable.js","../../../Source/Scene/Cesium3DTileFeature.js","../../../Source/Scene/Cesium3DTileFeatureTable.js","../../../Source/ThirdParty/GltfPipeline/addToArray.js","../../../Source/ThirdParty/GltfPipeline/hasExtension.js","../../../Source/ThirdParty/GltfPipeline/ForEach.js","../../../Source/ThirdParty/GltfPipeline/numberOfComponentsForType.js","../../../Source/ThirdParty/GltfPipeline/getAccessorByteStride.js","../../../Source/ThirdParty/GltfPipeline/addDefaults.js","../../../Source/ThirdParty/GltfPipeline/addPipelineExtras.js","../../../Source/ThirdParty/GltfPipeline/removeExtensionsRequired.js","../../../Source/ThirdParty/GltfPipeline/removeExtensionsUsed.js","../../../Source/ThirdParty/GltfPipeline/parseGlb.js","../../../Source/ThirdParty/GltfPipeline/addExtensionsUsed.js","../../../Source/ThirdParty/GltfPipeline/getComponentReader.js","../../../Source/ThirdParty/GltfPipeline/findAccessorMinMax.js","../../../Source/ThirdParty/GltfPipeline/moveTechniqueRenderStates.js","../../../Source/ThirdParty/GltfPipeline/addExtensionsRequired.js","../../../Source/ThirdParty/GltfPipeline/moveTechniquesToExtension.js","../../../Source/ThirdParty/GltfPipeline/removeUnusedElements.js","../../../Source/ThirdParty/GltfPipeline/addBuffer.js","../../../Source/ThirdParty/GltfPipeline/readAccessorPacked.js","../../../Source/ThirdParty/GltfPipeline/updateAccessorComponentTypes.js","../../../Source/ThirdParty/GltfPipeline/updateVersion.js","../../../Source/Scene/ModelLoadResources.js","../../../Source/Scene/ModelUtility.js","../../../Source/Scene/processModelMaterialsCommon.js","../../../Source/Scene/processPbrMaterials.js","../../../Source/Scene/Vector3DTileBatch.js","../../../Source/Shaders/VectorTileVS.js","../../../Source/ThirdParty/jsep.js","../../../Source/Scene/ExpressionNodeType.js","../../../Source/Scene/Expression.js","../../../Source/Scene/Vector3DTilePrimitive.js","../../../Source/Scene/ClassificationModel.js","../../../Source/Scene/ClippingPlane.js","../../../Source/Scene/ClippingPlaneCollection.js","../../../Source/Scene/ColorBlendMode.js","../../../Source/Scene/DracoLoader.js","../../../Source/Scene/getClipAndStyleCode.js","../../../Source/Scene/getClippingFunction.js","../../../Source/Scene/JobType.js","../../../Source/Scene/ModelAnimationCache.js","../../../Source/Scene/ModelAnimationLoop.js","../../../Source/Scene/ModelAnimationState.js","../../../Source/Scene/ModelAnimation.js","../../../Source/Scene/ModelAnimationCollection.js","../../../Source/Scene/ModelMaterial.js","../../../Source/Scene/ModelMesh.js","../../../Source/Scene/ModelNode.js","../../../Source/Scene/ModelOutlineLoader.js","../../../Source/Renderer/ComputeCommand.js","../../../Source/Shaders/OctahedralProjectionAtlasFS.js","../../../Source/Shaders/OctahedralProjectionFS.js","../../../Source/Shaders/OctahedralProjectionVS.js","../../../Source/Scene/OctahedralProjectedCubeMap.js","../../../Source/Scene/Model.js","../../../Source/Scene/Batched3DModel3DTileContent.js","../../../Source/Scene/Composite3DTileContent.js","../../../Source/Scene/Vector3DTileGeometry.js","../../../Source/Scene/Geometry3DTileContent.js","../../../Source/Scene/ModelInstance.js","../../../Source/Scene/ModelInstanceCollection.js","../../../Source/Scene/Instanced3DModel3DTileContent.js","../../../Source/Scene/Cesium3DTileRefine.js","../../../Source/Scene/PointCloud.js","../../../Source/Renderer/Framebuffer.js","../../../Source/Shaders/PostProcessStages/PointCloudEyeDomeLighting.js","../../../Source/Scene/PointCloudEyeDomeLighting.js","../../../Source/Scene/PointCloudShading.js","../../../Source/Scene/PointCloud3DTileContent.js","../../../Source/Scene/Tileset3DTileContent.js","../../../Source/Renderer/VertexArrayFacade.js","../../../Source/Shaders/BillboardCollectionFS.js","../../../Source/Shaders/BillboardCollectionVS.js","../../../Source/Scene/SceneTransforms.js","../../../Source/Scene/Billboard.js","../../../Source/Scene/BlendOption.js","../../../Source/Scene/SDFSettings.js","../../../Source/Scene/TextureAtlas.js","../../../Source/Scene/BillboardCollection.js","../../../Source/Scene/createBillboardPointCallback.js","../../../Source/Scene/Cesium3DTilePointFeature.js","../../../Source/ThirdParty/bitmap-sdf.js","../../../Source/Scene/LabelStyle.js","../../../Source/Scene/Label.js","../../../Source/ThirdParty/graphemesplitter.js","../../../Source/Scene/LabelCollection.js","../../../Source/Shaders/PolylineVS.js","../../../Source/Scene/Polyline.js","../../../Source/Scene/PolylineCollection.js","../../../Source/Scene/Vector3DTilePoints.js","../../../Source/Scene/Vector3DTilePolygons.js","../../../Source/Shaders/Vector3DTilePolylinesVS.js","../../../Source/Scene/Vector3DTilePolylines.js","../../../Source/Shaders/Vector3DTileClampedPolylinesVS.js","../../../Source/Shaders/Vector3DTileClampedPolylinesFS.js","../../../Source/Scene/Vector3DTileClampedPolylines.js","../../../Source/Scene/Vector3DTileContent.js","../../../Source/Scene/Cesium3DTileContentFactory.js","../../../Source/Scene/Cesium3DTileContentState.js","../../../Source/Scene/Cesium3DTileOptimizationHint.js","../../../Source/Scene/Cesium3DTilesetMostDetailedTraversal.js","../../../Source/Scene/Cesium3DTilesetTraversal.js","../../../Source/Scene/Cesium3DTilePass.js","../../../Source/Scene/Empty3DTileContent.js","../../../Source/Scene/TileBoundingRegion.js","../../../Source/Scene/TileBoundingSphere.js","../../../Source/Scene/TileOrientedBoundingBox.js","../../../Source/Scene/Cesium3DTile.js","../../../Source/Scene/Cesium3DTileOptimizations.js","../../../Source/Scene/Cesium3DTilesetCache.js","../../../Source/Scene/Cesium3DTilesetHeatmap.js","../../../Source/Scene/Cesium3DTilesetStatistics.js","../../../Source/Scene/Cesium3DTileStyleEngine.js","../../../Source/Scene/Cesium3DTileset.js","../../../Source/DataSources/Cesium3DTilesetVisualizer.js","../../../Source/DataSources/CheckerboardMaterialProperty.js","../../../Source/DataSources/EntityCollection.js","../../../Source/DataSources/CompositeEntityCollection.js","../../../Source/DataSources/CompositeProperty.js","../../../Source/DataSources/CompositeMaterialProperty.js","../../../Source/DataSources/CompositePositionProperty.js","../../../Source/DataSources/GroundGeometryUpdater.js","../../../Source/DataSources/CorridorGeometryUpdater.js","../../../Source/DataSources/DataSource.js","../../../Source/Scene/PointPrimitive.js","../../../Source/Shaders/PointPrimitiveCollectionFS.js","../../../Source/Shaders/PointPrimitiveCollectionVS.js","../../../Source/Scene/PointPrimitiveCollection.js","../../../Source/ThirdParty/kdbush.js","../../../Source/DataSources/EntityCluster.js","../../../Source/DataSources/CustomDataSource.js","../../../Source/DataSources/CylinderGeometryUpdater.js","../../../Source/DataSources/DataSourceClock.js","../../../Source/DataSources/GridMaterialProperty.js","../../../Source/DataSources/PolylineArrowMaterialProperty.js","../../../Source/DataSources/PolylineDashMaterialProperty.js","../../../Source/DataSources/PolylineGlowMaterialProperty.js","../../../Source/DataSources/PolylineOutlineMaterialProperty.js","../../../Source/DataSources/PositionPropertyArray.js","../../../Source/DataSources/PropertyArray.js","../../../Source/DataSources/ReferenceProperty.js","../../../Source/DataSources/Rotation.js","../../../Source/DataSources/SampledProperty.js","../../../Source/DataSources/SampledPositionProperty.js","../../../Source/DataSources/StripeOrientation.js","../../../Source/DataSources/StripeMaterialProperty.js","../../../Source/DataSources/TimeIntervalCollectionPositionProperty.js","../../../Source/DataSources/TimeIntervalCollectionProperty.js","../../../Source/DataSources/VelocityVectorProperty.js","../../../Source/DataSources/VelocityOrientationProperty.js","../../../Source/DataSources/CzmlDataSource.js","../../../Source/DataSources/DataSourceCollection.js","../../../Source/Scene/PrimitiveCollection.js","../../../Source/Scene/OrderedGroundPrimitiveCollection.js","../../../Source/DataSources/DynamicGeometryBatch.js","../../../Source/DataSources/EllipseGeometryUpdater.js","../../../Source/DataSources/EllipsoidGeometryUpdater.js","../../../Source/DataSources/PlaneGeometryUpdater.js","../../../Source/DataSources/PolygonGeometryUpdater.js","../../../Source/DataSources/PolylineVolumeGeometryUpdater.js","../../../Source/DataSources/RectangleGeometryUpdater.js","../../../Source/DataSources/StaticGeometryColorBatch.js","../../../Source/DataSources/StaticGeometryPerMaterialBatch.js","../../../Source/DataSources/StaticGroundGeometryColorBatch.js","../../../Source/DataSources/StaticGroundGeometryPerMaterialBatch.js","../../../Source/DataSources/StaticOutlineGeometryBatch.js","../../../Source/DataSources/WallGeometryUpdater.js","../../../Source/DataSources/GeometryVisualizer.js","../../../Source/DataSources/LabelVisualizer.js","../../../Source/DataSources/ModelVisualizer.js","../../../Source/DataSources/ScaledPositionProperty.js","../../../Source/DataSources/PathVisualizer.js","../../../Source/DataSources/PointVisualizer.js","../../../Source/DataSources/PolylineGeometryUpdater.js","../../../Source/DataSources/StaticGroundPolylinePerMaterialBatch.js","../../../Source/DataSources/PolylineVisualizer.js","../../../Source/DataSources/DataSourceDisplay.js","../../../Source/DataSources/EntityView.js","../../../Source/ThirdParty/zip.js","../../../Source/DataSources/exportKml.js","../../../Source/ThirdParty/topojson.js","../../../Source/DataSources/GeoJsonDataSource.js","../../../Source/DataSources/KmlCamera.js","../../../Source/ThirdParty/Autolinker.js","../../../Source/DataSources/KmlLookAt.js","../../../Source/DataSources/KmlTour.js","../../../Source/DataSources/KmlTourFlyTo.js","../../../Source/DataSources/KmlTourWait.js","../../../Source/DataSources/KmlDataSource.js","../../../Source/DataSources/Visualizer.js","../../../Source/Shaders/ViewportQuadVS.js","../../../Source/Renderer/ComputeEngine.js","../../../Source/Renderer/PassState.js","../../../Source/Renderer/ShaderCache.js","../../../Source/Renderer/TextureCache.js","../../../Source/Scene/SunLight.js","../../../Source/Renderer/UniformState.js","../../../Source/Renderer/Context.js","../../../Source/Renderer/loadCubeMap.js","../../../Source/Renderer/RenderbufferFormat.js","../../../Source/Renderer/Renderbuffer.js","../../../Source/Scene/DiscardMissingTileImagePolicy.js","../../../Source/Scene/ImageryLayerFeatureInfo.js","../../../Source/Scene/ImageryProvider.js","../../../Source/Scene/ArcGisMapServerImageryProvider.js","../../../Source/Scene/AutoExposure.js","../../../Source/Scene/BingMapsStyle.js","../../../Source/Scene/DiscardEmptyTileImagePolicy.js","../../../Source/Scene/BingMapsImageryProvider.js","../../../Source/Scene/BoxEmitter.js","../../../Source/Shaders/BrdfLutGeneratorFS.js","../../../Source/Scene/BrdfLutGenerator.js","../../../Source/Scene/CameraFlightPath.js","../../../Source/Scene/MapMode2D.js","../../../Source/Scene/Camera.js","../../../Source/Scene/CameraEventType.js","../../../Source/Scene/CameraEventAggregator.js","../../../Source/Scene/Cesium3DTileContent.js","../../../Source/Scene/Cesium3DTilePassState.js","../../../Source/Scene/ConditionsExpression.js","../../../Source/Scene/Cesium3DTileStyle.js","../../../Source/Scene/CircleEmitter.js","../../../Source/Scene/computeFlyToLocationForRectangle.js","../../../Source/Scene/ConeEmitter.js","../../../Source/Scene/createElevationBandMaterial.js","../../../Source/Scene/createOsmBuildings.js","../../../Source/Scene/createTangentSpaceDebugPrimitive.js","../../../Source/Scene/UrlTemplateImageryProvider.js","../../../Source/Scene/TileMapServiceImageryProvider.js","../../../Source/Scene/GoogleEarthEnterpriseMapsProvider.js","../../../Source/Scene/MapboxImageryProvider.js","../../../Source/Scene/SingleTileImageryProvider.js","../../../Source/Scene/GetFeatureInfoFormat.js","../../../Source/Scene/TimeDynamicImagery.js","../../../Source/Scene/WebMapServiceImageryProvider.js","../../../Source/Scene/WebMapTileServiceImageryProvider.js","../../../Source/Scene/IonImageryProvider.js","../../../Source/Scene/IonWorldImageryStyle.js","../../../Source/Scene/createWorldImagery.js","../../../Source/Scene/CreditDisplay.js","../../../Source/Scene/DebugAppearance.js","../../../Source/Scene/DebugCameraPrimitive.js","../../../Source/Scene/DebugInspector.js","../../../Source/Scene/DebugModelMatrixPrimitive.js","../../../Source/Shaders/DepthPlaneFS.js","../../../Source/Shaders/DepthPlaneVS.js","../../../Source/Scene/DepthPlane.js","../../../Source/Scene/DerivedCommand.js","../../../Source/Scene/DeviceOrientationCameraController.js","../../../Source/Scene/DirectionalLight.js","../../../Source/Shaders/EllipsoidFS.js","../../../Source/Shaders/EllipsoidVS.js","../../../Source/Scene/EllipsoidPrimitive.js","../../../Source/Shaders/Appearances/EllipsoidSurfaceAppearanceFS.js","../../../Source/Shaders/Appearances/EllipsoidSurfaceAppearanceVS.js","../../../Source/Scene/EllipsoidSurfaceAppearance.js","../../../Source/Scene/Fog.js","../../../Source/Scene/FrameRateMonitor.js","../../../Source/Scene/FrameState.js","../../../Source/Scene/FrustumCommands.js","../../../Source/Shaders/GlobeFS.js","../../../Source/Shaders/GlobeVS.js","../../../Source/Shaders/GroundAtmosphere.js","../../../Source/Scene/GlobeSurfaceShaderSet.js","../../../Source/Scene/ImageryState.js","../../../Source/Scene/QuadtreeTileLoadState.js","../../../Source/Scene/TerrainState.js","../../../Source/Scene/GlobeSurfaceTile.js","../../../Source/Shaders/ReprojectWebMercatorFS.js","../../../Source/Shaders/ReprojectWebMercatorVS.js","../../../Source/Scene/Imagery.js","../../../Source/Scene/ImagerySplitDirection.js","../../../Source/Scene/TileImagery.js","../../../Source/Scene/ImageryLayer.js","../../../Source/Scene/TileSelectionResult.js","../../../Source/Scene/TerrainFillMesh.js","../../../Source/Scene/GlobeSurfaceTileProvider.js","../../../Source/Scene/GlobeTranslucency.js","../../../Source/Scene/ImageryLayerCollection.js","../../../Source/Scene/QuadtreeOccluders.js","../../../Source/Scene/QuadtreeTile.js","../../../Source/Scene/TileReplacementQueue.js","../../../Source/Scene/QuadtreePrimitive.js","../../../Source/Scene/Globe.js","../../../Source/Shaders/PostProcessStages/PassThrough.js","../../../Source/Shaders/PostProcessStages/PassThroughDepth.js","../../../Source/Scene/GlobeDepth.js","../../../Source/Scene/GlobeTranslucencyFramebuffer.js","../../../Source/Scene/GlobeTranslucencyState.js","../../../Source/Scene/GoogleEarthEnterpriseImageryProvider.js","../../../Source/Scene/GridImageryProvider.js","../../../Source/Scene/InvertClassification.js","../../../Source/Scene/JobScheduler.js","../../../Source/Scene/Light.js","../../../Source/Scene/MapboxStyleImageryProvider.js","../../../Source/Scene/Moon.js","../../../Source/Scene/NeverTileDiscardPolicy.js","../../../Source/Shaders/AdjustTranslucentFS.js","../../../Source/Shaders/CompositeOITFS.js","../../../Source/Scene/OIT.js","../../../Source/Scene/OpenStreetMapImageryProvider.js","../../../Source/Scene/Particle.js","../../../Source/Scene/ParticleBurst.js","../../../Source/Scene/ParticleEmitter.js","../../../Source/Scene/ParticleSystem.js","../../../Source/Widgets/getElement.js","../../../Source/Scene/PerformanceDisplay.js","../../../Source/Scene/PickDepth.js","../../../Source/Scene/PickDepthFramebuffer.js","../../../Source/Scene/PickFramebuffer.js","../../../Source/Scene/SceneFramebuffer.js","../../../Source/Scene/ShadowMapShader.js","../../../Source/Scene/ShadowMap.js","../../../Source/Shaders/CompareAndPackTranslucentDepth.js","../../../Source/Shaders/PostProcessStages/CompositeTranslucentClassification.js","../../../Source/Scene/TranslucentTileClassification.js","../../../Source/Scene/View.js","../../../Source/Scene/Picking.js","../../../Source/Scene/PostProcessStageSampleMode.js","../../../Source/Scene/PostProcessStage.js","../../../Source/Shaders/PostProcessStages/AcesTonemappingStage.js","../../../Source/Shaders/PostProcessStages/AmbientOcclusionGenerate.js","../../../Source/Shaders/PostProcessStages/AmbientOcclusionModulate.js","../../../Source/Shaders/PostProcessStages/BlackAndWhite.js","../../../Source/Shaders/PostProcessStages/BloomComposite.js","../../../Source/Shaders/PostProcessStages/Brightness.js","../../../Source/Shaders/PostProcessStages/ContrastBias.js","../../../Source/Shaders/PostProcessStages/DepthOfField.js","../../../Source/Shaders/PostProcessStages/DepthView.js","../../../Source/Shaders/PostProcessStages/EdgeDetection.js","../../../Source/Shaders/PostProcessStages/FilmicTonemapping.js","../../../Source/Shaders/PostProcessStages/FXAA.js","../../../Source/Shaders/PostProcessStages/GaussianBlur1D.js","../../../Source/Shaders/PostProcessStages/LensFlare.js","../../../Source/Shaders/PostProcessStages/ModifiedReinhardTonemapping.js","../../../Source/Shaders/PostProcessStages/NightVision.js","../../../Source/Shaders/PostProcessStages/ReinhardTonemapping.js","../../../Source/Shaders/PostProcessStages/Silhouette.js","../../../Source/ThirdParty/Shaders/FXAA3_11.js","../../../Source/Scene/PostProcessStageComposite.js","../../../Source/Scene/PostProcessStageLibrary.js","../../../Source/Scene/PostProcessStageTextureCache.js","../../../Source/Scene/Tonemapper.js","../../../Source/Scene/PostProcessStageCollection.js","../../../Source/Scene/QuadtreeTileProvider.js","../../../Source/Scene/SceneTransitioner.js","../../../Source/Scene/TweenCollection.js","../../../Source/Scene/ScreenSpaceCameraController.js","../../../Source/Shaders/PostProcessStages/AdditiveBlend.js","../../../Source/Shaders/PostProcessStages/BrightPass.js","../../../Source/Scene/SunPostProcess.js","../../../Source/Scene/Scene.js","../../../Source/Shaders/SkyAtmosphereCommon.js","../../../Source/Shaders/SkyAtmosphereFS.js","../../../Source/Shaders/SkyAtmosphereVS.js","../../../Source/Scene/SkyAtmosphere.js","../../../Source/Shaders/SkyBoxFS.js","../../../Source/Shaders/SkyBoxVS.js","../../../Source/Scene/SkyBox.js","../../../Source/Scene/SphereEmitter.js","../../../Source/Scene/StyleExpression.js","../../../Source/Shaders/SunFS.js","../../../Source/Shaders/SunTextureFS.js","../../../Source/Shaders/SunVS.js","../../../Source/Scene/Sun.js","../../../Source/Scene/TileBoundingVolume.js","../../../Source/Scene/TileCoordinatesImageryProvider.js","../../../Source/Scene/TileDiscardPolicy.js","../../../Source/Scene/TileState.js","../../../Source/Scene/TimeDynamicPointCloud.js","../../../Source/Shaders/ViewportQuadFS.js","../../../Source/Scene/ViewportQuad.js","../../../Source/ThirdParty/knockout-3.5.1.js","../../../Source/ThirdParty/knockout-es5.js","../../../Source/Widgets/SvgPathBindingHandler.js","../../../Source/ThirdParty/knockout.js","../../../Source/ThirdParty/LercDecode.js","../../../Source/ThirdParty/NoSleep.js","../../../Source/ThirdParty/quickselect.js","../../../Source/Widgets/ClockViewModel.js","../../../Source/Widgets/Command.js","../../../Source/Widgets/createCommand.js","../../../Source/Widgets/InspectorShared.js","../../../Source/Widgets/subscribeAndEvaluate.js","../../../Source/Widgets/ToggleButtonViewModel.js","../../../Source/Shaders/PostProcessStages/DepthViewPacked.js","../../../Source/ThirdParty/GltfPipeline/removePipelineExtras.js","../../../Source/Widgets/Animation/Animation.js","../../../Source/Widgets/Animation/AnimationViewModel.js","../../../Source/Widgets/BaseLayerPicker/BaseLayerPickerViewModel.js","../../../Source/Widgets/BaseLayerPicker/BaseLayerPicker.js","../../../Source/Widgets/BaseLayerPicker/ProviderViewModel.js","../../../Source/Widgets/BaseLayerPicker/createDefaultImageryProviderViewModels.js","../../../Source/Widgets/BaseLayerPicker/createDefaultTerrainProviderViewModels.js","../../../Source/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspectorViewModel.js","../../../Source/Widgets/Cesium3DTilesInspector/Cesium3DTilesInspector.js","../../../Source/Widgets/CesiumInspector/CesiumInspectorViewModel.js","../../../Source/Widgets/CesiumInspector/CesiumInspector.js","../../../Source/Widgets/CesiumWidget/CesiumWidget.js","../../../Source/Widgets/FullscreenButton/FullscreenButtonViewModel.js","../../../Source/Widgets/FullscreenButton/FullscreenButton.js","../../../Source/Widgets/Geocoder/GeocoderViewModel.js","../../../Source/Widgets/Geocoder/Geocoder.js","../../../Source/Widgets/HomeButton/HomeButtonViewModel.js","../../../Source/Widgets/HomeButton/HomeButton.js","../../../Source/Widgets/InfoBox/InfoBoxViewModel.js","../../../Source/Widgets/InfoBox/InfoBox.js","../../../Source/Widgets/NavigationHelpButton/NavigationHelpButtonViewModel.js","../../../Source/Widgets/NavigationHelpButton/NavigationHelpButton.js","../../../Source/Widgets/PerformanceWatchdog/PerformanceWatchdogViewModel.js","../../../Source/Widgets/PerformanceWatchdog/PerformanceWatchdog.js","../../../Source/Widgets/ProjectionPicker/ProjectionPickerViewModel.js","../../../Source/Widgets/ProjectionPicker/ProjectionPicker.js","../../../Source/Widgets/SceneModePicker/SceneModePickerViewModel.js","../../../Source/Widgets/SceneModePicker/SceneModePicker.js","../../../Source/Widgets/SelectionIndicator/SelectionIndicatorViewModel.js","../../../Source/Widgets/SelectionIndicator/SelectionIndicator.js","../../../Source/Widgets/Timeline/TimelineHighlightRange.js","../../../Source/Widgets/Timeline/TimelineTrack.js","../../../Source/Widgets/Timeline/Timeline.js","../../../Source/Widgets/VRButton/VRButtonViewModel.js","../../../Source/Widgets/VRButton/VRButton.js","../../../Source/Widgets/Viewer/Viewer.js","../../../Source/Widgets/Viewer/viewerCesium3DTilesInspectorMixin.js","../../../Source/Widgets/Viewer/viewerCesiumInspectorMixin.js","../../../Source/Widgets/Viewer/viewerDragDropMixin.js","../../../Source/Widgets/Viewer/viewerPerformanceWatchdogMixin.js","../../../Source/WorkersES6/createTaskProcessorWorker.js","../../../Source/Cesium.js"],"sourcesContent":["/**\r\n * @private\r\n */\r\nfunction appendForwardSlash(url) {\r\n if (url.length === 0 || url[url.length - 1] !== \"/\") {\r\n url = url + \"/\";\r\n }\r\n return url;\r\n}\r\nexport default appendForwardSlash;\r\n","/**\r\n * @function\r\n *\r\n * @param {*} value The object.\r\n * @returns {Boolean} Returns true if the object is defined, returns false otherwise.\r\n *\r\n * @example\r\n * if (Cesium.defined(positions)) {\r\n * doSomething();\r\n * } else {\r\n * doSomethingElse();\r\n * }\r\n */\r\nfunction defined(value) {\r\n return value !== undefined && value !== null;\r\n}\r\nexport default defined;\r\n","import defined from \"./defined.js\";\r\n\r\n/**\r\n * Constructs an exception object that is thrown due to a developer error, e.g., invalid argument,\r\n * argument out of range, etc. This exception should only be thrown during development;\r\n * it usually indicates a bug in the calling code. This exception should never be\r\n * caught; instead the calling code should strive not to generate it.\r\n *

\r\n * On the other hand, a {@link RuntimeError} indicates an exception that may\r\n * be thrown at runtime, e.g., out of memory, that the calling code should be prepared\r\n * to catch.\r\n *\r\n * @alias DeveloperError\r\n * @constructor\r\n * @extends Error\r\n *\r\n * @param {String} [message] The error message for this exception.\r\n *\r\n * @see RuntimeError\r\n */\r\nfunction DeveloperError(message) {\r\n /**\r\n * 'DeveloperError' indicating that this exception was thrown due to a developer error.\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = \"DeveloperError\";\r\n\r\n /**\r\n * The explanation for why this exception was thrown.\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.message = message;\r\n\r\n //Browsers such as IE don't have a stack property until you actually throw the error.\r\n var stack;\r\n try {\r\n throw new Error();\r\n } catch (e) {\r\n stack = e.stack;\r\n }\r\n\r\n /**\r\n * The stack trace of this exception, if available.\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.stack = stack;\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DeveloperError.prototype = Object.create(Error.prototype);\r\n DeveloperError.prototype.constructor = DeveloperError;\r\n}\r\n\r\nDeveloperError.prototype.toString = function () {\r\n var str = this.name + \": \" + this.message;\r\n\r\n if (defined(this.stack)) {\r\n str += \"\\n\" + this.stack.toString();\r\n }\r\n\r\n return str;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nDeveloperError.throwInstantiationError = function () {\r\n throw new DeveloperError(\r\n \"This function defines an interface and should not be called directly.\"\r\n );\r\n};\r\nexport default DeveloperError;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Contains functions for checking that supplied arguments are of a specified type\r\n * or meet specified conditions\r\n * @private\r\n */\r\nvar Check = {};\r\n\r\n/**\r\n * Contains type checking functions, all using the typeof operator\r\n */\r\nCheck.typeOf = {};\r\n\r\nfunction getUndefinedErrorMessage(name) {\r\n return name + \" is required, actual value was undefined\";\r\n}\r\n\r\nfunction getFailedTypeErrorMessage(actual, expected, name) {\r\n return (\r\n \"Expected \" +\r\n name +\r\n \" to be typeof \" +\r\n expected +\r\n \", actual typeof was \" +\r\n actual\r\n );\r\n}\r\n\r\n/**\r\n * Throws if test is not defined\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value that is to be checked\r\n * @exception {DeveloperError} test must be defined\r\n */\r\nCheck.defined = function (name, test) {\r\n if (!defined(test)) {\r\n throw new DeveloperError(getUndefinedErrorMessage(name));\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'function'\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @exception {DeveloperError} test must be typeof 'function'\r\n */\r\nCheck.typeOf.func = function (name, test) {\r\n if (typeof test !== \"function\") {\r\n throw new DeveloperError(\r\n getFailedTypeErrorMessage(typeof test, \"function\", name)\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'string'\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @exception {DeveloperError} test must be typeof 'string'\r\n */\r\nCheck.typeOf.string = function (name, test) {\r\n if (typeof test !== \"string\") {\r\n throw new DeveloperError(\r\n getFailedTypeErrorMessage(typeof test, \"string\", name)\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'number'\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @exception {DeveloperError} test must be typeof 'number'\r\n */\r\nCheck.typeOf.number = function (name, test) {\r\n if (typeof test !== \"number\") {\r\n throw new DeveloperError(\r\n getFailedTypeErrorMessage(typeof test, \"number\", name)\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'number' and less than limit\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @param {Number} limit The limit value to compare against\r\n * @exception {DeveloperError} test must be typeof 'number' and less than limit\r\n */\r\nCheck.typeOf.number.lessThan = function (name, test, limit) {\r\n Check.typeOf.number(name, test);\r\n if (test >= limit) {\r\n throw new DeveloperError(\r\n \"Expected \" +\r\n name +\r\n \" to be less than \" +\r\n limit +\r\n \", actual value was \" +\r\n test\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'number' and less than or equal to limit\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @param {Number} limit The limit value to compare against\r\n * @exception {DeveloperError} test must be typeof 'number' and less than or equal to limit\r\n */\r\nCheck.typeOf.number.lessThanOrEquals = function (name, test, limit) {\r\n Check.typeOf.number(name, test);\r\n if (test > limit) {\r\n throw new DeveloperError(\r\n \"Expected \" +\r\n name +\r\n \" to be less than or equal to \" +\r\n limit +\r\n \", actual value was \" +\r\n test\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'number' and greater than limit\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @param {Number} limit The limit value to compare against\r\n * @exception {DeveloperError} test must be typeof 'number' and greater than limit\r\n */\r\nCheck.typeOf.number.greaterThan = function (name, test, limit) {\r\n Check.typeOf.number(name, test);\r\n if (test <= limit) {\r\n throw new DeveloperError(\r\n \"Expected \" +\r\n name +\r\n \" to be greater than \" +\r\n limit +\r\n \", actual value was \" +\r\n test\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'number' and greater than or equal to limit\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @param {Number} limit The limit value to compare against\r\n * @exception {DeveloperError} test must be typeof 'number' and greater than or equal to limit\r\n */\r\nCheck.typeOf.number.greaterThanOrEquals = function (name, test, limit) {\r\n Check.typeOf.number(name, test);\r\n if (test < limit) {\r\n throw new DeveloperError(\r\n \"Expected \" +\r\n name +\r\n \" to be greater than or equal to\" +\r\n limit +\r\n \", actual value was \" +\r\n test\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'object'\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @exception {DeveloperError} test must be typeof 'object'\r\n */\r\nCheck.typeOf.object = function (name, test) {\r\n if (typeof test !== \"object\") {\r\n throw new DeveloperError(\r\n getFailedTypeErrorMessage(typeof test, \"object\", name)\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test is not typeof 'boolean'\r\n *\r\n * @param {String} name The name of the variable being tested\r\n * @param {*} test The value to test\r\n * @exception {DeveloperError} test must be typeof 'boolean'\r\n */\r\nCheck.typeOf.bool = function (name, test) {\r\n if (typeof test !== \"boolean\") {\r\n throw new DeveloperError(\r\n getFailedTypeErrorMessage(typeof test, \"boolean\", name)\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Throws if test1 and test2 is not typeof 'number' and not equal in value\r\n *\r\n * @param {String} name1 The name of the first variable being tested\r\n * @param {String} name2 The name of the second variable being tested against\r\n * @param {*} test1 The value to test\r\n * @param {*} test2 The value to test against\r\n * @exception {DeveloperError} test1 and test2 should be type of 'number' and be equal in value\r\n */\r\nCheck.typeOf.number.equals = function (name1, name2, test1, test2) {\r\n Check.typeOf.number(name1, test1);\r\n Check.typeOf.number(name2, test2);\r\n if (test1 !== test2) {\r\n throw new DeveloperError(\r\n name1 +\r\n \" must be equal to \" +\r\n name2 +\r\n \", the actual values are \" +\r\n test1 +\r\n \" and \" +\r\n test2\r\n );\r\n }\r\n};\r\nexport default Check;\r\n","/**\r\n * Returns the first parameter if not undefined, otherwise the second parameter.\r\n * Useful for setting a default value for a parameter.\r\n *\r\n * @function\r\n *\r\n * @param {*} a\r\n * @param {*} b\r\n * @returns {*} Returns the first parameter if not undefined, otherwise the second parameter.\r\n *\r\n * @example\r\n * param = Cesium.defaultValue(param, 'default');\r\n */\r\nfunction defaultValue(a, b) {\r\n if (a !== undefined && a !== null) {\r\n return a;\r\n }\r\n return b;\r\n}\r\n\r\n/**\r\n * A frozen empty object that can be used as the default value for options passed as\r\n * an object literal.\r\n * @type {Object}\r\n * @memberof defaultValue\r\n */\r\ndefaultValue.EMPTY_OBJECT = Object.freeze({});\r\n\r\nexport default defaultValue;\r\n","/*\r\n I've wrapped Makoto Matsumoto and Takuji Nishimura's code in a namespace\r\n so it's better encapsulated. Now you can have multiple random number generators\r\n and they won't stomp all over eachother's state.\r\n\r\n If you want to use this as a substitute for Math.random(), use the random()\r\n method like so:\r\n\r\n var m = new MersenneTwister();\r\n var randomNumber = m.random();\r\n\r\n You can also call the other genrand_{foo}() methods on the instance.\r\n\r\n If you want to use a specific seed in order to get a repeatable random\r\n sequence, pass an integer into the constructor:\r\n\r\n var m = new MersenneTwister(123);\r\n\r\n and that will always produce the same random sequence.\r\n\r\n Sean McCullough (banksean@gmail.com)\r\n*/\r\n\r\n/*\r\n A C-program for MT19937, with initialization improved 2002/1/26.\r\n Coded by Takuji Nishimura and Makoto Matsumoto.\r\n\r\n Before using, initialize the state by using init_genrand(seed)\r\n or init_by_array(init_key, key_length).\r\n*/\r\n/**\r\n@license\r\nmersenne-twister.js - https://gist.github.com/banksean/300494\r\n\r\n Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,\r\n All rights reserved.\r\n\r\n Redistribution and use in source and binary forms, with or without\r\n modification, are permitted provided that the following conditions\r\n are met:\r\n\r\n 1. Redistributions of source code must retain the above copyright\r\n notice, this list of conditions and the following disclaimer.\r\n\r\n 2. Redistributions in binary form must reproduce the above copyright\r\n notice, this list of conditions and the following disclaimer in the\r\n documentation and/or other materials provided with the distribution.\r\n\r\n 3. The names of its contributors may not be used to endorse or promote\r\n products derived from this software without specific prior written\r\n permission.\r\n\r\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r\n \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r\n LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r\n A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r\n CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n*/\r\n/*\r\n Any feedback is very welcome.\r\n http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html\r\n email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)\r\n*/\r\n\r\nfunction MersenneTwister(seed) {\r\n if (seed == undefined) {\r\n seed = new Date().getTime();\r\n }\r\n /* Period parameters */\r\n this.N = 624;\r\n this.M = 397;\r\n this.MATRIX_A = 0x9908b0df; /* constant vector a */\r\n this.UPPER_MASK = 0x80000000; /* most significant w-r bits */\r\n this.LOWER_MASK = 0x7fffffff; /* least significant r bits */\r\n\r\n this.mt = new Array(this.N); /* the array for the state vector */\r\n this.mti=this.N+1; /* mti==N+1 means mt[N] is not initialized */\r\n\r\n this.init_genrand(seed);\r\n}\r\n\r\n/* initializes mt[N] with a seed */\r\nMersenneTwister.prototype.init_genrand = function(s) {\r\n this.mt[0] = s >>> 0;\r\n for (this.mti=1; this.mti>> 30);\r\n this.mt[this.mti] = (((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253)\r\n + this.mti;\r\n /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */\r\n /* In the previous versions, MSBs of the seed affect */\r\n /* only MSBs of the array mt[]. */\r\n /* 2002/01/09 modified by Makoto Matsumoto */\r\n this.mt[this.mti] >>>= 0;\r\n /* for >32 bit machines */\r\n }\r\n}\r\n\r\n/* initialize by an array with array-length */\r\n/* init_key is the array for initializing keys */\r\n/* key_length is its length */\r\n/* slight change for C++, 2004/2/26 */\r\n//MersenneTwister.prototype.init_by_array = function(init_key, key_length) {\r\n// var i, j, k;\r\n// this.init_genrand(19650218);\r\n// i=1; j=0;\r\n// k = (this.N>key_length ? this.N : key_length);\r\n// for (; k; k--) {\r\n// var s = this.mt[i-1] ^ (this.mt[i-1] >>> 30)\r\n// this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1664525) << 16) + ((s & 0x0000ffff) * 1664525)))\r\n// + init_key[j] + j; /* non linear */\r\n// this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */\r\n// i++; j++;\r\n// if (i>=this.N) { this.mt[0] = this.mt[this.N-1]; i=1; }\r\n// if (j>=key_length) j=0;\r\n// }\r\n// for (k=this.N-1; k; k--) {\r\n// var s = this.mt[i-1] ^ (this.mt[i-1] >>> 30);\r\n// this.mt[i] = (this.mt[i] ^ (((((s & 0xffff0000) >>> 16) * 1566083941) << 16) + (s & 0x0000ffff) * 1566083941))\r\n// - i; /* non linear */\r\n// this.mt[i] >>>= 0; /* for WORDSIZE > 32 machines */\r\n// i++;\r\n// if (i>=this.N) { this.mt[0] = this.mt[this.N-1]; i=1; }\r\n// }\r\n//\r\n// this.mt[0] = 0x80000000; /* MSB is 1; assuring non-zero initial array */\r\n//}\r\n\r\n/* generates a random number on [0,0xffffffff]-interval */\r\nMersenneTwister.prototype.genrand_int32 = function() {\r\n var y;\r\n var mag01 = new Array(0x0, this.MATRIX_A);\r\n /* mag01[x] = x * MATRIX_A for x=0,1 */\r\n\r\n if (this.mti >= this.N) { /* generate N words at one time */\r\n var kk;\r\n\r\n if (this.mti == this.N+1) /* if init_genrand() has not been called, */\r\n this.init_genrand(5489); /* a default initial seed is used */\r\n\r\n for (kk=0;kk>> 1) ^ mag01[y & 0x1];\r\n }\r\n for (;kk>> 1) ^ mag01[y & 0x1];\r\n }\r\n y = (this.mt[this.N-1]&this.UPPER_MASK)|(this.mt[0]&this.LOWER_MASK);\r\n this.mt[this.N-1] = this.mt[this.M-1] ^ (y >>> 1) ^ mag01[y & 0x1];\r\n\r\n this.mti = 0;\r\n }\r\n\r\n y = this.mt[this.mti++];\r\n\r\n /* Tempering */\r\n y ^= (y >>> 11);\r\n y ^= (y << 7) & 0x9d2c5680;\r\n y ^= (y << 15) & 0xefc60000;\r\n y ^= (y >>> 18);\r\n\r\n return y >>> 0;\r\n}\r\n\r\n/* generates a random number on [0,0x7fffffff]-interval */\r\n//MersenneTwister.prototype.genrand_int31 = function() {\r\n// return (this.genrand_int32()>>>1);\r\n//}\r\n\r\n/* generates a random number on [0,1]-real-interval */\r\n//MersenneTwister.prototype.genrand_real1 = function() {\r\n// return this.genrand_int32()*(1.0/4294967295.0);\r\n// /* divided by 2^32-1 */\r\n//}\r\n\r\n/* generates a random number on [0,1)-real-interval */\r\nMersenneTwister.prototype.random = function() {\r\n return this.genrand_int32()*(1.0/4294967296.0);\r\n /* divided by 2^32 */\r\n}\r\n\r\n/* generates a random number on (0,1)-real-interval */\r\n//MersenneTwister.prototype.genrand_real3 = function() {\r\n// return (this.genrand_int32() + 0.5)*(1.0/4294967296.0);\r\n// /* divided by 2^32 */\r\n//}\r\n\r\n/* generates a random number on [0,1) with 53-bit resolution*/\r\n//MersenneTwister.prototype.genrand_res53 = function() {\r\n// var a=this.genrand_int32()>>>5, b=this.genrand_int32()>>>6;\r\n// return(a*67108864.0+b)*(1.0/9007199254740992.0);\r\n//}\r\n\r\n/* These real versions are due to Isaku Wada, 2002/01/09 added */\r\n\r\nexport default MersenneTwister;\r\n","import MersenneTwister from \"../ThirdParty/mersenne-twister.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Math functions.\r\n *\r\n * @exports CesiumMath\r\n * @alias Math\r\n */\r\nvar CesiumMath = {};\r\n\r\n/**\r\n * 0.1\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON1 = 0.1;\r\n\r\n/**\r\n * 0.01\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON2 = 0.01;\r\n\r\n/**\r\n * 0.001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON3 = 0.001;\r\n\r\n/**\r\n * 0.0001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON4 = 0.0001;\r\n\r\n/**\r\n * 0.00001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON5 = 0.00001;\r\n\r\n/**\r\n * 0.000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON6 = 0.000001;\r\n\r\n/**\r\n * 0.0000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON7 = 0.0000001;\r\n\r\n/**\r\n * 0.00000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON8 = 0.00000001;\r\n\r\n/**\r\n * 0.000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON9 = 0.000000001;\r\n\r\n/**\r\n * 0.0000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON10 = 0.0000000001;\r\n\r\n/**\r\n * 0.00000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON11 = 0.00000000001;\r\n\r\n/**\r\n * 0.000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON12 = 0.000000000001;\r\n\r\n/**\r\n * 0.0000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON13 = 0.0000000000001;\r\n\r\n/**\r\n * 0.00000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON14 = 0.00000000000001;\r\n\r\n/**\r\n * 0.000000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON15 = 0.000000000000001;\r\n\r\n/**\r\n * 0.0000000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON16 = 0.0000000000000001;\r\n\r\n/**\r\n * 0.00000000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON17 = 0.00000000000000001;\r\n\r\n/**\r\n * 0.000000000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON18 = 0.000000000000000001;\r\n\r\n/**\r\n * 0.0000000000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON19 = 0.0000000000000000001;\r\n\r\n/**\r\n * 0.00000000000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON20 = 0.00000000000000000001;\r\n\r\n/**\r\n * 0.000000000000000000001\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.EPSILON21 = 0.000000000000000000001;\r\n\r\n/**\r\n * The gravitational parameter of the Earth in meters cubed\r\n * per second squared as defined by the WGS84 model: 3.986004418e14\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.GRAVITATIONALPARAMETER = 3.986004418e14;\r\n\r\n/**\r\n * Radius of the sun in meters: 6.955e8\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.SOLAR_RADIUS = 6.955e8;\r\n\r\n/**\r\n * The mean radius of the moon, according to the \"Report of the IAU/IAG Working Group on\r\n * Cartographic Coordinates and Rotational Elements of the Planets and satellites: 2000\",\r\n * Celestial Mechanics 82: 83-110, 2002.\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.LUNAR_RADIUS = 1737400.0;\r\n\r\n/**\r\n * 64 * 1024\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.SIXTY_FOUR_KILOBYTES = 64 * 1024;\r\n\r\n/**\r\n * 4 * 1024 * 1024 * 1024\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.FOUR_GIGABYTES = 4 * 1024 * 1024 * 1024;\r\n\r\n/**\r\n * Returns the sign of the value; 1 if the value is positive, -1 if the value is\r\n * negative, or 0 if the value is 0.\r\n *\r\n * @function\r\n * @param {Number} value The value to return the sign of.\r\n * @returns {Number} The sign of value.\r\n */\r\n// eslint-disable-next-line es/no-math-sign\r\nCesiumMath.sign = defaultValue(Math.sign, function sign(value) {\r\n value = +value; // coerce to number\r\n if (value === 0 || value !== value) {\r\n // zero or NaN\r\n return value;\r\n }\r\n return value > 0 ? 1 : -1;\r\n});\r\n\r\n/**\r\n * Returns 1.0 if the given value is positive or zero, and -1.0 if it is negative.\r\n * This is similar to {@link CesiumMath#sign} except that returns 1.0 instead of\r\n * 0.0 when the input value is 0.0.\r\n * @param {Number} value The value to return the sign of.\r\n * @returns {Number} The sign of value.\r\n */\r\nCesiumMath.signNotZero = function (value) {\r\n return value < 0.0 ? -1.0 : 1.0;\r\n};\r\n\r\n/**\r\n * Converts a scalar value in the range [-1.0, 1.0] to a SNORM in the range [0, rangeMaximum]\r\n * @param {Number} value The scalar value in the range [-1.0, 1.0]\r\n * @param {Number} [rangeMaximum=255] The maximum value in the mapped range, 255 by default.\r\n * @returns {Number} A SNORM value, where 0 maps to -1.0 and rangeMaximum maps to 1.0.\r\n *\r\n * @see CesiumMath.fromSNorm\r\n */\r\nCesiumMath.toSNorm = function (value, rangeMaximum) {\r\n rangeMaximum = defaultValue(rangeMaximum, 255);\r\n return Math.round(\r\n (CesiumMath.clamp(value, -1.0, 1.0) * 0.5 + 0.5) * rangeMaximum\r\n );\r\n};\r\n\r\n/**\r\n * Converts a SNORM value in the range [0, rangeMaximum] to a scalar in the range [-1.0, 1.0].\r\n * @param {Number} value SNORM value in the range [0, rangeMaximum]\r\n * @param {Number} [rangeMaximum=255] The maximum value in the SNORM range, 255 by default.\r\n * @returns {Number} Scalar in the range [-1.0, 1.0].\r\n *\r\n * @see CesiumMath.toSNorm\r\n */\r\nCesiumMath.fromSNorm = function (value, rangeMaximum) {\r\n rangeMaximum = defaultValue(rangeMaximum, 255);\r\n return (\r\n (CesiumMath.clamp(value, 0.0, rangeMaximum) / rangeMaximum) * 2.0 - 1.0\r\n );\r\n};\r\n\r\n/**\r\n * Converts a scalar value in the range [rangeMinimum, rangeMaximum] to a scalar in the range [0.0, 1.0]\r\n * @param {Number} value The scalar value in the range [rangeMinimum, rangeMaximum]\r\n * @param {Number} rangeMinimum The minimum value in the mapped range.\r\n * @param {Number} rangeMaximum The maximum value in the mapped range.\r\n * @returns {Number} A scalar value, where rangeMinimum maps to 0.0 and rangeMaximum maps to 1.0.\r\n */\r\nCesiumMath.normalize = function (value, rangeMinimum, rangeMaximum) {\r\n rangeMaximum = Math.max(rangeMaximum - rangeMinimum, 0.0);\r\n return rangeMaximum === 0.0\r\n ? 0.0\r\n : CesiumMath.clamp((value - rangeMinimum) / rangeMaximum, 0.0, 1.0);\r\n};\r\n\r\n/**\r\n * Returns the hyperbolic sine of a number.\r\n * The hyperbolic sine of value is defined to be\r\n * (ex - e-x)/2.0\r\n * where e is Euler's number, approximately 2.71828183.\r\n *\r\n *

Special cases:\r\n *

    \r\n *
  • If the argument is NaN, then the result is NaN.
  • \r\n *\r\n *
  • If the argument is infinite, then the result is an infinity\r\n * with the same sign as the argument.
  • \r\n *\r\n *
  • If the argument is zero, then the result is a zero with the\r\n * same sign as the argument.
  • \r\n *
\r\n *

\r\n *\r\n * @function\r\n * @param {Number} value The number whose hyperbolic sine is to be returned.\r\n * @returns {Number} The hyperbolic sine of value.\r\n */\r\n// eslint-disable-next-line es/no-math-sinh\r\nCesiumMath.sinh = defaultValue(Math.sinh, function sinh(value) {\r\n return (Math.exp(value) - Math.exp(-value)) / 2.0;\r\n});\r\n\r\n/**\r\n * Returns the hyperbolic cosine of a number.\r\n * The hyperbolic cosine of value is defined to be\r\n * (ex + e-x)/2.0\r\n * where e is Euler's number, approximately 2.71828183.\r\n *\r\n *

Special cases:\r\n *

    \r\n *
  • If the argument is NaN, then the result is NaN.
  • \r\n *\r\n *
  • If the argument is infinite, then the result is positive infinity.
  • \r\n *\r\n *
  • If the argument is zero, then the result is 1.0.
  • \r\n *
\r\n *

\r\n *\r\n * @function\r\n * @param {Number} value The number whose hyperbolic cosine is to be returned.\r\n * @returns {Number} The hyperbolic cosine of value.\r\n */\r\n// eslint-disable-next-line es/no-math-cosh\r\nCesiumMath.cosh = defaultValue(Math.cosh, function cosh(value) {\r\n return (Math.exp(value) + Math.exp(-value)) / 2.0;\r\n});\r\n\r\n/**\r\n * Computes the linear interpolation of two values.\r\n *\r\n * @param {Number} p The start value to interpolate.\r\n * @param {Number} q The end value to interpolate.\r\n * @param {Number} time The time of interpolation generally in the range [0.0, 1.0].\r\n * @returns {Number} The linearly interpolated value.\r\n *\r\n * @example\r\n * var n = Cesium.Math.lerp(0.0, 2.0, 0.5); // returns 1.0\r\n */\r\nCesiumMath.lerp = function (p, q, time) {\r\n return (1.0 - time) * p + time * q;\r\n};\r\n\r\n/**\r\n * pi\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.PI = Math.PI;\r\n\r\n/**\r\n * 1/pi\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.ONE_OVER_PI = 1.0 / Math.PI;\r\n\r\n/**\r\n * pi/2\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.PI_OVER_TWO = Math.PI / 2.0;\r\n\r\n/**\r\n * pi/3\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.PI_OVER_THREE = Math.PI / 3.0;\r\n\r\n/**\r\n * pi/4\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.PI_OVER_FOUR = Math.PI / 4.0;\r\n\r\n/**\r\n * pi/6\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.PI_OVER_SIX = Math.PI / 6.0;\r\n\r\n/**\r\n * 3pi/2\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.THREE_PI_OVER_TWO = (3.0 * Math.PI) / 2.0;\r\n\r\n/**\r\n * 2pi\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.TWO_PI = 2.0 * Math.PI;\r\n\r\n/**\r\n * 1/2pi\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.ONE_OVER_TWO_PI = 1.0 / (2.0 * Math.PI);\r\n\r\n/**\r\n * The number of radians in a degree.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.RADIANS_PER_DEGREE = Math.PI / 180.0;\r\n\r\n/**\r\n * The number of degrees in a radian.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.DEGREES_PER_RADIAN = 180.0 / Math.PI;\r\n\r\n/**\r\n * The number of radians in an arc second.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nCesiumMath.RADIANS_PER_ARCSECOND = CesiumMath.RADIANS_PER_DEGREE / 3600.0;\r\n\r\n/**\r\n * Converts degrees to radians.\r\n * @param {Number} degrees The angle to convert in degrees.\r\n * @returns {Number} The corresponding angle in radians.\r\n */\r\nCesiumMath.toRadians = function (degrees) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(degrees)) {\r\n throw new DeveloperError(\"degrees is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return degrees * CesiumMath.RADIANS_PER_DEGREE;\r\n};\r\n\r\n/**\r\n * Converts radians to degrees.\r\n * @param {Number} radians The angle to convert in radians.\r\n * @returns {Number} The corresponding angle in degrees.\r\n */\r\nCesiumMath.toDegrees = function (radians) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(radians)) {\r\n throw new DeveloperError(\"radians is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return radians * CesiumMath.DEGREES_PER_RADIAN;\r\n};\r\n\r\n/**\r\n * Converts a longitude value, in radians, to the range [-Math.PI, Math.PI).\r\n *\r\n * @param {Number} angle The longitude value, in radians, to convert to the range [-Math.PI, Math.PI).\r\n * @returns {Number} The equivalent longitude value in the range [-Math.PI, Math.PI).\r\n *\r\n * @example\r\n * // Convert 270 degrees to -90 degrees longitude\r\n * var longitude = Cesium.Math.convertLongitudeRange(Cesium.Math.toRadians(270.0));\r\n */\r\nCesiumMath.convertLongitudeRange = function (angle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(angle)) {\r\n throw new DeveloperError(\"angle is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n var twoPi = CesiumMath.TWO_PI;\r\n\r\n var simplified = angle - Math.floor(angle / twoPi) * twoPi;\r\n\r\n if (simplified < -Math.PI) {\r\n return simplified + twoPi;\r\n }\r\n if (simplified >= Math.PI) {\r\n return simplified - twoPi;\r\n }\r\n\r\n return simplified;\r\n};\r\n\r\n/**\r\n * Convenience function that clamps a latitude value, in radians, to the range [-Math.PI/2, Math.PI/2).\r\n * Useful for sanitizing data before use in objects requiring correct range.\r\n *\r\n * @param {Number} angle The latitude value, in radians, to clamp to the range [-Math.PI/2, Math.PI/2).\r\n * @returns {Number} The latitude value clamped to the range [-Math.PI/2, Math.PI/2).\r\n *\r\n * @example\r\n * // Clamp 108 degrees latitude to 90 degrees latitude\r\n * var latitude = Cesium.Math.clampToLatitudeRange(Cesium.Math.toRadians(108.0));\r\n */\r\nCesiumMath.clampToLatitudeRange = function (angle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(angle)) {\r\n throw new DeveloperError(\"angle is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return CesiumMath.clamp(\r\n angle,\r\n -1 * CesiumMath.PI_OVER_TWO,\r\n CesiumMath.PI_OVER_TWO\r\n );\r\n};\r\n\r\n/**\r\n * Produces an angle in the range -Pi <= angle <= Pi which is equivalent to the provided angle.\r\n *\r\n * @param {Number} angle in radians\r\n * @returns {Number} The angle in the range [-CesiumMath.PI, CesiumMath.PI].\r\n */\r\nCesiumMath.negativePiToPi = function (angle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(angle)) {\r\n throw new DeveloperError(\"angle is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n if (angle >= -CesiumMath.PI && angle <= CesiumMath.PI) {\r\n // Early exit if the input is already inside the range. This avoids\r\n // unnecessary math which could introduce floating point error.\r\n return angle;\r\n }\r\n return CesiumMath.zeroToTwoPi(angle + CesiumMath.PI) - CesiumMath.PI;\r\n};\r\n\r\n/**\r\n * Produces an angle in the range 0 <= angle <= 2Pi which is equivalent to the provided angle.\r\n *\r\n * @param {Number} angle in radians\r\n * @returns {Number} The angle in the range [0, CesiumMath.TWO_PI].\r\n */\r\nCesiumMath.zeroToTwoPi = function (angle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(angle)) {\r\n throw new DeveloperError(\"angle is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n if (angle >= 0 && angle <= CesiumMath.TWO_PI) {\r\n // Early exit if the input is already inside the range. This avoids\r\n // unnecessary math which could introduce floating point error.\r\n return angle;\r\n }\r\n var mod = CesiumMath.mod(angle, CesiumMath.TWO_PI);\r\n if (\r\n Math.abs(mod) < CesiumMath.EPSILON14 &&\r\n Math.abs(angle) > CesiumMath.EPSILON14\r\n ) {\r\n return CesiumMath.TWO_PI;\r\n }\r\n return mod;\r\n};\r\n\r\n/**\r\n * The modulo operation that also works for negative dividends.\r\n *\r\n * @param {Number} m The dividend.\r\n * @param {Number} n The divisor.\r\n * @returns {Number} The remainder.\r\n */\r\nCesiumMath.mod = function (m, n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(m)) {\r\n throw new DeveloperError(\"m is required.\");\r\n }\r\n if (!defined(n)) {\r\n throw new DeveloperError(\"n is required.\");\r\n }\r\n if (n === 0.0) {\r\n throw new DeveloperError(\"divisor cannot be 0.\");\r\n }\r\n //>>includeEnd('debug');\r\n if (CesiumMath.sign(m) === CesiumMath.sign(n) && Math.abs(m) < Math.abs(n)) {\r\n // Early exit if the input does not need to be modded. This avoids\r\n // unnecessary math which could introduce floating point error.\r\n return m;\r\n }\r\n\r\n return ((m % n) + n) % n;\r\n};\r\n\r\n/**\r\n * Determines if two values are equal using an absolute or relative tolerance test. This is useful\r\n * to avoid problems due to roundoff error when comparing floating-point values directly. The values are\r\n * first compared using an absolute tolerance test. If that fails, a relative tolerance test is performed.\r\n * Use this test if you are unsure of the magnitudes of left and right.\r\n *\r\n * @param {Number} left The first value to compare.\r\n * @param {Number} right The other value to compare.\r\n * @param {Number} [relativeEpsilon=0] The maximum inclusive delta between left and right for the relative tolerance test.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The maximum inclusive delta between left and right for the absolute tolerance test.\r\n * @returns {Boolean} true if the values are equal within the epsilon; otherwise, false.\r\n *\r\n * @example\r\n * var a = Cesium.Math.equalsEpsilon(0.0, 0.01, Cesium.Math.EPSILON2); // true\r\n * var b = Cesium.Math.equalsEpsilon(0.0, 0.1, Cesium.Math.EPSILON2); // false\r\n * var c = Cesium.Math.equalsEpsilon(3699175.1634344, 3699175.2, Cesium.Math.EPSILON7); // true\r\n * var d = Cesium.Math.equalsEpsilon(3699175.1634344, 3699175.2, Cesium.Math.EPSILON9); // false\r\n */\r\nCesiumMath.equalsEpsilon = function (\r\n left,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\"left is required.\");\r\n }\r\n if (!defined(right)) {\r\n throw new DeveloperError(\"right is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n relativeEpsilon = defaultValue(relativeEpsilon, 0.0);\r\n absoluteEpsilon = defaultValue(absoluteEpsilon, relativeEpsilon);\r\n var absDiff = Math.abs(left - right);\r\n return (\r\n absDiff <= absoluteEpsilon ||\r\n absDiff <= relativeEpsilon * Math.max(Math.abs(left), Math.abs(right))\r\n );\r\n};\r\n\r\n/**\r\n * Determines if the left value is less than the right value. If the two values are within\r\n * absoluteEpsilon of each other, they are considered equal and this function returns false.\r\n *\r\n * @param {Number} left The first number to compare.\r\n * @param {Number} right The second number to compare.\r\n * @param {Number} absoluteEpsilon The absolute epsilon to use in comparison.\r\n * @returns {Boolean} true if left is less than right by more than\r\n * absoluteEpsilon. false if left is greater or if the two\r\n * values are nearly equal.\r\n */\r\nCesiumMath.lessThan = function (left, right, absoluteEpsilon) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\"first is required.\");\r\n }\r\n if (!defined(right)) {\r\n throw new DeveloperError(\"second is required.\");\r\n }\r\n if (!defined(absoluteEpsilon)) {\r\n throw new DeveloperError(\"absoluteEpsilon is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return left - right < -absoluteEpsilon;\r\n};\r\n\r\n/**\r\n * Determines if the left value is less than or equal to the right value. If the two values are within\r\n * absoluteEpsilon of each other, they are considered equal and this function returns true.\r\n *\r\n * @param {Number} left The first number to compare.\r\n * @param {Number} right The second number to compare.\r\n * @param {Number} absoluteEpsilon The absolute epsilon to use in comparison.\r\n * @returns {Boolean} true if left is less than right or if the\r\n * the values are nearly equal.\r\n */\r\nCesiumMath.lessThanOrEquals = function (left, right, absoluteEpsilon) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\"first is required.\");\r\n }\r\n if (!defined(right)) {\r\n throw new DeveloperError(\"second is required.\");\r\n }\r\n if (!defined(absoluteEpsilon)) {\r\n throw new DeveloperError(\"absoluteEpsilon is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return left - right < absoluteEpsilon;\r\n};\r\n\r\n/**\r\n * Determines if the left value is greater the right value. If the two values are within\r\n * absoluteEpsilon of each other, they are considered equal and this function returns false.\r\n *\r\n * @param {Number} left The first number to compare.\r\n * @param {Number} right The second number to compare.\r\n * @param {Number} absoluteEpsilon The absolute epsilon to use in comparison.\r\n * @returns {Boolean} true if left is greater than right by more than\r\n * absoluteEpsilon. false if left is less or if the two\r\n * values are nearly equal.\r\n */\r\nCesiumMath.greaterThan = function (left, right, absoluteEpsilon) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\"first is required.\");\r\n }\r\n if (!defined(right)) {\r\n throw new DeveloperError(\"second is required.\");\r\n }\r\n if (!defined(absoluteEpsilon)) {\r\n throw new DeveloperError(\"absoluteEpsilon is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return left - right > absoluteEpsilon;\r\n};\r\n\r\n/**\r\n * Determines if the left value is greater than or equal to the right value. If the two values are within\r\n * absoluteEpsilon of each other, they are considered equal and this function returns true.\r\n *\r\n * @param {Number} left The first number to compare.\r\n * @param {Number} right The second number to compare.\r\n * @param {Number} absoluteEpsilon The absolute epsilon to use in comparison.\r\n * @returns {Boolean} true if left is greater than right or if the\r\n * the values are nearly equal.\r\n */\r\nCesiumMath.greaterThanOrEquals = function (left, right, absoluteEpsilon) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\"first is required.\");\r\n }\r\n if (!defined(right)) {\r\n throw new DeveloperError(\"second is required.\");\r\n }\r\n if (!defined(absoluteEpsilon)) {\r\n throw new DeveloperError(\"absoluteEpsilon is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return left - right > -absoluteEpsilon;\r\n};\r\n\r\nvar factorials = [1];\r\n\r\n/**\r\n * Computes the factorial of the provided number.\r\n *\r\n * @param {Number} n The number whose factorial is to be computed.\r\n * @returns {Number} The factorial of the provided number or undefined if the number is less than 0.\r\n *\r\n * @exception {DeveloperError} A number greater than or equal to 0 is required.\r\n *\r\n *\r\n * @example\r\n * //Compute 7!, which is equal to 5040\r\n * var computedFactorial = Cesium.Math.factorial(7);\r\n *\r\n * @see {@link http://en.wikipedia.org/wiki/Factorial|Factorial on Wikipedia}\r\n */\r\nCesiumMath.factorial = function (n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof n !== \"number\" || n < 0) {\r\n throw new DeveloperError(\r\n \"A number greater than or equal to 0 is required.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = factorials.length;\r\n if (n >= length) {\r\n var sum = factorials[length - 1];\r\n for (var i = length; i <= n; i++) {\r\n var next = sum * i;\r\n factorials.push(next);\r\n sum = next;\r\n }\r\n }\r\n return factorials[n];\r\n};\r\n\r\n/**\r\n * Increments a number with a wrapping to a minimum value if the number exceeds the maximum value.\r\n *\r\n * @param {Number} [n] The number to be incremented.\r\n * @param {Number} [maximumValue] The maximum incremented value before rolling over to the minimum value.\r\n * @param {Number} [minimumValue=0.0] The number reset to after the maximum value has been exceeded.\r\n * @returns {Number} The incremented number.\r\n *\r\n * @exception {DeveloperError} Maximum value must be greater than minimum value.\r\n *\r\n * @example\r\n * var n = Cesium.Math.incrementWrap(5, 10, 0); // returns 6\r\n * var n = Cesium.Math.incrementWrap(10, 10, 0); // returns 0\r\n */\r\nCesiumMath.incrementWrap = function (n, maximumValue, minimumValue) {\r\n minimumValue = defaultValue(minimumValue, 0.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(n)) {\r\n throw new DeveloperError(\"n is required.\");\r\n }\r\n if (maximumValue <= minimumValue) {\r\n throw new DeveloperError(\"maximumValue must be greater than minimumValue.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n ++n;\r\n if (n > maximumValue) {\r\n n = minimumValue;\r\n }\r\n return n;\r\n};\r\n\r\n/**\r\n * Determines if a non-negative integer is a power of two.\r\n * The maximum allowed input is (2^32)-1 due to 32-bit bitwise operator limitation in Javascript.\r\n *\r\n * @param {Number} n The integer to test in the range [0, (2^32)-1].\r\n * @returns {Boolean} true if the number if a power of two; otherwise, false.\r\n *\r\n * @exception {DeveloperError} A number between 0 and (2^32)-1 is required.\r\n *\r\n * @example\r\n * var t = Cesium.Math.isPowerOfTwo(16); // true\r\n * var f = Cesium.Math.isPowerOfTwo(20); // false\r\n */\r\nCesiumMath.isPowerOfTwo = function (n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof n !== \"number\" || n < 0 || n > 4294967295) {\r\n throw new DeveloperError(\"A number between 0 and (2^32)-1 is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return n !== 0 && (n & (n - 1)) === 0;\r\n};\r\n\r\n/**\r\n * Computes the next power-of-two integer greater than or equal to the provided non-negative integer.\r\n * The maximum allowed input is 2^31 due to 32-bit bitwise operator limitation in Javascript.\r\n *\r\n * @param {Number} n The integer to test in the range [0, 2^31].\r\n * @returns {Number} The next power-of-two integer.\r\n *\r\n * @exception {DeveloperError} A number between 0 and 2^31 is required.\r\n *\r\n * @example\r\n * var n = Cesium.Math.nextPowerOfTwo(29); // 32\r\n * var m = Cesium.Math.nextPowerOfTwo(32); // 32\r\n */\r\nCesiumMath.nextPowerOfTwo = function (n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof n !== \"number\" || n < 0 || n > 2147483648) {\r\n throw new DeveloperError(\"A number between 0 and 2^31 is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // From http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2\r\n --n;\r\n n |= n >> 1;\r\n n |= n >> 2;\r\n n |= n >> 4;\r\n n |= n >> 8;\r\n n |= n >> 16;\r\n ++n;\r\n\r\n return n;\r\n};\r\n\r\n/**\r\n * Computes the previous power-of-two integer less than or equal to the provided non-negative integer.\r\n * The maximum allowed input is (2^32)-1 due to 32-bit bitwise operator limitation in Javascript.\r\n *\r\n * @param {Number} n The integer to test in the range [0, (2^32)-1].\r\n * @returns {Number} The previous power-of-two integer.\r\n *\r\n * @exception {DeveloperError} A number between 0 and (2^32)-1 is required.\r\n *\r\n * @example\r\n * var n = Cesium.Math.previousPowerOfTwo(29); // 16\r\n * var m = Cesium.Math.previousPowerOfTwo(32); // 32\r\n */\r\nCesiumMath.previousPowerOfTwo = function (n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof n !== \"number\" || n < 0 || n > 4294967295) {\r\n throw new DeveloperError(\"A number between 0 and (2^32)-1 is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n n |= n >> 1;\r\n n |= n >> 2;\r\n n |= n >> 4;\r\n n |= n >> 8;\r\n n |= n >> 16;\r\n n |= n >> 32;\r\n\r\n // The previous bitwise operations implicitly convert to signed 32-bit. Use `>>>` to convert to unsigned\r\n n = (n >>> 0) - (n >>> 1);\r\n\r\n return n;\r\n};\r\n\r\n/**\r\n * Constraint a value to lie between two values.\r\n *\r\n * @param {Number} value The value to constrain.\r\n * @param {Number} min The minimum value.\r\n * @param {Number} max The maximum value.\r\n * @returns {Number} The value clamped so that min <= value <= max.\r\n */\r\nCesiumMath.clamp = function (value, min, max) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(min)) {\r\n throw new DeveloperError(\"min is required.\");\r\n }\r\n if (!defined(max)) {\r\n throw new DeveloperError(\"max is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return value < min ? min : value > max ? max : value;\r\n};\r\n\r\nvar randomNumberGenerator = new MersenneTwister();\r\n\r\n/**\r\n * Sets the seed used by the random number generator\r\n * in {@link CesiumMath#nextRandomNumber}.\r\n *\r\n * @param {Number} seed An integer used as the seed.\r\n */\r\nCesiumMath.setRandomNumberSeed = function (seed) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(seed)) {\r\n throw new DeveloperError(\"seed is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n randomNumberGenerator = new MersenneTwister(seed);\r\n};\r\n\r\n/**\r\n * Generates a random floating point number in the range of [0.0, 1.0)\r\n * using a Mersenne twister.\r\n *\r\n * @returns {Number} A random number in the range of [0.0, 1.0).\r\n *\r\n * @see CesiumMath.setRandomNumberSeed\r\n * @see {@link http://en.wikipedia.org/wiki/Mersenne_twister|Mersenne twister on Wikipedia}\r\n */\r\nCesiumMath.nextRandomNumber = function () {\r\n return randomNumberGenerator.random();\r\n};\r\n\r\n/**\r\n * Generates a random number between two numbers.\r\n *\r\n * @param {Number} min The minimum value.\r\n * @param {Number} max The maximum value.\r\n * @returns {Number} A random number between the min and max.\r\n */\r\nCesiumMath.randomBetween = function (min, max) {\r\n return CesiumMath.nextRandomNumber() * (max - min) + min;\r\n};\r\n\r\n/**\r\n * Computes Math.acos(value), but first clamps value to the range [-1.0, 1.0]\r\n * so that the function will never return NaN.\r\n *\r\n * @param {Number} value The value for which to compute acos.\r\n * @returns {Number} The acos of the value if the value is in the range [-1.0, 1.0], or the acos of -1.0 or 1.0,\r\n * whichever is closer, if the value is outside the range.\r\n */\r\nCesiumMath.acosClamped = function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return Math.acos(CesiumMath.clamp(value, -1.0, 1.0));\r\n};\r\n\r\n/**\r\n * Computes Math.asin(value), but first clamps value to the range [-1.0, 1.0]\r\n * so that the function will never return NaN.\r\n *\r\n * @param {Number} value The value for which to compute asin.\r\n * @returns {Number} The asin of the value if the value is in the range [-1.0, 1.0], or the asin of -1.0 or 1.0,\r\n * whichever is closer, if the value is outside the range.\r\n */\r\nCesiumMath.asinClamped = function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return Math.asin(CesiumMath.clamp(value, -1.0, 1.0));\r\n};\r\n\r\n/**\r\n * Finds the chord length between two points given the circle's radius and the angle between the points.\r\n *\r\n * @param {Number} angle The angle between the two points.\r\n * @param {Number} radius The radius of the circle.\r\n * @returns {Number} The chord length.\r\n */\r\nCesiumMath.chordLength = function (angle, radius) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(angle)) {\r\n throw new DeveloperError(\"angle is required.\");\r\n }\r\n if (!defined(radius)) {\r\n throw new DeveloperError(\"radius is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return 2.0 * radius * Math.sin(angle * 0.5);\r\n};\r\n\r\n/**\r\n * Finds the logarithm of a number to a base.\r\n *\r\n * @param {Number} number The number.\r\n * @param {Number} base The base.\r\n * @returns {Number} The result.\r\n */\r\nCesiumMath.logBase = function (number, base) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(number)) {\r\n throw new DeveloperError(\"number is required.\");\r\n }\r\n if (!defined(base)) {\r\n throw new DeveloperError(\"base is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return Math.log(number) / Math.log(base);\r\n};\r\n\r\n/**\r\n * Finds the cube root of a number.\r\n * Returns NaN if number is not provided.\r\n *\r\n * @function\r\n * @param {Number} [number] The number.\r\n * @returns {Number} The result.\r\n */\r\n// eslint-disable-next-line es/no-math-cbrt\r\nCesiumMath.cbrt = defaultValue(Math.cbrt, function cbrt(number) {\r\n var result = Math.pow(Math.abs(number), 1.0 / 3.0);\r\n return number < 0.0 ? -result : result;\r\n});\r\n\r\n/**\r\n * Finds the base 2 logarithm of a number.\r\n *\r\n * @function\r\n * @param {Number} number The number.\r\n * @returns {Number} The result.\r\n */\r\n// eslint-disable-next-line es/no-math-log2\r\nCesiumMath.log2 = defaultValue(Math.log2, function log2(number) {\r\n return Math.log(number) * Math.LOG2E;\r\n});\r\n\r\n/**\r\n * @private\r\n */\r\nCesiumMath.fog = function (distanceToCamera, density) {\r\n var scalar = distanceToCamera * density;\r\n return 1.0 - Math.exp(-(scalar * scalar));\r\n};\r\n\r\n/**\r\n * Computes a fast approximation of Atan for input in the range [-1, 1].\r\n *\r\n * Based on Michal Drobot's approximation from ShaderFastLibs,\r\n * which in turn is based on \"Efficient approximations for the arctangent function,\"\r\n * Rajan, S. Sichun Wang Inkol, R. Joyal, A., May 2006.\r\n * Adapted from ShaderFastLibs under MIT License.\r\n *\r\n * @param {Number} x An input number in the range [-1, 1]\r\n * @returns {Number} An approximation of atan(x)\r\n */\r\nCesiumMath.fastApproximateAtan = function (x) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"x\", x);\r\n //>>includeEnd('debug');\r\n\r\n return x * (-0.1784 * Math.abs(x) - 0.0663 * x * x + 1.0301);\r\n};\r\n\r\n/**\r\n * Computes a fast approximation of Atan2(x, y) for arbitrary input scalars.\r\n *\r\n * Range reduction math based on nvidia's cg reference implementation: http://developer.download.nvidia.com/cg/atan2.html\r\n *\r\n * @param {Number} x An input number that isn't zero if y is zero.\r\n * @param {Number} y An input number that isn't zero if x is zero.\r\n * @returns {Number} An approximation of atan2(x, y)\r\n */\r\nCesiumMath.fastApproximateAtan2 = function (x, y) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"x\", x);\r\n Check.typeOf.number(\"y\", y);\r\n //>>includeEnd('debug');\r\n\r\n // atan approximations are usually only reliable over [-1, 1]\r\n // So reduce the range by flipping whether x or y is on top based on which is bigger.\r\n var opposite;\r\n var adjacent;\r\n var t = Math.abs(x); // t used as swap and atan result.\r\n opposite = Math.abs(y);\r\n adjacent = Math.max(t, opposite);\r\n opposite = Math.min(t, opposite);\r\n\r\n var oppositeOverAdjacent = opposite / adjacent;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (isNaN(oppositeOverAdjacent)) {\r\n throw new DeveloperError(\"either x or y must be nonzero\");\r\n }\r\n //>>includeEnd('debug');\r\n t = CesiumMath.fastApproximateAtan(oppositeOverAdjacent);\r\n\r\n // Undo range reduction\r\n t = Math.abs(y) > Math.abs(x) ? CesiumMath.PI_OVER_TWO - t : t;\r\n t = x < 0.0 ? CesiumMath.PI - t : t;\r\n t = y < 0.0 ? -t : t;\r\n return t;\r\n};\r\nexport default CesiumMath;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * A 3D Cartesian point.\r\n * @alias Cartesian3\r\n * @constructor\r\n *\r\n * @param {Number} [x=0.0] The X component.\r\n * @param {Number} [y=0.0] The Y component.\r\n * @param {Number} [z=0.0] The Z component.\r\n *\r\n * @see Cartesian2\r\n * @see Cartesian4\r\n * @see Packable\r\n */\r\nfunction Cartesian3(x, y, z) {\r\n /**\r\n * The X component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.x = defaultValue(x, 0.0);\r\n\r\n /**\r\n * The Y component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.y = defaultValue(y, 0.0);\r\n\r\n /**\r\n * The Z component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.z = defaultValue(z, 0.0);\r\n}\r\n\r\n/**\r\n * Converts the provided Spherical into Cartesian3 coordinates.\r\n *\r\n * @param {Spherical} spherical The Spherical to be converted to Cartesian3.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.\r\n */\r\nCartesian3.fromSpherical = function (spherical, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"spherical\", spherical);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n var clock = spherical.clock;\r\n var cone = spherical.cone;\r\n var magnitude = defaultValue(spherical.magnitude, 1.0);\r\n var radial = magnitude * Math.sin(cone);\r\n result.x = radial * Math.cos(clock);\r\n result.y = radial * Math.sin(clock);\r\n result.z = magnitude * Math.cos(cone);\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Cartesian3 instance from x, y and z coordinates.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {Number} z The z coordinate.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.\r\n */\r\nCartesian3.fromElements = function (x, y, z, result) {\r\n if (!defined(result)) {\r\n return new Cartesian3(x, y, z);\r\n }\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a Cartesian3 instance.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian to duplicate.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided. (Returns undefined if cartesian is undefined)\r\n */\r\nCartesian3.clone = function (cartesian, result) {\r\n if (!defined(cartesian)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new Cartesian3(cartesian.x, cartesian.y, cartesian.z);\r\n }\r\n\r\n result.x = cartesian.x;\r\n result.y = cartesian.y;\r\n result.z = cartesian.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Cartesian3 instance from an existing Cartesian4. This simply takes the\r\n * x, y, and z properties of the Cartesian4 and drops w.\r\n * @function\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian4 instance to create a Cartesian3 instance from.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.\r\n */\r\nCartesian3.fromCartesian4 = Cartesian3.clone;\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nCartesian3.packedLength = 3;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Cartesian3} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCartesian3.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.x;\r\n array[startingIndex++] = value.y;\r\n array[startingIndex] = value.z;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Cartesian3} [result] The object into which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.\r\n */\r\nCartesian3.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n result.x = array[startingIndex++];\r\n result.y = array[startingIndex++];\r\n result.z = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Flattens an array of Cartesian3s into an array of components.\r\n *\r\n * @param {Cartesian3[]} array The array of cartesians to pack.\r\n * @param {Number[]} [result] The array onto which to store the result. If this is a typed array, it must have array.length * 3 components, else a {@link DeveloperError} will be thrown. If it is a regular array, it will be resized to have (array.length * 3) elements.\r\n * @returns {Number[]} The packed array.\r\n */\r\nCartesian3.packArray = function (array, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n var length = array.length;\r\n var resultLength = length * 3;\r\n if (!defined(result)) {\r\n result = new Array(resultLength);\r\n } else if (!Array.isArray(result) && result.length !== resultLength) {\r\n throw new DeveloperError(\r\n \"If result is a typed array, it must have exactly array.length * 3 elements\"\r\n );\r\n } else if (result.length !== resultLength) {\r\n result.length = resultLength;\r\n }\r\n\r\n for (var i = 0; i < length; ++i) {\r\n Cartesian3.pack(array[i], result, i * 3);\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Unpacks an array of cartesian components into an array of Cartesian3s.\r\n *\r\n * @param {Number[]} array The array of components to unpack.\r\n * @param {Cartesian3[]} [result] The array onto which to store the result.\r\n * @returns {Cartesian3[]} The unpacked array.\r\n */\r\nCartesian3.unpackArray = function (array, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n Check.typeOf.number.greaterThanOrEquals(\"array.length\", array.length, 3);\r\n if (array.length % 3 !== 0) {\r\n throw new DeveloperError(\"array length must be a multiple of 3.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = array.length;\r\n if (!defined(result)) {\r\n result = new Array(length / 3);\r\n } else {\r\n result.length = length / 3;\r\n }\r\n\r\n for (var i = 0; i < length; i += 3) {\r\n var index = i / 3;\r\n result[index] = Cartesian3.unpack(array, i, result[index]);\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Cartesian3 from three consecutive elements in an array.\r\n * @function\r\n *\r\n * @param {Number[]} array The array whose three consecutive elements correspond to the x, y, and z components, respectively.\r\n * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to the x component.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Create a Cartesian3 with (1.0, 2.0, 3.0)\r\n * var v = [1.0, 2.0, 3.0];\r\n * var p = Cesium.Cartesian3.fromArray(v);\r\n *\r\n * // Create a Cartesian3 with (1.0, 2.0, 3.0) using an offset into an array\r\n * var v2 = [0.0, 0.0, 1.0, 2.0, 3.0];\r\n * var p2 = Cesium.Cartesian3.fromArray(v2, 2);\r\n */\r\nCartesian3.fromArray = Cartesian3.unpack;\r\n\r\n/**\r\n * Computes the value of the maximum component for the supplied Cartesian.\r\n *\r\n * @param {Cartesian3} cartesian The cartesian to use.\r\n * @returns {Number} The value of the maximum component.\r\n */\r\nCartesian3.maximumComponent = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return Math.max(cartesian.x, cartesian.y, cartesian.z);\r\n};\r\n\r\n/**\r\n * Computes the value of the minimum component for the supplied Cartesian.\r\n *\r\n * @param {Cartesian3} cartesian The cartesian to use.\r\n * @returns {Number} The value of the minimum component.\r\n */\r\nCartesian3.minimumComponent = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return Math.min(cartesian.x, cartesian.y, cartesian.z);\r\n};\r\n\r\n/**\r\n * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians.\r\n *\r\n * @param {Cartesian3} first A cartesian to compare.\r\n * @param {Cartesian3} second A cartesian to compare.\r\n * @param {Cartesian3} result The object into which to store the result.\r\n * @returns {Cartesian3} A cartesian with the minimum components.\r\n */\r\nCartesian3.minimumByComponent = function (first, second, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"first\", first);\r\n Check.typeOf.object(\"second\", second);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.min(first.x, second.x);\r\n result.y = Math.min(first.y, second.y);\r\n result.z = Math.min(first.z, second.z);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians.\r\n *\r\n * @param {Cartesian3} first A cartesian to compare.\r\n * @param {Cartesian3} second A cartesian to compare.\r\n * @param {Cartesian3} result The object into which to store the result.\r\n * @returns {Cartesian3} A cartesian with the maximum components.\r\n */\r\nCartesian3.maximumByComponent = function (first, second, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"first\", first);\r\n Check.typeOf.object(\"second\", second);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.max(first.x, second.x);\r\n result.y = Math.max(first.y, second.y);\r\n result.z = Math.max(first.z, second.z);\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the provided Cartesian's squared magnitude.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian instance whose squared magnitude is to be computed.\r\n * @returns {Number} The squared magnitude.\r\n */\r\nCartesian3.magnitudeSquared = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return (\r\n cartesian.x * cartesian.x +\r\n cartesian.y * cartesian.y +\r\n cartesian.z * cartesian.z\r\n );\r\n};\r\n\r\n/**\r\n * Computes the Cartesian's magnitude (length).\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian instance whose magnitude is to be computed.\r\n * @returns {Number} The magnitude.\r\n */\r\nCartesian3.magnitude = function (cartesian) {\r\n return Math.sqrt(Cartesian3.magnitudeSquared(cartesian));\r\n};\r\n\r\nvar distanceScratch = new Cartesian3();\r\n\r\n/**\r\n * Computes the distance between two points.\r\n *\r\n * @param {Cartesian3} left The first point to compute the distance from.\r\n * @param {Cartesian3} right The second point to compute the distance to.\r\n * @returns {Number} The distance between two points.\r\n *\r\n * @example\r\n * // Returns 1.0\r\n * var d = Cesium.Cartesian3.distance(new Cesium.Cartesian3(1.0, 0.0, 0.0), new Cesium.Cartesian3(2.0, 0.0, 0.0));\r\n */\r\nCartesian3.distance = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian3.subtract(left, right, distanceScratch);\r\n return Cartesian3.magnitude(distanceScratch);\r\n};\r\n\r\n/**\r\n * Computes the squared distance between two points. Comparing squared distances\r\n * using this function is more efficient than comparing distances using {@link Cartesian3#distance}.\r\n *\r\n * @param {Cartesian3} left The first point to compute the distance from.\r\n * @param {Cartesian3} right The second point to compute the distance to.\r\n * @returns {Number} The distance between two points.\r\n *\r\n * @example\r\n * // Returns 4.0, not 2.0\r\n * var d = Cesium.Cartesian3.distanceSquared(new Cesium.Cartesian3(1.0, 0.0, 0.0), new Cesium.Cartesian3(3.0, 0.0, 0.0));\r\n */\r\nCartesian3.distanceSquared = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian3.subtract(left, right, distanceScratch);\r\n return Cartesian3.magnitudeSquared(distanceScratch);\r\n};\r\n\r\n/**\r\n * Computes the normalized form of the supplied Cartesian.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian to be normalized.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.normalize = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var magnitude = Cartesian3.magnitude(cartesian);\r\n\r\n result.x = cartesian.x / magnitude;\r\n result.y = cartesian.y / magnitude;\r\n result.z = cartesian.z / magnitude;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (isNaN(result.x) || isNaN(result.y) || isNaN(result.z)) {\r\n throw new DeveloperError(\"normalized result is not a number\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the dot (scalar) product of two Cartesians.\r\n *\r\n * @param {Cartesian3} left The first Cartesian.\r\n * @param {Cartesian3} right The second Cartesian.\r\n * @returns {Number} The dot product.\r\n */\r\nCartesian3.dot = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n return left.x * right.x + left.y * right.y + left.z * right.z;\r\n};\r\n\r\n/**\r\n * Computes the componentwise product of two Cartesians.\r\n *\r\n * @param {Cartesian3} left The first Cartesian.\r\n * @param {Cartesian3} right The second Cartesian.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.multiplyComponents = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x * right.x;\r\n result.y = left.y * right.y;\r\n result.z = left.z * right.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise quotient of two Cartesians.\r\n *\r\n * @param {Cartesian3} left The first Cartesian.\r\n * @param {Cartesian3} right The second Cartesian.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.divideComponents = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x / right.x;\r\n result.y = left.y / right.y;\r\n result.z = left.z / right.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise sum of two Cartesians.\r\n *\r\n * @param {Cartesian3} left The first Cartesian.\r\n * @param {Cartesian3} right The second Cartesian.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.add = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x + right.x;\r\n result.y = left.y + right.y;\r\n result.z = left.z + right.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise difference of two Cartesians.\r\n *\r\n * @param {Cartesian3} left The first Cartesian.\r\n * @param {Cartesian3} right The second Cartesian.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.subtract = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x - right.x;\r\n result.y = left.y - right.y;\r\n result.z = left.z - right.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Multiplies the provided Cartesian componentwise by the provided scalar.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian to be scaled.\r\n * @param {Number} scalar The scalar to multiply with.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.multiplyByScalar = function (cartesian, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = cartesian.x * scalar;\r\n result.y = cartesian.y * scalar;\r\n result.z = cartesian.z * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Divides the provided Cartesian componentwise by the provided scalar.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian to be divided.\r\n * @param {Number} scalar The scalar to divide by.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.divideByScalar = function (cartesian, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = cartesian.x / scalar;\r\n result.y = cartesian.y / scalar;\r\n result.z = cartesian.z / scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Negates the provided Cartesian.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian to be negated.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.negate = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = -cartesian.x;\r\n result.y = -cartesian.y;\r\n result.z = -cartesian.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the absolute value of the provided Cartesian.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian whose absolute value is to be computed.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.abs = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.abs(cartesian.x);\r\n result.y = Math.abs(cartesian.y);\r\n result.z = Math.abs(cartesian.z);\r\n return result;\r\n};\r\n\r\nvar lerpScratch = new Cartesian3();\r\n/**\r\n * Computes the linear interpolation or extrapolation at t using the provided cartesians.\r\n *\r\n * @param {Cartesian3} start The value corresponding to t at 0.0.\r\n * @param {Cartesian3} end The value corresponding to t at 1.0.\r\n * @param {Number} t The point along t at which to interpolate.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nCartesian3.lerp = function (start, end, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"start\", start);\r\n Check.typeOf.object(\"end\", end);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian3.multiplyByScalar(end, t, lerpScratch);\r\n result = Cartesian3.multiplyByScalar(start, 1.0 - t, result);\r\n return Cartesian3.add(lerpScratch, result, result);\r\n};\r\n\r\nvar angleBetweenScratch = new Cartesian3();\r\nvar angleBetweenScratch2 = new Cartesian3();\r\n/**\r\n * Returns the angle, in radians, between the provided Cartesians.\r\n *\r\n * @param {Cartesian3} left The first Cartesian.\r\n * @param {Cartesian3} right The second Cartesian.\r\n * @returns {Number} The angle between the Cartesians.\r\n */\r\nCartesian3.angleBetween = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian3.normalize(left, angleBetweenScratch);\r\n Cartesian3.normalize(right, angleBetweenScratch2);\r\n var cosine = Cartesian3.dot(angleBetweenScratch, angleBetweenScratch2);\r\n var sine = Cartesian3.magnitude(\r\n Cartesian3.cross(\r\n angleBetweenScratch,\r\n angleBetweenScratch2,\r\n angleBetweenScratch\r\n )\r\n );\r\n return Math.atan2(sine, cosine);\r\n};\r\n\r\nvar mostOrthogonalAxisScratch = new Cartesian3();\r\n/**\r\n * Returns the axis that is most orthogonal to the provided Cartesian.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian on which to find the most orthogonal axis.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The most orthogonal axis.\r\n */\r\nCartesian3.mostOrthogonalAxis = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var f = Cartesian3.normalize(cartesian, mostOrthogonalAxisScratch);\r\n Cartesian3.abs(f, f);\r\n\r\n if (f.x <= f.y) {\r\n if (f.x <= f.z) {\r\n result = Cartesian3.clone(Cartesian3.UNIT_X, result);\r\n } else {\r\n result = Cartesian3.clone(Cartesian3.UNIT_Z, result);\r\n }\r\n } else if (f.y <= f.z) {\r\n result = Cartesian3.clone(Cartesian3.UNIT_Y, result);\r\n } else {\r\n result = Cartesian3.clone(Cartesian3.UNIT_Z, result);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Projects vector a onto vector b\r\n * @param {Cartesian3} a The vector that needs projecting\r\n * @param {Cartesian3} b The vector to project onto\r\n * @param {Cartesian3} result The result cartesian\r\n * @returns {Cartesian3} The modified result parameter\r\n */\r\nCartesian3.projectVector = function (a, b, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"a\", a);\r\n Check.defined(\"b\", b);\r\n Check.defined(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var scalar = Cartesian3.dot(a, b) / Cartesian3.dot(b, b);\r\n return Cartesian3.multiplyByScalar(b, scalar, result);\r\n};\r\n\r\n/**\r\n * Compares the provided Cartesians componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Cartesian3} [left] The first Cartesian.\r\n * @param {Cartesian3} [right] The second Cartesian.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCartesian3.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.x === right.x &&\r\n left.y === right.y &&\r\n left.z === right.z)\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCartesian3.equalsArray = function (cartesian, array, offset) {\r\n return (\r\n cartesian.x === array[offset] &&\r\n cartesian.y === array[offset + 1] &&\r\n cartesian.z === array[offset + 2]\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided Cartesians componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {Cartesian3} [left] The first Cartesian.\r\n * @param {Cartesian3} [right] The second Cartesian.\r\n * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nCartesian3.equalsEpsilon = function (\r\n left,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n CesiumMath.equalsEpsilon(\r\n left.x,\r\n right.x,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n left.y,\r\n right.y,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n left.z,\r\n right.z,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ))\r\n );\r\n};\r\n\r\n/**\r\n * Computes the cross (outer) product of two Cartesians.\r\n *\r\n * @param {Cartesian3} left The first Cartesian.\r\n * @param {Cartesian3} right The second Cartesian.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The cross product.\r\n */\r\nCartesian3.cross = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var leftX = left.x;\r\n var leftY = left.y;\r\n var leftZ = left.z;\r\n var rightX = right.x;\r\n var rightY = right.y;\r\n var rightZ = right.z;\r\n\r\n var x = leftY * rightZ - leftZ * rightY;\r\n var y = leftZ * rightX - leftX * rightZ;\r\n var z = leftX * rightY - leftY * rightX;\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the midpoint between the right and left Cartesian.\r\n * @param {Cartesian3} left The first Cartesian.\r\n * @param {Cartesian3} right The second Cartesian.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The midpoint.\r\n */\r\nCartesian3.midpoint = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = (left.x + right.x) * 0.5;\r\n result.y = (left.y + right.y) * 0.5;\r\n result.z = (left.z + right.z) * 0.5;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns a Cartesian3 position from longitude and latitude values given in degrees.\r\n *\r\n * @param {Number} longitude The longitude, in degrees\r\n * @param {Number} latitude The latitude, in degrees\r\n * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The position\r\n *\r\n * @example\r\n * var position = Cesium.Cartesian3.fromDegrees(-115.0, 37.0);\r\n */\r\nCartesian3.fromDegrees = function (\r\n longitude,\r\n latitude,\r\n height,\r\n ellipsoid,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"longitude\", longitude);\r\n Check.typeOf.number(\"latitude\", latitude);\r\n //>>includeEnd('debug');\r\n\r\n longitude = CesiumMath.toRadians(longitude);\r\n latitude = CesiumMath.toRadians(latitude);\r\n return Cartesian3.fromRadians(longitude, latitude, height, ellipsoid, result);\r\n};\r\n\r\nvar scratchN = new Cartesian3();\r\nvar scratchK = new Cartesian3();\r\nvar wgs84RadiiSquared = new Cartesian3(\r\n 6378137.0 * 6378137.0,\r\n 6378137.0 * 6378137.0,\r\n 6356752.3142451793 * 6356752.3142451793\r\n);\r\n\r\n/**\r\n * Returns a Cartesian3 position from longitude and latitude values given in radians.\r\n *\r\n * @param {Number} longitude The longitude, in radians\r\n * @param {Number} latitude The latitude, in radians\r\n * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The position\r\n *\r\n * @example\r\n * var position = Cesium.Cartesian3.fromRadians(-2.007, 0.645);\r\n */\r\nCartesian3.fromRadians = function (\r\n longitude,\r\n latitude,\r\n height,\r\n ellipsoid,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"longitude\", longitude);\r\n Check.typeOf.number(\"latitude\", latitude);\r\n //>>includeEnd('debug');\r\n\r\n height = defaultValue(height, 0.0);\r\n var radiiSquared = defined(ellipsoid)\r\n ? ellipsoid.radiiSquared\r\n : wgs84RadiiSquared;\r\n\r\n var cosLatitude = Math.cos(latitude);\r\n scratchN.x = cosLatitude * Math.cos(longitude);\r\n scratchN.y = cosLatitude * Math.sin(longitude);\r\n scratchN.z = Math.sin(latitude);\r\n scratchN = Cartesian3.normalize(scratchN, scratchN);\r\n\r\n Cartesian3.multiplyComponents(radiiSquared, scratchN, scratchK);\r\n var gamma = Math.sqrt(Cartesian3.dot(scratchN, scratchK));\r\n scratchK = Cartesian3.divideByScalar(scratchK, gamma, scratchK);\r\n scratchN = Cartesian3.multiplyByScalar(scratchN, height, scratchN);\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n return Cartesian3.add(scratchK, scratchN, result);\r\n};\r\n\r\n/**\r\n * Returns an array of Cartesian3 positions given an array of longitude and latitude values given in degrees.\r\n *\r\n * @param {Number[]} coordinates A list of longitude and latitude values. Values alternate [longitude, latitude, longitude, latitude...].\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the coordinates lie.\r\n * @param {Cartesian3[]} [result] An array of Cartesian3 objects to store the result.\r\n * @returns {Cartesian3[]} The array of positions.\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromDegreesArray([-115.0, 37.0, -107.0, 33.0]);\r\n */\r\nCartesian3.fromDegreesArray = function (coordinates, ellipsoid, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"coordinates\", coordinates);\r\n if (coordinates.length < 2 || coordinates.length % 2 !== 0) {\r\n throw new DeveloperError(\r\n \"the number of coordinates must be a multiple of 2 and at least 2\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = coordinates.length;\r\n if (!defined(result)) {\r\n result = new Array(length / 2);\r\n } else {\r\n result.length = length / 2;\r\n }\r\n\r\n for (var i = 0; i < length; i += 2) {\r\n var longitude = coordinates[i];\r\n var latitude = coordinates[i + 1];\r\n var index = i / 2;\r\n result[index] = Cartesian3.fromDegrees(\r\n longitude,\r\n latitude,\r\n 0,\r\n ellipsoid,\r\n result[index]\r\n );\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns an array of Cartesian3 positions given an array of longitude and latitude values given in radians.\r\n *\r\n * @param {Number[]} coordinates A list of longitude and latitude values. Values alternate [longitude, latitude, longitude, latitude...].\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the coordinates lie.\r\n * @param {Cartesian3[]} [result] An array of Cartesian3 objects to store the result.\r\n * @returns {Cartesian3[]} The array of positions.\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromRadiansArray([-2.007, 0.645, -1.867, .575]);\r\n */\r\nCartesian3.fromRadiansArray = function (coordinates, ellipsoid, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"coordinates\", coordinates);\r\n if (coordinates.length < 2 || coordinates.length % 2 !== 0) {\r\n throw new DeveloperError(\r\n \"the number of coordinates must be a multiple of 2 and at least 2\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = coordinates.length;\r\n if (!defined(result)) {\r\n result = new Array(length / 2);\r\n } else {\r\n result.length = length / 2;\r\n }\r\n\r\n for (var i = 0; i < length; i += 2) {\r\n var longitude = coordinates[i];\r\n var latitude = coordinates[i + 1];\r\n var index = i / 2;\r\n result[index] = Cartesian3.fromRadians(\r\n longitude,\r\n latitude,\r\n 0,\r\n ellipsoid,\r\n result[index]\r\n );\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns an array of Cartesian3 positions given an array of longitude, latitude and height values where longitude and latitude are given in degrees.\r\n *\r\n * @param {Number[]} coordinates A list of longitude, latitude and height values. Values alternate [longitude, latitude, height, longitude, latitude, height...].\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.\r\n * @param {Cartesian3[]} [result] An array of Cartesian3 objects to store the result.\r\n * @returns {Cartesian3[]} The array of positions.\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromDegreesArrayHeights([-115.0, 37.0, 100000.0, -107.0, 33.0, 150000.0]);\r\n */\r\nCartesian3.fromDegreesArrayHeights = function (coordinates, ellipsoid, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"coordinates\", coordinates);\r\n if (coordinates.length < 3 || coordinates.length % 3 !== 0) {\r\n throw new DeveloperError(\r\n \"the number of coordinates must be a multiple of 3 and at least 3\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = coordinates.length;\r\n if (!defined(result)) {\r\n result = new Array(length / 3);\r\n } else {\r\n result.length = length / 3;\r\n }\r\n\r\n for (var i = 0; i < length; i += 3) {\r\n var longitude = coordinates[i];\r\n var latitude = coordinates[i + 1];\r\n var height = coordinates[i + 2];\r\n var index = i / 3;\r\n result[index] = Cartesian3.fromDegrees(\r\n longitude,\r\n latitude,\r\n height,\r\n ellipsoid,\r\n result[index]\r\n );\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns an array of Cartesian3 positions given an array of longitude, latitude and height values where longitude and latitude are given in radians.\r\n *\r\n * @param {Number[]} coordinates A list of longitude, latitude and height values. Values alternate [longitude, latitude, height, longitude, latitude, height...].\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.\r\n * @param {Cartesian3[]} [result] An array of Cartesian3 objects to store the result.\r\n * @returns {Cartesian3[]} The array of positions.\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromRadiansArrayHeights([-2.007, 0.645, 100000.0, -1.867, .575, 150000.0]);\r\n */\r\nCartesian3.fromRadiansArrayHeights = function (coordinates, ellipsoid, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"coordinates\", coordinates);\r\n if (coordinates.length < 3 || coordinates.length % 3 !== 0) {\r\n throw new DeveloperError(\r\n \"the number of coordinates must be a multiple of 3 and at least 3\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = coordinates.length;\r\n if (!defined(result)) {\r\n result = new Array(length / 3);\r\n } else {\r\n result.length = length / 3;\r\n }\r\n\r\n for (var i = 0; i < length; i += 3) {\r\n var longitude = coordinates[i];\r\n var latitude = coordinates[i + 1];\r\n var height = coordinates[i + 2];\r\n var index = i / 3;\r\n result[index] = Cartesian3.fromRadians(\r\n longitude,\r\n latitude,\r\n height,\r\n ellipsoid,\r\n result[index]\r\n );\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * An immutable Cartesian3 instance initialized to (0.0, 0.0, 0.0).\r\n *\r\n * @type {Cartesian3}\r\n * @constant\r\n */\r\nCartesian3.ZERO = Object.freeze(new Cartesian3(0.0, 0.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian3 instance initialized to (1.0, 0.0, 0.0).\r\n *\r\n * @type {Cartesian3}\r\n * @constant\r\n */\r\nCartesian3.UNIT_X = Object.freeze(new Cartesian3(1.0, 0.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian3 instance initialized to (0.0, 1.0, 0.0).\r\n *\r\n * @type {Cartesian3}\r\n * @constant\r\n */\r\nCartesian3.UNIT_Y = Object.freeze(new Cartesian3(0.0, 1.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian3 instance initialized to (0.0, 0.0, 1.0).\r\n *\r\n * @type {Cartesian3}\r\n * @constant\r\n */\r\nCartesian3.UNIT_Z = Object.freeze(new Cartesian3(0.0, 0.0, 1.0));\r\n\r\n/**\r\n * Duplicates this Cartesian3 instance.\r\n *\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.\r\n */\r\nCartesian3.prototype.clone = function (result) {\r\n return Cartesian3.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this Cartesian against the provided Cartesian componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Cartesian3} [right] The right hand side Cartesian.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nCartesian3.prototype.equals = function (right) {\r\n return Cartesian3.equals(this, right);\r\n};\r\n\r\n/**\r\n * Compares this Cartesian against the provided Cartesian componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {Cartesian3} [right] The right hand side Cartesian.\r\n * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if they are within the provided epsilon, false otherwise.\r\n */\r\nCartesian3.prototype.equalsEpsilon = function (\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return Cartesian3.equalsEpsilon(\r\n this,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n );\r\n};\r\n\r\n/**\r\n * Creates a string representing this Cartesian in the format '(x, y, z)'.\r\n *\r\n * @returns {String} A string representing this Cartesian in the format '(x, y, z)'.\r\n */\r\nCartesian3.prototype.toString = function () {\r\n return \"(\" + this.x + \", \" + this.y + \", \" + this.z + \")\";\r\n};\r\nexport default Cartesian3;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nvar scaleToGeodeticSurfaceIntersection = new Cartesian3();\r\nvar scaleToGeodeticSurfaceGradient = new Cartesian3();\r\n\r\n/**\r\n * Scales the provided Cartesian position along the geodetic surface normal\r\n * so that it is on the surface of this ellipsoid. If the position is\r\n * at the center of the ellipsoid, this function returns undefined.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian position to scale.\r\n * @param {Cartesian3} oneOverRadii One over radii of the ellipsoid.\r\n * @param {Cartesian3} oneOverRadiiSquared One over radii squared of the ellipsoid.\r\n * @param {Number} centerToleranceSquared Tolerance for closeness to the center.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter, a new Cartesian3 instance if none was provided, or undefined if the position is at the center.\r\n *\r\n * @function scaleToGeodeticSurface\r\n *\r\n * @private\r\n */\r\nfunction scaleToGeodeticSurface(\r\n cartesian,\r\n oneOverRadii,\r\n oneOverRadiiSquared,\r\n centerToleranceSquared,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(cartesian)) {\r\n throw new DeveloperError(\"cartesian is required.\");\r\n }\r\n if (!defined(oneOverRadii)) {\r\n throw new DeveloperError(\"oneOverRadii is required.\");\r\n }\r\n if (!defined(oneOverRadiiSquared)) {\r\n throw new DeveloperError(\"oneOverRadiiSquared is required.\");\r\n }\r\n if (!defined(centerToleranceSquared)) {\r\n throw new DeveloperError(\"centerToleranceSquared is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var positionX = cartesian.x;\r\n var positionY = cartesian.y;\r\n var positionZ = cartesian.z;\r\n\r\n var oneOverRadiiX = oneOverRadii.x;\r\n var oneOverRadiiY = oneOverRadii.y;\r\n var oneOverRadiiZ = oneOverRadii.z;\r\n\r\n var x2 = positionX * positionX * oneOverRadiiX * oneOverRadiiX;\r\n var y2 = positionY * positionY * oneOverRadiiY * oneOverRadiiY;\r\n var z2 = positionZ * positionZ * oneOverRadiiZ * oneOverRadiiZ;\r\n\r\n // Compute the squared ellipsoid norm.\r\n var squaredNorm = x2 + y2 + z2;\r\n var ratio = Math.sqrt(1.0 / squaredNorm);\r\n\r\n // As an initial approximation, assume that the radial intersection is the projection point.\r\n var intersection = Cartesian3.multiplyByScalar(\r\n cartesian,\r\n ratio,\r\n scaleToGeodeticSurfaceIntersection\r\n );\r\n\r\n // If the position is near the center, the iteration will not converge.\r\n if (squaredNorm < centerToleranceSquared) {\r\n return !isFinite(ratio)\r\n ? undefined\r\n : Cartesian3.clone(intersection, result);\r\n }\r\n\r\n var oneOverRadiiSquaredX = oneOverRadiiSquared.x;\r\n var oneOverRadiiSquaredY = oneOverRadiiSquared.y;\r\n var oneOverRadiiSquaredZ = oneOverRadiiSquared.z;\r\n\r\n // Use the gradient at the intersection point in place of the true unit normal.\r\n // The difference in magnitude will be absorbed in the multiplier.\r\n var gradient = scaleToGeodeticSurfaceGradient;\r\n gradient.x = intersection.x * oneOverRadiiSquaredX * 2.0;\r\n gradient.y = intersection.y * oneOverRadiiSquaredY * 2.0;\r\n gradient.z = intersection.z * oneOverRadiiSquaredZ * 2.0;\r\n\r\n // Compute the initial guess at the normal vector multiplier, lambda.\r\n var lambda =\r\n ((1.0 - ratio) * Cartesian3.magnitude(cartesian)) /\r\n (0.5 * Cartesian3.magnitude(gradient));\r\n var correction = 0.0;\r\n\r\n var func;\r\n var denominator;\r\n var xMultiplier;\r\n var yMultiplier;\r\n var zMultiplier;\r\n var xMultiplier2;\r\n var yMultiplier2;\r\n var zMultiplier2;\r\n var xMultiplier3;\r\n var yMultiplier3;\r\n var zMultiplier3;\r\n\r\n do {\r\n lambda -= correction;\r\n\r\n xMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredX);\r\n yMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredY);\r\n zMultiplier = 1.0 / (1.0 + lambda * oneOverRadiiSquaredZ);\r\n\r\n xMultiplier2 = xMultiplier * xMultiplier;\r\n yMultiplier2 = yMultiplier * yMultiplier;\r\n zMultiplier2 = zMultiplier * zMultiplier;\r\n\r\n xMultiplier3 = xMultiplier2 * xMultiplier;\r\n yMultiplier3 = yMultiplier2 * yMultiplier;\r\n zMultiplier3 = zMultiplier2 * zMultiplier;\r\n\r\n func = x2 * xMultiplier2 + y2 * yMultiplier2 + z2 * zMultiplier2 - 1.0;\r\n\r\n // \"denominator\" here refers to the use of this expression in the velocity and acceleration\r\n // computations in the sections to follow.\r\n denominator =\r\n x2 * xMultiplier3 * oneOverRadiiSquaredX +\r\n y2 * yMultiplier3 * oneOverRadiiSquaredY +\r\n z2 * zMultiplier3 * oneOverRadiiSquaredZ;\r\n\r\n var derivative = -2.0 * denominator;\r\n\r\n correction = func / derivative;\r\n } while (Math.abs(func) > CesiumMath.EPSILON12);\r\n\r\n if (!defined(result)) {\r\n return new Cartesian3(\r\n positionX * xMultiplier,\r\n positionY * yMultiplier,\r\n positionZ * zMultiplier\r\n );\r\n }\r\n result.x = positionX * xMultiplier;\r\n result.y = positionY * yMultiplier;\r\n result.z = positionZ * zMultiplier;\r\n return result;\r\n}\r\nexport default scaleToGeodeticSurface;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport scaleToGeodeticSurface from \"./scaleToGeodeticSurface.js\";\r\n\r\n/**\r\n * A position defined by longitude, latitude, and height.\r\n * @alias Cartographic\r\n * @constructor\r\n *\r\n * @param {Number} [longitude=0.0] The longitude, in radians.\r\n * @param {Number} [latitude=0.0] The latitude, in radians.\r\n * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.\r\n *\r\n * @see Ellipsoid\r\n */\r\nfunction Cartographic(longitude, latitude, height) {\r\n /**\r\n * The longitude, in radians.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.longitude = defaultValue(longitude, 0.0);\r\n\r\n /**\r\n * The latitude, in radians.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.latitude = defaultValue(latitude, 0.0);\r\n\r\n /**\r\n * The height, in meters, above the ellipsoid.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.height = defaultValue(height, 0.0);\r\n}\r\n\r\n/**\r\n * Creates a new Cartographic instance from longitude and latitude\r\n * specified in radians.\r\n *\r\n * @param {Number} longitude The longitude, in radians.\r\n * @param {Number} latitude The latitude, in radians.\r\n * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.\r\n */\r\nCartographic.fromRadians = function (longitude, latitude, height, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"longitude\", longitude);\r\n Check.typeOf.number(\"latitude\", latitude);\r\n //>>includeEnd('debug');\r\n\r\n height = defaultValue(height, 0.0);\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(longitude, latitude, height);\r\n }\r\n\r\n result.longitude = longitude;\r\n result.latitude = latitude;\r\n result.height = height;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new Cartographic instance from longitude and latitude\r\n * specified in degrees. The values in the resulting object will\r\n * be in radians.\r\n *\r\n * @param {Number} longitude The longitude, in degrees.\r\n * @param {Number} latitude The latitude, in degrees.\r\n * @param {Number} [height=0.0] The height, in meters, above the ellipsoid.\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.\r\n */\r\nCartographic.fromDegrees = function (longitude, latitude, height, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"longitude\", longitude);\r\n Check.typeOf.number(\"latitude\", latitude);\r\n //>>includeEnd('debug');\r\n longitude = CesiumMath.toRadians(longitude);\r\n latitude = CesiumMath.toRadians(latitude);\r\n\r\n return Cartographic.fromRadians(longitude, latitude, height, result);\r\n};\r\n\r\nvar cartesianToCartographicN = new Cartesian3();\r\nvar cartesianToCartographicP = new Cartesian3();\r\nvar cartesianToCartographicH = new Cartesian3();\r\nvar wgs84OneOverRadii = new Cartesian3(\r\n 1.0 / 6378137.0,\r\n 1.0 / 6378137.0,\r\n 1.0 / 6356752.3142451793\r\n);\r\nvar wgs84OneOverRadiiSquared = new Cartesian3(\r\n 1.0 / (6378137.0 * 6378137.0),\r\n 1.0 / (6378137.0 * 6378137.0),\r\n 1.0 / (6356752.3142451793 * 6356752.3142451793)\r\n);\r\nvar wgs84CenterToleranceSquared = CesiumMath.EPSILON1;\r\n\r\n/**\r\n * Creates a new Cartographic instance from a Cartesian position. The values in the\r\n * resulting object will be in radians.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian position to convert to cartographic representation.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter, new Cartographic instance if none was provided, or undefined if the cartesian is at the center of the ellipsoid.\r\n */\r\nCartographic.fromCartesian = function (cartesian, ellipsoid, result) {\r\n var oneOverRadii = defined(ellipsoid)\r\n ? ellipsoid.oneOverRadii\r\n : wgs84OneOverRadii;\r\n var oneOverRadiiSquared = defined(ellipsoid)\r\n ? ellipsoid.oneOverRadiiSquared\r\n : wgs84OneOverRadiiSquared;\r\n var centerToleranceSquared = defined(ellipsoid)\r\n ? ellipsoid._centerToleranceSquared\r\n : wgs84CenterToleranceSquared;\r\n\r\n //`cartesian is required.` is thrown from scaleToGeodeticSurface\r\n var p = scaleToGeodeticSurface(\r\n cartesian,\r\n oneOverRadii,\r\n oneOverRadiiSquared,\r\n centerToleranceSquared,\r\n cartesianToCartographicP\r\n );\r\n\r\n if (!defined(p)) {\r\n return undefined;\r\n }\r\n\r\n var n = Cartesian3.multiplyComponents(\r\n p,\r\n oneOverRadiiSquared,\r\n cartesianToCartographicN\r\n );\r\n n = Cartesian3.normalize(n, n);\r\n\r\n var h = Cartesian3.subtract(cartesian, p, cartesianToCartographicH);\r\n\r\n var longitude = Math.atan2(n.y, n.x);\r\n var latitude = Math.asin(n.z);\r\n var height =\r\n CesiumMath.sign(Cartesian3.dot(h, cartesian)) * Cartesian3.magnitude(h);\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(longitude, latitude, height);\r\n }\r\n result.longitude = longitude;\r\n result.latitude = latitude;\r\n result.height = height;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new Cartesian3 instance from a Cartographic input. The values in the inputted\r\n * object should be in radians.\r\n *\r\n * @param {Cartographic} cartographic Input to be converted into a Cartesian3 output.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the position lies.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The position\r\n */\r\nCartographic.toCartesian = function (cartographic, ellipsoid, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartographic\", cartographic);\r\n //>>includeEnd('debug');\r\n\r\n return Cartesian3.fromRadians(\r\n cartographic.longitude,\r\n cartographic.latitude,\r\n cartographic.height,\r\n ellipsoid,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates a Cartographic instance.\r\n *\r\n * @param {Cartographic} cartographic The cartographic to duplicate.\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided. (Returns undefined if cartographic is undefined)\r\n */\r\nCartographic.clone = function (cartographic, result) {\r\n if (!defined(cartographic)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new Cartographic(\r\n cartographic.longitude,\r\n cartographic.latitude,\r\n cartographic.height\r\n );\r\n }\r\n result.longitude = cartographic.longitude;\r\n result.latitude = cartographic.latitude;\r\n result.height = cartographic.height;\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided cartographics componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Cartographic} [left] The first cartographic.\r\n * @param {Cartographic} [right] The second cartographic.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCartographic.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.longitude === right.longitude &&\r\n left.latitude === right.latitude &&\r\n left.height === right.height)\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided cartographics componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Cartographic} [left] The first cartographic.\r\n * @param {Cartographic} [right] The second cartographic.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nCartographic.equalsEpsilon = function (left, right, epsilon) {\r\n epsilon = defaultValue(epsilon, 0);\r\n\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Math.abs(left.longitude - right.longitude) <= epsilon &&\r\n Math.abs(left.latitude - right.latitude) <= epsilon &&\r\n Math.abs(left.height - right.height) <= epsilon)\r\n );\r\n};\r\n\r\n/**\r\n * An immutable Cartographic instance initialized to (0.0, 0.0, 0.0).\r\n *\r\n * @type {Cartographic}\r\n * @constant\r\n */\r\nCartographic.ZERO = Object.freeze(new Cartographic(0.0, 0.0, 0.0));\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if one was not provided.\r\n */\r\nCartographic.prototype.clone = function (result) {\r\n return Cartographic.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares the provided against this cartographic componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Cartographic} [right] The second cartographic.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCartographic.prototype.equals = function (right) {\r\n return Cartographic.equals(this, right);\r\n};\r\n\r\n/**\r\n * Compares the provided against this cartographic componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Cartographic} [right] The second cartographic.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nCartographic.prototype.equalsEpsilon = function (right, epsilon) {\r\n return Cartographic.equalsEpsilon(this, right, epsilon);\r\n};\r\n\r\n/**\r\n * Creates a string representing this cartographic in the format '(longitude, latitude, height)'.\r\n *\r\n * @returns {String} A string representing the provided cartographic in the format '(longitude, latitude, height)'.\r\n */\r\nCartographic.prototype.toString = function () {\r\n return \"(\" + this.longitude + \", \" + this.latitude + \", \" + this.height + \")\";\r\n};\r\nexport default Cartographic;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport scaleToGeodeticSurface from \"./scaleToGeodeticSurface.js\";\r\n\r\nfunction initialize(ellipsoid, x, y, z) {\r\n x = defaultValue(x, 0.0);\r\n y = defaultValue(y, 0.0);\r\n z = defaultValue(z, 0.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"x\", x, 0.0);\r\n Check.typeOf.number.greaterThanOrEquals(\"y\", y, 0.0);\r\n Check.typeOf.number.greaterThanOrEquals(\"z\", z, 0.0);\r\n //>>includeEnd('debug');\r\n\r\n ellipsoid._radii = new Cartesian3(x, y, z);\r\n\r\n ellipsoid._radiiSquared = new Cartesian3(x * x, y * y, z * z);\r\n\r\n ellipsoid._radiiToTheFourth = new Cartesian3(\r\n x * x * x * x,\r\n y * y * y * y,\r\n z * z * z * z\r\n );\r\n\r\n ellipsoid._oneOverRadii = new Cartesian3(\r\n x === 0.0 ? 0.0 : 1.0 / x,\r\n y === 0.0 ? 0.0 : 1.0 / y,\r\n z === 0.0 ? 0.0 : 1.0 / z\r\n );\r\n\r\n ellipsoid._oneOverRadiiSquared = new Cartesian3(\r\n x === 0.0 ? 0.0 : 1.0 / (x * x),\r\n y === 0.0 ? 0.0 : 1.0 / (y * y),\r\n z === 0.0 ? 0.0 : 1.0 / (z * z)\r\n );\r\n\r\n ellipsoid._minimumRadius = Math.min(x, y, z);\r\n\r\n ellipsoid._maximumRadius = Math.max(x, y, z);\r\n\r\n ellipsoid._centerToleranceSquared = CesiumMath.EPSILON1;\r\n\r\n if (ellipsoid._radiiSquared.z !== 0) {\r\n ellipsoid._squaredXOverSquaredZ =\r\n ellipsoid._radiiSquared.x / ellipsoid._radiiSquared.z;\r\n }\r\n}\r\n\r\n/**\r\n * A quadratic surface defined in Cartesian coordinates by the equation\r\n * (x / a)^2 + (y / b)^2 + (z / c)^2 = 1. Primarily used\r\n * by Cesium to represent the shape of planetary bodies.\r\n *\r\n * Rather than constructing this object directly, one of the provided\r\n * constants is normally used.\r\n * @alias Ellipsoid\r\n * @constructor\r\n *\r\n * @param {Number} [x=0] The radius in the x direction.\r\n * @param {Number} [y=0] The radius in the y direction.\r\n * @param {Number} [z=0] The radius in the z direction.\r\n *\r\n * @exception {DeveloperError} All radii components must be greater than or equal to zero.\r\n *\r\n * @see Ellipsoid.fromCartesian3\r\n * @see Ellipsoid.WGS84\r\n * @see Ellipsoid.UNIT_SPHERE\r\n */\r\nfunction Ellipsoid(x, y, z) {\r\n this._radii = undefined;\r\n this._radiiSquared = undefined;\r\n this._radiiToTheFourth = undefined;\r\n this._oneOverRadii = undefined;\r\n this._oneOverRadiiSquared = undefined;\r\n this._minimumRadius = undefined;\r\n this._maximumRadius = undefined;\r\n this._centerToleranceSquared = undefined;\r\n this._squaredXOverSquaredZ = undefined;\r\n\r\n initialize(this, x, y, z);\r\n}\r\n\r\nObject.defineProperties(Ellipsoid.prototype, {\r\n /**\r\n * Gets the radii of the ellipsoid.\r\n * @memberof Ellipsoid.prototype\r\n * @type {Cartesian3}\r\n * @readonly\r\n */\r\n radii: {\r\n get: function () {\r\n return this._radii;\r\n },\r\n },\r\n /**\r\n * Gets the squared radii of the ellipsoid.\r\n * @memberof Ellipsoid.prototype\r\n * @type {Cartesian3}\r\n * @readonly\r\n */\r\n radiiSquared: {\r\n get: function () {\r\n return this._radiiSquared;\r\n },\r\n },\r\n /**\r\n * Gets the radii of the ellipsoid raise to the fourth power.\r\n * @memberof Ellipsoid.prototype\r\n * @type {Cartesian3}\r\n * @readonly\r\n */\r\n radiiToTheFourth: {\r\n get: function () {\r\n return this._radiiToTheFourth;\r\n },\r\n },\r\n /**\r\n * Gets one over the radii of the ellipsoid.\r\n * @memberof Ellipsoid.prototype\r\n * @type {Cartesian3}\r\n * @readonly\r\n */\r\n oneOverRadii: {\r\n get: function () {\r\n return this._oneOverRadii;\r\n },\r\n },\r\n /**\r\n * Gets one over the squared radii of the ellipsoid.\r\n * @memberof Ellipsoid.prototype\r\n * @type {Cartesian3}\r\n * @readonly\r\n */\r\n oneOverRadiiSquared: {\r\n get: function () {\r\n return this._oneOverRadiiSquared;\r\n },\r\n },\r\n /**\r\n * Gets the minimum radius of the ellipsoid.\r\n * @memberof Ellipsoid.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n minimumRadius: {\r\n get: function () {\r\n return this._minimumRadius;\r\n },\r\n },\r\n /**\r\n * Gets the maximum radius of the ellipsoid.\r\n * @memberof Ellipsoid.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n maximumRadius: {\r\n get: function () {\r\n return this._maximumRadius;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Duplicates an Ellipsoid instance.\r\n *\r\n * @param {Ellipsoid} ellipsoid The ellipsoid to duplicate.\r\n * @param {Ellipsoid} [result] The object onto which to store the result, or undefined if a new\r\n * instance should be created.\r\n * @returns {Ellipsoid} The cloned Ellipsoid. (Returns undefined if ellipsoid is undefined)\r\n */\r\nEllipsoid.clone = function (ellipsoid, result) {\r\n if (!defined(ellipsoid)) {\r\n return undefined;\r\n }\r\n var radii = ellipsoid._radii;\r\n\r\n if (!defined(result)) {\r\n return new Ellipsoid(radii.x, radii.y, radii.z);\r\n }\r\n\r\n Cartesian3.clone(radii, result._radii);\r\n Cartesian3.clone(ellipsoid._radiiSquared, result._radiiSquared);\r\n Cartesian3.clone(ellipsoid._radiiToTheFourth, result._radiiToTheFourth);\r\n Cartesian3.clone(ellipsoid._oneOverRadii, result._oneOverRadii);\r\n Cartesian3.clone(ellipsoid._oneOverRadiiSquared, result._oneOverRadiiSquared);\r\n result._minimumRadius = ellipsoid._minimumRadius;\r\n result._maximumRadius = ellipsoid._maximumRadius;\r\n result._centerToleranceSquared = ellipsoid._centerToleranceSquared;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes an Ellipsoid from a Cartesian specifying the radii in x, y, and z directions.\r\n *\r\n * @param {Cartesian3} [cartesian=Cartesian3.ZERO] The ellipsoid's radius in the x, y, and z directions.\r\n * @param {Ellipsoid} [result] The object onto which to store the result, or undefined if a new\r\n * instance should be created.\r\n * @returns {Ellipsoid} A new Ellipsoid instance.\r\n *\r\n * @exception {DeveloperError} All radii components must be greater than or equal to zero.\r\n *\r\n * @see Ellipsoid.WGS84\r\n * @see Ellipsoid.UNIT_SPHERE\r\n */\r\nEllipsoid.fromCartesian3 = function (cartesian, result) {\r\n if (!defined(result)) {\r\n result = new Ellipsoid();\r\n }\r\n\r\n if (!defined(cartesian)) {\r\n return result;\r\n }\r\n\r\n initialize(result, cartesian.x, cartesian.y, cartesian.z);\r\n return result;\r\n};\r\n\r\n/**\r\n * An Ellipsoid instance initialized to the WGS84 standard.\r\n *\r\n * @type {Ellipsoid}\r\n * @constant\r\n */\r\nEllipsoid.WGS84 = Object.freeze(\r\n new Ellipsoid(6378137.0, 6378137.0, 6356752.3142451793)\r\n);\r\n\r\n/**\r\n * An Ellipsoid instance initialized to radii of (1.0, 1.0, 1.0).\r\n *\r\n * @type {Ellipsoid}\r\n * @constant\r\n */\r\nEllipsoid.UNIT_SPHERE = Object.freeze(new Ellipsoid(1.0, 1.0, 1.0));\r\n\r\n/**\r\n * An Ellipsoid instance initialized to a sphere with the lunar radius.\r\n *\r\n * @type {Ellipsoid}\r\n * @constant\r\n */\r\nEllipsoid.MOON = Object.freeze(\r\n new Ellipsoid(\r\n CesiumMath.LUNAR_RADIUS,\r\n CesiumMath.LUNAR_RADIUS,\r\n CesiumMath.LUNAR_RADIUS\r\n )\r\n);\r\n\r\n/**\r\n * Duplicates an Ellipsoid instance.\r\n *\r\n * @param {Ellipsoid} [result] The object onto which to store the result, or undefined if a new\r\n * instance should be created.\r\n * @returns {Ellipsoid} The cloned Ellipsoid.\r\n */\r\nEllipsoid.prototype.clone = function (result) {\r\n return Ellipsoid.clone(this, result);\r\n};\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nEllipsoid.packedLength = Cartesian3.packedLength;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Ellipsoid} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nEllipsoid.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Cartesian3.pack(value._radii, array, startingIndex);\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Ellipsoid} [result] The object into which to store the result.\r\n * @returns {Ellipsoid} The modified result parameter or a new Ellipsoid instance if one was not provided.\r\n */\r\nEllipsoid.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var radii = Cartesian3.unpack(array, startingIndex);\r\n return Ellipsoid.fromCartesian3(radii, result);\r\n};\r\n\r\n/**\r\n * Computes the unit vector directed from the center of this ellipsoid toward the provided Cartesian position.\r\n * @function\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian for which to to determine the geocentric normal.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.\r\n */\r\nEllipsoid.prototype.geocentricSurfaceNormal = Cartesian3.normalize;\r\n\r\n/**\r\n * Computes the normal of the plane tangent to the surface of the ellipsoid at the provided position.\r\n *\r\n * @param {Cartographic} cartographic The cartographic position for which to to determine the geodetic normal.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.\r\n */\r\nEllipsoid.prototype.geodeticSurfaceNormalCartographic = function (\r\n cartographic,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartographic\", cartographic);\r\n //>>includeEnd('debug');\r\n\r\n var longitude = cartographic.longitude;\r\n var latitude = cartographic.latitude;\r\n var cosLatitude = Math.cos(latitude);\r\n\r\n var x = cosLatitude * Math.cos(longitude);\r\n var y = cosLatitude * Math.sin(longitude);\r\n var z = Math.sin(latitude);\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return Cartesian3.normalize(result, result);\r\n};\r\n\r\n/**\r\n * Computes the normal of the plane tangent to the surface of the ellipsoid at the provided position.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian position for which to to determine the surface normal.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided, or undefined if a normal cannot be found.\r\n */\r\nEllipsoid.prototype.geodeticSurfaceNormal = function (cartesian, result) {\r\n if (\r\n Cartesian3.equalsEpsilon(cartesian, Cartesian3.ZERO, CesiumMath.EPSILON14)\r\n ) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n result = Cartesian3.multiplyComponents(\r\n cartesian,\r\n this._oneOverRadiiSquared,\r\n result\r\n );\r\n return Cartesian3.normalize(result, result);\r\n};\r\n\r\nvar cartographicToCartesianNormal = new Cartesian3();\r\nvar cartographicToCartesianK = new Cartesian3();\r\n\r\n/**\r\n * Converts the provided cartographic to Cartesian representation.\r\n *\r\n * @param {Cartographic} cartographic The cartographic position.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.\r\n *\r\n * @example\r\n * //Create a Cartographic and determine it's Cartesian representation on a WGS84 ellipsoid.\r\n * var position = new Cesium.Cartographic(Cesium.Math.toRadians(21), Cesium.Math.toRadians(78), 5000);\r\n * var cartesianPosition = Cesium.Ellipsoid.WGS84.cartographicToCartesian(position);\r\n */\r\nEllipsoid.prototype.cartographicToCartesian = function (cartographic, result) {\r\n //`cartographic is required` is thrown from geodeticSurfaceNormalCartographic.\r\n var n = cartographicToCartesianNormal;\r\n var k = cartographicToCartesianK;\r\n this.geodeticSurfaceNormalCartographic(cartographic, n);\r\n Cartesian3.multiplyComponents(this._radiiSquared, n, k);\r\n var gamma = Math.sqrt(Cartesian3.dot(n, k));\r\n Cartesian3.divideByScalar(k, gamma, k);\r\n Cartesian3.multiplyByScalar(n, cartographic.height, n);\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n return Cartesian3.add(k, n, result);\r\n};\r\n\r\n/**\r\n * Converts the provided array of cartographics to an array of Cartesians.\r\n *\r\n * @param {Cartographic[]} cartographics An array of cartographic positions.\r\n * @param {Cartesian3[]} [result] The object onto which to store the result.\r\n * @returns {Cartesian3[]} The modified result parameter or a new Array instance if none was provided.\r\n *\r\n * @example\r\n * //Convert an array of Cartographics and determine their Cartesian representation on a WGS84 ellipsoid.\r\n * var positions = [new Cesium.Cartographic(Cesium.Math.toRadians(21), Cesium.Math.toRadians(78), 0),\r\n * new Cesium.Cartographic(Cesium.Math.toRadians(21.321), Cesium.Math.toRadians(78.123), 100),\r\n * new Cesium.Cartographic(Cesium.Math.toRadians(21.645), Cesium.Math.toRadians(78.456), 250)];\r\n * var cartesianPositions = Cesium.Ellipsoid.WGS84.cartographicArrayToCartesianArray(positions);\r\n */\r\nEllipsoid.prototype.cartographicArrayToCartesianArray = function (\r\n cartographics,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartographics\", cartographics);\r\n //>>includeEnd('debug')\r\n\r\n var length = cartographics.length;\r\n if (!defined(result)) {\r\n result = new Array(length);\r\n } else {\r\n result.length = length;\r\n }\r\n for (var i = 0; i < length; i++) {\r\n result[i] = this.cartographicToCartesian(cartographics[i], result[i]);\r\n }\r\n return result;\r\n};\r\n\r\nvar cartesianToCartographicN = new Cartesian3();\r\nvar cartesianToCartographicP = new Cartesian3();\r\nvar cartesianToCartographicH = new Cartesian3();\r\n\r\n/**\r\n * Converts the provided cartesian to cartographic representation.\r\n * The cartesian is undefined at the center of the ellipsoid.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian position to convert to cartographic representation.\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter, new Cartographic instance if none was provided, or undefined if the cartesian is at the center of the ellipsoid.\r\n *\r\n * @example\r\n * //Create a Cartesian and determine it's Cartographic representation on a WGS84 ellipsoid.\r\n * var position = new Cesium.Cartesian3(17832.12, 83234.52, 952313.73);\r\n * var cartographicPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);\r\n */\r\nEllipsoid.prototype.cartesianToCartographic = function (cartesian, result) {\r\n //`cartesian is required.` is thrown from scaleToGeodeticSurface\r\n var p = this.scaleToGeodeticSurface(cartesian, cartesianToCartographicP);\r\n\r\n if (!defined(p)) {\r\n return undefined;\r\n }\r\n\r\n var n = this.geodeticSurfaceNormal(p, cartesianToCartographicN);\r\n var h = Cartesian3.subtract(cartesian, p, cartesianToCartographicH);\r\n\r\n var longitude = Math.atan2(n.y, n.x);\r\n var latitude = Math.asin(n.z);\r\n var height =\r\n CesiumMath.sign(Cartesian3.dot(h, cartesian)) * Cartesian3.magnitude(h);\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(longitude, latitude, height);\r\n }\r\n result.longitude = longitude;\r\n result.latitude = latitude;\r\n result.height = height;\r\n return result;\r\n};\r\n\r\n/**\r\n * Converts the provided array of cartesians to an array of cartographics.\r\n *\r\n * @param {Cartesian3[]} cartesians An array of Cartesian positions.\r\n * @param {Cartographic[]} [result] The object onto which to store the result.\r\n * @returns {Cartographic[]} The modified result parameter or a new Array instance if none was provided.\r\n *\r\n * @example\r\n * //Create an array of Cartesians and determine their Cartographic representation on a WGS84 ellipsoid.\r\n * var positions = [new Cesium.Cartesian3(17832.12, 83234.52, 952313.73),\r\n * new Cesium.Cartesian3(17832.13, 83234.53, 952313.73),\r\n * new Cesium.Cartesian3(17832.14, 83234.54, 952313.73)]\r\n * var cartographicPositions = Cesium.Ellipsoid.WGS84.cartesianArrayToCartographicArray(positions);\r\n */\r\nEllipsoid.prototype.cartesianArrayToCartographicArray = function (\r\n cartesians,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesians\", cartesians);\r\n //>>includeEnd('debug');\r\n\r\n var length = cartesians.length;\r\n if (!defined(result)) {\r\n result = new Array(length);\r\n } else {\r\n result.length = length;\r\n }\r\n for (var i = 0; i < length; ++i) {\r\n result[i] = this.cartesianToCartographic(cartesians[i], result[i]);\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Scales the provided Cartesian position along the geodetic surface normal\r\n * so that it is on the surface of this ellipsoid. If the position is\r\n * at the center of the ellipsoid, this function returns undefined.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian position to scale.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter, a new Cartesian3 instance if none was provided, or undefined if the position is at the center.\r\n */\r\nEllipsoid.prototype.scaleToGeodeticSurface = function (cartesian, result) {\r\n return scaleToGeodeticSurface(\r\n cartesian,\r\n this._oneOverRadii,\r\n this._oneOverRadiiSquared,\r\n this._centerToleranceSquared,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Scales the provided Cartesian position along the geocentric surface normal\r\n * so that it is on the surface of this ellipsoid.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian position to scale.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.\r\n */\r\nEllipsoid.prototype.scaleToGeocentricSurface = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n var positionX = cartesian.x;\r\n var positionY = cartesian.y;\r\n var positionZ = cartesian.z;\r\n var oneOverRadiiSquared = this._oneOverRadiiSquared;\r\n\r\n var beta =\r\n 1.0 /\r\n Math.sqrt(\r\n positionX * positionX * oneOverRadiiSquared.x +\r\n positionY * positionY * oneOverRadiiSquared.y +\r\n positionZ * positionZ * oneOverRadiiSquared.z\r\n );\r\n\r\n return Cartesian3.multiplyByScalar(cartesian, beta, result);\r\n};\r\n\r\n/**\r\n * Transforms a Cartesian X, Y, Z position to the ellipsoid-scaled space by multiplying\r\n * its components by the result of {@link Ellipsoid#oneOverRadii}.\r\n *\r\n * @param {Cartesian3} position The position to transform.\r\n * @param {Cartesian3} [result] The position to which to copy the result, or undefined to create and\r\n * return a new instance.\r\n * @returns {Cartesian3} The position expressed in the scaled space. The returned instance is the\r\n * one passed as the result parameter if it is not undefined, or a new instance of it is.\r\n */\r\nEllipsoid.prototype.transformPositionToScaledSpace = function (\r\n position,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n return Cartesian3.multiplyComponents(position, this._oneOverRadii, result);\r\n};\r\n\r\n/**\r\n * Transforms a Cartesian X, Y, Z position from the ellipsoid-scaled space by multiplying\r\n * its components by the result of {@link Ellipsoid#radii}.\r\n *\r\n * @param {Cartesian3} position The position to transform.\r\n * @param {Cartesian3} [result] The position to which to copy the result, or undefined to create and\r\n * return a new instance.\r\n * @returns {Cartesian3} The position expressed in the unscaled space. The returned instance is the\r\n * one passed as the result parameter if it is not undefined, or a new instance of it is.\r\n */\r\nEllipsoid.prototype.transformPositionFromScaledSpace = function (\r\n position,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n return Cartesian3.multiplyComponents(position, this._radii, result);\r\n};\r\n\r\n/**\r\n * Compares this Ellipsoid against the provided Ellipsoid componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Ellipsoid} [right] The other Ellipsoid.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nEllipsoid.prototype.equals = function (right) {\r\n return (\r\n this === right ||\r\n (defined(right) && Cartesian3.equals(this._radii, right._radii))\r\n );\r\n};\r\n\r\n/**\r\n * Creates a string representing this Ellipsoid in the format '(radii.x, radii.y, radii.z)'.\r\n *\r\n * @returns {String} A string representing this ellipsoid in the format '(radii.x, radii.y, radii.z)'.\r\n */\r\nEllipsoid.prototype.toString = function () {\r\n return this._radii.toString();\r\n};\r\n\r\n/**\r\n * Computes a point which is the intersection of the surface normal with the z-axis.\r\n *\r\n * @param {Cartesian3} position the position. must be on the surface of the ellipsoid.\r\n * @param {Number} [buffer = 0.0] A buffer to subtract from the ellipsoid size when checking if the point is inside the ellipsoid.\r\n * In earth case, with common earth datums, there is no need for this buffer since the intersection point is always (relatively) very close to the center.\r\n * In WGS84 datum, intersection point is at max z = +-42841.31151331382 (0.673% of z-axis).\r\n * Intersection point could be outside the ellipsoid if the ratio of MajorAxis / AxisOfRotation is bigger than the square root of 2\r\n * @param {Cartesian3} [result] The cartesian to which to copy the result, or undefined to create and\r\n * return a new instance.\r\n * @returns {Cartesian3 | undefined} the intersection point if it's inside the ellipsoid, undefined otherwise\r\n *\r\n * @exception {DeveloperError} position is required.\r\n * @exception {DeveloperError} Ellipsoid must be an ellipsoid of revolution (radii.x == radii.y).\r\n * @exception {DeveloperError} Ellipsoid.radii.z must be greater than 0.\r\n */\r\nEllipsoid.prototype.getSurfaceNormalIntersectionWithZAxis = function (\r\n position,\r\n buffer,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"position\", position);\r\n\r\n if (\r\n !CesiumMath.equalsEpsilon(\r\n this._radii.x,\r\n this._radii.y,\r\n CesiumMath.EPSILON15\r\n )\r\n ) {\r\n throw new DeveloperError(\r\n \"Ellipsoid must be an ellipsoid of revolution (radii.x == radii.y)\"\r\n );\r\n }\r\n\r\n Check.typeOf.number.greaterThan(\"Ellipsoid.radii.z\", this._radii.z, 0);\r\n //>>includeEnd('debug');\r\n\r\n buffer = defaultValue(buffer, 0.0);\r\n\r\n var squaredXOverSquaredZ = this._squaredXOverSquaredZ;\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n result.x = 0.0;\r\n result.y = 0.0;\r\n result.z = position.z * (1 - squaredXOverSquaredZ);\r\n\r\n if (Math.abs(result.z) >= this._radii.z - buffer) {\r\n return undefined;\r\n }\r\n\r\n return result;\r\n};\r\n\r\nvar abscissas = [\r\n 0.14887433898163,\r\n 0.43339539412925,\r\n 0.67940956829902,\r\n 0.86506336668898,\r\n 0.97390652851717,\r\n 0.0,\r\n];\r\nvar weights = [\r\n 0.29552422471475,\r\n 0.26926671930999,\r\n 0.21908636251598,\r\n 0.14945134915058,\r\n 0.066671344308684,\r\n 0.0,\r\n];\r\n\r\n/**\r\n * Compute the 10th order Gauss-Legendre Quadrature of the given definite integral.\r\n *\r\n * @param {Number} a The lower bound for the integration.\r\n * @param {Number} b The upper bound for the integration.\r\n * @param {Ellipsoid~RealValuedScalarFunction} func The function to integrate.\r\n * @returns {Number} The value of the integral of the given function over the given domain.\r\n *\r\n * @private\r\n */\r\nfunction gaussLegendreQuadrature(a, b, func) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"a\", a);\r\n Check.typeOf.number(\"b\", b);\r\n Check.typeOf.func(\"func\", func);\r\n //>>includeEnd('debug');\r\n\r\n // The range is half of the normal range since the five weights add to one (ten weights add to two).\r\n // The values of the abscissas are multiplied by two to account for this.\r\n var xMean = 0.5 * (b + a);\r\n var xRange = 0.5 * (b - a);\r\n\r\n var sum = 0.0;\r\n for (var i = 0; i < 5; i++) {\r\n var dx = xRange * abscissas[i];\r\n sum += weights[i] * (func(xMean + dx) + func(xMean - dx));\r\n }\r\n\r\n // Scale the sum to the range of x.\r\n sum *= xRange;\r\n return sum;\r\n}\r\n\r\n/**\r\n * A real valued scalar function.\r\n * @callback Ellipsoid~RealValuedScalarFunction\r\n *\r\n * @param {Number} x The value used to evaluate the function.\r\n * @returns {Number} The value of the function at x.\r\n *\r\n * @private\r\n */\r\n\r\n/**\r\n * Computes an approximation of the surface area of a rectangle on the surface of an ellipsoid using\r\n * Gauss-Legendre 10th order quadrature.\r\n *\r\n * @param {Rectangle} rectangle The rectangle used for computing the surface area.\r\n * @returns {Number} The approximate area of the rectangle on the surface of this ellipsoid.\r\n */\r\nEllipsoid.prototype.surfaceArea = function (rectangle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n var minLongitude = rectangle.west;\r\n var maxLongitude = rectangle.east;\r\n var minLatitude = rectangle.south;\r\n var maxLatitude = rectangle.north;\r\n\r\n while (maxLongitude < minLongitude) {\r\n maxLongitude += CesiumMath.TWO_PI;\r\n }\r\n\r\n var radiiSquared = this._radiiSquared;\r\n var a2 = radiiSquared.x;\r\n var b2 = radiiSquared.y;\r\n var c2 = radiiSquared.z;\r\n var a2b2 = a2 * b2;\r\n return gaussLegendreQuadrature(minLatitude, maxLatitude, function (lat) {\r\n // phi represents the angle measured from the north pole\r\n // sin(phi) = sin(pi / 2 - lat) = cos(lat), cos(phi) is similar\r\n var sinPhi = Math.cos(lat);\r\n var cosPhi = Math.sin(lat);\r\n return (\r\n Math.cos(lat) *\r\n gaussLegendreQuadrature(minLongitude, maxLongitude, function (lon) {\r\n var cosTheta = Math.cos(lon);\r\n var sinTheta = Math.sin(lon);\r\n return Math.sqrt(\r\n a2b2 * cosPhi * cosPhi +\r\n c2 *\r\n (b2 * cosTheta * cosTheta + a2 * sinTheta * sinTheta) *\r\n sinPhi *\r\n sinPhi\r\n );\r\n })\r\n );\r\n });\r\n};\r\n\r\nexport default Ellipsoid;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\n\r\n/**\r\n * A simple map projection where longitude and latitude are linearly mapped to X and Y by multiplying\r\n * them by the {@link Ellipsoid#maximumRadius}. This projection\r\n * is commonly known as geographic, equirectangular, equidistant cylindrical, or plate carrée. It\r\n * is also known as EPSG:4326.\r\n *\r\n * @alias GeographicProjection\r\n * @constructor\r\n *\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid.\r\n *\r\n * @see WebMercatorProjection\r\n */\r\nfunction GeographicProjection(ellipsoid) {\r\n this._ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n this._semimajorAxis = this._ellipsoid.maximumRadius;\r\n this._oneOverSemimajorAxis = 1.0 / this._semimajorAxis;\r\n}\r\n\r\nObject.defineProperties(GeographicProjection.prototype, {\r\n /**\r\n * Gets the {@link Ellipsoid}.\r\n *\r\n * @memberof GeographicProjection.prototype\r\n *\r\n * @type {Ellipsoid}\r\n * @readonly\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Projects a set of {@link Cartographic} coordinates, in radians, to map coordinates, in meters.\r\n * X and Y are the longitude and latitude, respectively, multiplied by the maximum radius of the\r\n * ellipsoid. Z is the unmodified height.\r\n *\r\n * @param {Cartographic} cartographic The coordinates to project.\r\n * @param {Cartesian3} [result] An instance into which to copy the result. If this parameter is\r\n * undefined, a new instance is created and returned.\r\n * @returns {Cartesian3} The projected coordinates. If the result parameter is not undefined, the\r\n * coordinates are copied there and that instance is returned. Otherwise, a new instance is\r\n * created and returned.\r\n */\r\nGeographicProjection.prototype.project = function (cartographic, result) {\r\n // Actually this is the special case of equidistant cylindrical called the plate carree\r\n var semimajorAxis = this._semimajorAxis;\r\n var x = cartographic.longitude * semimajorAxis;\r\n var y = cartographic.latitude * semimajorAxis;\r\n var z = cartographic.height;\r\n\r\n if (!defined(result)) {\r\n return new Cartesian3(x, y, z);\r\n }\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Unprojects a set of projected {@link Cartesian3} coordinates, in meters, to {@link Cartographic}\r\n * coordinates, in radians. Longitude and Latitude are the X and Y coordinates, respectively,\r\n * divided by the maximum radius of the ellipsoid. Height is the unmodified Z coordinate.\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian position to unproject with height (z) in meters.\r\n * @param {Cartographic} [result] An instance into which to copy the result. If this parameter is\r\n * undefined, a new instance is created and returned.\r\n * @returns {Cartographic} The unprojected coordinates. If the result parameter is not undefined, the\r\n * coordinates are copied there and that instance is returned. Otherwise, a new instance is\r\n * created and returned.\r\n */\r\nGeographicProjection.prototype.unproject = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(cartesian)) {\r\n throw new DeveloperError(\"cartesian is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var oneOverEarthSemimajorAxis = this._oneOverSemimajorAxis;\r\n var longitude = cartesian.x * oneOverEarthSemimajorAxis;\r\n var latitude = cartesian.y * oneOverEarthSemimajorAxis;\r\n var height = cartesian.z;\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(longitude, latitude, height);\r\n }\r\n\r\n result.longitude = longitude;\r\n result.latitude = latitude;\r\n result.height = height;\r\n return result;\r\n};\r\nexport default GeographicProjection;\r\n","/**\r\n * This enumerated type is used in determining where, relative to the frustum, an\r\n * object is located. The object can either be fully contained within the frustum (INSIDE),\r\n * partially inside the frustum and partially outside (INTERSECTING), or somewhere entirely\r\n * outside of the frustum's 6 planes (OUTSIDE).\r\n *\r\n * @enum {Number}\r\n */\r\nvar Intersect = {\r\n /**\r\n * Represents that an object is not contained within the frustum.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n OUTSIDE: -1,\r\n\r\n /**\r\n * Represents that an object intersects one of the frustum's planes.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n INTERSECTING: 0,\r\n\r\n /**\r\n * Represents that an object is fully within the frustum.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n INSIDE: 1,\r\n};\r\nexport default Object.freeze(Intersect);\r\n","import defaultValue from \"./defaultValue.js\";\r\n\r\n/**\r\n * Represents the closed interval [start, stop].\r\n * @alias Interval\r\n * @constructor\r\n *\r\n * @param {Number} [start=0.0] The beginning of the interval.\r\n * @param {Number} [stop=0.0] The end of the interval.\r\n */\r\nfunction Interval(start, stop) {\r\n /**\r\n * The beginning of the interval.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.start = defaultValue(start, 0.0);\r\n /**\r\n * The end of the interval.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.stop = defaultValue(stop, 0.0);\r\n}\r\nexport default Interval;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * A 3x3 matrix, indexable as a column-major order array.\r\n * Constructor parameters are in row-major order for code readability.\r\n * @alias Matrix3\r\n * @constructor\r\n * @implements {ArrayLike}\r\n *\r\n * @param {Number} [column0Row0=0.0] The value for column 0, row 0.\r\n * @param {Number} [column1Row0=0.0] The value for column 1, row 0.\r\n * @param {Number} [column2Row0=0.0] The value for column 2, row 0.\r\n * @param {Number} [column0Row1=0.0] The value for column 0, row 1.\r\n * @param {Number} [column1Row1=0.0] The value for column 1, row 1.\r\n * @param {Number} [column2Row1=0.0] The value for column 2, row 1.\r\n * @param {Number} [column0Row2=0.0] The value for column 0, row 2.\r\n * @param {Number} [column1Row2=0.0] The value for column 1, row 2.\r\n * @param {Number} [column2Row2=0.0] The value for column 2, row 2.\r\n *\r\n * @see Matrix3.fromColumnMajorArray\r\n * @see Matrix3.fromRowMajorArray\r\n * @see Matrix3.fromQuaternion\r\n * @see Matrix3.fromScale\r\n * @see Matrix3.fromUniformScale\r\n * @see Matrix2\r\n * @see Matrix4\r\n */\r\nfunction Matrix3(\r\n column0Row0,\r\n column1Row0,\r\n column2Row0,\r\n column0Row1,\r\n column1Row1,\r\n column2Row1,\r\n column0Row2,\r\n column1Row2,\r\n column2Row2\r\n) {\r\n this[0] = defaultValue(column0Row0, 0.0);\r\n this[1] = defaultValue(column0Row1, 0.0);\r\n this[2] = defaultValue(column0Row2, 0.0);\r\n this[3] = defaultValue(column1Row0, 0.0);\r\n this[4] = defaultValue(column1Row1, 0.0);\r\n this[5] = defaultValue(column1Row2, 0.0);\r\n this[6] = defaultValue(column2Row0, 0.0);\r\n this[7] = defaultValue(column2Row1, 0.0);\r\n this[8] = defaultValue(column2Row2, 0.0);\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nMatrix3.packedLength = 9;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Matrix3} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nMatrix3.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value[0];\r\n array[startingIndex++] = value[1];\r\n array[startingIndex++] = value[2];\r\n array[startingIndex++] = value[3];\r\n array[startingIndex++] = value[4];\r\n array[startingIndex++] = value[5];\r\n array[startingIndex++] = value[6];\r\n array[startingIndex++] = value[7];\r\n array[startingIndex++] = value[8];\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Matrix3} [result] The object into which to store the result.\r\n * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if one was not provided.\r\n */\r\nMatrix3.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Matrix3();\r\n }\r\n\r\n result[0] = array[startingIndex++];\r\n result[1] = array[startingIndex++];\r\n result[2] = array[startingIndex++];\r\n result[3] = array[startingIndex++];\r\n result[4] = array[startingIndex++];\r\n result[5] = array[startingIndex++];\r\n result[6] = array[startingIndex++];\r\n result[7] = array[startingIndex++];\r\n result[8] = array[startingIndex++];\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a Matrix3 instance.\r\n *\r\n * @param {Matrix3} matrix The matrix to duplicate.\r\n * @param {Matrix3} [result] The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if one was not provided. (Returns undefined if matrix is undefined)\r\n */\r\nMatrix3.clone = function (matrix, result) {\r\n if (!defined(matrix)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new Matrix3(\r\n matrix[0],\r\n matrix[3],\r\n matrix[6],\r\n matrix[1],\r\n matrix[4],\r\n matrix[7],\r\n matrix[2],\r\n matrix[5],\r\n matrix[8]\r\n );\r\n }\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[3];\r\n result[4] = matrix[4];\r\n result[5] = matrix[5];\r\n result[6] = matrix[6];\r\n result[7] = matrix[7];\r\n result[8] = matrix[8];\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Matrix3 from 9 consecutive elements in an array.\r\n *\r\n * @param {Number[]} array The array whose 9 consecutive elements correspond to the positions of the matrix. Assumes column-major order.\r\n * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to first column first row position in the matrix.\r\n * @param {Matrix3} [result] The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Create the Matrix3:\r\n * // [1.0, 2.0, 3.0]\r\n * // [1.0, 2.0, 3.0]\r\n * // [1.0, 2.0, 3.0]\r\n *\r\n * var v = [1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0];\r\n * var m = Cesium.Matrix3.fromArray(v);\r\n *\r\n * // Create same Matrix3 with using an offset into an array\r\n * var v2 = [0.0, 0.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0];\r\n * var m2 = Cesium.Matrix3.fromArray(v2, 2);\r\n */\r\nMatrix3.fromArray = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Matrix3();\r\n }\r\n\r\n result[0] = array[startingIndex];\r\n result[1] = array[startingIndex + 1];\r\n result[2] = array[startingIndex + 2];\r\n result[3] = array[startingIndex + 3];\r\n result[4] = array[startingIndex + 4];\r\n result[5] = array[startingIndex + 5];\r\n result[6] = array[startingIndex + 6];\r\n result[7] = array[startingIndex + 7];\r\n result[8] = array[startingIndex + 8];\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Matrix3 instance from a column-major order array.\r\n *\r\n * @param {Number[]} values The column-major order array.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.\r\n */\r\nMatrix3.fromColumnMajorArray = function (values, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"values\", values);\r\n //>>includeEnd('debug');\r\n\r\n return Matrix3.clone(values, result);\r\n};\r\n\r\n/**\r\n * Creates a Matrix3 instance from a row-major order array.\r\n * The resulting matrix will be in column-major order.\r\n *\r\n * @param {Number[]} values The row-major order array.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.\r\n */\r\nMatrix3.fromRowMajorArray = function (values, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"values\", values);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(\r\n values[0],\r\n values[1],\r\n values[2],\r\n values[3],\r\n values[4],\r\n values[5],\r\n values[6],\r\n values[7],\r\n values[8]\r\n );\r\n }\r\n result[0] = values[0];\r\n result[1] = values[3];\r\n result[2] = values[6];\r\n result[3] = values[1];\r\n result[4] = values[4];\r\n result[5] = values[7];\r\n result[6] = values[2];\r\n result[7] = values[5];\r\n result[8] = values[8];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a 3x3 rotation matrix from the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion the quaternion to use.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The 3x3 rotation matrix from this quaternion.\r\n */\r\nMatrix3.fromQuaternion = function (quaternion, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n //>>includeEnd('debug');\r\n\r\n var x2 = quaternion.x * quaternion.x;\r\n var xy = quaternion.x * quaternion.y;\r\n var xz = quaternion.x * quaternion.z;\r\n var xw = quaternion.x * quaternion.w;\r\n var y2 = quaternion.y * quaternion.y;\r\n var yz = quaternion.y * quaternion.z;\r\n var yw = quaternion.y * quaternion.w;\r\n var z2 = quaternion.z * quaternion.z;\r\n var zw = quaternion.z * quaternion.w;\r\n var w2 = quaternion.w * quaternion.w;\r\n\r\n var m00 = x2 - y2 - z2 + w2;\r\n var m01 = 2.0 * (xy - zw);\r\n var m02 = 2.0 * (xz + yw);\r\n\r\n var m10 = 2.0 * (xy + zw);\r\n var m11 = -x2 + y2 - z2 + w2;\r\n var m12 = 2.0 * (yz - xw);\r\n\r\n var m20 = 2.0 * (xz - yw);\r\n var m21 = 2.0 * (yz + xw);\r\n var m22 = -x2 - y2 + z2 + w2;\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(m00, m01, m02, m10, m11, m12, m20, m21, m22);\r\n }\r\n result[0] = m00;\r\n result[1] = m10;\r\n result[2] = m20;\r\n result[3] = m01;\r\n result[4] = m11;\r\n result[5] = m21;\r\n result[6] = m02;\r\n result[7] = m12;\r\n result[8] = m22;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a 3x3 rotation matrix from the provided headingPitchRoll. (see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles )\r\n *\r\n * @param {HeadingPitchRoll} headingPitchRoll the headingPitchRoll to use.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The 3x3 rotation matrix from this headingPitchRoll.\r\n */\r\nMatrix3.fromHeadingPitchRoll = function (headingPitchRoll, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"headingPitchRoll\", headingPitchRoll);\r\n //>>includeEnd('debug');\r\n\r\n var cosTheta = Math.cos(-headingPitchRoll.pitch);\r\n var cosPsi = Math.cos(-headingPitchRoll.heading);\r\n var cosPhi = Math.cos(headingPitchRoll.roll);\r\n var sinTheta = Math.sin(-headingPitchRoll.pitch);\r\n var sinPsi = Math.sin(-headingPitchRoll.heading);\r\n var sinPhi = Math.sin(headingPitchRoll.roll);\r\n\r\n var m00 = cosTheta * cosPsi;\r\n var m01 = -cosPhi * sinPsi + sinPhi * sinTheta * cosPsi;\r\n var m02 = sinPhi * sinPsi + cosPhi * sinTheta * cosPsi;\r\n\r\n var m10 = cosTheta * sinPsi;\r\n var m11 = cosPhi * cosPsi + sinPhi * sinTheta * sinPsi;\r\n var m12 = -sinPhi * cosPsi + cosPhi * sinTheta * sinPsi;\r\n\r\n var m20 = -sinTheta;\r\n var m21 = sinPhi * cosTheta;\r\n var m22 = cosPhi * cosTheta;\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(m00, m01, m02, m10, m11, m12, m20, m21, m22);\r\n }\r\n result[0] = m00;\r\n result[1] = m10;\r\n result[2] = m20;\r\n result[3] = m01;\r\n result[4] = m11;\r\n result[5] = m21;\r\n result[6] = m02;\r\n result[7] = m12;\r\n result[8] = m22;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix3 instance representing a non-uniform scale.\r\n *\r\n * @param {Cartesian3} scale The x, y, and z scale factors.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Creates\r\n * // [7.0, 0.0, 0.0]\r\n * // [0.0, 8.0, 0.0]\r\n * // [0.0, 0.0, 9.0]\r\n * var m = Cesium.Matrix3.fromScale(new Cesium.Cartesian3(7.0, 8.0, 9.0));\r\n */\r\nMatrix3.fromScale = function (scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"scale\", scale);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(scale.x, 0.0, 0.0, 0.0, scale.y, 0.0, 0.0, 0.0, scale.z);\r\n }\r\n\r\n result[0] = scale.x;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = scale.y;\r\n result[5] = 0.0;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = scale.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix3 instance representing a uniform scale.\r\n *\r\n * @param {Number} scale The uniform scale factor.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Creates\r\n * // [2.0, 0.0, 0.0]\r\n * // [0.0, 2.0, 0.0]\r\n * // [0.0, 0.0, 2.0]\r\n * var m = Cesium.Matrix3.fromUniformScale(2.0);\r\n */\r\nMatrix3.fromUniformScale = function (scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"scale\", scale);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(scale, 0.0, 0.0, 0.0, scale, 0.0, 0.0, 0.0, scale);\r\n }\r\n\r\n result[0] = scale;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = scale;\r\n result[5] = 0.0;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = scale;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix3 instance representing the cross product equivalent matrix of a Cartesian3 vector.\r\n *\r\n * @param {Cartesian3} vector the vector on the left hand side of the cross product operation.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Creates\r\n * // [0.0, -9.0, 8.0]\r\n * // [9.0, 0.0, -7.0]\r\n * // [-8.0, 7.0, 0.0]\r\n * var m = Cesium.Matrix3.fromCrossProduct(new Cesium.Cartesian3(7.0, 8.0, 9.0));\r\n */\r\nMatrix3.fromCrossProduct = function (vector, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"vector\", vector);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(\r\n 0.0,\r\n -vector.z,\r\n vector.y,\r\n vector.z,\r\n 0.0,\r\n -vector.x,\r\n -vector.y,\r\n vector.x,\r\n 0.0\r\n );\r\n }\r\n\r\n result[0] = 0.0;\r\n result[1] = vector.z;\r\n result[2] = -vector.y;\r\n result[3] = -vector.z;\r\n result[4] = 0.0;\r\n result[5] = vector.x;\r\n result[6] = vector.y;\r\n result[7] = -vector.x;\r\n result[8] = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a rotation matrix around the x-axis.\r\n *\r\n * @param {Number} angle The angle, in radians, of the rotation. Positive angles are counterclockwise.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Rotate a point 45 degrees counterclockwise around the x-axis.\r\n * var p = new Cesium.Cartesian3(5, 6, 7);\r\n * var m = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(45.0));\r\n * var rotated = Cesium.Matrix3.multiplyByVector(m, p, new Cesium.Cartesian3());\r\n */\r\nMatrix3.fromRotationX = function (angle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"angle\", angle);\r\n //>>includeEnd('debug');\r\n\r\n var cosAngle = Math.cos(angle);\r\n var sinAngle = Math.sin(angle);\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(\r\n 1.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n cosAngle,\r\n -sinAngle,\r\n 0.0,\r\n sinAngle,\r\n cosAngle\r\n );\r\n }\r\n\r\n result[0] = 1.0;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = cosAngle;\r\n result[5] = sinAngle;\r\n result[6] = 0.0;\r\n result[7] = -sinAngle;\r\n result[8] = cosAngle;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a rotation matrix around the y-axis.\r\n *\r\n * @param {Number} angle The angle, in radians, of the rotation. Positive angles are counterclockwise.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Rotate a point 45 degrees counterclockwise around the y-axis.\r\n * var p = new Cesium.Cartesian3(5, 6, 7);\r\n * var m = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(45.0));\r\n * var rotated = Cesium.Matrix3.multiplyByVector(m, p, new Cesium.Cartesian3());\r\n */\r\nMatrix3.fromRotationY = function (angle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"angle\", angle);\r\n //>>includeEnd('debug');\r\n\r\n var cosAngle = Math.cos(angle);\r\n var sinAngle = Math.sin(angle);\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(\r\n cosAngle,\r\n 0.0,\r\n sinAngle,\r\n 0.0,\r\n 1.0,\r\n 0.0,\r\n -sinAngle,\r\n 0.0,\r\n cosAngle\r\n );\r\n }\r\n\r\n result[0] = cosAngle;\r\n result[1] = 0.0;\r\n result[2] = -sinAngle;\r\n result[3] = 0.0;\r\n result[4] = 1.0;\r\n result[5] = 0.0;\r\n result[6] = sinAngle;\r\n result[7] = 0.0;\r\n result[8] = cosAngle;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a rotation matrix around the z-axis.\r\n *\r\n * @param {Number} angle The angle, in radians, of the rotation. Positive angles are counterclockwise.\r\n * @param {Matrix3} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix3} The modified result parameter, or a new Matrix3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Rotate a point 45 degrees counterclockwise around the z-axis.\r\n * var p = new Cesium.Cartesian3(5, 6, 7);\r\n * var m = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(45.0));\r\n * var rotated = Cesium.Matrix3.multiplyByVector(m, p, new Cesium.Cartesian3());\r\n */\r\nMatrix3.fromRotationZ = function (angle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"angle\", angle);\r\n //>>includeEnd('debug');\r\n\r\n var cosAngle = Math.cos(angle);\r\n var sinAngle = Math.sin(angle);\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(\r\n cosAngle,\r\n -sinAngle,\r\n 0.0,\r\n sinAngle,\r\n cosAngle,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n );\r\n }\r\n\r\n result[0] = cosAngle;\r\n result[1] = sinAngle;\r\n result[2] = 0.0;\r\n result[3] = -sinAngle;\r\n result[4] = cosAngle;\r\n result[5] = 0.0;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = 1.0;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates an Array from the provided Matrix3 instance.\r\n * The array will be in column-major order.\r\n *\r\n * @param {Matrix3} matrix The matrix to use..\r\n * @param {Number[]} [result] The Array onto which to store the result.\r\n * @returns {Number[]} The modified Array parameter or a new Array instance if one was not provided.\r\n */\r\nMatrix3.toArray = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return [\r\n matrix[0],\r\n matrix[1],\r\n matrix[2],\r\n matrix[3],\r\n matrix[4],\r\n matrix[5],\r\n matrix[6],\r\n matrix[7],\r\n matrix[8],\r\n ];\r\n }\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[3];\r\n result[4] = matrix[4];\r\n result[5] = matrix[5];\r\n result[6] = matrix[6];\r\n result[7] = matrix[7];\r\n result[8] = matrix[8];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the array index of the element at the provided row and column.\r\n *\r\n * @param {Number} row The zero-based index of the row.\r\n * @param {Number} column The zero-based index of the column.\r\n * @returns {Number} The index of the element at the provided row and column.\r\n *\r\n * @exception {DeveloperError} row must be 0, 1, or 2.\r\n * @exception {DeveloperError} column must be 0, 1, or 2.\r\n *\r\n * @example\r\n * var myMatrix = new Cesium.Matrix3();\r\n * var column1Row0Index = Cesium.Matrix3.getElementIndex(1, 0);\r\n * var column1Row0 = myMatrix[column1Row0Index]\r\n * myMatrix[column1Row0Index] = 10.0;\r\n */\r\nMatrix3.getElementIndex = function (column, row) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"row\", row, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"row\", row, 2);\r\n Check.typeOf.number.greaterThanOrEquals(\"column\", column, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"column\", column, 2);\r\n //>>includeEnd('debug');\r\n\r\n return column * 3 + row;\r\n};\r\n\r\n/**\r\n * Retrieves a copy of the matrix column at the provided index as a Cartesian3 instance.\r\n *\r\n * @param {Matrix3} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the column to retrieve.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0, 1, or 2.\r\n */\r\nMatrix3.getColumn = function (matrix, index, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 2);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var startIndex = index * 3;\r\n var x = matrix[startIndex];\r\n var y = matrix[startIndex + 1];\r\n var z = matrix[startIndex + 2];\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a new matrix that replaces the specified column in the provided matrix with the provided Cartesian3 instance.\r\n *\r\n * @param {Matrix3} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the column to set.\r\n * @param {Cartesian3} cartesian The Cartesian whose values will be assigned to the specified column.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0, 1, or 2.\r\n */\r\nMatrix3.setColumn = function (matrix, index, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 2);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result = Matrix3.clone(matrix, result);\r\n var startIndex = index * 3;\r\n result[startIndex] = cartesian.x;\r\n result[startIndex + 1] = cartesian.y;\r\n result[startIndex + 2] = cartesian.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Retrieves a copy of the matrix row at the provided index as a Cartesian3 instance.\r\n *\r\n * @param {Matrix3} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the row to retrieve.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0, 1, or 2.\r\n */\r\nMatrix3.getRow = function (matrix, index, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 2);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var x = matrix[index];\r\n var y = matrix[index + 3];\r\n var z = matrix[index + 6];\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a new matrix that replaces the specified row in the provided matrix with the provided Cartesian3 instance.\r\n *\r\n * @param {Matrix3} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the row to set.\r\n * @param {Cartesian3} cartesian The Cartesian whose values will be assigned to the specified row.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0, 1, or 2.\r\n */\r\nMatrix3.setRow = function (matrix, index, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 2);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result = Matrix3.clone(matrix, result);\r\n result[index] = cartesian.x;\r\n result[index + 3] = cartesian.y;\r\n result[index + 6] = cartesian.z;\r\n return result;\r\n};\r\n\r\nvar scratchColumn = new Cartesian3();\r\n\r\n/**\r\n * Extracts the non-uniform scale assuming the matrix is an affine transformation.\r\n *\r\n * @param {Matrix3} matrix The matrix.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nMatrix3.getScale = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Cartesian3.magnitude(\r\n Cartesian3.fromElements(matrix[0], matrix[1], matrix[2], scratchColumn)\r\n );\r\n result.y = Cartesian3.magnitude(\r\n Cartesian3.fromElements(matrix[3], matrix[4], matrix[5], scratchColumn)\r\n );\r\n result.z = Cartesian3.magnitude(\r\n Cartesian3.fromElements(matrix[6], matrix[7], matrix[8], scratchColumn)\r\n );\r\n return result;\r\n};\r\n\r\nvar scratchScale = new Cartesian3();\r\n\r\n/**\r\n * Computes the maximum scale assuming the matrix is an affine transformation.\r\n * The maximum scale is the maximum length of the column vectors.\r\n *\r\n * @param {Matrix3} matrix The matrix.\r\n * @returns {Number} The maximum scale.\r\n */\r\nMatrix3.getMaximumScale = function (matrix) {\r\n Matrix3.getScale(matrix, scratchScale);\r\n return Cartesian3.maximumComponent(scratchScale);\r\n};\r\n\r\n/**\r\n * Computes the product of two matrices.\r\n *\r\n * @param {Matrix3} left The first matrix.\r\n * @param {Matrix3} right The second matrix.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n */\r\nMatrix3.multiply = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var column0Row0 =\r\n left[0] * right[0] + left[3] * right[1] + left[6] * right[2];\r\n var column0Row1 =\r\n left[1] * right[0] + left[4] * right[1] + left[7] * right[2];\r\n var column0Row2 =\r\n left[2] * right[0] + left[5] * right[1] + left[8] * right[2];\r\n\r\n var column1Row0 =\r\n left[0] * right[3] + left[3] * right[4] + left[6] * right[5];\r\n var column1Row1 =\r\n left[1] * right[3] + left[4] * right[4] + left[7] * right[5];\r\n var column1Row2 =\r\n left[2] * right[3] + left[5] * right[4] + left[8] * right[5];\r\n\r\n var column2Row0 =\r\n left[0] * right[6] + left[3] * right[7] + left[6] * right[8];\r\n var column2Row1 =\r\n left[1] * right[6] + left[4] * right[7] + left[7] * right[8];\r\n var column2Row2 =\r\n left[2] * right[6] + left[5] * right[7] + left[8] * right[8];\r\n\r\n result[0] = column0Row0;\r\n result[1] = column0Row1;\r\n result[2] = column0Row2;\r\n result[3] = column1Row0;\r\n result[4] = column1Row1;\r\n result[5] = column1Row2;\r\n result[6] = column2Row0;\r\n result[7] = column2Row1;\r\n result[8] = column2Row2;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the sum of two matrices.\r\n *\r\n * @param {Matrix3} left The first matrix.\r\n * @param {Matrix3} right The second matrix.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n */\r\nMatrix3.add = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = left[0] + right[0];\r\n result[1] = left[1] + right[1];\r\n result[2] = left[2] + right[2];\r\n result[3] = left[3] + right[3];\r\n result[4] = left[4] + right[4];\r\n result[5] = left[5] + right[5];\r\n result[6] = left[6] + right[6];\r\n result[7] = left[7] + right[7];\r\n result[8] = left[8] + right[8];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the difference of two matrices.\r\n *\r\n * @param {Matrix3} left The first matrix.\r\n * @param {Matrix3} right The second matrix.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n */\r\nMatrix3.subtract = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = left[0] - right[0];\r\n result[1] = left[1] - right[1];\r\n result[2] = left[2] - right[2];\r\n result[3] = left[3] - right[3];\r\n result[4] = left[4] - right[4];\r\n result[5] = left[5] - right[5];\r\n result[6] = left[6] - right[6];\r\n result[7] = left[7] - right[7];\r\n result[8] = left[8] - right[8];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix and a column vector.\r\n *\r\n * @param {Matrix3} matrix The matrix.\r\n * @param {Cartesian3} cartesian The column.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nMatrix3.multiplyByVector = function (matrix, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var vX = cartesian.x;\r\n var vY = cartesian.y;\r\n var vZ = cartesian.z;\r\n\r\n var x = matrix[0] * vX + matrix[3] * vY + matrix[6] * vZ;\r\n var y = matrix[1] * vX + matrix[4] * vY + matrix[7] * vZ;\r\n var z = matrix[2] * vX + matrix[5] * vY + matrix[8] * vZ;\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix and a scalar.\r\n *\r\n * @param {Matrix3} matrix The matrix.\r\n * @param {Number} scalar The number to multiply by.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n */\r\nMatrix3.multiplyByScalar = function (matrix, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = matrix[0] * scalar;\r\n result[1] = matrix[1] * scalar;\r\n result[2] = matrix[2] * scalar;\r\n result[3] = matrix[3] * scalar;\r\n result[4] = matrix[4] * scalar;\r\n result[5] = matrix[5] * scalar;\r\n result[6] = matrix[6] * scalar;\r\n result[7] = matrix[7] * scalar;\r\n result[8] = matrix[8] * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix times a (non-uniform) scale, as if the scale were a scale matrix.\r\n *\r\n * @param {Matrix3} matrix The matrix on the left-hand side.\r\n * @param {Cartesian3} scale The non-uniform scale on the right-hand side.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n *\r\n *\r\n * @example\r\n * // Instead of Cesium.Matrix3.multiply(m, Cesium.Matrix3.fromScale(scale), m);\r\n * Cesium.Matrix3.multiplyByScale(m, scale, m);\r\n *\r\n * @see Matrix3.fromScale\r\n * @see Matrix3.multiplyByUniformScale\r\n */\r\nMatrix3.multiplyByScale = function (matrix, scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"scale\", scale);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = matrix[0] * scale.x;\r\n result[1] = matrix[1] * scale.x;\r\n result[2] = matrix[2] * scale.x;\r\n result[3] = matrix[3] * scale.y;\r\n result[4] = matrix[4] * scale.y;\r\n result[5] = matrix[5] * scale.y;\r\n result[6] = matrix[6] * scale.z;\r\n result[7] = matrix[7] * scale.z;\r\n result[8] = matrix[8] * scale.z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a negated copy of the provided matrix.\r\n *\r\n * @param {Matrix3} matrix The matrix to negate.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n */\r\nMatrix3.negate = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = -matrix[0];\r\n result[1] = -matrix[1];\r\n result[2] = -matrix[2];\r\n result[3] = -matrix[3];\r\n result[4] = -matrix[4];\r\n result[5] = -matrix[5];\r\n result[6] = -matrix[6];\r\n result[7] = -matrix[7];\r\n result[8] = -matrix[8];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the transpose of the provided matrix.\r\n *\r\n * @param {Matrix3} matrix The matrix to transpose.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n */\r\nMatrix3.transpose = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var column0Row0 = matrix[0];\r\n var column0Row1 = matrix[3];\r\n var column0Row2 = matrix[6];\r\n var column1Row0 = matrix[1];\r\n var column1Row1 = matrix[4];\r\n var column1Row2 = matrix[7];\r\n var column2Row0 = matrix[2];\r\n var column2Row1 = matrix[5];\r\n var column2Row2 = matrix[8];\r\n\r\n result[0] = column0Row0;\r\n result[1] = column0Row1;\r\n result[2] = column0Row2;\r\n result[3] = column1Row0;\r\n result[4] = column1Row1;\r\n result[5] = column1Row2;\r\n result[6] = column2Row0;\r\n result[7] = column2Row1;\r\n result[8] = column2Row2;\r\n return result;\r\n};\r\n\r\nvar UNIT = new Cartesian3(1, 1, 1);\r\n\r\n/**\r\n * Extracts the rotation assuming the matrix is an affine transformation.\r\n *\r\n * @param {Matrix3} matrix The matrix.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter\r\n */\r\nMatrix3.getRotation = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var inverseScale = Cartesian3.divideComponents(\r\n UNIT,\r\n Matrix3.getScale(matrix, scratchScale),\r\n scratchScale\r\n );\r\n result = Matrix3.multiplyByScale(matrix, inverseScale, result);\r\n\r\n return result;\r\n};\r\n\r\nfunction computeFrobeniusNorm(matrix) {\r\n var norm = 0.0;\r\n for (var i = 0; i < 9; ++i) {\r\n var temp = matrix[i];\r\n norm += temp * temp;\r\n }\r\n\r\n return Math.sqrt(norm);\r\n}\r\n\r\nvar rowVal = [1, 0, 0];\r\nvar colVal = [2, 2, 1];\r\n\r\nfunction offDiagonalFrobeniusNorm(matrix) {\r\n // Computes the \"off-diagonal\" Frobenius norm.\r\n // Assumes matrix is symmetric.\r\n\r\n var norm = 0.0;\r\n for (var i = 0; i < 3; ++i) {\r\n var temp = matrix[Matrix3.getElementIndex(colVal[i], rowVal[i])];\r\n norm += 2.0 * temp * temp;\r\n }\r\n\r\n return Math.sqrt(norm);\r\n}\r\n\r\nfunction shurDecomposition(matrix, result) {\r\n // This routine was created based upon Matrix Computations, 3rd ed., by Golub and Van Loan,\r\n // section 8.4.2 The 2by2 Symmetric Schur Decomposition.\r\n //\r\n // The routine takes a matrix, which is assumed to be symmetric, and\r\n // finds the largest off-diagonal term, and then creates\r\n // a matrix (result) which can be used to help reduce it\r\n\r\n var tolerance = CesiumMath.EPSILON15;\r\n\r\n var maxDiagonal = 0.0;\r\n var rotAxis = 1;\r\n\r\n // find pivot (rotAxis) based on max diagonal of matrix\r\n for (var i = 0; i < 3; ++i) {\r\n var temp = Math.abs(matrix[Matrix3.getElementIndex(colVal[i], rowVal[i])]);\r\n if (temp > maxDiagonal) {\r\n rotAxis = i;\r\n maxDiagonal = temp;\r\n }\r\n }\r\n\r\n var c = 1.0;\r\n var s = 0.0;\r\n\r\n var p = rowVal[rotAxis];\r\n var q = colVal[rotAxis];\r\n\r\n if (Math.abs(matrix[Matrix3.getElementIndex(q, p)]) > tolerance) {\r\n var qq = matrix[Matrix3.getElementIndex(q, q)];\r\n var pp = matrix[Matrix3.getElementIndex(p, p)];\r\n var qp = matrix[Matrix3.getElementIndex(q, p)];\r\n\r\n var tau = (qq - pp) / 2.0 / qp;\r\n var t;\r\n\r\n if (tau < 0.0) {\r\n t = -1.0 / (-tau + Math.sqrt(1.0 + tau * tau));\r\n } else {\r\n t = 1.0 / (tau + Math.sqrt(1.0 + tau * tau));\r\n }\r\n\r\n c = 1.0 / Math.sqrt(1.0 + t * t);\r\n s = t * c;\r\n }\r\n\r\n result = Matrix3.clone(Matrix3.IDENTITY, result);\r\n\r\n result[Matrix3.getElementIndex(p, p)] = result[\r\n Matrix3.getElementIndex(q, q)\r\n ] = c;\r\n result[Matrix3.getElementIndex(q, p)] = s;\r\n result[Matrix3.getElementIndex(p, q)] = -s;\r\n\r\n return result;\r\n}\r\n\r\nvar jMatrix = new Matrix3();\r\nvar jMatrixTranspose = new Matrix3();\r\n\r\n/**\r\n * Computes the eigenvectors and eigenvalues of a symmetric matrix.\r\n *

\r\n * Returns a diagonal matrix and unitary matrix such that:\r\n * matrix = unitary matrix * diagonal matrix * transpose(unitary matrix)\r\n *

\r\n *

\r\n * The values along the diagonal of the diagonal matrix are the eigenvalues. The columns\r\n * of the unitary matrix are the corresponding eigenvectors.\r\n *

\r\n *\r\n * @param {Matrix3} matrix The matrix to decompose into diagonal and unitary matrix. Expected to be symmetric.\r\n * @param {Object} [result] An object with unitary and diagonal properties which are matrices onto which to store the result.\r\n * @returns {Object} An object with unitary and diagonal properties which are the unitary and diagonal matrices, respectively.\r\n *\r\n * @example\r\n * var a = //... symetric matrix\r\n * var result = {\r\n * unitary : new Cesium.Matrix3(),\r\n * diagonal : new Cesium.Matrix3()\r\n * };\r\n * Cesium.Matrix3.computeEigenDecomposition(a, result);\r\n *\r\n * var unitaryTranspose = Cesium.Matrix3.transpose(result.unitary, new Cesium.Matrix3());\r\n * var b = Cesium.Matrix3.multiply(result.unitary, result.diagonal, new Cesium.Matrix3());\r\n * Cesium.Matrix3.multiply(b, unitaryTranspose, b); // b is now equal to a\r\n *\r\n * var lambda = Cesium.Matrix3.getColumn(result.diagonal, 0, new Cesium.Cartesian3()).x; // first eigenvalue\r\n * var v = Cesium.Matrix3.getColumn(result.unitary, 0, new Cesium.Cartesian3()); // first eigenvector\r\n * var c = Cesium.Cartesian3.multiplyByScalar(v, lambda, new Cesium.Cartesian3()); // equal to Cesium.Matrix3.multiplyByVector(a, v)\r\n */\r\nMatrix3.computeEigenDecomposition = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n //>>includeEnd('debug');\r\n\r\n // This routine was created based upon Matrix Computations, 3rd ed., by Golub and Van Loan,\r\n // section 8.4.3 The Classical Jacobi Algorithm\r\n\r\n var tolerance = CesiumMath.EPSILON20;\r\n var maxSweeps = 10;\r\n\r\n var count = 0;\r\n var sweep = 0;\r\n\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n\r\n var unitaryMatrix = (result.unitary = Matrix3.clone(\r\n Matrix3.IDENTITY,\r\n result.unitary\r\n ));\r\n var diagMatrix = (result.diagonal = Matrix3.clone(matrix, result.diagonal));\r\n\r\n var epsilon = tolerance * computeFrobeniusNorm(diagMatrix);\r\n\r\n while (sweep < maxSweeps && offDiagonalFrobeniusNorm(diagMatrix) > epsilon) {\r\n shurDecomposition(diagMatrix, jMatrix);\r\n Matrix3.transpose(jMatrix, jMatrixTranspose);\r\n Matrix3.multiply(diagMatrix, jMatrix, diagMatrix);\r\n Matrix3.multiply(jMatrixTranspose, diagMatrix, diagMatrix);\r\n Matrix3.multiply(unitaryMatrix, jMatrix, unitaryMatrix);\r\n\r\n if (++count > 2) {\r\n ++sweep;\r\n count = 0;\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a matrix, which contains the absolute (unsigned) values of the provided matrix's elements.\r\n *\r\n * @param {Matrix3} matrix The matrix with signed elements.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n */\r\nMatrix3.abs = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = Math.abs(matrix[0]);\r\n result[1] = Math.abs(matrix[1]);\r\n result[2] = Math.abs(matrix[2]);\r\n result[3] = Math.abs(matrix[3]);\r\n result[4] = Math.abs(matrix[4]);\r\n result[5] = Math.abs(matrix[5]);\r\n result[6] = Math.abs(matrix[6]);\r\n result[7] = Math.abs(matrix[7]);\r\n result[8] = Math.abs(matrix[8]);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the determinant of the provided matrix.\r\n *\r\n * @param {Matrix3} matrix The matrix to use.\r\n * @returns {Number} The value of the determinant of the matrix.\r\n */\r\nMatrix3.determinant = function (matrix) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n //>>includeEnd('debug');\r\n\r\n var m11 = matrix[0];\r\n var m21 = matrix[3];\r\n var m31 = matrix[6];\r\n var m12 = matrix[1];\r\n var m22 = matrix[4];\r\n var m32 = matrix[7];\r\n var m13 = matrix[2];\r\n var m23 = matrix[5];\r\n var m33 = matrix[8];\r\n\r\n return (\r\n m11 * (m22 * m33 - m23 * m32) +\r\n m12 * (m23 * m31 - m21 * m33) +\r\n m13 * (m21 * m32 - m22 * m31)\r\n );\r\n};\r\n\r\n/**\r\n * Computes the inverse of the provided matrix.\r\n *\r\n * @param {Matrix3} matrix The matrix to invert.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} matrix is not invertible.\r\n */\r\nMatrix3.inverse = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var m11 = matrix[0];\r\n var m21 = matrix[1];\r\n var m31 = matrix[2];\r\n var m12 = matrix[3];\r\n var m22 = matrix[4];\r\n var m32 = matrix[5];\r\n var m13 = matrix[6];\r\n var m23 = matrix[7];\r\n var m33 = matrix[8];\r\n\r\n var determinant = Matrix3.determinant(matrix);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (Math.abs(determinant) <= CesiumMath.EPSILON15) {\r\n throw new DeveloperError(\"matrix is not invertible\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n result[0] = m22 * m33 - m23 * m32;\r\n result[1] = m23 * m31 - m21 * m33;\r\n result[2] = m21 * m32 - m22 * m31;\r\n result[3] = m13 * m32 - m12 * m33;\r\n result[4] = m11 * m33 - m13 * m31;\r\n result[5] = m12 * m31 - m11 * m32;\r\n result[6] = m12 * m23 - m13 * m22;\r\n result[7] = m13 * m21 - m11 * m23;\r\n result[8] = m11 * m22 - m12 * m21;\r\n\r\n var scale = 1.0 / determinant;\r\n return Matrix3.multiplyByScalar(result, scale, result);\r\n};\r\n\r\nvar scratchTransposeMatrix = new Matrix3();\r\n\r\n/**\r\n * Computes the inverse transpose of a matrix.\r\n *\r\n * @param {Matrix3} matrix The matrix to transpose and invert.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n */\r\nMatrix3.inverseTranspose = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n return Matrix3.inverse(\r\n Matrix3.transpose(matrix, scratchTransposeMatrix),\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided matrices componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Matrix3} [left] The first matrix.\r\n * @param {Matrix3} [right] The second matrix.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nMatrix3.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left[0] === right[0] &&\r\n left[1] === right[1] &&\r\n left[2] === right[2] &&\r\n left[3] === right[3] &&\r\n left[4] === right[4] &&\r\n left[5] === right[5] &&\r\n left[6] === right[6] &&\r\n left[7] === right[7] &&\r\n left[8] === right[8])\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided matrices componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Matrix3} [left] The first matrix.\r\n * @param {Matrix3} [right] The second matrix.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nMatrix3.equalsEpsilon = function (left, right, epsilon) {\r\n epsilon = defaultValue(epsilon, 0);\r\n\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Math.abs(left[0] - right[0]) <= epsilon &&\r\n Math.abs(left[1] - right[1]) <= epsilon &&\r\n Math.abs(left[2] - right[2]) <= epsilon &&\r\n Math.abs(left[3] - right[3]) <= epsilon &&\r\n Math.abs(left[4] - right[4]) <= epsilon &&\r\n Math.abs(left[5] - right[5]) <= epsilon &&\r\n Math.abs(left[6] - right[6]) <= epsilon &&\r\n Math.abs(left[7] - right[7]) <= epsilon &&\r\n Math.abs(left[8] - right[8]) <= epsilon)\r\n );\r\n};\r\n\r\n/**\r\n * An immutable Matrix3 instance initialized to the identity matrix.\r\n *\r\n * @type {Matrix3}\r\n * @constant\r\n */\r\nMatrix3.IDENTITY = Object.freeze(\r\n new Matrix3(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)\r\n);\r\n\r\n/**\r\n * An immutable Matrix3 instance initialized to the zero matrix.\r\n *\r\n * @type {Matrix3}\r\n * @constant\r\n */\r\nMatrix3.ZERO = Object.freeze(\r\n new Matrix3(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)\r\n);\r\n\r\n/**\r\n * The index into Matrix3 for column 0, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN0ROW0 = 0;\r\n\r\n/**\r\n * The index into Matrix3 for column 0, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN0ROW1 = 1;\r\n\r\n/**\r\n * The index into Matrix3 for column 0, row 2.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN0ROW2 = 2;\r\n\r\n/**\r\n * The index into Matrix3 for column 1, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN1ROW0 = 3;\r\n\r\n/**\r\n * The index into Matrix3 for column 1, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN1ROW1 = 4;\r\n\r\n/**\r\n * The index into Matrix3 for column 1, row 2.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN1ROW2 = 5;\r\n\r\n/**\r\n * The index into Matrix3 for column 2, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN2ROW0 = 6;\r\n\r\n/**\r\n * The index into Matrix3 for column 2, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN2ROW1 = 7;\r\n\r\n/**\r\n * The index into Matrix3 for column 2, row 2.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix3.COLUMN2ROW2 = 8;\r\n\r\nObject.defineProperties(Matrix3.prototype, {\r\n /**\r\n * Gets the number of items in the collection.\r\n * @memberof Matrix3.prototype\r\n *\r\n * @type {Number}\r\n */\r\n length: {\r\n get: function () {\r\n return Matrix3.packedLength;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Duplicates the provided Matrix3 instance.\r\n *\r\n * @param {Matrix3} [result] The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if one was not provided.\r\n */\r\nMatrix3.prototype.clone = function (result) {\r\n return Matrix3.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this matrix to the provided matrix componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Matrix3} [right] The right hand side matrix.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nMatrix3.prototype.equals = function (right) {\r\n return Matrix3.equals(this, right);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nMatrix3.equalsArray = function (matrix, array, offset) {\r\n return (\r\n matrix[0] === array[offset] &&\r\n matrix[1] === array[offset + 1] &&\r\n matrix[2] === array[offset + 2] &&\r\n matrix[3] === array[offset + 3] &&\r\n matrix[4] === array[offset + 4] &&\r\n matrix[5] === array[offset + 5] &&\r\n matrix[6] === array[offset + 6] &&\r\n matrix[7] === array[offset + 7] &&\r\n matrix[8] === array[offset + 8]\r\n );\r\n};\r\n\r\n/**\r\n * Compares this matrix to the provided matrix componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Matrix3} [right] The right hand side matrix.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if they are within the provided epsilon, false otherwise.\r\n */\r\nMatrix3.prototype.equalsEpsilon = function (right, epsilon) {\r\n return Matrix3.equalsEpsilon(this, right, epsilon);\r\n};\r\n\r\n/**\r\n * Creates a string representing this Matrix with each row being\r\n * on a separate line and in the format '(column0, column1, column2)'.\r\n *\r\n * @returns {String} A string representing the provided Matrix with each row being on a separate line and in the format '(column0, column1, column2)'.\r\n */\r\nMatrix3.prototype.toString = function () {\r\n return (\r\n \"(\" +\r\n this[0] +\r\n \", \" +\r\n this[3] +\r\n \", \" +\r\n this[6] +\r\n \")\\n\" +\r\n \"(\" +\r\n this[1] +\r\n \", \" +\r\n this[4] +\r\n \", \" +\r\n this[7] +\r\n \")\\n\" +\r\n \"(\" +\r\n this[2] +\r\n \", \" +\r\n this[5] +\r\n \", \" +\r\n this[8] +\r\n \")\"\r\n );\r\n};\r\nexport default Matrix3;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * A 4D Cartesian point.\r\n * @alias Cartesian4\r\n * @constructor\r\n *\r\n * @param {Number} [x=0.0] The X component.\r\n * @param {Number} [y=0.0] The Y component.\r\n * @param {Number} [z=0.0] The Z component.\r\n * @param {Number} [w=0.0] The W component.\r\n *\r\n * @see Cartesian2\r\n * @see Cartesian3\r\n * @see Packable\r\n */\r\nfunction Cartesian4(x, y, z, w) {\r\n /**\r\n * The X component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.x = defaultValue(x, 0.0);\r\n\r\n /**\r\n * The Y component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.y = defaultValue(y, 0.0);\r\n\r\n /**\r\n * The Z component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.z = defaultValue(z, 0.0);\r\n\r\n /**\r\n * The W component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.w = defaultValue(w, 0.0);\r\n}\r\n\r\n/**\r\n * Creates a Cartesian4 instance from x, y, z and w coordinates.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {Number} z The z coordinate.\r\n * @param {Number} w The w coordinate.\r\n * @param {Cartesian4} [result] The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.\r\n */\r\nCartesian4.fromElements = function (x, y, z, w, result) {\r\n if (!defined(result)) {\r\n return new Cartesian4(x, y, z, w);\r\n }\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n result.w = w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Cartesian4 instance from a {@link Color}. red, green, blue,\r\n * and alpha map to x, y, z, and w, respectively.\r\n *\r\n * @param {Color} color The source color.\r\n * @param {Cartesian4} [result] The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.\r\n */\r\nCartesian4.fromColor = function (color, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"color\", color);\r\n //>>includeEnd('debug');\r\n if (!defined(result)) {\r\n return new Cartesian4(color.red, color.green, color.blue, color.alpha);\r\n }\r\n\r\n result.x = color.red;\r\n result.y = color.green;\r\n result.z = color.blue;\r\n result.w = color.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a Cartesian4 instance.\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian to duplicate.\r\n * @param {Cartesian4} [result] The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided. (Returns undefined if cartesian is undefined)\r\n */\r\nCartesian4.clone = function (cartesian, result) {\r\n if (!defined(cartesian)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Cartesian4(cartesian.x, cartesian.y, cartesian.z, cartesian.w);\r\n }\r\n\r\n result.x = cartesian.x;\r\n result.y = cartesian.y;\r\n result.z = cartesian.z;\r\n result.w = cartesian.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nCartesian4.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Cartesian4} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCartesian4.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.x;\r\n array[startingIndex++] = value.y;\r\n array[startingIndex++] = value.z;\r\n array[startingIndex] = value.w;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Cartesian4} [result] The object into which to store the result.\r\n * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.\r\n */\r\nCartesian4.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian4();\r\n }\r\n result.x = array[startingIndex++];\r\n result.y = array[startingIndex++];\r\n result.z = array[startingIndex++];\r\n result.w = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Flattens an array of Cartesian4s into and array of components.\r\n *\r\n * @param {Cartesian4[]} array The array of cartesians to pack.\r\n * @param {Number[]} [result] The array onto which to store the result. If this is a typed array, it must have array.length * 4 components, else a {@link DeveloperError} will be thrown. If it is a regular array, it will be resized to have (array.length * 4) elements.\r\n\r\n * @returns {Number[]} The packed array.\r\n */\r\nCartesian4.packArray = function (array, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n var length = array.length;\r\n var resultLength = length * 4;\r\n if (!defined(result)) {\r\n result = new Array(resultLength);\r\n } else if (!Array.isArray(result) && result.length !== resultLength) {\r\n throw new DeveloperError(\r\n \"If result is a typed array, it must have exactly array.length * 4 elements\"\r\n );\r\n } else if (result.length !== resultLength) {\r\n result.length = resultLength;\r\n }\r\n\r\n for (var i = 0; i < length; ++i) {\r\n Cartesian4.pack(array[i], result, i * 4);\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Unpacks an array of cartesian components into and array of Cartesian4s.\r\n *\r\n * @param {Number[]} array The array of components to unpack.\r\n * @param {Cartesian4[]} [result] The array onto which to store the result.\r\n * @returns {Cartesian4[]} The unpacked array.\r\n */\r\nCartesian4.unpackArray = function (array, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n Check.typeOf.number.greaterThanOrEquals(\"array.length\", array.length, 4);\r\n if (array.length % 4 !== 0) {\r\n throw new DeveloperError(\"array length must be a multiple of 4.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = array.length;\r\n if (!defined(result)) {\r\n result = new Array(length / 4);\r\n } else {\r\n result.length = length / 4;\r\n }\r\n\r\n for (var i = 0; i < length; i += 4) {\r\n var index = i / 4;\r\n result[index] = Cartesian4.unpack(array, i, result[index]);\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Cartesian4 from four consecutive elements in an array.\r\n * @function\r\n *\r\n * @param {Number[]} array The array whose four consecutive elements correspond to the x, y, z, and w components, respectively.\r\n * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to the x component.\r\n * @param {Cartesian4} [result] The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.\r\n *\r\n * @example\r\n * // Create a Cartesian4 with (1.0, 2.0, 3.0, 4.0)\r\n * var v = [1.0, 2.0, 3.0, 4.0];\r\n * var p = Cesium.Cartesian4.fromArray(v);\r\n *\r\n * // Create a Cartesian4 with (1.0, 2.0, 3.0, 4.0) using an offset into an array\r\n * var v2 = [0.0, 0.0, 1.0, 2.0, 3.0, 4.0];\r\n * var p2 = Cesium.Cartesian4.fromArray(v2, 2);\r\n */\r\nCartesian4.fromArray = Cartesian4.unpack;\r\n\r\n/**\r\n * Computes the value of the maximum component for the supplied Cartesian.\r\n *\r\n * @param {Cartesian4} cartesian The cartesian to use.\r\n * @returns {Number} The value of the maximum component.\r\n */\r\nCartesian4.maximumComponent = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return Math.max(cartesian.x, cartesian.y, cartesian.z, cartesian.w);\r\n};\r\n\r\n/**\r\n * Computes the value of the minimum component for the supplied Cartesian.\r\n *\r\n * @param {Cartesian4} cartesian The cartesian to use.\r\n * @returns {Number} The value of the minimum component.\r\n */\r\nCartesian4.minimumComponent = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return Math.min(cartesian.x, cartesian.y, cartesian.z, cartesian.w);\r\n};\r\n\r\n/**\r\n * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians.\r\n *\r\n * @param {Cartesian4} first A cartesian to compare.\r\n * @param {Cartesian4} second A cartesian to compare.\r\n * @param {Cartesian4} result The object into which to store the result.\r\n * @returns {Cartesian4} A cartesian with the minimum components.\r\n */\r\nCartesian4.minimumByComponent = function (first, second, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"first\", first);\r\n Check.typeOf.object(\"second\", second);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.min(first.x, second.x);\r\n result.y = Math.min(first.y, second.y);\r\n result.z = Math.min(first.z, second.z);\r\n result.w = Math.min(first.w, second.w);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians.\r\n *\r\n * @param {Cartesian4} first A cartesian to compare.\r\n * @param {Cartesian4} second A cartesian to compare.\r\n * @param {Cartesian4} result The object into which to store the result.\r\n * @returns {Cartesian4} A cartesian with the maximum components.\r\n */\r\nCartesian4.maximumByComponent = function (first, second, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"first\", first);\r\n Check.typeOf.object(\"second\", second);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.max(first.x, second.x);\r\n result.y = Math.max(first.y, second.y);\r\n result.z = Math.max(first.z, second.z);\r\n result.w = Math.max(first.w, second.w);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the provided Cartesian's squared magnitude.\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian instance whose squared magnitude is to be computed.\r\n * @returns {Number} The squared magnitude.\r\n */\r\nCartesian4.magnitudeSquared = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return (\r\n cartesian.x * cartesian.x +\r\n cartesian.y * cartesian.y +\r\n cartesian.z * cartesian.z +\r\n cartesian.w * cartesian.w\r\n );\r\n};\r\n\r\n/**\r\n * Computes the Cartesian's magnitude (length).\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian instance whose magnitude is to be computed.\r\n * @returns {Number} The magnitude.\r\n */\r\nCartesian4.magnitude = function (cartesian) {\r\n return Math.sqrt(Cartesian4.magnitudeSquared(cartesian));\r\n};\r\n\r\nvar distanceScratch = new Cartesian4();\r\n\r\n/**\r\n * Computes the 4-space distance between two points.\r\n *\r\n * @param {Cartesian4} left The first point to compute the distance from.\r\n * @param {Cartesian4} right The second point to compute the distance to.\r\n * @returns {Number} The distance between two points.\r\n *\r\n * @example\r\n * // Returns 1.0\r\n * var d = Cesium.Cartesian4.distance(\r\n * new Cesium.Cartesian4(1.0, 0.0, 0.0, 0.0),\r\n * new Cesium.Cartesian4(2.0, 0.0, 0.0, 0.0));\r\n */\r\nCartesian4.distance = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian4.subtract(left, right, distanceScratch);\r\n return Cartesian4.magnitude(distanceScratch);\r\n};\r\n\r\n/**\r\n * Computes the squared distance between two points. Comparing squared distances\r\n * using this function is more efficient than comparing distances using {@link Cartesian4#distance}.\r\n *\r\n * @param {Cartesian4} left The first point to compute the distance from.\r\n * @param {Cartesian4} right The second point to compute the distance to.\r\n * @returns {Number} The distance between two points.\r\n *\r\n * @example\r\n * // Returns 4.0, not 2.0\r\n * var d = Cesium.Cartesian4.distance(\r\n * new Cesium.Cartesian4(1.0, 0.0, 0.0, 0.0),\r\n * new Cesium.Cartesian4(3.0, 0.0, 0.0, 0.0));\r\n */\r\nCartesian4.distanceSquared = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian4.subtract(left, right, distanceScratch);\r\n return Cartesian4.magnitudeSquared(distanceScratch);\r\n};\r\n\r\n/**\r\n * Computes the normalized form of the supplied Cartesian.\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian to be normalized.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.normalize = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var magnitude = Cartesian4.magnitude(cartesian);\r\n\r\n result.x = cartesian.x / magnitude;\r\n result.y = cartesian.y / magnitude;\r\n result.z = cartesian.z / magnitude;\r\n result.w = cartesian.w / magnitude;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n isNaN(result.x) ||\r\n isNaN(result.y) ||\r\n isNaN(result.z) ||\r\n isNaN(result.w)\r\n ) {\r\n throw new DeveloperError(\"normalized result is not a number\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the dot (scalar) product of two Cartesians.\r\n *\r\n * @param {Cartesian4} left The first Cartesian.\r\n * @param {Cartesian4} right The second Cartesian.\r\n * @returns {Number} The dot product.\r\n */\r\nCartesian4.dot = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n return (\r\n left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w\r\n );\r\n};\r\n\r\n/**\r\n * Computes the componentwise product of two Cartesians.\r\n *\r\n * @param {Cartesian4} left The first Cartesian.\r\n * @param {Cartesian4} right The second Cartesian.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.multiplyComponents = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x * right.x;\r\n result.y = left.y * right.y;\r\n result.z = left.z * right.z;\r\n result.w = left.w * right.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise quotient of two Cartesians.\r\n *\r\n * @param {Cartesian4} left The first Cartesian.\r\n * @param {Cartesian4} right The second Cartesian.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.divideComponents = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x / right.x;\r\n result.y = left.y / right.y;\r\n result.z = left.z / right.z;\r\n result.w = left.w / right.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise sum of two Cartesians.\r\n *\r\n * @param {Cartesian4} left The first Cartesian.\r\n * @param {Cartesian4} right The second Cartesian.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.add = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x + right.x;\r\n result.y = left.y + right.y;\r\n result.z = left.z + right.z;\r\n result.w = left.w + right.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise difference of two Cartesians.\r\n *\r\n * @param {Cartesian4} left The first Cartesian.\r\n * @param {Cartesian4} right The second Cartesian.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.subtract = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x - right.x;\r\n result.y = left.y - right.y;\r\n result.z = left.z - right.z;\r\n result.w = left.w - right.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Multiplies the provided Cartesian componentwise by the provided scalar.\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian to be scaled.\r\n * @param {Number} scalar The scalar to multiply with.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.multiplyByScalar = function (cartesian, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = cartesian.x * scalar;\r\n result.y = cartesian.y * scalar;\r\n result.z = cartesian.z * scalar;\r\n result.w = cartesian.w * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Divides the provided Cartesian componentwise by the provided scalar.\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian to be divided.\r\n * @param {Number} scalar The scalar to divide by.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.divideByScalar = function (cartesian, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = cartesian.x / scalar;\r\n result.y = cartesian.y / scalar;\r\n result.z = cartesian.z / scalar;\r\n result.w = cartesian.w / scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Negates the provided Cartesian.\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian to be negated.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.negate = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = -cartesian.x;\r\n result.y = -cartesian.y;\r\n result.z = -cartesian.z;\r\n result.w = -cartesian.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the absolute value of the provided Cartesian.\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian whose absolute value is to be computed.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.abs = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.abs(cartesian.x);\r\n result.y = Math.abs(cartesian.y);\r\n result.z = Math.abs(cartesian.z);\r\n result.w = Math.abs(cartesian.w);\r\n return result;\r\n};\r\n\r\nvar lerpScratch = new Cartesian4();\r\n/**\r\n * Computes the linear interpolation or extrapolation at t using the provided cartesians.\r\n *\r\n * @param {Cartesian4} start The value corresponding to t at 0.0.\r\n * @param {Cartesian4}end The value corresponding to t at 1.0.\r\n * @param {Number} t The point along t at which to interpolate.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nCartesian4.lerp = function (start, end, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"start\", start);\r\n Check.typeOf.object(\"end\", end);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian4.multiplyByScalar(end, t, lerpScratch);\r\n result = Cartesian4.multiplyByScalar(start, 1.0 - t, result);\r\n return Cartesian4.add(lerpScratch, result, result);\r\n};\r\n\r\nvar mostOrthogonalAxisScratch = new Cartesian4();\r\n/**\r\n * Returns the axis that is most orthogonal to the provided Cartesian.\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian on which to find the most orthogonal axis.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The most orthogonal axis.\r\n */\r\nCartesian4.mostOrthogonalAxis = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var f = Cartesian4.normalize(cartesian, mostOrthogonalAxisScratch);\r\n Cartesian4.abs(f, f);\r\n\r\n if (f.x <= f.y) {\r\n if (f.x <= f.z) {\r\n if (f.x <= f.w) {\r\n result = Cartesian4.clone(Cartesian4.UNIT_X, result);\r\n } else {\r\n result = Cartesian4.clone(Cartesian4.UNIT_W, result);\r\n }\r\n } else if (f.z <= f.w) {\r\n result = Cartesian4.clone(Cartesian4.UNIT_Z, result);\r\n } else {\r\n result = Cartesian4.clone(Cartesian4.UNIT_W, result);\r\n }\r\n } else if (f.y <= f.z) {\r\n if (f.y <= f.w) {\r\n result = Cartesian4.clone(Cartesian4.UNIT_Y, result);\r\n } else {\r\n result = Cartesian4.clone(Cartesian4.UNIT_W, result);\r\n }\r\n } else if (f.z <= f.w) {\r\n result = Cartesian4.clone(Cartesian4.UNIT_Z, result);\r\n } else {\r\n result = Cartesian4.clone(Cartesian4.UNIT_W, result);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided Cartesians componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Cartesian4} [left] The first Cartesian.\r\n * @param {Cartesian4} [right] The second Cartesian.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCartesian4.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.x === right.x &&\r\n left.y === right.y &&\r\n left.z === right.z &&\r\n left.w === right.w)\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCartesian4.equalsArray = function (cartesian, array, offset) {\r\n return (\r\n cartesian.x === array[offset] &&\r\n cartesian.y === array[offset + 1] &&\r\n cartesian.z === array[offset + 2] &&\r\n cartesian.w === array[offset + 3]\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided Cartesians componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {Cartesian4} [left] The first Cartesian.\r\n * @param {Cartesian4} [right] The second Cartesian.\r\n * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nCartesian4.equalsEpsilon = function (\r\n left,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n CesiumMath.equalsEpsilon(\r\n left.x,\r\n right.x,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n left.y,\r\n right.y,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n left.z,\r\n right.z,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n left.w,\r\n right.w,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ))\r\n );\r\n};\r\n\r\n/**\r\n * An immutable Cartesian4 instance initialized to (0.0, 0.0, 0.0, 0.0).\r\n *\r\n * @type {Cartesian4}\r\n * @constant\r\n */\r\nCartesian4.ZERO = Object.freeze(new Cartesian4(0.0, 0.0, 0.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian4 instance initialized to (1.0, 0.0, 0.0, 0.0).\r\n *\r\n * @type {Cartesian4}\r\n * @constant\r\n */\r\nCartesian4.UNIT_X = Object.freeze(new Cartesian4(1.0, 0.0, 0.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian4 instance initialized to (0.0, 1.0, 0.0, 0.0).\r\n *\r\n * @type {Cartesian4}\r\n * @constant\r\n */\r\nCartesian4.UNIT_Y = Object.freeze(new Cartesian4(0.0, 1.0, 0.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian4 instance initialized to (0.0, 0.0, 1.0, 0.0).\r\n *\r\n * @type {Cartesian4}\r\n * @constant\r\n */\r\nCartesian4.UNIT_Z = Object.freeze(new Cartesian4(0.0, 0.0, 1.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian4 instance initialized to (0.0, 0.0, 0.0, 1.0).\r\n *\r\n * @type {Cartesian4}\r\n * @constant\r\n */\r\nCartesian4.UNIT_W = Object.freeze(new Cartesian4(0.0, 0.0, 0.0, 1.0));\r\n\r\n/**\r\n * Duplicates this Cartesian4 instance.\r\n *\r\n * @param {Cartesian4} [result] The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter or a new Cartesian4 instance if one was not provided.\r\n */\r\nCartesian4.prototype.clone = function (result) {\r\n return Cartesian4.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this Cartesian against the provided Cartesian componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Cartesian4} [right] The right hand side Cartesian.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nCartesian4.prototype.equals = function (right) {\r\n return Cartesian4.equals(this, right);\r\n};\r\n\r\n/**\r\n * Compares this Cartesian against the provided Cartesian componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {Cartesian4} [right] The right hand side Cartesian.\r\n * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if they are within the provided epsilon, false otherwise.\r\n */\r\nCartesian4.prototype.equalsEpsilon = function (\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return Cartesian4.equalsEpsilon(\r\n this,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n );\r\n};\r\n\r\n/**\r\n * Creates a string representing this Cartesian in the format '(x, y, z, w)'.\r\n *\r\n * @returns {String} A string representing the provided Cartesian in the format '(x, y, z, w)'.\r\n */\r\nCartesian4.prototype.toString = function () {\r\n return \"(\" + this.x + \", \" + this.y + \", \" + this.z + \", \" + this.w + \")\";\r\n};\r\n\r\n// scratchU8Array and scratchF32Array are views into the same buffer\r\nvar scratchF32Array = new Float32Array(1);\r\nvar scratchU8Array = new Uint8Array(scratchF32Array.buffer);\r\n\r\nvar testU32 = new Uint32Array([0x11223344]);\r\nvar testU8 = new Uint8Array(testU32.buffer);\r\nvar littleEndian = testU8[0] === 0x44;\r\n\r\n/**\r\n * Packs an arbitrary floating point value to 4 values representable using uint8.\r\n *\r\n * @param {Number} value A floating point number.\r\n * @param {Cartesian4} [result] The Cartesian4 that will contain the packed float.\r\n * @returns {Cartesian4} A Cartesian4 representing the float packed to values in x, y, z, and w.\r\n */\r\nCartesian4.packFloat = function (value, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"value\", value);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian4();\r\n }\r\n\r\n // scratchU8Array and scratchF32Array are views into the same buffer\r\n scratchF32Array[0] = value;\r\n\r\n if (littleEndian) {\r\n result.x = scratchU8Array[0];\r\n result.y = scratchU8Array[1];\r\n result.z = scratchU8Array[2];\r\n result.w = scratchU8Array[3];\r\n } else {\r\n // convert from big-endian to little-endian\r\n result.x = scratchU8Array[3];\r\n result.y = scratchU8Array[2];\r\n result.z = scratchU8Array[1];\r\n result.w = scratchU8Array[0];\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Unpacks a float packed using Cartesian4.packFloat.\r\n *\r\n * @param {Cartesian4} packedFloat A Cartesian4 containing a float packed to 4 values representable using uint8.\r\n * @returns {Number} The unpacked float.\r\n * @private\r\n */\r\nCartesian4.unpackFloat = function (packedFloat) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"packedFloat\", packedFloat);\r\n //>>includeEnd('debug');\r\n\r\n // scratchU8Array and scratchF32Array are views into the same buffer\r\n if (littleEndian) {\r\n scratchU8Array[0] = packedFloat.x;\r\n scratchU8Array[1] = packedFloat.y;\r\n scratchU8Array[2] = packedFloat.z;\r\n scratchU8Array[3] = packedFloat.w;\r\n } else {\r\n // convert from little-endian to big-endian\r\n scratchU8Array[0] = packedFloat.w;\r\n scratchU8Array[1] = packedFloat.z;\r\n scratchU8Array[2] = packedFloat.y;\r\n scratchU8Array[3] = packedFloat.x;\r\n }\r\n return scratchF32Array[0];\r\n};\r\nexport default Cartesian4;\r\n","import defined from \"./defined.js\";\r\n\r\n/**\r\n * Constructs an exception object that is thrown due to an error that can occur at runtime, e.g.,\r\n * out of memory, could not compile shader, etc. If a function may throw this\r\n * exception, the calling code should be prepared to catch it.\r\n *

\r\n * On the other hand, a {@link DeveloperError} indicates an exception due\r\n * to a developer error, e.g., invalid argument, that usually indicates a bug in the\r\n * calling code.\r\n *\r\n * @alias RuntimeError\r\n * @constructor\r\n * @extends Error\r\n *\r\n * @param {String} [message] The error message for this exception.\r\n *\r\n * @see DeveloperError\r\n */\r\nfunction RuntimeError(message) {\r\n /**\r\n * 'RuntimeError' indicating that this exception was thrown due to a runtime error.\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = \"RuntimeError\";\r\n\r\n /**\r\n * The explanation for why this exception was thrown.\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.message = message;\r\n\r\n //Browsers such as IE don't have a stack property until you actually throw the error.\r\n var stack;\r\n try {\r\n throw new Error();\r\n } catch (e) {\r\n stack = e.stack;\r\n }\r\n\r\n /**\r\n * The stack trace of this exception, if available.\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.stack = stack;\r\n}\r\n\r\nif (defined(Object.create)) {\r\n RuntimeError.prototype = Object.create(Error.prototype);\r\n RuntimeError.prototype.constructor = RuntimeError;\r\n}\r\n\r\nRuntimeError.prototype.toString = function () {\r\n var str = this.name + \": \" + this.message;\r\n\r\n if (defined(this.stack)) {\r\n str += \"\\n\" + this.stack.toString();\r\n }\r\n\r\n return str;\r\n};\r\nexport default RuntimeError;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\n\r\n/**\r\n * A 4x4 matrix, indexable as a column-major order array.\r\n * Constructor parameters are in row-major order for code readability.\r\n * @alias Matrix4\r\n * @constructor\r\n * @implements {ArrayLike}\r\n *\r\n * @param {Number} [column0Row0=0.0] The value for column 0, row 0.\r\n * @param {Number} [column1Row0=0.0] The value for column 1, row 0.\r\n * @param {Number} [column2Row0=0.0] The value for column 2, row 0.\r\n * @param {Number} [column3Row0=0.0] The value for column 3, row 0.\r\n * @param {Number} [column0Row1=0.0] The value for column 0, row 1.\r\n * @param {Number} [column1Row1=0.0] The value for column 1, row 1.\r\n * @param {Number} [column2Row1=0.0] The value for column 2, row 1.\r\n * @param {Number} [column3Row1=0.0] The value for column 3, row 1.\r\n * @param {Number} [column0Row2=0.0] The value for column 0, row 2.\r\n * @param {Number} [column1Row2=0.0] The value for column 1, row 2.\r\n * @param {Number} [column2Row2=0.0] The value for column 2, row 2.\r\n * @param {Number} [column3Row2=0.0] The value for column 3, row 2.\r\n * @param {Number} [column0Row3=0.0] The value for column 0, row 3.\r\n * @param {Number} [column1Row3=0.0] The value for column 1, row 3.\r\n * @param {Number} [column2Row3=0.0] The value for column 2, row 3.\r\n * @param {Number} [column3Row3=0.0] The value for column 3, row 3.\r\n *\r\n * @see Matrix4.fromColumnMajorArray\r\n * @see Matrix4.fromRowMajorArray\r\n * @see Matrix4.fromRotationTranslation\r\n * @see Matrix4.fromTranslationRotationScale\r\n * @see Matrix4.fromTranslationQuaternionRotationScale\r\n * @see Matrix4.fromTranslation\r\n * @see Matrix4.fromScale\r\n * @see Matrix4.fromUniformScale\r\n * @see Matrix4.fromCamera\r\n * @see Matrix4.computePerspectiveFieldOfView\r\n * @see Matrix4.computeOrthographicOffCenter\r\n * @see Matrix4.computePerspectiveOffCenter\r\n * @see Matrix4.computeInfinitePerspectiveOffCenter\r\n * @see Matrix4.computeViewportTransformation\r\n * @see Matrix4.computeView\r\n * @see Matrix2\r\n * @see Matrix3\r\n * @see Packable\r\n */\r\nfunction Matrix4(\r\n column0Row0,\r\n column1Row0,\r\n column2Row0,\r\n column3Row0,\r\n column0Row1,\r\n column1Row1,\r\n column2Row1,\r\n column3Row1,\r\n column0Row2,\r\n column1Row2,\r\n column2Row2,\r\n column3Row2,\r\n column0Row3,\r\n column1Row3,\r\n column2Row3,\r\n column3Row3\r\n) {\r\n this[0] = defaultValue(column0Row0, 0.0);\r\n this[1] = defaultValue(column0Row1, 0.0);\r\n this[2] = defaultValue(column0Row2, 0.0);\r\n this[3] = defaultValue(column0Row3, 0.0);\r\n this[4] = defaultValue(column1Row0, 0.0);\r\n this[5] = defaultValue(column1Row1, 0.0);\r\n this[6] = defaultValue(column1Row2, 0.0);\r\n this[7] = defaultValue(column1Row3, 0.0);\r\n this[8] = defaultValue(column2Row0, 0.0);\r\n this[9] = defaultValue(column2Row1, 0.0);\r\n this[10] = defaultValue(column2Row2, 0.0);\r\n this[11] = defaultValue(column2Row3, 0.0);\r\n this[12] = defaultValue(column3Row0, 0.0);\r\n this[13] = defaultValue(column3Row1, 0.0);\r\n this[14] = defaultValue(column3Row2, 0.0);\r\n this[15] = defaultValue(column3Row3, 0.0);\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nMatrix4.packedLength = 16;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Matrix4} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nMatrix4.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value[0];\r\n array[startingIndex++] = value[1];\r\n array[startingIndex++] = value[2];\r\n array[startingIndex++] = value[3];\r\n array[startingIndex++] = value[4];\r\n array[startingIndex++] = value[5];\r\n array[startingIndex++] = value[6];\r\n array[startingIndex++] = value[7];\r\n array[startingIndex++] = value[8];\r\n array[startingIndex++] = value[9];\r\n array[startingIndex++] = value[10];\r\n array[startingIndex++] = value[11];\r\n array[startingIndex++] = value[12];\r\n array[startingIndex++] = value[13];\r\n array[startingIndex++] = value[14];\r\n array[startingIndex] = value[15];\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Matrix4} [result] The object into which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided.\r\n */\r\nMatrix4.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Matrix4();\r\n }\r\n\r\n result[0] = array[startingIndex++];\r\n result[1] = array[startingIndex++];\r\n result[2] = array[startingIndex++];\r\n result[3] = array[startingIndex++];\r\n result[4] = array[startingIndex++];\r\n result[5] = array[startingIndex++];\r\n result[6] = array[startingIndex++];\r\n result[7] = array[startingIndex++];\r\n result[8] = array[startingIndex++];\r\n result[9] = array[startingIndex++];\r\n result[10] = array[startingIndex++];\r\n result[11] = array[startingIndex++];\r\n result[12] = array[startingIndex++];\r\n result[13] = array[startingIndex++];\r\n result[14] = array[startingIndex++];\r\n result[15] = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a Matrix4 instance.\r\n *\r\n * @param {Matrix4} matrix The matrix to duplicate.\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided. (Returns undefined if matrix is undefined)\r\n */\r\nMatrix4.clone = function (matrix, result) {\r\n if (!defined(matrix)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new Matrix4(\r\n matrix[0],\r\n matrix[4],\r\n matrix[8],\r\n matrix[12],\r\n matrix[1],\r\n matrix[5],\r\n matrix[9],\r\n matrix[13],\r\n matrix[2],\r\n matrix[6],\r\n matrix[10],\r\n matrix[14],\r\n matrix[3],\r\n matrix[7],\r\n matrix[11],\r\n matrix[15]\r\n );\r\n }\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[3];\r\n result[4] = matrix[4];\r\n result[5] = matrix[5];\r\n result[6] = matrix[6];\r\n result[7] = matrix[7];\r\n result[8] = matrix[8];\r\n result[9] = matrix[9];\r\n result[10] = matrix[10];\r\n result[11] = matrix[11];\r\n result[12] = matrix[12];\r\n result[13] = matrix[13];\r\n result[14] = matrix[14];\r\n result[15] = matrix[15];\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Matrix4 from 16 consecutive elements in an array.\r\n * @function\r\n *\r\n * @param {Number[]} array The array whose 16 consecutive elements correspond to the positions of the matrix. Assumes column-major order.\r\n * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to first column first row position in the matrix.\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided.\r\n *\r\n * @example\r\n * // Create the Matrix4:\r\n * // [1.0, 2.0, 3.0, 4.0]\r\n * // [1.0, 2.0, 3.0, 4.0]\r\n * // [1.0, 2.0, 3.0, 4.0]\r\n * // [1.0, 2.0, 3.0, 4.0]\r\n *\r\n * var v = [1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0];\r\n * var m = Cesium.Matrix4.fromArray(v);\r\n *\r\n * // Create same Matrix4 with using an offset into an array\r\n * var v2 = [0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0];\r\n * var m2 = Cesium.Matrix4.fromArray(v2, 2);\r\n */\r\nMatrix4.fromArray = Matrix4.unpack;\r\n\r\n/**\r\n * Computes a Matrix4 instance from a column-major order array.\r\n *\r\n * @param {Number[]} values The column-major order array.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n */\r\nMatrix4.fromColumnMajorArray = function (values, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"values\", values);\r\n //>>includeEnd('debug');\r\n\r\n return Matrix4.clone(values, result);\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance from a row-major order array.\r\n * The resulting matrix will be in column-major order.\r\n *\r\n * @param {Number[]} values The row-major order array.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n */\r\nMatrix4.fromRowMajorArray = function (values, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"values\", values);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix4(\r\n values[0],\r\n values[1],\r\n values[2],\r\n values[3],\r\n values[4],\r\n values[5],\r\n values[6],\r\n values[7],\r\n values[8],\r\n values[9],\r\n values[10],\r\n values[11],\r\n values[12],\r\n values[13],\r\n values[14],\r\n values[15]\r\n );\r\n }\r\n result[0] = values[0];\r\n result[1] = values[4];\r\n result[2] = values[8];\r\n result[3] = values[12];\r\n result[4] = values[1];\r\n result[5] = values[5];\r\n result[6] = values[9];\r\n result[7] = values[13];\r\n result[8] = values[2];\r\n result[9] = values[6];\r\n result[10] = values[10];\r\n result[11] = values[14];\r\n result[12] = values[3];\r\n result[13] = values[7];\r\n result[14] = values[11];\r\n result[15] = values[15];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance from a Matrix3 representing the rotation\r\n * and a Cartesian3 representing the translation.\r\n *\r\n * @param {Matrix3} rotation The upper left portion of the matrix representing the rotation.\r\n * @param {Cartesian3} [translation=Cartesian3.ZERO] The upper right portion of the matrix representing the translation.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n */\r\nMatrix4.fromRotationTranslation = function (rotation, translation, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rotation\", rotation);\r\n //>>includeEnd('debug');\r\n\r\n translation = defaultValue(translation, Cartesian3.ZERO);\r\n\r\n if (!defined(result)) {\r\n return new Matrix4(\r\n rotation[0],\r\n rotation[3],\r\n rotation[6],\r\n translation.x,\r\n rotation[1],\r\n rotation[4],\r\n rotation[7],\r\n translation.y,\r\n rotation[2],\r\n rotation[5],\r\n rotation[8],\r\n translation.z,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n );\r\n }\r\n\r\n result[0] = rotation[0];\r\n result[1] = rotation[1];\r\n result[2] = rotation[2];\r\n result[3] = 0.0;\r\n result[4] = rotation[3];\r\n result[5] = rotation[4];\r\n result[6] = rotation[5];\r\n result[7] = 0.0;\r\n result[8] = rotation[6];\r\n result[9] = rotation[7];\r\n result[10] = rotation[8];\r\n result[11] = 0.0;\r\n result[12] = translation.x;\r\n result[13] = translation.y;\r\n result[14] = translation.z;\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance from a translation, rotation, and scale (TRS)\r\n * representation with the rotation represented as a quaternion.\r\n *\r\n * @param {Cartesian3} translation The translation transformation.\r\n * @param {Quaternion} rotation The rotation transformation.\r\n * @param {Cartesian3} scale The non-uniform scale transformation.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n *\r\n * @example\r\n * var result = Cesium.Matrix4.fromTranslationQuaternionRotationScale(\r\n * new Cesium.Cartesian3(1.0, 2.0, 3.0), // translation\r\n * Cesium.Quaternion.IDENTITY, // rotation\r\n * new Cesium.Cartesian3(7.0, 8.0, 9.0), // scale\r\n * result);\r\n */\r\nMatrix4.fromTranslationQuaternionRotationScale = function (\r\n translation,\r\n rotation,\r\n scale,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"translation\", translation);\r\n Check.typeOf.object(\"rotation\", rotation);\r\n Check.typeOf.object(\"scale\", scale);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Matrix4();\r\n }\r\n\r\n var scaleX = scale.x;\r\n var scaleY = scale.y;\r\n var scaleZ = scale.z;\r\n\r\n var x2 = rotation.x * rotation.x;\r\n var xy = rotation.x * rotation.y;\r\n var xz = rotation.x * rotation.z;\r\n var xw = rotation.x * rotation.w;\r\n var y2 = rotation.y * rotation.y;\r\n var yz = rotation.y * rotation.z;\r\n var yw = rotation.y * rotation.w;\r\n var z2 = rotation.z * rotation.z;\r\n var zw = rotation.z * rotation.w;\r\n var w2 = rotation.w * rotation.w;\r\n\r\n var m00 = x2 - y2 - z2 + w2;\r\n var m01 = 2.0 * (xy - zw);\r\n var m02 = 2.0 * (xz + yw);\r\n\r\n var m10 = 2.0 * (xy + zw);\r\n var m11 = -x2 + y2 - z2 + w2;\r\n var m12 = 2.0 * (yz - xw);\r\n\r\n var m20 = 2.0 * (xz - yw);\r\n var m21 = 2.0 * (yz + xw);\r\n var m22 = -x2 - y2 + z2 + w2;\r\n\r\n result[0] = m00 * scaleX;\r\n result[1] = m10 * scaleX;\r\n result[2] = m20 * scaleX;\r\n result[3] = 0.0;\r\n result[4] = m01 * scaleY;\r\n result[5] = m11 * scaleY;\r\n result[6] = m21 * scaleY;\r\n result[7] = 0.0;\r\n result[8] = m02 * scaleZ;\r\n result[9] = m12 * scaleZ;\r\n result[10] = m22 * scaleZ;\r\n result[11] = 0.0;\r\n result[12] = translation.x;\r\n result[13] = translation.y;\r\n result[14] = translation.z;\r\n result[15] = 1.0;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Matrix4 instance from a {@link TranslationRotationScale} instance.\r\n *\r\n * @param {TranslationRotationScale} translationRotationScale The instance.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n */\r\nMatrix4.fromTranslationRotationScale = function (\r\n translationRotationScale,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"translationRotationScale\", translationRotationScale);\r\n //>>includeEnd('debug');\r\n\r\n return Matrix4.fromTranslationQuaternionRotationScale(\r\n translationRotationScale.translation,\r\n translationRotationScale.rotation,\r\n translationRotationScale.scale,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Creates a Matrix4 instance from a Cartesian3 representing the translation.\r\n *\r\n * @param {Cartesian3} translation The upper right portion of the matrix representing the translation.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n *\r\n * @see Matrix4.multiplyByTranslation\r\n */\r\nMatrix4.fromTranslation = function (translation, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"translation\", translation);\r\n //>>includeEnd('debug');\r\n\r\n return Matrix4.fromRotationTranslation(Matrix3.IDENTITY, translation, result);\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance representing a non-uniform scale.\r\n *\r\n * @param {Cartesian3} scale The x, y, and z scale factors.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n *\r\n * @example\r\n * // Creates\r\n * // [7.0, 0.0, 0.0, 0.0]\r\n * // [0.0, 8.0, 0.0, 0.0]\r\n * // [0.0, 0.0, 9.0, 0.0]\r\n * // [0.0, 0.0, 0.0, 1.0]\r\n * var m = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(7.0, 8.0, 9.0));\r\n */\r\nMatrix4.fromScale = function (scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"scale\", scale);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix4(\r\n scale.x,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n scale.y,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n scale.z,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n );\r\n }\r\n\r\n result[0] = scale.x;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = 0.0;\r\n result[5] = scale.y;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = 0.0;\r\n result[9] = 0.0;\r\n result[10] = scale.z;\r\n result[11] = 0.0;\r\n result[12] = 0.0;\r\n result[13] = 0.0;\r\n result[14] = 0.0;\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance representing a uniform scale.\r\n *\r\n * @param {Number} scale The uniform scale factor.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n *\r\n * @example\r\n * // Creates\r\n * // [2.0, 0.0, 0.0, 0.0]\r\n * // [0.0, 2.0, 0.0, 0.0]\r\n * // [0.0, 0.0, 2.0, 0.0]\r\n * // [0.0, 0.0, 0.0, 1.0]\r\n * var m = Cesium.Matrix4.fromUniformScale(2.0);\r\n */\r\nMatrix4.fromUniformScale = function (scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"scale\", scale);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix4(\r\n scale,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n scale,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n scale,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n );\r\n }\r\n\r\n result[0] = scale;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = 0.0;\r\n result[5] = scale;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = 0.0;\r\n result[9] = 0.0;\r\n result[10] = scale;\r\n result[11] = 0.0;\r\n result[12] = 0.0;\r\n result[13] = 0.0;\r\n result[14] = 0.0;\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\nvar fromCameraF = new Cartesian3();\r\nvar fromCameraR = new Cartesian3();\r\nvar fromCameraU = new Cartesian3();\r\n\r\n/**\r\n * Computes a Matrix4 instance from a Camera.\r\n *\r\n * @param {Camera} camera The camera to use.\r\n * @param {Matrix4} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix4} The modified result parameter, or a new Matrix4 instance if one was not provided.\r\n */\r\nMatrix4.fromCamera = function (camera, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"camera\", camera);\r\n //>>includeEnd('debug');\r\n\r\n var position = camera.position;\r\n var direction = camera.direction;\r\n var up = camera.up;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"camera.position\", position);\r\n Check.typeOf.object(\"camera.direction\", direction);\r\n Check.typeOf.object(\"camera.up\", up);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian3.normalize(direction, fromCameraF);\r\n Cartesian3.normalize(\r\n Cartesian3.cross(fromCameraF, up, fromCameraR),\r\n fromCameraR\r\n );\r\n Cartesian3.normalize(\r\n Cartesian3.cross(fromCameraR, fromCameraF, fromCameraU),\r\n fromCameraU\r\n );\r\n\r\n var sX = fromCameraR.x;\r\n var sY = fromCameraR.y;\r\n var sZ = fromCameraR.z;\r\n var fX = fromCameraF.x;\r\n var fY = fromCameraF.y;\r\n var fZ = fromCameraF.z;\r\n var uX = fromCameraU.x;\r\n var uY = fromCameraU.y;\r\n var uZ = fromCameraU.z;\r\n var positionX = position.x;\r\n var positionY = position.y;\r\n var positionZ = position.z;\r\n var t0 = sX * -positionX + sY * -positionY + sZ * -positionZ;\r\n var t1 = uX * -positionX + uY * -positionY + uZ * -positionZ;\r\n var t2 = fX * positionX + fY * positionY + fZ * positionZ;\r\n\r\n // The code below this comment is an optimized\r\n // version of the commented lines.\r\n // Rather that create two matrices and then multiply,\r\n // we just bake in the multiplcation as part of creation.\r\n // var rotation = new Matrix4(\r\n // sX, sY, sZ, 0.0,\r\n // uX, uY, uZ, 0.0,\r\n // -fX, -fY, -fZ, 0.0,\r\n // 0.0, 0.0, 0.0, 1.0);\r\n // var translation = new Matrix4(\r\n // 1.0, 0.0, 0.0, -position.x,\r\n // 0.0, 1.0, 0.0, -position.y,\r\n // 0.0, 0.0, 1.0, -position.z,\r\n // 0.0, 0.0, 0.0, 1.0);\r\n // return rotation.multiply(translation);\r\n if (!defined(result)) {\r\n return new Matrix4(\r\n sX,\r\n sY,\r\n sZ,\r\n t0,\r\n uX,\r\n uY,\r\n uZ,\r\n t1,\r\n -fX,\r\n -fY,\r\n -fZ,\r\n t2,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n );\r\n }\r\n result[0] = sX;\r\n result[1] = uX;\r\n result[2] = -fX;\r\n result[3] = 0.0;\r\n result[4] = sY;\r\n result[5] = uY;\r\n result[6] = -fY;\r\n result[7] = 0.0;\r\n result[8] = sZ;\r\n result[9] = uZ;\r\n result[10] = -fZ;\r\n result[11] = 0.0;\r\n result[12] = t0;\r\n result[13] = t1;\r\n result[14] = t2;\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance representing a perspective transformation matrix.\r\n *\r\n * @param {Number} fovY The field of view along the Y axis in radians.\r\n * @param {Number} aspectRatio The aspect ratio.\r\n * @param {Number} near The distance to the near plane in meters.\r\n * @param {Number} far The distance to the far plane in meters.\r\n * @param {Matrix4} result The object in which the result will be stored.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} fovY must be in (0, PI].\r\n * @exception {DeveloperError} aspectRatio must be greater than zero.\r\n * @exception {DeveloperError} near must be greater than zero.\r\n * @exception {DeveloperError} far must be greater than zero.\r\n */\r\nMatrix4.computePerspectiveFieldOfView = function (\r\n fovY,\r\n aspectRatio,\r\n near,\r\n far,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThan(\"fovY\", fovY, 0.0);\r\n Check.typeOf.number.lessThan(\"fovY\", fovY, Math.PI);\r\n Check.typeOf.number.greaterThan(\"near\", near, 0.0);\r\n Check.typeOf.number.greaterThan(\"far\", far, 0.0);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var bottom = Math.tan(fovY * 0.5);\r\n\r\n var column1Row1 = 1.0 / bottom;\r\n var column0Row0 = column1Row1 / aspectRatio;\r\n var column2Row2 = (far + near) / (near - far);\r\n var column3Row2 = (2.0 * far * near) / (near - far);\r\n\r\n result[0] = column0Row0;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = 0.0;\r\n result[5] = column1Row1;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = 0.0;\r\n result[9] = 0.0;\r\n result[10] = column2Row2;\r\n result[11] = -1.0;\r\n result[12] = 0.0;\r\n result[13] = 0.0;\r\n result[14] = column3Row2;\r\n result[15] = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance representing an orthographic transformation matrix.\r\n *\r\n * @param {Number} left The number of meters to the left of the camera that will be in view.\r\n * @param {Number} right The number of meters to the right of the camera that will be in view.\r\n * @param {Number} bottom The number of meters below of the camera that will be in view.\r\n * @param {Number} top The number of meters above of the camera that will be in view.\r\n * @param {Number} near The distance to the near plane in meters.\r\n * @param {Number} far The distance to the far plane in meters.\r\n * @param {Matrix4} result The object in which the result will be stored.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.computeOrthographicOffCenter = function (\r\n left,\r\n right,\r\n bottom,\r\n top,\r\n near,\r\n far,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"left\", left);\r\n Check.typeOf.number(\"right\", right);\r\n Check.typeOf.number(\"bottom\", bottom);\r\n Check.typeOf.number(\"top\", top);\r\n Check.typeOf.number(\"near\", near);\r\n Check.typeOf.number(\"far\", far);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var a = 1.0 / (right - left);\r\n var b = 1.0 / (top - bottom);\r\n var c = 1.0 / (far - near);\r\n\r\n var tx = -(right + left) * a;\r\n var ty = -(top + bottom) * b;\r\n var tz = -(far + near) * c;\r\n a *= 2.0;\r\n b *= 2.0;\r\n c *= -2.0;\r\n\r\n result[0] = a;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = 0.0;\r\n result[5] = b;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = 0.0;\r\n result[9] = 0.0;\r\n result[10] = c;\r\n result[11] = 0.0;\r\n result[12] = tx;\r\n result[13] = ty;\r\n result[14] = tz;\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance representing an off center perspective transformation.\r\n *\r\n * @param {Number} left The number of meters to the left of the camera that will be in view.\r\n * @param {Number} right The number of meters to the right of the camera that will be in view.\r\n * @param {Number} bottom The number of meters below of the camera that will be in view.\r\n * @param {Number} top The number of meters above of the camera that will be in view.\r\n * @param {Number} near The distance to the near plane in meters.\r\n * @param {Number} far The distance to the far plane in meters.\r\n * @param {Matrix4} result The object in which the result will be stored.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.computePerspectiveOffCenter = function (\r\n left,\r\n right,\r\n bottom,\r\n top,\r\n near,\r\n far,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"left\", left);\r\n Check.typeOf.number(\"right\", right);\r\n Check.typeOf.number(\"bottom\", bottom);\r\n Check.typeOf.number(\"top\", top);\r\n Check.typeOf.number(\"near\", near);\r\n Check.typeOf.number(\"far\", far);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var column0Row0 = (2.0 * near) / (right - left);\r\n var column1Row1 = (2.0 * near) / (top - bottom);\r\n var column2Row0 = (right + left) / (right - left);\r\n var column2Row1 = (top + bottom) / (top - bottom);\r\n var column2Row2 = -(far + near) / (far - near);\r\n var column2Row3 = -1.0;\r\n var column3Row2 = (-2.0 * far * near) / (far - near);\r\n\r\n result[0] = column0Row0;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = 0.0;\r\n result[5] = column1Row1;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = column2Row0;\r\n result[9] = column2Row1;\r\n result[10] = column2Row2;\r\n result[11] = column2Row3;\r\n result[12] = 0.0;\r\n result[13] = 0.0;\r\n result[14] = column3Row2;\r\n result[15] = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance representing an infinite off center perspective transformation.\r\n *\r\n * @param {Number} left The number of meters to the left of the camera that will be in view.\r\n * @param {Number} right The number of meters to the right of the camera that will be in view.\r\n * @param {Number} bottom The number of meters below of the camera that will be in view.\r\n * @param {Number} top The number of meters above of the camera that will be in view.\r\n * @param {Number} near The distance to the near plane in meters.\r\n * @param {Matrix4} result The object in which the result will be stored.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.computeInfinitePerspectiveOffCenter = function (\r\n left,\r\n right,\r\n bottom,\r\n top,\r\n near,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"left\", left);\r\n Check.typeOf.number(\"right\", right);\r\n Check.typeOf.number(\"bottom\", bottom);\r\n Check.typeOf.number(\"top\", top);\r\n Check.typeOf.number(\"near\", near);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var column0Row0 = (2.0 * near) / (right - left);\r\n var column1Row1 = (2.0 * near) / (top - bottom);\r\n var column2Row0 = (right + left) / (right - left);\r\n var column2Row1 = (top + bottom) / (top - bottom);\r\n var column2Row2 = -1.0;\r\n var column2Row3 = -1.0;\r\n var column3Row2 = -2.0 * near;\r\n\r\n result[0] = column0Row0;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = 0.0;\r\n result[5] = column1Row1;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = column2Row0;\r\n result[9] = column2Row1;\r\n result[10] = column2Row2;\r\n result[11] = column2Row3;\r\n result[12] = 0.0;\r\n result[13] = 0.0;\r\n result[14] = column3Row2;\r\n result[15] = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance that transforms from normalized device coordinates to window coordinates.\r\n *\r\n * @param {Object} [viewport = { x : 0.0, y : 0.0, width : 0.0, height : 0.0 }] The viewport's corners as shown in Example 1.\r\n * @param {Number} [nearDepthRange=0.0] The near plane distance in window coordinates.\r\n * @param {Number} [farDepthRange=1.0] The far plane distance in window coordinates.\r\n * @param {Matrix4} [result] The object in which the result will be stored.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @example\r\n * // Create viewport transformation using an explicit viewport and depth range.\r\n * var m = Cesium.Matrix4.computeViewportTransformation({\r\n * x : 0.0,\r\n * y : 0.0,\r\n * width : 1024.0,\r\n * height : 768.0\r\n * }, 0.0, 1.0, new Cesium.Matrix4());\r\n */\r\nMatrix4.computeViewportTransformation = function (\r\n viewport,\r\n nearDepthRange,\r\n farDepthRange,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new Matrix4();\r\n }\r\n\r\n viewport = defaultValue(viewport, defaultValue.EMPTY_OBJECT);\r\n var x = defaultValue(viewport.x, 0.0);\r\n var y = defaultValue(viewport.y, 0.0);\r\n var width = defaultValue(viewport.width, 0.0);\r\n var height = defaultValue(viewport.height, 0.0);\r\n nearDepthRange = defaultValue(nearDepthRange, 0.0);\r\n farDepthRange = defaultValue(farDepthRange, 1.0);\r\n\r\n var halfWidth = width * 0.5;\r\n var halfHeight = height * 0.5;\r\n var halfDepth = (farDepthRange - nearDepthRange) * 0.5;\r\n\r\n var column0Row0 = halfWidth;\r\n var column1Row1 = halfHeight;\r\n var column2Row2 = halfDepth;\r\n var column3Row0 = x + halfWidth;\r\n var column3Row1 = y + halfHeight;\r\n var column3Row2 = nearDepthRange + halfDepth;\r\n var column3Row3 = 1.0;\r\n\r\n result[0] = column0Row0;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = 0.0;\r\n result[5] = column1Row1;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = 0.0;\r\n result[9] = 0.0;\r\n result[10] = column2Row2;\r\n result[11] = 0.0;\r\n result[12] = column3Row0;\r\n result[13] = column3Row1;\r\n result[14] = column3Row2;\r\n result[15] = column3Row3;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix4 instance that transforms from world space to view space.\r\n *\r\n * @param {Cartesian3} position The position of the camera.\r\n * @param {Cartesian3} direction The forward direction.\r\n * @param {Cartesian3} up The up direction.\r\n * @param {Cartesian3} right The right direction.\r\n * @param {Matrix4} result The object in which the result will be stored.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.computeView = function (position, direction, up, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"position\", position);\r\n Check.typeOf.object(\"direction\", direction);\r\n Check.typeOf.object(\"up\", up);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = right.x;\r\n result[1] = up.x;\r\n result[2] = -direction.x;\r\n result[3] = 0.0;\r\n result[4] = right.y;\r\n result[5] = up.y;\r\n result[6] = -direction.y;\r\n result[7] = 0.0;\r\n result[8] = right.z;\r\n result[9] = up.z;\r\n result[10] = -direction.z;\r\n result[11] = 0.0;\r\n result[12] = -Cartesian3.dot(right, position);\r\n result[13] = -Cartesian3.dot(up, position);\r\n result[14] = Cartesian3.dot(direction, position);\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes an Array from the provided Matrix4 instance.\r\n * The array will be in column-major order.\r\n *\r\n * @param {Matrix4} matrix The matrix to use..\r\n * @param {Number[]} [result] The Array onto which to store the result.\r\n * @returns {Number[]} The modified Array parameter or a new Array instance if one was not provided.\r\n *\r\n * @example\r\n * //create an array from an instance of Matrix4\r\n * // m = [10.0, 14.0, 18.0, 22.0]\r\n * // [11.0, 15.0, 19.0, 23.0]\r\n * // [12.0, 16.0, 20.0, 24.0]\r\n * // [13.0, 17.0, 21.0, 25.0]\r\n * var a = Cesium.Matrix4.toArray(m);\r\n *\r\n * // m remains the same\r\n * //creates a = [10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0]\r\n */\r\nMatrix4.toArray = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return [\r\n matrix[0],\r\n matrix[1],\r\n matrix[2],\r\n matrix[3],\r\n matrix[4],\r\n matrix[5],\r\n matrix[6],\r\n matrix[7],\r\n matrix[8],\r\n matrix[9],\r\n matrix[10],\r\n matrix[11],\r\n matrix[12],\r\n matrix[13],\r\n matrix[14],\r\n matrix[15],\r\n ];\r\n }\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[3];\r\n result[4] = matrix[4];\r\n result[5] = matrix[5];\r\n result[6] = matrix[6];\r\n result[7] = matrix[7];\r\n result[8] = matrix[8];\r\n result[9] = matrix[9];\r\n result[10] = matrix[10];\r\n result[11] = matrix[11];\r\n result[12] = matrix[12];\r\n result[13] = matrix[13];\r\n result[14] = matrix[14];\r\n result[15] = matrix[15];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the array index of the element at the provided row and column.\r\n *\r\n * @param {Number} row The zero-based index of the row.\r\n * @param {Number} column The zero-based index of the column.\r\n * @returns {Number} The index of the element at the provided row and column.\r\n *\r\n * @exception {DeveloperError} row must be 0, 1, 2, or 3.\r\n * @exception {DeveloperError} column must be 0, 1, 2, or 3.\r\n *\r\n * @example\r\n * var myMatrix = new Cesium.Matrix4();\r\n * var column1Row0Index = Cesium.Matrix4.getElementIndex(1, 0);\r\n * var column1Row0 = myMatrix[column1Row0Index];\r\n * myMatrix[column1Row0Index] = 10.0;\r\n */\r\nMatrix4.getElementIndex = function (column, row) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"row\", row, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"row\", row, 3);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"column\", column, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"column\", column, 3);\r\n //>>includeEnd('debug');\r\n\r\n return column * 4 + row;\r\n};\r\n\r\n/**\r\n * Retrieves a copy of the matrix column at the provided index as a Cartesian4 instance.\r\n *\r\n * @param {Matrix4} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the column to retrieve.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0, 1, 2, or 3.\r\n *\r\n * @example\r\n * //returns a Cartesian4 instance with values from the specified column\r\n * // m = [10.0, 11.0, 12.0, 13.0]\r\n * // [14.0, 15.0, 16.0, 17.0]\r\n * // [18.0, 19.0, 20.0, 21.0]\r\n * // [22.0, 23.0, 24.0, 25.0]\r\n *\r\n * //Example 1: Creates an instance of Cartesian\r\n * var a = Cesium.Matrix4.getColumn(m, 2, new Cesium.Cartesian4());\r\n *\r\n * @example\r\n * //Example 2: Sets values for Cartesian instance\r\n * var a = new Cesium.Cartesian4();\r\n * Cesium.Matrix4.getColumn(m, 2, a);\r\n *\r\n * // a.x = 12.0; a.y = 16.0; a.z = 20.0; a.w = 24.0;\r\n */\r\nMatrix4.getColumn = function (matrix, index, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 3);\r\n\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var startIndex = index * 4;\r\n var x = matrix[startIndex];\r\n var y = matrix[startIndex + 1];\r\n var z = matrix[startIndex + 2];\r\n var w = matrix[startIndex + 3];\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n result.w = w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a new matrix that replaces the specified column in the provided matrix with the provided Cartesian4 instance.\r\n *\r\n * @param {Matrix4} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the column to set.\r\n * @param {Cartesian4} cartesian The Cartesian whose values will be assigned to the specified column.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0, 1, 2, or 3.\r\n *\r\n * @example\r\n * //creates a new Matrix4 instance with new column values from the Cartesian4 instance\r\n * // m = [10.0, 11.0, 12.0, 13.0]\r\n * // [14.0, 15.0, 16.0, 17.0]\r\n * // [18.0, 19.0, 20.0, 21.0]\r\n * // [22.0, 23.0, 24.0, 25.0]\r\n *\r\n * var a = Cesium.Matrix4.setColumn(m, 2, new Cesium.Cartesian4(99.0, 98.0, 97.0, 96.0), new Cesium.Matrix4());\r\n *\r\n * // m remains the same\r\n * // a = [10.0, 11.0, 99.0, 13.0]\r\n * // [14.0, 15.0, 98.0, 17.0]\r\n * // [18.0, 19.0, 97.0, 21.0]\r\n * // [22.0, 23.0, 96.0, 25.0]\r\n */\r\nMatrix4.setColumn = function (matrix, index, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 3);\r\n\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result = Matrix4.clone(matrix, result);\r\n var startIndex = index * 4;\r\n result[startIndex] = cartesian.x;\r\n result[startIndex + 1] = cartesian.y;\r\n result[startIndex + 2] = cartesian.z;\r\n result[startIndex + 3] = cartesian.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a new matrix that replaces the translation in the rightmost column of the provided\r\n * matrix with the provided translation. This assumes the matrix is an affine transformation\r\n *\r\n * @param {Matrix4} matrix The matrix to use.\r\n * @param {Cartesian3} translation The translation that replaces the translation of the provided matrix.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.setTranslation = function (matrix, translation, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"translation\", translation);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[3];\r\n\r\n result[4] = matrix[4];\r\n result[5] = matrix[5];\r\n result[6] = matrix[6];\r\n result[7] = matrix[7];\r\n\r\n result[8] = matrix[8];\r\n result[9] = matrix[9];\r\n result[10] = matrix[10];\r\n result[11] = matrix[11];\r\n\r\n result[12] = translation.x;\r\n result[13] = translation.y;\r\n result[14] = translation.z;\r\n result[15] = matrix[15];\r\n\r\n return result;\r\n};\r\n\r\nvar scaleScratch = new Cartesian3();\r\n/**\r\n * Computes a new matrix that replaces the scale with the provided scale. This assumes the matrix is an affine transformation\r\n *\r\n * @param {Matrix4} matrix The matrix to use.\r\n * @param {Cartesian3} scale The scale that replaces the scale of the provided matrix.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.setScale = function (matrix, scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"scale\", scale);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var existingScale = Matrix4.getScale(matrix, scaleScratch);\r\n var newScale = Cartesian3.divideComponents(\r\n scale,\r\n existingScale,\r\n scaleScratch\r\n );\r\n return Matrix4.multiplyByScale(matrix, newScale, result);\r\n};\r\n\r\n/**\r\n * Retrieves a copy of the matrix row at the provided index as a Cartesian4 instance.\r\n *\r\n * @param {Matrix4} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the row to retrieve.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0, 1, 2, or 3.\r\n *\r\n * @example\r\n * //returns a Cartesian4 instance with values from the specified column\r\n * // m = [10.0, 11.0, 12.0, 13.0]\r\n * // [14.0, 15.0, 16.0, 17.0]\r\n * // [18.0, 19.0, 20.0, 21.0]\r\n * // [22.0, 23.0, 24.0, 25.0]\r\n *\r\n * //Example 1: Returns an instance of Cartesian\r\n * var a = Cesium.Matrix4.getRow(m, 2, new Cesium.Cartesian4());\r\n *\r\n * @example\r\n * //Example 2: Sets values for a Cartesian instance\r\n * var a = new Cesium.Cartesian4();\r\n * Cesium.Matrix4.getRow(m, 2, a);\r\n *\r\n * // a.x = 18.0; a.y = 19.0; a.z = 20.0; a.w = 21.0;\r\n */\r\nMatrix4.getRow = function (matrix, index, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 3);\r\n\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var x = matrix[index];\r\n var y = matrix[index + 4];\r\n var z = matrix[index + 8];\r\n var w = matrix[index + 12];\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n result.w = w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a new matrix that replaces the specified row in the provided matrix with the provided Cartesian4 instance.\r\n *\r\n * @param {Matrix4} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the row to set.\r\n * @param {Cartesian4} cartesian The Cartesian whose values will be assigned to the specified row.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0, 1, 2, or 3.\r\n *\r\n * @example\r\n * //create a new Matrix4 instance with new row values from the Cartesian4 instance\r\n * // m = [10.0, 11.0, 12.0, 13.0]\r\n * // [14.0, 15.0, 16.0, 17.0]\r\n * // [18.0, 19.0, 20.0, 21.0]\r\n * // [22.0, 23.0, 24.0, 25.0]\r\n *\r\n * var a = Cesium.Matrix4.setRow(m, 2, new Cesium.Cartesian4(99.0, 98.0, 97.0, 96.0), new Cesium.Matrix4());\r\n *\r\n * // m remains the same\r\n * // a = [10.0, 11.0, 12.0, 13.0]\r\n * // [14.0, 15.0, 16.0, 17.0]\r\n * // [99.0, 98.0, 97.0, 96.0]\r\n * // [22.0, 23.0, 24.0, 25.0]\r\n */\r\nMatrix4.setRow = function (matrix, index, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 3);\r\n\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result = Matrix4.clone(matrix, result);\r\n result[index] = cartesian.x;\r\n result[index + 4] = cartesian.y;\r\n result[index + 8] = cartesian.z;\r\n result[index + 12] = cartesian.w;\r\n return result;\r\n};\r\n\r\nvar scratchColumn = new Cartesian3();\r\n\r\n/**\r\n * Extracts the non-uniform scale assuming the matrix is an affine transformation.\r\n *\r\n * @param {Matrix4} matrix The matrix.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter\r\n */\r\nMatrix4.getScale = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Cartesian3.magnitude(\r\n Cartesian3.fromElements(matrix[0], matrix[1], matrix[2], scratchColumn)\r\n );\r\n result.y = Cartesian3.magnitude(\r\n Cartesian3.fromElements(matrix[4], matrix[5], matrix[6], scratchColumn)\r\n );\r\n result.z = Cartesian3.magnitude(\r\n Cartesian3.fromElements(matrix[8], matrix[9], matrix[10], scratchColumn)\r\n );\r\n return result;\r\n};\r\n\r\nvar scratchScale = new Cartesian3();\r\n\r\n/**\r\n * Computes the maximum scale assuming the matrix is an affine transformation.\r\n * The maximum scale is the maximum length of the column vectors in the upper-left\r\n * 3x3 matrix.\r\n *\r\n * @param {Matrix4} matrix The matrix.\r\n * @returns {Number} The maximum scale.\r\n */\r\nMatrix4.getMaximumScale = function (matrix) {\r\n Matrix4.getScale(matrix, scratchScale);\r\n return Cartesian3.maximumComponent(scratchScale);\r\n};\r\n\r\n/**\r\n * Computes the product of two matrices.\r\n *\r\n * @param {Matrix4} left The first matrix.\r\n * @param {Matrix4} right The second matrix.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.multiply = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var left0 = left[0];\r\n var left1 = left[1];\r\n var left2 = left[2];\r\n var left3 = left[3];\r\n var left4 = left[4];\r\n var left5 = left[5];\r\n var left6 = left[6];\r\n var left7 = left[7];\r\n var left8 = left[8];\r\n var left9 = left[9];\r\n var left10 = left[10];\r\n var left11 = left[11];\r\n var left12 = left[12];\r\n var left13 = left[13];\r\n var left14 = left[14];\r\n var left15 = left[15];\r\n\r\n var right0 = right[0];\r\n var right1 = right[1];\r\n var right2 = right[2];\r\n var right3 = right[3];\r\n var right4 = right[4];\r\n var right5 = right[5];\r\n var right6 = right[6];\r\n var right7 = right[7];\r\n var right8 = right[8];\r\n var right9 = right[9];\r\n var right10 = right[10];\r\n var right11 = right[11];\r\n var right12 = right[12];\r\n var right13 = right[13];\r\n var right14 = right[14];\r\n var right15 = right[15];\r\n\r\n var column0Row0 =\r\n left0 * right0 + left4 * right1 + left8 * right2 + left12 * right3;\r\n var column0Row1 =\r\n left1 * right0 + left5 * right1 + left9 * right2 + left13 * right3;\r\n var column0Row2 =\r\n left2 * right0 + left6 * right1 + left10 * right2 + left14 * right3;\r\n var column0Row3 =\r\n left3 * right0 + left7 * right1 + left11 * right2 + left15 * right3;\r\n\r\n var column1Row0 =\r\n left0 * right4 + left4 * right5 + left8 * right6 + left12 * right7;\r\n var column1Row1 =\r\n left1 * right4 + left5 * right5 + left9 * right6 + left13 * right7;\r\n var column1Row2 =\r\n left2 * right4 + left6 * right5 + left10 * right6 + left14 * right7;\r\n var column1Row3 =\r\n left3 * right4 + left7 * right5 + left11 * right6 + left15 * right7;\r\n\r\n var column2Row0 =\r\n left0 * right8 + left4 * right9 + left8 * right10 + left12 * right11;\r\n var column2Row1 =\r\n left1 * right8 + left5 * right9 + left9 * right10 + left13 * right11;\r\n var column2Row2 =\r\n left2 * right8 + left6 * right9 + left10 * right10 + left14 * right11;\r\n var column2Row3 =\r\n left3 * right8 + left7 * right9 + left11 * right10 + left15 * right11;\r\n\r\n var column3Row0 =\r\n left0 * right12 + left4 * right13 + left8 * right14 + left12 * right15;\r\n var column3Row1 =\r\n left1 * right12 + left5 * right13 + left9 * right14 + left13 * right15;\r\n var column3Row2 =\r\n left2 * right12 + left6 * right13 + left10 * right14 + left14 * right15;\r\n var column3Row3 =\r\n left3 * right12 + left7 * right13 + left11 * right14 + left15 * right15;\r\n\r\n result[0] = column0Row0;\r\n result[1] = column0Row1;\r\n result[2] = column0Row2;\r\n result[3] = column0Row3;\r\n result[4] = column1Row0;\r\n result[5] = column1Row1;\r\n result[6] = column1Row2;\r\n result[7] = column1Row3;\r\n result[8] = column2Row0;\r\n result[9] = column2Row1;\r\n result[10] = column2Row2;\r\n result[11] = column2Row3;\r\n result[12] = column3Row0;\r\n result[13] = column3Row1;\r\n result[14] = column3Row2;\r\n result[15] = column3Row3;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the sum of two matrices.\r\n *\r\n * @param {Matrix4} left The first matrix.\r\n * @param {Matrix4} right The second matrix.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.add = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = left[0] + right[0];\r\n result[1] = left[1] + right[1];\r\n result[2] = left[2] + right[2];\r\n result[3] = left[3] + right[3];\r\n result[4] = left[4] + right[4];\r\n result[5] = left[5] + right[5];\r\n result[6] = left[6] + right[6];\r\n result[7] = left[7] + right[7];\r\n result[8] = left[8] + right[8];\r\n result[9] = left[9] + right[9];\r\n result[10] = left[10] + right[10];\r\n result[11] = left[11] + right[11];\r\n result[12] = left[12] + right[12];\r\n result[13] = left[13] + right[13];\r\n result[14] = left[14] + right[14];\r\n result[15] = left[15] + right[15];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the difference of two matrices.\r\n *\r\n * @param {Matrix4} left The first matrix.\r\n * @param {Matrix4} right The second matrix.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.subtract = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = left[0] - right[0];\r\n result[1] = left[1] - right[1];\r\n result[2] = left[2] - right[2];\r\n result[3] = left[3] - right[3];\r\n result[4] = left[4] - right[4];\r\n result[5] = left[5] - right[5];\r\n result[6] = left[6] - right[6];\r\n result[7] = left[7] - right[7];\r\n result[8] = left[8] - right[8];\r\n result[9] = left[9] - right[9];\r\n result[10] = left[10] - right[10];\r\n result[11] = left[11] - right[11];\r\n result[12] = left[12] - right[12];\r\n result[13] = left[13] - right[13];\r\n result[14] = left[14] - right[14];\r\n result[15] = left[15] - right[15];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of two matrices assuming the matrices are\r\n * affine transformation matrices, where the upper left 3x3 elements\r\n * are a rotation matrix, and the upper three elements in the fourth\r\n * column are the translation. The bottom row is assumed to be [0, 0, 0, 1].\r\n * The matrix is not verified to be in the proper form.\r\n * This method is faster than computing the product for general 4x4\r\n * matrices using {@link Matrix4.multiply}.\r\n *\r\n * @param {Matrix4} left The first matrix.\r\n * @param {Matrix4} right The second matrix.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @example\r\n * var m1 = new Cesium.Matrix4(1.0, 6.0, 7.0, 0.0, 2.0, 5.0, 8.0, 0.0, 3.0, 4.0, 9.0, 0.0, 0.0, 0.0, 0.0, 1.0);\r\n * var m2 = Cesium.Transforms.eastNorthUpToFixedFrame(new Cesium.Cartesian3(1.0, 1.0, 1.0));\r\n * var m3 = Cesium.Matrix4.multiplyTransformation(m1, m2, new Cesium.Matrix4());\r\n */\r\nMatrix4.multiplyTransformation = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var left0 = left[0];\r\n var left1 = left[1];\r\n var left2 = left[2];\r\n var left4 = left[4];\r\n var left5 = left[5];\r\n var left6 = left[6];\r\n var left8 = left[8];\r\n var left9 = left[9];\r\n var left10 = left[10];\r\n var left12 = left[12];\r\n var left13 = left[13];\r\n var left14 = left[14];\r\n\r\n var right0 = right[0];\r\n var right1 = right[1];\r\n var right2 = right[2];\r\n var right4 = right[4];\r\n var right5 = right[5];\r\n var right6 = right[6];\r\n var right8 = right[8];\r\n var right9 = right[9];\r\n var right10 = right[10];\r\n var right12 = right[12];\r\n var right13 = right[13];\r\n var right14 = right[14];\r\n\r\n var column0Row0 = left0 * right0 + left4 * right1 + left8 * right2;\r\n var column0Row1 = left1 * right0 + left5 * right1 + left9 * right2;\r\n var column0Row2 = left2 * right0 + left6 * right1 + left10 * right2;\r\n\r\n var column1Row0 = left0 * right4 + left4 * right5 + left8 * right6;\r\n var column1Row1 = left1 * right4 + left5 * right5 + left9 * right6;\r\n var column1Row2 = left2 * right4 + left6 * right5 + left10 * right6;\r\n\r\n var column2Row0 = left0 * right8 + left4 * right9 + left8 * right10;\r\n var column2Row1 = left1 * right8 + left5 * right9 + left9 * right10;\r\n var column2Row2 = left2 * right8 + left6 * right9 + left10 * right10;\r\n\r\n var column3Row0 =\r\n left0 * right12 + left4 * right13 + left8 * right14 + left12;\r\n var column3Row1 =\r\n left1 * right12 + left5 * right13 + left9 * right14 + left13;\r\n var column3Row2 =\r\n left2 * right12 + left6 * right13 + left10 * right14 + left14;\r\n\r\n result[0] = column0Row0;\r\n result[1] = column0Row1;\r\n result[2] = column0Row2;\r\n result[3] = 0.0;\r\n result[4] = column1Row0;\r\n result[5] = column1Row1;\r\n result[6] = column1Row2;\r\n result[7] = 0.0;\r\n result[8] = column2Row0;\r\n result[9] = column2Row1;\r\n result[10] = column2Row2;\r\n result[11] = 0.0;\r\n result[12] = column3Row0;\r\n result[13] = column3Row1;\r\n result[14] = column3Row2;\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Multiplies a transformation matrix (with a bottom row of [0.0, 0.0, 0.0, 1.0])\r\n * by a 3x3 rotation matrix. This is an optimization\r\n * for Matrix4.multiply(m, Matrix4.fromRotationTranslation(rotation), m); with less allocations and arithmetic operations.\r\n *\r\n * @param {Matrix4} matrix The matrix on the left-hand side.\r\n * @param {Matrix3} rotation The 3x3 rotation matrix on the right-hand side.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @example\r\n * // Instead of Cesium.Matrix4.multiply(m, Cesium.Matrix4.fromRotationTranslation(rotation), m);\r\n * Cesium.Matrix4.multiplyByMatrix3(m, rotation, m);\r\n */\r\nMatrix4.multiplyByMatrix3 = function (matrix, rotation, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"rotation\", rotation);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var left0 = matrix[0];\r\n var left1 = matrix[1];\r\n var left2 = matrix[2];\r\n var left4 = matrix[4];\r\n var left5 = matrix[5];\r\n var left6 = matrix[6];\r\n var left8 = matrix[8];\r\n var left9 = matrix[9];\r\n var left10 = matrix[10];\r\n\r\n var right0 = rotation[0];\r\n var right1 = rotation[1];\r\n var right2 = rotation[2];\r\n var right4 = rotation[3];\r\n var right5 = rotation[4];\r\n var right6 = rotation[5];\r\n var right8 = rotation[6];\r\n var right9 = rotation[7];\r\n var right10 = rotation[8];\r\n\r\n var column0Row0 = left0 * right0 + left4 * right1 + left8 * right2;\r\n var column0Row1 = left1 * right0 + left5 * right1 + left9 * right2;\r\n var column0Row2 = left2 * right0 + left6 * right1 + left10 * right2;\r\n\r\n var column1Row0 = left0 * right4 + left4 * right5 + left8 * right6;\r\n var column1Row1 = left1 * right4 + left5 * right5 + left9 * right6;\r\n var column1Row2 = left2 * right4 + left6 * right5 + left10 * right6;\r\n\r\n var column2Row0 = left0 * right8 + left4 * right9 + left8 * right10;\r\n var column2Row1 = left1 * right8 + left5 * right9 + left9 * right10;\r\n var column2Row2 = left2 * right8 + left6 * right9 + left10 * right10;\r\n\r\n result[0] = column0Row0;\r\n result[1] = column0Row1;\r\n result[2] = column0Row2;\r\n result[3] = 0.0;\r\n result[4] = column1Row0;\r\n result[5] = column1Row1;\r\n result[6] = column1Row2;\r\n result[7] = 0.0;\r\n result[8] = column2Row0;\r\n result[9] = column2Row1;\r\n result[10] = column2Row2;\r\n result[11] = 0.0;\r\n result[12] = matrix[12];\r\n result[13] = matrix[13];\r\n result[14] = matrix[14];\r\n result[15] = matrix[15];\r\n return result;\r\n};\r\n\r\n/**\r\n * Multiplies a transformation matrix (with a bottom row of [0.0, 0.0, 0.0, 1.0])\r\n * by an implicit translation matrix defined by a {@link Cartesian3}. This is an optimization\r\n * for Matrix4.multiply(m, Matrix4.fromTranslation(position), m); with less allocations and arithmetic operations.\r\n *\r\n * @param {Matrix4} matrix The matrix on the left-hand side.\r\n * @param {Cartesian3} translation The translation on the right-hand side.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @example\r\n * // Instead of Cesium.Matrix4.multiply(m, Cesium.Matrix4.fromTranslation(position), m);\r\n * Cesium.Matrix4.multiplyByTranslation(m, position, m);\r\n */\r\nMatrix4.multiplyByTranslation = function (matrix, translation, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"translation\", translation);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var x = translation.x;\r\n var y = translation.y;\r\n var z = translation.z;\r\n\r\n var tx = x * matrix[0] + y * matrix[4] + z * matrix[8] + matrix[12];\r\n var ty = x * matrix[1] + y * matrix[5] + z * matrix[9] + matrix[13];\r\n var tz = x * matrix[2] + y * matrix[6] + z * matrix[10] + matrix[14];\r\n\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[3];\r\n result[4] = matrix[4];\r\n result[5] = matrix[5];\r\n result[6] = matrix[6];\r\n result[7] = matrix[7];\r\n result[8] = matrix[8];\r\n result[9] = matrix[9];\r\n result[10] = matrix[10];\r\n result[11] = matrix[11];\r\n result[12] = tx;\r\n result[13] = ty;\r\n result[14] = tz;\r\n result[15] = matrix[15];\r\n return result;\r\n};\r\n\r\nvar uniformScaleScratch = new Cartesian3();\r\n\r\n/**\r\n * Multiplies an affine transformation matrix (with a bottom row of [0.0, 0.0, 0.0, 1.0])\r\n * by an implicit uniform scale matrix. This is an optimization\r\n * for Matrix4.multiply(m, Matrix4.fromUniformScale(scale), m);, where\r\n * m must be an affine matrix.\r\n * This function performs fewer allocations and arithmetic operations.\r\n *\r\n * @param {Matrix4} matrix The affine matrix on the left-hand side.\r\n * @param {Number} scale The uniform scale on the right-hand side.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n *\r\n * @example\r\n * // Instead of Cesium.Matrix4.multiply(m, Cesium.Matrix4.fromUniformScale(scale), m);\r\n * Cesium.Matrix4.multiplyByUniformScale(m, scale, m);\r\n *\r\n * @see Matrix4.fromUniformScale\r\n * @see Matrix4.multiplyByScale\r\n */\r\nMatrix4.multiplyByUniformScale = function (matrix, scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.number(\"scale\", scale);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n uniformScaleScratch.x = scale;\r\n uniformScaleScratch.y = scale;\r\n uniformScaleScratch.z = scale;\r\n return Matrix4.multiplyByScale(matrix, uniformScaleScratch, result);\r\n};\r\n\r\n/**\r\n * Multiplies an affine transformation matrix (with a bottom row of [0.0, 0.0, 0.0, 1.0])\r\n * by an implicit non-uniform scale matrix. This is an optimization\r\n * for Matrix4.multiply(m, Matrix4.fromUniformScale(scale), m);, where\r\n * m must be an affine matrix.\r\n * This function performs fewer allocations and arithmetic operations.\r\n *\r\n * @param {Matrix4} matrix The affine matrix on the left-hand side.\r\n * @param {Cartesian3} scale The non-uniform scale on the right-hand side.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n *\r\n * @example\r\n * // Instead of Cesium.Matrix4.multiply(m, Cesium.Matrix4.fromScale(scale), m);\r\n * Cesium.Matrix4.multiplyByScale(m, scale, m);\r\n *\r\n * @see Matrix4.fromScale\r\n * @see Matrix4.multiplyByUniformScale\r\n */\r\nMatrix4.multiplyByScale = function (matrix, scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"scale\", scale);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var scaleX = scale.x;\r\n var scaleY = scale.y;\r\n var scaleZ = scale.z;\r\n\r\n // Faster than Cartesian3.equals\r\n if (scaleX === 1.0 && scaleY === 1.0 && scaleZ === 1.0) {\r\n return Matrix4.clone(matrix, result);\r\n }\r\n\r\n result[0] = scaleX * matrix[0];\r\n result[1] = scaleX * matrix[1];\r\n result[2] = scaleX * matrix[2];\r\n result[3] = 0.0;\r\n result[4] = scaleY * matrix[4];\r\n result[5] = scaleY * matrix[5];\r\n result[6] = scaleY * matrix[6];\r\n result[7] = 0.0;\r\n result[8] = scaleZ * matrix[8];\r\n result[9] = scaleZ * matrix[9];\r\n result[10] = scaleZ * matrix[10];\r\n result[11] = 0.0;\r\n result[12] = matrix[12];\r\n result[13] = matrix[13];\r\n result[14] = matrix[14];\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix and a column vector.\r\n *\r\n * @param {Matrix4} matrix The matrix.\r\n * @param {Cartesian4} cartesian The vector.\r\n * @param {Cartesian4} result The object onto which to store the result.\r\n * @returns {Cartesian4} The modified result parameter.\r\n */\r\nMatrix4.multiplyByVector = function (matrix, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var vX = cartesian.x;\r\n var vY = cartesian.y;\r\n var vZ = cartesian.z;\r\n var vW = cartesian.w;\r\n\r\n var x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ + matrix[12] * vW;\r\n var y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ + matrix[13] * vW;\r\n var z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ + matrix[14] * vW;\r\n var w = matrix[3] * vX + matrix[7] * vY + matrix[11] * vZ + matrix[15] * vW;\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n result.w = w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix and a {@link Cartesian3}. This is equivalent to calling {@link Matrix4.multiplyByVector}\r\n * with a {@link Cartesian4} with a w component of zero.\r\n *\r\n * @param {Matrix4} matrix The matrix.\r\n * @param {Cartesian3} cartesian The point.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n *\r\n * @example\r\n * var p = new Cesium.Cartesian3(1.0, 2.0, 3.0);\r\n * var result = Cesium.Matrix4.multiplyByPointAsVector(matrix, p, new Cesium.Cartesian3());\r\n * // A shortcut for\r\n * // Cartesian3 p = ...\r\n * // Cesium.Matrix4.multiplyByVector(matrix, new Cesium.Cartesian4(p.x, p.y, p.z, 0.0), result);\r\n */\r\nMatrix4.multiplyByPointAsVector = function (matrix, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var vX = cartesian.x;\r\n var vY = cartesian.y;\r\n var vZ = cartesian.z;\r\n\r\n var x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ;\r\n var y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ;\r\n var z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ;\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix and a {@link Cartesian3}. This is equivalent to calling {@link Matrix4.multiplyByVector}\r\n * with a {@link Cartesian4} with a w component of 1, but returns a {@link Cartesian3} instead of a {@link Cartesian4}.\r\n *\r\n * @param {Matrix4} matrix The matrix.\r\n * @param {Cartesian3} cartesian The point.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n *\r\n * @example\r\n * var p = new Cesium.Cartesian3(1.0, 2.0, 3.0);\r\n * var result = Cesium.Matrix4.multiplyByPoint(matrix, p, new Cesium.Cartesian3());\r\n */\r\nMatrix4.multiplyByPoint = function (matrix, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var vX = cartesian.x;\r\n var vY = cartesian.y;\r\n var vZ = cartesian.z;\r\n\r\n var x = matrix[0] * vX + matrix[4] * vY + matrix[8] * vZ + matrix[12];\r\n var y = matrix[1] * vX + matrix[5] * vY + matrix[9] * vZ + matrix[13];\r\n var z = matrix[2] * vX + matrix[6] * vY + matrix[10] * vZ + matrix[14];\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix and a scalar.\r\n *\r\n * @param {Matrix4} matrix The matrix.\r\n * @param {Number} scalar The number to multiply by.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @example\r\n * //create a Matrix4 instance which is a scaled version of the supplied Matrix4\r\n * // m = [10.0, 11.0, 12.0, 13.0]\r\n * // [14.0, 15.0, 16.0, 17.0]\r\n * // [18.0, 19.0, 20.0, 21.0]\r\n * // [22.0, 23.0, 24.0, 25.0]\r\n *\r\n * var a = Cesium.Matrix4.multiplyByScalar(m, -2, new Cesium.Matrix4());\r\n *\r\n * // m remains the same\r\n * // a = [-20.0, -22.0, -24.0, -26.0]\r\n * // [-28.0, -30.0, -32.0, -34.0]\r\n * // [-36.0, -38.0, -40.0, -42.0]\r\n * // [-44.0, -46.0, -48.0, -50.0]\r\n */\r\nMatrix4.multiplyByScalar = function (matrix, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = matrix[0] * scalar;\r\n result[1] = matrix[1] * scalar;\r\n result[2] = matrix[2] * scalar;\r\n result[3] = matrix[3] * scalar;\r\n result[4] = matrix[4] * scalar;\r\n result[5] = matrix[5] * scalar;\r\n result[6] = matrix[6] * scalar;\r\n result[7] = matrix[7] * scalar;\r\n result[8] = matrix[8] * scalar;\r\n result[9] = matrix[9] * scalar;\r\n result[10] = matrix[10] * scalar;\r\n result[11] = matrix[11] * scalar;\r\n result[12] = matrix[12] * scalar;\r\n result[13] = matrix[13] * scalar;\r\n result[14] = matrix[14] * scalar;\r\n result[15] = matrix[15] * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a negated copy of the provided matrix.\r\n *\r\n * @param {Matrix4} matrix The matrix to negate.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @example\r\n * //create a new Matrix4 instance which is a negation of a Matrix4\r\n * // m = [10.0, 11.0, 12.0, 13.0]\r\n * // [14.0, 15.0, 16.0, 17.0]\r\n * // [18.0, 19.0, 20.0, 21.0]\r\n * // [22.0, 23.0, 24.0, 25.0]\r\n *\r\n * var a = Cesium.Matrix4.negate(m, new Cesium.Matrix4());\r\n *\r\n * // m remains the same\r\n * // a = [-10.0, -11.0, -12.0, -13.0]\r\n * // [-14.0, -15.0, -16.0, -17.0]\r\n * // [-18.0, -19.0, -20.0, -21.0]\r\n * // [-22.0, -23.0, -24.0, -25.0]\r\n */\r\nMatrix4.negate = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = -matrix[0];\r\n result[1] = -matrix[1];\r\n result[2] = -matrix[2];\r\n result[3] = -matrix[3];\r\n result[4] = -matrix[4];\r\n result[5] = -matrix[5];\r\n result[6] = -matrix[6];\r\n result[7] = -matrix[7];\r\n result[8] = -matrix[8];\r\n result[9] = -matrix[9];\r\n result[10] = -matrix[10];\r\n result[11] = -matrix[11];\r\n result[12] = -matrix[12];\r\n result[13] = -matrix[13];\r\n result[14] = -matrix[14];\r\n result[15] = -matrix[15];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the transpose of the provided matrix.\r\n *\r\n * @param {Matrix4} matrix The matrix to transpose.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @example\r\n * //returns transpose of a Matrix4\r\n * // m = [10.0, 11.0, 12.0, 13.0]\r\n * // [14.0, 15.0, 16.0, 17.0]\r\n * // [18.0, 19.0, 20.0, 21.0]\r\n * // [22.0, 23.0, 24.0, 25.0]\r\n *\r\n * var a = Cesium.Matrix4.transpose(m, new Cesium.Matrix4());\r\n *\r\n * // m remains the same\r\n * // a = [10.0, 14.0, 18.0, 22.0]\r\n * // [11.0, 15.0, 19.0, 23.0]\r\n * // [12.0, 16.0, 20.0, 24.0]\r\n * // [13.0, 17.0, 21.0, 25.0]\r\n */\r\nMatrix4.transpose = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var matrix1 = matrix[1];\r\n var matrix2 = matrix[2];\r\n var matrix3 = matrix[3];\r\n var matrix6 = matrix[6];\r\n var matrix7 = matrix[7];\r\n var matrix11 = matrix[11];\r\n\r\n result[0] = matrix[0];\r\n result[1] = matrix[4];\r\n result[2] = matrix[8];\r\n result[3] = matrix[12];\r\n result[4] = matrix1;\r\n result[5] = matrix[5];\r\n result[6] = matrix[9];\r\n result[7] = matrix[13];\r\n result[8] = matrix2;\r\n result[9] = matrix6;\r\n result[10] = matrix[10];\r\n result[11] = matrix[14];\r\n result[12] = matrix3;\r\n result[13] = matrix7;\r\n result[14] = matrix11;\r\n result[15] = matrix[15];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a matrix, which contains the absolute (unsigned) values of the provided matrix's elements.\r\n *\r\n * @param {Matrix4} matrix The matrix with signed elements.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.abs = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = Math.abs(matrix[0]);\r\n result[1] = Math.abs(matrix[1]);\r\n result[2] = Math.abs(matrix[2]);\r\n result[3] = Math.abs(matrix[3]);\r\n result[4] = Math.abs(matrix[4]);\r\n result[5] = Math.abs(matrix[5]);\r\n result[6] = Math.abs(matrix[6]);\r\n result[7] = Math.abs(matrix[7]);\r\n result[8] = Math.abs(matrix[8]);\r\n result[9] = Math.abs(matrix[9]);\r\n result[10] = Math.abs(matrix[10]);\r\n result[11] = Math.abs(matrix[11]);\r\n result[12] = Math.abs(matrix[12]);\r\n result[13] = Math.abs(matrix[13]);\r\n result[14] = Math.abs(matrix[14]);\r\n result[15] = Math.abs(matrix[15]);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided matrices componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Matrix4} [left] The first matrix.\r\n * @param {Matrix4} [right] The second matrix.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n *\r\n * @example\r\n * //compares two Matrix4 instances\r\n *\r\n * // a = [10.0, 14.0, 18.0, 22.0]\r\n * // [11.0, 15.0, 19.0, 23.0]\r\n * // [12.0, 16.0, 20.0, 24.0]\r\n * // [13.0, 17.0, 21.0, 25.0]\r\n *\r\n * // b = [10.0, 14.0, 18.0, 22.0]\r\n * // [11.0, 15.0, 19.0, 23.0]\r\n * // [12.0, 16.0, 20.0, 24.0]\r\n * // [13.0, 17.0, 21.0, 25.0]\r\n *\r\n * if(Cesium.Matrix4.equals(a,b)) {\r\n * console.log(\"Both matrices are equal\");\r\n * } else {\r\n * console.log(\"They are not equal\");\r\n * }\r\n *\r\n * //Prints \"Both matrices are equal\" on the console\r\n */\r\nMatrix4.equals = function (left, right) {\r\n // Given that most matrices will be transformation matrices, the elements\r\n // are tested in order such that the test is likely to fail as early\r\n // as possible. I _think_ this is just as friendly to the L1 cache\r\n // as testing in index order. It is certainty faster in practice.\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n // Translation\r\n left[12] === right[12] &&\r\n left[13] === right[13] &&\r\n left[14] === right[14] &&\r\n // Rotation/scale\r\n left[0] === right[0] &&\r\n left[1] === right[1] &&\r\n left[2] === right[2] &&\r\n left[4] === right[4] &&\r\n left[5] === right[5] &&\r\n left[6] === right[6] &&\r\n left[8] === right[8] &&\r\n left[9] === right[9] &&\r\n left[10] === right[10] &&\r\n // Bottom row\r\n left[3] === right[3] &&\r\n left[7] === right[7] &&\r\n left[11] === right[11] &&\r\n left[15] === right[15])\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided matrices componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Matrix4} [left] The first matrix.\r\n * @param {Matrix4} [right] The second matrix.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n *\r\n * @example\r\n * //compares two Matrix4 instances\r\n *\r\n * // a = [10.5, 14.5, 18.5, 22.5]\r\n * // [11.5, 15.5, 19.5, 23.5]\r\n * // [12.5, 16.5, 20.5, 24.5]\r\n * // [13.5, 17.5, 21.5, 25.5]\r\n *\r\n * // b = [10.0, 14.0, 18.0, 22.0]\r\n * // [11.0, 15.0, 19.0, 23.0]\r\n * // [12.0, 16.0, 20.0, 24.0]\r\n * // [13.0, 17.0, 21.0, 25.0]\r\n *\r\n * if(Cesium.Matrix4.equalsEpsilon(a,b,0.1)){\r\n * console.log(\"Difference between both the matrices is less than 0.1\");\r\n * } else {\r\n * console.log(\"Difference between both the matrices is not less than 0.1\");\r\n * }\r\n *\r\n * //Prints \"Difference between both the matrices is not less than 0.1\" on the console\r\n */\r\nMatrix4.equalsEpsilon = function (left, right, epsilon) {\r\n epsilon = defaultValue(epsilon, 0);\r\n\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Math.abs(left[0] - right[0]) <= epsilon &&\r\n Math.abs(left[1] - right[1]) <= epsilon &&\r\n Math.abs(left[2] - right[2]) <= epsilon &&\r\n Math.abs(left[3] - right[3]) <= epsilon &&\r\n Math.abs(left[4] - right[4]) <= epsilon &&\r\n Math.abs(left[5] - right[5]) <= epsilon &&\r\n Math.abs(left[6] - right[6]) <= epsilon &&\r\n Math.abs(left[7] - right[7]) <= epsilon &&\r\n Math.abs(left[8] - right[8]) <= epsilon &&\r\n Math.abs(left[9] - right[9]) <= epsilon &&\r\n Math.abs(left[10] - right[10]) <= epsilon &&\r\n Math.abs(left[11] - right[11]) <= epsilon &&\r\n Math.abs(left[12] - right[12]) <= epsilon &&\r\n Math.abs(left[13] - right[13]) <= epsilon &&\r\n Math.abs(left[14] - right[14]) <= epsilon &&\r\n Math.abs(left[15] - right[15]) <= epsilon)\r\n );\r\n};\r\n\r\n/**\r\n * Gets the translation portion of the provided matrix, assuming the matrix is a affine transformation matrix.\r\n *\r\n * @param {Matrix4} matrix The matrix to use.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nMatrix4.getTranslation = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = matrix[12];\r\n result.y = matrix[13];\r\n result.z = matrix[14];\r\n return result;\r\n};\r\n\r\n/**\r\n * Gets the upper left 3x3 rotation matrix of the provided matrix, assuming the matrix is an affine transformation matrix.\r\n *\r\n * @param {Matrix4} matrix The matrix to use.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter.\r\n *\r\n * @example\r\n * // returns a Matrix3 instance from a Matrix4 instance\r\n *\r\n * // m = [10.0, 14.0, 18.0, 22.0]\r\n * // [11.0, 15.0, 19.0, 23.0]\r\n * // [12.0, 16.0, 20.0, 24.0]\r\n * // [13.0, 17.0, 21.0, 25.0]\r\n *\r\n * var b = new Cesium.Matrix3();\r\n * Cesium.Matrix4.getMatrix3(m,b);\r\n *\r\n * // b = [10.0, 14.0, 18.0]\r\n * // [11.0, 15.0, 19.0]\r\n * // [12.0, 16.0, 20.0]\r\n */\r\nMatrix4.getMatrix3 = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[4];\r\n result[4] = matrix[5];\r\n result[5] = matrix[6];\r\n result[6] = matrix[8];\r\n result[7] = matrix[9];\r\n result[8] = matrix[10];\r\n return result;\r\n};\r\n\r\nvar scratchInverseRotation = new Matrix3();\r\nvar scratchMatrix3Zero = new Matrix3();\r\nvar scratchBottomRow = new Cartesian4();\r\nvar scratchExpectedBottomRow = new Cartesian4(0.0, 0.0, 0.0, 1.0);\r\n\r\n/**\r\n * Computes the inverse of the provided matrix using Cramers Rule.\r\n * If the determinant is zero, the matrix can not be inverted, and an exception is thrown.\r\n * If the matrix is an affine transformation matrix, it is more efficient\r\n * to invert it with {@link Matrix4.inverseTransformation}.\r\n *\r\n * @param {Matrix4} matrix The matrix to invert.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n *\r\n * @exception {RuntimeError} matrix is not invertible because its determinate is zero.\r\n */\r\nMatrix4.inverse = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n //\r\n // Ported from:\r\n // ftp://download.intel.com/design/PentiumIII/sml/24504301.pdf\r\n //\r\n var src0 = matrix[0];\r\n var src1 = matrix[4];\r\n var src2 = matrix[8];\r\n var src3 = matrix[12];\r\n var src4 = matrix[1];\r\n var src5 = matrix[5];\r\n var src6 = matrix[9];\r\n var src7 = matrix[13];\r\n var src8 = matrix[2];\r\n var src9 = matrix[6];\r\n var src10 = matrix[10];\r\n var src11 = matrix[14];\r\n var src12 = matrix[3];\r\n var src13 = matrix[7];\r\n var src14 = matrix[11];\r\n var src15 = matrix[15];\r\n\r\n // calculate pairs for first 8 elements (cofactors)\r\n var tmp0 = src10 * src15;\r\n var tmp1 = src11 * src14;\r\n var tmp2 = src9 * src15;\r\n var tmp3 = src11 * src13;\r\n var tmp4 = src9 * src14;\r\n var tmp5 = src10 * src13;\r\n var tmp6 = src8 * src15;\r\n var tmp7 = src11 * src12;\r\n var tmp8 = src8 * src14;\r\n var tmp9 = src10 * src12;\r\n var tmp10 = src8 * src13;\r\n var tmp11 = src9 * src12;\r\n\r\n // calculate first 8 elements (cofactors)\r\n var dst0 =\r\n tmp0 * src5 +\r\n tmp3 * src6 +\r\n tmp4 * src7 -\r\n (tmp1 * src5 + tmp2 * src6 + tmp5 * src7);\r\n var dst1 =\r\n tmp1 * src4 +\r\n tmp6 * src6 +\r\n tmp9 * src7 -\r\n (tmp0 * src4 + tmp7 * src6 + tmp8 * src7);\r\n var dst2 =\r\n tmp2 * src4 +\r\n tmp7 * src5 +\r\n tmp10 * src7 -\r\n (tmp3 * src4 + tmp6 * src5 + tmp11 * src7);\r\n var dst3 =\r\n tmp5 * src4 +\r\n tmp8 * src5 +\r\n tmp11 * src6 -\r\n (tmp4 * src4 + tmp9 * src5 + tmp10 * src6);\r\n var dst4 =\r\n tmp1 * src1 +\r\n tmp2 * src2 +\r\n tmp5 * src3 -\r\n (tmp0 * src1 + tmp3 * src2 + tmp4 * src3);\r\n var dst5 =\r\n tmp0 * src0 +\r\n tmp7 * src2 +\r\n tmp8 * src3 -\r\n (tmp1 * src0 + tmp6 * src2 + tmp9 * src3);\r\n var dst6 =\r\n tmp3 * src0 +\r\n tmp6 * src1 +\r\n tmp11 * src3 -\r\n (tmp2 * src0 + tmp7 * src1 + tmp10 * src3);\r\n var dst7 =\r\n tmp4 * src0 +\r\n tmp9 * src1 +\r\n tmp10 * src2 -\r\n (tmp5 * src0 + tmp8 * src1 + tmp11 * src2);\r\n\r\n // calculate pairs for second 8 elements (cofactors)\r\n tmp0 = src2 * src7;\r\n tmp1 = src3 * src6;\r\n tmp2 = src1 * src7;\r\n tmp3 = src3 * src5;\r\n tmp4 = src1 * src6;\r\n tmp5 = src2 * src5;\r\n tmp6 = src0 * src7;\r\n tmp7 = src3 * src4;\r\n tmp8 = src0 * src6;\r\n tmp9 = src2 * src4;\r\n tmp10 = src0 * src5;\r\n tmp11 = src1 * src4;\r\n\r\n // calculate second 8 elements (cofactors)\r\n var dst8 =\r\n tmp0 * src13 +\r\n tmp3 * src14 +\r\n tmp4 * src15 -\r\n (tmp1 * src13 + tmp2 * src14 + tmp5 * src15);\r\n var dst9 =\r\n tmp1 * src12 +\r\n tmp6 * src14 +\r\n tmp9 * src15 -\r\n (tmp0 * src12 + tmp7 * src14 + tmp8 * src15);\r\n var dst10 =\r\n tmp2 * src12 +\r\n tmp7 * src13 +\r\n tmp10 * src15 -\r\n (tmp3 * src12 + tmp6 * src13 + tmp11 * src15);\r\n var dst11 =\r\n tmp5 * src12 +\r\n tmp8 * src13 +\r\n tmp11 * src14 -\r\n (tmp4 * src12 + tmp9 * src13 + tmp10 * src14);\r\n var dst12 =\r\n tmp2 * src10 +\r\n tmp5 * src11 +\r\n tmp1 * src9 -\r\n (tmp4 * src11 + tmp0 * src9 + tmp3 * src10);\r\n var dst13 =\r\n tmp8 * src11 +\r\n tmp0 * src8 +\r\n tmp7 * src10 -\r\n (tmp6 * src10 + tmp9 * src11 + tmp1 * src8);\r\n var dst14 =\r\n tmp6 * src9 +\r\n tmp11 * src11 +\r\n tmp3 * src8 -\r\n (tmp10 * src11 + tmp2 * src8 + tmp7 * src9);\r\n var dst15 =\r\n tmp10 * src10 +\r\n tmp4 * src8 +\r\n tmp9 * src9 -\r\n (tmp8 * src9 + tmp11 * src10 + tmp5 * src8);\r\n\r\n // calculate determinant\r\n var det = src0 * dst0 + src1 * dst1 + src2 * dst2 + src3 * dst3;\r\n\r\n if (Math.abs(det) < CesiumMath.EPSILON21) {\r\n // Special case for a zero scale matrix that can occur, for example,\r\n // when a model's node has a [0, 0, 0] scale.\r\n if (\r\n Matrix3.equalsEpsilon(\r\n Matrix4.getMatrix3(matrix, scratchInverseRotation),\r\n scratchMatrix3Zero,\r\n CesiumMath.EPSILON7\r\n ) &&\r\n Cartesian4.equals(\r\n Matrix4.getRow(matrix, 3, scratchBottomRow),\r\n scratchExpectedBottomRow\r\n )\r\n ) {\r\n result[0] = 0.0;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = 0.0;\r\n result[4] = 0.0;\r\n result[5] = 0.0;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = 0.0;\r\n result[9] = 0.0;\r\n result[10] = 0.0;\r\n result[11] = 0.0;\r\n result[12] = -matrix[12];\r\n result[13] = -matrix[13];\r\n result[14] = -matrix[14];\r\n result[15] = 1.0;\r\n return result;\r\n }\r\n\r\n throw new RuntimeError(\r\n \"matrix is not invertible because its determinate is zero.\"\r\n );\r\n }\r\n\r\n // calculate matrix inverse\r\n det = 1.0 / det;\r\n\r\n result[0] = dst0 * det;\r\n result[1] = dst1 * det;\r\n result[2] = dst2 * det;\r\n result[3] = dst3 * det;\r\n result[4] = dst4 * det;\r\n result[5] = dst5 * det;\r\n result[6] = dst6 * det;\r\n result[7] = dst7 * det;\r\n result[8] = dst8 * det;\r\n result[9] = dst9 * det;\r\n result[10] = dst10 * det;\r\n result[11] = dst11 * det;\r\n result[12] = dst12 * det;\r\n result[13] = dst13 * det;\r\n result[14] = dst14 * det;\r\n result[15] = dst15 * det;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the inverse of the provided matrix assuming it is\r\n * an affine transformation matrix, where the upper left 3x3 elements\r\n * are a rotation matrix, and the upper three elements in the fourth\r\n * column are the translation. The bottom row is assumed to be [0, 0, 0, 1].\r\n * The matrix is not verified to be in the proper form.\r\n * This method is faster than computing the inverse for a general 4x4\r\n * matrix using {@link Matrix4.inverse}.\r\n *\r\n * @param {Matrix4} matrix The matrix to invert.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.inverseTransformation = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n //This function is an optimized version of the below 4 lines.\r\n //var rT = Matrix3.transpose(Matrix4.getMatrix3(matrix));\r\n //var rTN = Matrix3.negate(rT);\r\n //var rTT = Matrix3.multiplyByVector(rTN, Matrix4.getTranslation(matrix));\r\n //return Matrix4.fromRotationTranslation(rT, rTT, result);\r\n\r\n var matrix0 = matrix[0];\r\n var matrix1 = matrix[1];\r\n var matrix2 = matrix[2];\r\n var matrix4 = matrix[4];\r\n var matrix5 = matrix[5];\r\n var matrix6 = matrix[6];\r\n var matrix8 = matrix[8];\r\n var matrix9 = matrix[9];\r\n var matrix10 = matrix[10];\r\n\r\n var vX = matrix[12];\r\n var vY = matrix[13];\r\n var vZ = matrix[14];\r\n\r\n var x = -matrix0 * vX - matrix1 * vY - matrix2 * vZ;\r\n var y = -matrix4 * vX - matrix5 * vY - matrix6 * vZ;\r\n var z = -matrix8 * vX - matrix9 * vY - matrix10 * vZ;\r\n\r\n result[0] = matrix0;\r\n result[1] = matrix4;\r\n result[2] = matrix8;\r\n result[3] = 0.0;\r\n result[4] = matrix1;\r\n result[5] = matrix5;\r\n result[6] = matrix9;\r\n result[7] = 0.0;\r\n result[8] = matrix2;\r\n result[9] = matrix6;\r\n result[10] = matrix10;\r\n result[11] = 0.0;\r\n result[12] = x;\r\n result[13] = y;\r\n result[14] = z;\r\n result[15] = 1.0;\r\n return result;\r\n};\r\n\r\nvar scratchTransposeMatrix = new Matrix4();\r\n\r\n/**\r\n * Computes the inverse transpose of a matrix.\r\n *\r\n * @param {Matrix4} matrix The matrix to transpose and invert.\r\n * @param {Matrix4} result The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter.\r\n */\r\nMatrix4.inverseTranspose = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n return Matrix4.inverse(\r\n Matrix4.transpose(matrix, scratchTransposeMatrix),\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * An immutable Matrix4 instance initialized to the identity matrix.\r\n *\r\n * @type {Matrix4}\r\n * @constant\r\n */\r\nMatrix4.IDENTITY = Object.freeze(\r\n new Matrix4(\r\n 1.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n )\r\n);\r\n\r\n/**\r\n * An immutable Matrix4 instance initialized to the zero matrix.\r\n *\r\n * @type {Matrix4}\r\n * @constant\r\n */\r\nMatrix4.ZERO = Object.freeze(\r\n new Matrix4(\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0\r\n )\r\n);\r\n\r\n/**\r\n * The index into Matrix4 for column 0, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN0ROW0 = 0;\r\n\r\n/**\r\n * The index into Matrix4 for column 0, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN0ROW1 = 1;\r\n\r\n/**\r\n * The index into Matrix4 for column 0, row 2.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN0ROW2 = 2;\r\n\r\n/**\r\n * The index into Matrix4 for column 0, row 3.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN0ROW3 = 3;\r\n\r\n/**\r\n * The index into Matrix4 for column 1, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN1ROW0 = 4;\r\n\r\n/**\r\n * The index into Matrix4 for column 1, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN1ROW1 = 5;\r\n\r\n/**\r\n * The index into Matrix4 for column 1, row 2.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN1ROW2 = 6;\r\n\r\n/**\r\n * The index into Matrix4 for column 1, row 3.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN1ROW3 = 7;\r\n\r\n/**\r\n * The index into Matrix4 for column 2, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN2ROW0 = 8;\r\n\r\n/**\r\n * The index into Matrix4 for column 2, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN2ROW1 = 9;\r\n\r\n/**\r\n * The index into Matrix4 for column 2, row 2.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN2ROW2 = 10;\r\n\r\n/**\r\n * The index into Matrix4 for column 2, row 3.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN2ROW3 = 11;\r\n\r\n/**\r\n * The index into Matrix4 for column 3, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN3ROW0 = 12;\r\n\r\n/**\r\n * The index into Matrix4 for column 3, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN3ROW1 = 13;\r\n\r\n/**\r\n * The index into Matrix4 for column 3, row 2.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN3ROW2 = 14;\r\n\r\n/**\r\n * The index into Matrix4 for column 3, row 3.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\nMatrix4.COLUMN3ROW3 = 15;\r\n\r\nObject.defineProperties(Matrix4.prototype, {\r\n /**\r\n * Gets the number of items in the collection.\r\n * @memberof Matrix4.prototype\r\n *\r\n * @type {Number}\r\n */\r\n length: {\r\n get: function () {\r\n return Matrix4.packedLength;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Duplicates the provided Matrix4 instance.\r\n *\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided.\r\n */\r\nMatrix4.prototype.clone = function (result) {\r\n return Matrix4.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this matrix to the provided matrix componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Matrix4} [right] The right hand side matrix.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nMatrix4.prototype.equals = function (right) {\r\n return Matrix4.equals(this, right);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nMatrix4.equalsArray = function (matrix, array, offset) {\r\n return (\r\n matrix[0] === array[offset] &&\r\n matrix[1] === array[offset + 1] &&\r\n matrix[2] === array[offset + 2] &&\r\n matrix[3] === array[offset + 3] &&\r\n matrix[4] === array[offset + 4] &&\r\n matrix[5] === array[offset + 5] &&\r\n matrix[6] === array[offset + 6] &&\r\n matrix[7] === array[offset + 7] &&\r\n matrix[8] === array[offset + 8] &&\r\n matrix[9] === array[offset + 9] &&\r\n matrix[10] === array[offset + 10] &&\r\n matrix[11] === array[offset + 11] &&\r\n matrix[12] === array[offset + 12] &&\r\n matrix[13] === array[offset + 13] &&\r\n matrix[14] === array[offset + 14] &&\r\n matrix[15] === array[offset + 15]\r\n );\r\n};\r\n\r\n/**\r\n * Compares this matrix to the provided matrix componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Matrix4} [right] The right hand side matrix.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if they are within the provided epsilon, false otherwise.\r\n */\r\nMatrix4.prototype.equalsEpsilon = function (right, epsilon) {\r\n return Matrix4.equalsEpsilon(this, right, epsilon);\r\n};\r\n\r\n/**\r\n * Computes a string representing this Matrix with each row being\r\n * on a separate line and in the format '(column0, column1, column2, column3)'.\r\n *\r\n * @returns {String} A string representing the provided Matrix with each row being on a separate line and in the format '(column0, column1, column2, column3)'.\r\n */\r\nMatrix4.prototype.toString = function () {\r\n return (\r\n \"(\" +\r\n this[0] +\r\n \", \" +\r\n this[4] +\r\n \", \" +\r\n this[8] +\r\n \", \" +\r\n this[12] +\r\n \")\\n\" +\r\n \"(\" +\r\n this[1] +\r\n \", \" +\r\n this[5] +\r\n \", \" +\r\n this[9] +\r\n \", \" +\r\n this[13] +\r\n \")\\n\" +\r\n \"(\" +\r\n this[2] +\r\n \", \" +\r\n this[6] +\r\n \", \" +\r\n this[10] +\r\n \", \" +\r\n this[14] +\r\n \")\\n\" +\r\n \"(\" +\r\n this[3] +\r\n \", \" +\r\n this[7] +\r\n \", \" +\r\n this[11] +\r\n \", \" +\r\n this[15] +\r\n \")\"\r\n );\r\n};\r\nexport default Matrix4;\r\n","import Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * A two dimensional region specified as longitude and latitude coordinates.\r\n *\r\n * @alias Rectangle\r\n * @constructor\r\n *\r\n * @param {Number} [west=0.0] The westernmost longitude, in radians, in the range [-Pi, Pi].\r\n * @param {Number} [south=0.0] The southernmost latitude, in radians, in the range [-Pi/2, Pi/2].\r\n * @param {Number} [east=0.0] The easternmost longitude, in radians, in the range [-Pi, Pi].\r\n * @param {Number} [north=0.0] The northernmost latitude, in radians, in the range [-Pi/2, Pi/2].\r\n *\r\n * @see Packable\r\n */\r\nfunction Rectangle(west, south, east, north) {\r\n /**\r\n * The westernmost longitude in radians in the range [-Pi, Pi].\r\n *\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.west = defaultValue(west, 0.0);\r\n\r\n /**\r\n * The southernmost latitude in radians in the range [-Pi/2, Pi/2].\r\n *\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.south = defaultValue(south, 0.0);\r\n\r\n /**\r\n * The easternmost longitude in radians in the range [-Pi, Pi].\r\n *\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.east = defaultValue(east, 0.0);\r\n\r\n /**\r\n * The northernmost latitude in radians in the range [-Pi/2, Pi/2].\r\n *\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.north = defaultValue(north, 0.0);\r\n}\r\n\r\nObject.defineProperties(Rectangle.prototype, {\r\n /**\r\n * Gets the width of the rectangle in radians.\r\n * @memberof Rectangle.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n width: {\r\n get: function () {\r\n return Rectangle.computeWidth(this);\r\n },\r\n },\r\n\r\n /**\r\n * Gets the height of the rectangle in radians.\r\n * @memberof Rectangle.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n height: {\r\n get: function () {\r\n return Rectangle.computeHeight(this);\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nRectangle.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Rectangle} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nRectangle.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.west;\r\n array[startingIndex++] = value.south;\r\n array[startingIndex++] = value.east;\r\n array[startingIndex] = value.north;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Rectangle} [result] The object into which to store the result.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if one was not provided.\r\n */\r\nRectangle.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Rectangle();\r\n }\r\n\r\n result.west = array[startingIndex++];\r\n result.south = array[startingIndex++];\r\n result.east = array[startingIndex++];\r\n result.north = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the width of a rectangle in radians.\r\n * @param {Rectangle} rectangle The rectangle to compute the width of.\r\n * @returns {Number} The width.\r\n */\r\nRectangle.computeWidth = function (rectangle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n var east = rectangle.east;\r\n var west = rectangle.west;\r\n if (east < west) {\r\n east += CesiumMath.TWO_PI;\r\n }\r\n return east - west;\r\n};\r\n\r\n/**\r\n * Computes the height of a rectangle in radians.\r\n * @param {Rectangle} rectangle The rectangle to compute the height of.\r\n * @returns {Number} The height.\r\n */\r\nRectangle.computeHeight = function (rectangle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n return rectangle.north - rectangle.south;\r\n};\r\n\r\n/**\r\n * Creates a rectangle given the boundary longitude and latitude in degrees.\r\n *\r\n * @param {Number} [west=0.0] The westernmost longitude in degrees in the range [-180.0, 180.0].\r\n * @param {Number} [south=0.0] The southernmost latitude in degrees in the range [-90.0, 90.0].\r\n * @param {Number} [east=0.0] The easternmost longitude in degrees in the range [-180.0, 180.0].\r\n * @param {Number} [north=0.0] The northernmost latitude in degrees in the range [-90.0, 90.0].\r\n * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.\r\n *\r\n * @example\r\n * var rectangle = Cesium.Rectangle.fromDegrees(0.0, 20.0, 10.0, 30.0);\r\n */\r\nRectangle.fromDegrees = function (west, south, east, north, result) {\r\n west = CesiumMath.toRadians(defaultValue(west, 0.0));\r\n south = CesiumMath.toRadians(defaultValue(south, 0.0));\r\n east = CesiumMath.toRadians(defaultValue(east, 0.0));\r\n north = CesiumMath.toRadians(defaultValue(north, 0.0));\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(west, south, east, north);\r\n }\r\n\r\n result.west = west;\r\n result.south = south;\r\n result.east = east;\r\n result.north = north;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a rectangle given the boundary longitude and latitude in radians.\r\n *\r\n * @param {Number} [west=0.0] The westernmost longitude in radians in the range [-Math.PI, Math.PI].\r\n * @param {Number} [south=0.0] The southernmost latitude in radians in the range [-Math.PI/2, Math.PI/2].\r\n * @param {Number} [east=0.0] The easternmost longitude in radians in the range [-Math.PI, Math.PI].\r\n * @param {Number} [north=0.0] The northernmost latitude in radians in the range [-Math.PI/2, Math.PI/2].\r\n * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.\r\n *\r\n * @example\r\n * var rectangle = Cesium.Rectangle.fromRadians(0.0, Math.PI/4, Math.PI/8, 3*Math.PI/4);\r\n */\r\nRectangle.fromRadians = function (west, south, east, north, result) {\r\n if (!defined(result)) {\r\n return new Rectangle(west, south, east, north);\r\n }\r\n\r\n result.west = defaultValue(west, 0.0);\r\n result.south = defaultValue(south, 0.0);\r\n result.east = defaultValue(east, 0.0);\r\n result.north = defaultValue(north, 0.0);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates the smallest possible Rectangle that encloses all positions in the provided array.\r\n *\r\n * @param {Cartographic[]} cartographics The list of Cartographic instances.\r\n * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.\r\n */\r\nRectangle.fromCartographicArray = function (cartographics, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartographics\", cartographics);\r\n //>>includeEnd('debug');\r\n\r\n var west = Number.MAX_VALUE;\r\n var east = -Number.MAX_VALUE;\r\n var westOverIDL = Number.MAX_VALUE;\r\n var eastOverIDL = -Number.MAX_VALUE;\r\n var south = Number.MAX_VALUE;\r\n var north = -Number.MAX_VALUE;\r\n\r\n for (var i = 0, len = cartographics.length; i < len; i++) {\r\n var position = cartographics[i];\r\n west = Math.min(west, position.longitude);\r\n east = Math.max(east, position.longitude);\r\n south = Math.min(south, position.latitude);\r\n north = Math.max(north, position.latitude);\r\n\r\n var lonAdjusted =\r\n position.longitude >= 0\r\n ? position.longitude\r\n : position.longitude + CesiumMath.TWO_PI;\r\n westOverIDL = Math.min(westOverIDL, lonAdjusted);\r\n eastOverIDL = Math.max(eastOverIDL, lonAdjusted);\r\n }\r\n\r\n if (east - west > eastOverIDL - westOverIDL) {\r\n west = westOverIDL;\r\n east = eastOverIDL;\r\n\r\n if (east > CesiumMath.PI) {\r\n east = east - CesiumMath.TWO_PI;\r\n }\r\n if (west > CesiumMath.PI) {\r\n west = west - CesiumMath.TWO_PI;\r\n }\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(west, south, east, north);\r\n }\r\n\r\n result.west = west;\r\n result.south = south;\r\n result.east = east;\r\n result.north = north;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates the smallest possible Rectangle that encloses all positions in the provided array.\r\n *\r\n * @param {Cartesian3[]} cartesians The list of Cartesian instances.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid the cartesians are on.\r\n * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.\r\n */\r\nRectangle.fromCartesianArray = function (cartesians, ellipsoid, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesians\", cartesians);\r\n //>>includeEnd('debug');\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n\r\n var west = Number.MAX_VALUE;\r\n var east = -Number.MAX_VALUE;\r\n var westOverIDL = Number.MAX_VALUE;\r\n var eastOverIDL = -Number.MAX_VALUE;\r\n var south = Number.MAX_VALUE;\r\n var north = -Number.MAX_VALUE;\r\n\r\n for (var i = 0, len = cartesians.length; i < len; i++) {\r\n var position = ellipsoid.cartesianToCartographic(cartesians[i]);\r\n west = Math.min(west, position.longitude);\r\n east = Math.max(east, position.longitude);\r\n south = Math.min(south, position.latitude);\r\n north = Math.max(north, position.latitude);\r\n\r\n var lonAdjusted =\r\n position.longitude >= 0\r\n ? position.longitude\r\n : position.longitude + CesiumMath.TWO_PI;\r\n westOverIDL = Math.min(westOverIDL, lonAdjusted);\r\n eastOverIDL = Math.max(eastOverIDL, lonAdjusted);\r\n }\r\n\r\n if (east - west > eastOverIDL - westOverIDL) {\r\n west = westOverIDL;\r\n east = eastOverIDL;\r\n\r\n if (east > CesiumMath.PI) {\r\n east = east - CesiumMath.TWO_PI;\r\n }\r\n if (west > CesiumMath.PI) {\r\n west = west - CesiumMath.TWO_PI;\r\n }\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(west, south, east, north);\r\n }\r\n\r\n result.west = west;\r\n result.south = south;\r\n result.east = east;\r\n result.north = north;\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a Rectangle.\r\n *\r\n * @param {Rectangle} rectangle The rectangle to clone.\r\n * @param {Rectangle} [result] The object onto which to store the result, or undefined if a new instance should be created.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided. (Returns undefined if rectangle is undefined)\r\n */\r\nRectangle.clone = function (rectangle, result) {\r\n if (!defined(rectangle)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(\r\n rectangle.west,\r\n rectangle.south,\r\n rectangle.east,\r\n rectangle.north\r\n );\r\n }\r\n\r\n result.west = rectangle.west;\r\n result.south = rectangle.south;\r\n result.east = rectangle.east;\r\n result.north = rectangle.north;\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided Rectangles componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {Rectangle} [left] The first Rectangle.\r\n * @param {Rectangle} [right] The second Rectangle.\r\n * @param {Number} [absoluteEpsilon=0] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nRectangle.equalsEpsilon = function (left, right, absoluteEpsilon) {\r\n absoluteEpsilon = defaultValue(absoluteEpsilon, 0);\r\n\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Math.abs(left.west - right.west) <= absoluteEpsilon &&\r\n Math.abs(left.south - right.south) <= absoluteEpsilon &&\r\n Math.abs(left.east - right.east) <= absoluteEpsilon &&\r\n Math.abs(left.north - right.north) <= absoluteEpsilon)\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates this Rectangle.\r\n *\r\n * @param {Rectangle} [result] The object onto which to store the result.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.\r\n */\r\nRectangle.prototype.clone = function (result) {\r\n return Rectangle.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares the provided Rectangle with this Rectangle componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Rectangle} [other] The Rectangle to compare.\r\n * @returns {Boolean} true if the Rectangles are equal, false otherwise.\r\n */\r\nRectangle.prototype.equals = function (other) {\r\n return Rectangle.equals(this, other);\r\n};\r\n\r\n/**\r\n * Compares the provided rectangles and returns true if they are equal,\r\n * false otherwise.\r\n *\r\n * @param {Rectangle} [left] The first Rectangle.\r\n * @param {Rectangle} [right] The second Rectangle.\r\n * @returns {Boolean} true if left and right are equal; otherwise false.\r\n */\r\nRectangle.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.west === right.west &&\r\n left.south === right.south &&\r\n left.east === right.east &&\r\n left.north === right.north)\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided Rectangle with this Rectangle componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Rectangle} [other] The Rectangle to compare.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if the Rectangles are within the provided epsilon, false otherwise.\r\n */\r\nRectangle.prototype.equalsEpsilon = function (other, epsilon) {\r\n return Rectangle.equalsEpsilon(this, other, epsilon);\r\n};\r\n\r\n/**\r\n * Checks a Rectangle's properties and throws if they are not in valid ranges.\r\n *\r\n * @param {Rectangle} rectangle The rectangle to validate\r\n *\r\n * @exception {DeveloperError} north must be in the interval [-Pi/2, Pi/2].\r\n * @exception {DeveloperError} south must be in the interval [-Pi/2, Pi/2].\r\n * @exception {DeveloperError} east must be in the interval [-Pi, Pi].\r\n * @exception {DeveloperError} west must be in the interval [-Pi, Pi].\r\n */\r\nRectangle.validate = function (rectangle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n\r\n var north = rectangle.north;\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"north\",\r\n north,\r\n -CesiumMath.PI_OVER_TWO\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\"north\", north, CesiumMath.PI_OVER_TWO);\r\n\r\n var south = rectangle.south;\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"south\",\r\n south,\r\n -CesiumMath.PI_OVER_TWO\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\"south\", south, CesiumMath.PI_OVER_TWO);\r\n\r\n var west = rectangle.west;\r\n Check.typeOf.number.greaterThanOrEquals(\"west\", west, -Math.PI);\r\n Check.typeOf.number.lessThanOrEquals(\"west\", west, Math.PI);\r\n\r\n var east = rectangle.east;\r\n Check.typeOf.number.greaterThanOrEquals(\"east\", east, -Math.PI);\r\n Check.typeOf.number.lessThanOrEquals(\"east\", east, Math.PI);\r\n //>>includeEnd('debug');\r\n};\r\n\r\n/**\r\n * Computes the southwest corner of a rectangle.\r\n *\r\n * @param {Rectangle} rectangle The rectangle for which to find the corner\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.\r\n */\r\nRectangle.southwest = function (rectangle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(rectangle.west, rectangle.south);\r\n }\r\n result.longitude = rectangle.west;\r\n result.latitude = rectangle.south;\r\n result.height = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the northwest corner of a rectangle.\r\n *\r\n * @param {Rectangle} rectangle The rectangle for which to find the corner\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.\r\n */\r\nRectangle.northwest = function (rectangle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(rectangle.west, rectangle.north);\r\n }\r\n result.longitude = rectangle.west;\r\n result.latitude = rectangle.north;\r\n result.height = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the northeast corner of a rectangle.\r\n *\r\n * @param {Rectangle} rectangle The rectangle for which to find the corner\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.\r\n */\r\nRectangle.northeast = function (rectangle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(rectangle.east, rectangle.north);\r\n }\r\n result.longitude = rectangle.east;\r\n result.latitude = rectangle.north;\r\n result.height = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the southeast corner of a rectangle.\r\n *\r\n * @param {Rectangle} rectangle The rectangle for which to find the corner\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.\r\n */\r\nRectangle.southeast = function (rectangle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(rectangle.east, rectangle.south);\r\n }\r\n result.longitude = rectangle.east;\r\n result.latitude = rectangle.south;\r\n result.height = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the center of a rectangle.\r\n *\r\n * @param {Rectangle} rectangle The rectangle for which to find the center\r\n * @param {Cartographic} [result] The object onto which to store the result.\r\n * @returns {Cartographic} The modified result parameter or a new Cartographic instance if none was provided.\r\n */\r\nRectangle.center = function (rectangle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n var east = rectangle.east;\r\n var west = rectangle.west;\r\n\r\n if (east < west) {\r\n east += CesiumMath.TWO_PI;\r\n }\r\n\r\n var longitude = CesiumMath.negativePiToPi((west + east) * 0.5);\r\n var latitude = (rectangle.south + rectangle.north) * 0.5;\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(longitude, latitude);\r\n }\r\n\r\n result.longitude = longitude;\r\n result.latitude = latitude;\r\n result.height = 0.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the intersection of two rectangles. This function assumes that the rectangle's coordinates are\r\n * latitude and longitude in radians and produces a correct intersection, taking into account the fact that\r\n * the same angle can be represented with multiple values as well as the wrapping of longitude at the\r\n * anti-meridian. For a simple intersection that ignores these factors and can be used with projected\r\n * coordinates, see {@link Rectangle.simpleIntersection}.\r\n *\r\n * @param {Rectangle} rectangle On rectangle to find an intersection\r\n * @param {Rectangle} otherRectangle Another rectangle to find an intersection\r\n * @param {Rectangle} [result] The object onto which to store the result.\r\n * @returns {Rectangle|undefined} The modified result parameter, a new Rectangle instance if none was provided or undefined if there is no intersection.\r\n */\r\nRectangle.intersection = function (rectangle, otherRectangle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n Check.typeOf.object(\"otherRectangle\", otherRectangle);\r\n //>>includeEnd('debug');\r\n\r\n var rectangleEast = rectangle.east;\r\n var rectangleWest = rectangle.west;\r\n\r\n var otherRectangleEast = otherRectangle.east;\r\n var otherRectangleWest = otherRectangle.west;\r\n\r\n if (rectangleEast < rectangleWest && otherRectangleEast > 0.0) {\r\n rectangleEast += CesiumMath.TWO_PI;\r\n } else if (otherRectangleEast < otherRectangleWest && rectangleEast > 0.0) {\r\n otherRectangleEast += CesiumMath.TWO_PI;\r\n }\r\n\r\n if (rectangleEast < rectangleWest && otherRectangleWest < 0.0) {\r\n otherRectangleWest += CesiumMath.TWO_PI;\r\n } else if (otherRectangleEast < otherRectangleWest && rectangleWest < 0.0) {\r\n rectangleWest += CesiumMath.TWO_PI;\r\n }\r\n\r\n var west = CesiumMath.negativePiToPi(\r\n Math.max(rectangleWest, otherRectangleWest)\r\n );\r\n var east = CesiumMath.negativePiToPi(\r\n Math.min(rectangleEast, otherRectangleEast)\r\n );\r\n\r\n if (\r\n (rectangle.west < rectangle.east ||\r\n otherRectangle.west < otherRectangle.east) &&\r\n east <= west\r\n ) {\r\n return undefined;\r\n }\r\n\r\n var south = Math.max(rectangle.south, otherRectangle.south);\r\n var north = Math.min(rectangle.north, otherRectangle.north);\r\n\r\n if (south >= north) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(west, south, east, north);\r\n }\r\n result.west = west;\r\n result.south = south;\r\n result.east = east;\r\n result.north = north;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a simple intersection of two rectangles. Unlike {@link Rectangle.intersection}, this function\r\n * does not attempt to put the angular coordinates into a consistent range or to account for crossing the\r\n * anti-meridian. As such, it can be used for rectangles where the coordinates are not simply latitude\r\n * and longitude (i.e. projected coordinates).\r\n *\r\n * @param {Rectangle} rectangle On rectangle to find an intersection\r\n * @param {Rectangle} otherRectangle Another rectangle to find an intersection\r\n * @param {Rectangle} [result] The object onto which to store the result.\r\n * @returns {Rectangle|undefined} The modified result parameter, a new Rectangle instance if none was provided or undefined if there is no intersection.\r\n */\r\nRectangle.simpleIntersection = function (rectangle, otherRectangle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n Check.typeOf.object(\"otherRectangle\", otherRectangle);\r\n //>>includeEnd('debug');\r\n\r\n var west = Math.max(rectangle.west, otherRectangle.west);\r\n var south = Math.max(rectangle.south, otherRectangle.south);\r\n var east = Math.min(rectangle.east, otherRectangle.east);\r\n var north = Math.min(rectangle.north, otherRectangle.north);\r\n\r\n if (south >= north || west >= east) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(west, south, east, north);\r\n }\r\n\r\n result.west = west;\r\n result.south = south;\r\n result.east = east;\r\n result.north = north;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a rectangle that is the union of two rectangles.\r\n *\r\n * @param {Rectangle} rectangle A rectangle to enclose in rectangle.\r\n * @param {Rectangle} otherRectangle A rectangle to enclose in a rectangle.\r\n * @param {Rectangle} [result] The object onto which to store the result.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if none was provided.\r\n */\r\nRectangle.union = function (rectangle, otherRectangle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n Check.typeOf.object(\"otherRectangle\", otherRectangle);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Rectangle();\r\n }\r\n\r\n var rectangleEast = rectangle.east;\r\n var rectangleWest = rectangle.west;\r\n\r\n var otherRectangleEast = otherRectangle.east;\r\n var otherRectangleWest = otherRectangle.west;\r\n\r\n if (rectangleEast < rectangleWest && otherRectangleEast > 0.0) {\r\n rectangleEast += CesiumMath.TWO_PI;\r\n } else if (otherRectangleEast < otherRectangleWest && rectangleEast > 0.0) {\r\n otherRectangleEast += CesiumMath.TWO_PI;\r\n }\r\n\r\n if (rectangleEast < rectangleWest && otherRectangleWest < 0.0) {\r\n otherRectangleWest += CesiumMath.TWO_PI;\r\n } else if (otherRectangleEast < otherRectangleWest && rectangleWest < 0.0) {\r\n rectangleWest += CesiumMath.TWO_PI;\r\n }\r\n\r\n var west = CesiumMath.convertLongitudeRange(\r\n Math.min(rectangleWest, otherRectangleWest)\r\n );\r\n var east = CesiumMath.convertLongitudeRange(\r\n Math.max(rectangleEast, otherRectangleEast)\r\n );\r\n\r\n result.west = west;\r\n result.south = Math.min(rectangle.south, otherRectangle.south);\r\n result.east = east;\r\n result.north = Math.max(rectangle.north, otherRectangle.north);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a rectangle by enlarging the provided rectangle until it contains the provided cartographic.\r\n *\r\n * @param {Rectangle} rectangle A rectangle to expand.\r\n * @param {Cartographic} cartographic A cartographic to enclose in a rectangle.\r\n * @param {Rectangle} [result] The object onto which to store the result.\r\n * @returns {Rectangle} The modified result parameter or a new Rectangle instance if one was not provided.\r\n */\r\nRectangle.expand = function (rectangle, cartographic, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n Check.typeOf.object(\"cartographic\", cartographic);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Rectangle();\r\n }\r\n\r\n result.west = Math.min(rectangle.west, cartographic.longitude);\r\n result.south = Math.min(rectangle.south, cartographic.latitude);\r\n result.east = Math.max(rectangle.east, cartographic.longitude);\r\n result.north = Math.max(rectangle.north, cartographic.latitude);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns true if the cartographic is on or inside the rectangle, false otherwise.\r\n *\r\n * @param {Rectangle} rectangle The rectangle\r\n * @param {Cartographic} cartographic The cartographic to test.\r\n * @returns {Boolean} true if the provided cartographic is inside the rectangle, false otherwise.\r\n */\r\nRectangle.contains = function (rectangle, cartographic) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n Check.typeOf.object(\"cartographic\", cartographic);\r\n //>>includeEnd('debug');\r\n\r\n var longitude = cartographic.longitude;\r\n var latitude = cartographic.latitude;\r\n\r\n var west = rectangle.west;\r\n var east = rectangle.east;\r\n\r\n if (east < west) {\r\n east += CesiumMath.TWO_PI;\r\n if (longitude < 0.0) {\r\n longitude += CesiumMath.TWO_PI;\r\n }\r\n }\r\n return (\r\n (longitude > west ||\r\n CesiumMath.equalsEpsilon(longitude, west, CesiumMath.EPSILON14)) &&\r\n (longitude < east ||\r\n CesiumMath.equalsEpsilon(longitude, east, CesiumMath.EPSILON14)) &&\r\n latitude >= rectangle.south &&\r\n latitude <= rectangle.north\r\n );\r\n};\r\n\r\nvar subsampleLlaScratch = new Cartographic();\r\n/**\r\n * Samples a rectangle so that it includes a list of Cartesian points suitable for passing to\r\n * {@link BoundingSphere#fromPoints}. Sampling is necessary to account\r\n * for rectangles that cover the poles or cross the equator.\r\n *\r\n * @param {Rectangle} rectangle The rectangle to subsample.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use.\r\n * @param {Number} [surfaceHeight=0.0] The height of the rectangle above the ellipsoid.\r\n * @param {Cartesian3[]} [result] The array of Cartesians onto which to store the result.\r\n * @returns {Cartesian3[]} The modified result parameter or a new Array of Cartesians instances if none was provided.\r\n */\r\nRectangle.subsample = function (rectangle, ellipsoid, surfaceHeight, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n surfaceHeight = defaultValue(surfaceHeight, 0.0);\r\n\r\n if (!defined(result)) {\r\n result = [];\r\n }\r\n var length = 0;\r\n\r\n var north = rectangle.north;\r\n var south = rectangle.south;\r\n var east = rectangle.east;\r\n var west = rectangle.west;\r\n\r\n var lla = subsampleLlaScratch;\r\n lla.height = surfaceHeight;\r\n\r\n lla.longitude = west;\r\n lla.latitude = north;\r\n result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);\r\n length++;\r\n\r\n lla.longitude = east;\r\n result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);\r\n length++;\r\n\r\n lla.latitude = south;\r\n result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);\r\n length++;\r\n\r\n lla.longitude = west;\r\n result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);\r\n length++;\r\n\r\n if (north < 0.0) {\r\n lla.latitude = north;\r\n } else if (south > 0.0) {\r\n lla.latitude = south;\r\n } else {\r\n lla.latitude = 0.0;\r\n }\r\n\r\n for (var i = 1; i < 8; ++i) {\r\n lla.longitude = -Math.PI + i * CesiumMath.PI_OVER_TWO;\r\n if (Rectangle.contains(rectangle, lla)) {\r\n result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);\r\n length++;\r\n }\r\n }\r\n\r\n if (lla.latitude === 0.0) {\r\n lla.longitude = west;\r\n result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);\r\n length++;\r\n lla.longitude = east;\r\n result[length] = ellipsoid.cartographicToCartesian(lla, result[length]);\r\n length++;\r\n }\r\n result.length = length;\r\n return result;\r\n};\r\n\r\n/**\r\n * The largest possible rectangle.\r\n *\r\n * @type {Rectangle}\r\n * @constant\r\n */\r\nRectangle.MAX_VALUE = Object.freeze(\r\n new Rectangle(\r\n -Math.PI,\r\n -CesiumMath.PI_OVER_TWO,\r\n Math.PI,\r\n CesiumMath.PI_OVER_TWO\r\n )\r\n);\r\nexport default Rectangle;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport GeographicProjection from \"./GeographicProjection.js\";\r\nimport Intersect from \"./Intersect.js\";\r\nimport Interval from \"./Interval.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\n\r\n/**\r\n * A bounding sphere with a center and a radius.\r\n * @alias BoundingSphere\r\n * @constructor\r\n *\r\n * @param {Cartesian3} [center=Cartesian3.ZERO] The center of the bounding sphere.\r\n * @param {Number} [radius=0.0] The radius of the bounding sphere.\r\n *\r\n * @see AxisAlignedBoundingBox\r\n * @see BoundingRectangle\r\n * @see Packable\r\n */\r\nfunction BoundingSphere(center, radius) {\r\n /**\r\n * The center point of the sphere.\r\n * @type {Cartesian3}\r\n * @default {@link Cartesian3.ZERO}\r\n */\r\n this.center = Cartesian3.clone(defaultValue(center, Cartesian3.ZERO));\r\n\r\n /**\r\n * The radius of the sphere.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.radius = defaultValue(radius, 0.0);\r\n}\r\n\r\nvar fromPointsXMin = new Cartesian3();\r\nvar fromPointsYMin = new Cartesian3();\r\nvar fromPointsZMin = new Cartesian3();\r\nvar fromPointsXMax = new Cartesian3();\r\nvar fromPointsYMax = new Cartesian3();\r\nvar fromPointsZMax = new Cartesian3();\r\nvar fromPointsCurrentPos = new Cartesian3();\r\nvar fromPointsScratch = new Cartesian3();\r\nvar fromPointsRitterCenter = new Cartesian3();\r\nvar fromPointsMinBoxPt = new Cartesian3();\r\nvar fromPointsMaxBoxPt = new Cartesian3();\r\nvar fromPointsNaiveCenterScratch = new Cartesian3();\r\nvar volumeConstant = (4.0 / 3.0) * CesiumMath.PI;\r\n\r\n/**\r\n * Computes a tight-fitting bounding sphere enclosing a list of 3D Cartesian points.\r\n * The bounding sphere is computed by running two algorithms, a naive algorithm and\r\n * Ritter's algorithm. The smaller of the two spheres is used to ensure a tight fit.\r\n *\r\n * @param {Cartesian3[]} [positions] An array of points that the bounding sphere will enclose. Each point must have x, y, and z properties.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if one was not provided.\r\n *\r\n * @see {@link http://help.agi.com/AGIComponents/html/BlogBoundingSphere.htm|Bounding Sphere computation article}\r\n */\r\nBoundingSphere.fromPoints = function (positions, result) {\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n if (!defined(positions) || positions.length === 0) {\r\n result.center = Cartesian3.clone(Cartesian3.ZERO, result.center);\r\n result.radius = 0.0;\r\n return result;\r\n }\r\n\r\n var currentPos = Cartesian3.clone(positions[0], fromPointsCurrentPos);\r\n\r\n var xMin = Cartesian3.clone(currentPos, fromPointsXMin);\r\n var yMin = Cartesian3.clone(currentPos, fromPointsYMin);\r\n var zMin = Cartesian3.clone(currentPos, fromPointsZMin);\r\n\r\n var xMax = Cartesian3.clone(currentPos, fromPointsXMax);\r\n var yMax = Cartesian3.clone(currentPos, fromPointsYMax);\r\n var zMax = Cartesian3.clone(currentPos, fromPointsZMax);\r\n\r\n var numPositions = positions.length;\r\n var i;\r\n for (i = 1; i < numPositions; i++) {\r\n Cartesian3.clone(positions[i], currentPos);\r\n\r\n var x = currentPos.x;\r\n var y = currentPos.y;\r\n var z = currentPos.z;\r\n\r\n // Store points containing the the smallest and largest components\r\n if (x < xMin.x) {\r\n Cartesian3.clone(currentPos, xMin);\r\n }\r\n\r\n if (x > xMax.x) {\r\n Cartesian3.clone(currentPos, xMax);\r\n }\r\n\r\n if (y < yMin.y) {\r\n Cartesian3.clone(currentPos, yMin);\r\n }\r\n\r\n if (y > yMax.y) {\r\n Cartesian3.clone(currentPos, yMax);\r\n }\r\n\r\n if (z < zMin.z) {\r\n Cartesian3.clone(currentPos, zMin);\r\n }\r\n\r\n if (z > zMax.z) {\r\n Cartesian3.clone(currentPos, zMax);\r\n }\r\n }\r\n\r\n // Compute x-, y-, and z-spans (Squared distances b/n each component's min. and max.).\r\n var xSpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(xMax, xMin, fromPointsScratch)\r\n );\r\n var ySpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(yMax, yMin, fromPointsScratch)\r\n );\r\n var zSpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(zMax, zMin, fromPointsScratch)\r\n );\r\n\r\n // Set the diameter endpoints to the largest span.\r\n var diameter1 = xMin;\r\n var diameter2 = xMax;\r\n var maxSpan = xSpan;\r\n if (ySpan > maxSpan) {\r\n maxSpan = ySpan;\r\n diameter1 = yMin;\r\n diameter2 = yMax;\r\n }\r\n if (zSpan > maxSpan) {\r\n maxSpan = zSpan;\r\n diameter1 = zMin;\r\n diameter2 = zMax;\r\n }\r\n\r\n // Calculate the center of the initial sphere found by Ritter's algorithm\r\n var ritterCenter = fromPointsRitterCenter;\r\n ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;\r\n ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;\r\n ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;\r\n\r\n // Calculate the radius of the initial sphere found by Ritter's algorithm\r\n var radiusSquared = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(diameter2, ritterCenter, fromPointsScratch)\r\n );\r\n var ritterRadius = Math.sqrt(radiusSquared);\r\n\r\n // Find the center of the sphere found using the Naive method.\r\n var minBoxPt = fromPointsMinBoxPt;\r\n minBoxPt.x = xMin.x;\r\n minBoxPt.y = yMin.y;\r\n minBoxPt.z = zMin.z;\r\n\r\n var maxBoxPt = fromPointsMaxBoxPt;\r\n maxBoxPt.x = xMax.x;\r\n maxBoxPt.y = yMax.y;\r\n maxBoxPt.z = zMax.z;\r\n\r\n var naiveCenter = Cartesian3.midpoint(\r\n minBoxPt,\r\n maxBoxPt,\r\n fromPointsNaiveCenterScratch\r\n );\r\n\r\n // Begin 2nd pass to find naive radius and modify the ritter sphere.\r\n var naiveRadius = 0;\r\n for (i = 0; i < numPositions; i++) {\r\n Cartesian3.clone(positions[i], currentPos);\r\n\r\n // Find the furthest point from the naive center to calculate the naive radius.\r\n var r = Cartesian3.magnitude(\r\n Cartesian3.subtract(currentPos, naiveCenter, fromPointsScratch)\r\n );\r\n if (r > naiveRadius) {\r\n naiveRadius = r;\r\n }\r\n\r\n // Make adjustments to the Ritter Sphere to include all points.\r\n var oldCenterToPointSquared = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(currentPos, ritterCenter, fromPointsScratch)\r\n );\r\n if (oldCenterToPointSquared > radiusSquared) {\r\n var oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);\r\n // Calculate new radius to include the point that lies outside\r\n ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;\r\n radiusSquared = ritterRadius * ritterRadius;\r\n // Calculate center of new Ritter sphere\r\n var oldToNew = oldCenterToPoint - ritterRadius;\r\n ritterCenter.x =\r\n (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) /\r\n oldCenterToPoint;\r\n ritterCenter.y =\r\n (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) /\r\n oldCenterToPoint;\r\n ritterCenter.z =\r\n (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) /\r\n oldCenterToPoint;\r\n }\r\n }\r\n\r\n if (ritterRadius < naiveRadius) {\r\n Cartesian3.clone(ritterCenter, result.center);\r\n result.radius = ritterRadius;\r\n } else {\r\n Cartesian3.clone(naiveCenter, result.center);\r\n result.radius = naiveRadius;\r\n }\r\n\r\n return result;\r\n};\r\n\r\nvar defaultProjection = new GeographicProjection();\r\nvar fromRectangle2DLowerLeft = new Cartesian3();\r\nvar fromRectangle2DUpperRight = new Cartesian3();\r\nvar fromRectangle2DSouthwest = new Cartographic();\r\nvar fromRectangle2DNortheast = new Cartographic();\r\n\r\n/**\r\n * Computes a bounding sphere from a rectangle projected in 2D.\r\n *\r\n * @param {Rectangle} [rectangle] The rectangle around which to create a bounding sphere.\r\n * @param {Object} [projection=GeographicProjection] The projection used to project the rectangle into 2D.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.fromRectangle2D = function (rectangle, projection, result) {\r\n return BoundingSphere.fromRectangleWithHeights2D(\r\n rectangle,\r\n projection,\r\n 0.0,\r\n 0.0,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Computes a bounding sphere from a rectangle projected in 2D. The bounding sphere accounts for the\r\n * object's minimum and maximum heights over the rectangle.\r\n *\r\n * @param {Rectangle} [rectangle] The rectangle around which to create a bounding sphere.\r\n * @param {Object} [projection=GeographicProjection] The projection used to project the rectangle into 2D.\r\n * @param {Number} [minimumHeight=0.0] The minimum height over the rectangle.\r\n * @param {Number} [maximumHeight=0.0] The maximum height over the rectangle.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.fromRectangleWithHeights2D = function (\r\n rectangle,\r\n projection,\r\n minimumHeight,\r\n maximumHeight,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n if (!defined(rectangle)) {\r\n result.center = Cartesian3.clone(Cartesian3.ZERO, result.center);\r\n result.radius = 0.0;\r\n return result;\r\n }\r\n\r\n projection = defaultValue(projection, defaultProjection);\r\n\r\n Rectangle.southwest(rectangle, fromRectangle2DSouthwest);\r\n fromRectangle2DSouthwest.height = minimumHeight;\r\n Rectangle.northeast(rectangle, fromRectangle2DNortheast);\r\n fromRectangle2DNortheast.height = maximumHeight;\r\n\r\n var lowerLeft = projection.project(\r\n fromRectangle2DSouthwest,\r\n fromRectangle2DLowerLeft\r\n );\r\n var upperRight = projection.project(\r\n fromRectangle2DNortheast,\r\n fromRectangle2DUpperRight\r\n );\r\n\r\n var width = upperRight.x - lowerLeft.x;\r\n var height = upperRight.y - lowerLeft.y;\r\n var elevation = upperRight.z - lowerLeft.z;\r\n\r\n result.radius =\r\n Math.sqrt(width * width + height * height + elevation * elevation) * 0.5;\r\n var center = result.center;\r\n center.x = lowerLeft.x + width * 0.5;\r\n center.y = lowerLeft.y + height * 0.5;\r\n center.z = lowerLeft.z + elevation * 0.5;\r\n return result;\r\n};\r\n\r\nvar fromRectangle3DScratch = [];\r\n\r\n/**\r\n * Computes a bounding sphere from a rectangle in 3D. The bounding sphere is created using a subsample of points\r\n * on the ellipsoid and contained in the rectangle. It may not be accurate for all rectangles on all types of ellipsoids.\r\n *\r\n * @param {Rectangle} [rectangle] The valid rectangle used to create a bounding sphere.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid used to determine positions of the rectangle.\r\n * @param {Number} [surfaceHeight=0.0] The height above the surface of the ellipsoid.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.fromRectangle3D = function (\r\n rectangle,\r\n ellipsoid,\r\n surfaceHeight,\r\n result\r\n) {\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n surfaceHeight = defaultValue(surfaceHeight, 0.0);\r\n\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n if (!defined(rectangle)) {\r\n result.center = Cartesian3.clone(Cartesian3.ZERO, result.center);\r\n result.radius = 0.0;\r\n return result;\r\n }\r\n\r\n var positions = Rectangle.subsample(\r\n rectangle,\r\n ellipsoid,\r\n surfaceHeight,\r\n fromRectangle3DScratch\r\n );\r\n return BoundingSphere.fromPoints(positions, result);\r\n};\r\n\r\n/**\r\n * Computes a tight-fitting bounding sphere enclosing a list of 3D points, where the points are\r\n * stored in a flat array in X, Y, Z, order. The bounding sphere is computed by running two\r\n * algorithms, a naive algorithm and Ritter's algorithm. The smaller of the two spheres is used to\r\n * ensure a tight fit.\r\n *\r\n * @param {Number[]} [positions] An array of points that the bounding sphere will enclose. Each point\r\n * is formed from three elements in the array in the order X, Y, Z.\r\n * @param {Cartesian3} [center=Cartesian3.ZERO] The position to which the positions are relative, which need not be the\r\n * origin of the coordinate system. This is useful when the positions are to be used for\r\n * relative-to-center (RTC) rendering.\r\n * @param {Number} [stride=3] The number of array elements per vertex. It must be at least 3, but it may\r\n * be higher. Regardless of the value of this parameter, the X coordinate of the first position\r\n * is at array index 0, the Y coordinate is at array index 1, and the Z coordinate is at array index\r\n * 2. When stride is 3, the X coordinate of the next position then begins at array index 3. If\r\n * the stride is 5, however, two array elements are skipped and the next position begins at array\r\n * index 5.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if one was not provided.\r\n *\r\n * @example\r\n * // Compute the bounding sphere from 3 positions, each specified relative to a center.\r\n * // In addition to the X, Y, and Z coordinates, the points array contains two additional\r\n * // elements per point which are ignored for the purpose of computing the bounding sphere.\r\n * var center = new Cesium.Cartesian3(1.0, 2.0, 3.0);\r\n * var points = [1.0, 2.0, 3.0, 0.1, 0.2,\r\n * 4.0, 5.0, 6.0, 0.1, 0.2,\r\n * 7.0, 8.0, 9.0, 0.1, 0.2];\r\n * var sphere = Cesium.BoundingSphere.fromVertices(points, center, 5);\r\n *\r\n * @see {@link http://blogs.agi.com/insight3d/index.php/2008/02/04/a-bounding/|Bounding Sphere computation article}\r\n */\r\nBoundingSphere.fromVertices = function (positions, center, stride, result) {\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n if (!defined(positions) || positions.length === 0) {\r\n result.center = Cartesian3.clone(Cartesian3.ZERO, result.center);\r\n result.radius = 0.0;\r\n return result;\r\n }\r\n\r\n center = defaultValue(center, Cartesian3.ZERO);\r\n\r\n stride = defaultValue(stride, 3);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"stride\", stride, 3);\r\n //>>includeEnd('debug');\r\n\r\n var currentPos = fromPointsCurrentPos;\r\n currentPos.x = positions[0] + center.x;\r\n currentPos.y = positions[1] + center.y;\r\n currentPos.z = positions[2] + center.z;\r\n\r\n var xMin = Cartesian3.clone(currentPos, fromPointsXMin);\r\n var yMin = Cartesian3.clone(currentPos, fromPointsYMin);\r\n var zMin = Cartesian3.clone(currentPos, fromPointsZMin);\r\n\r\n var xMax = Cartesian3.clone(currentPos, fromPointsXMax);\r\n var yMax = Cartesian3.clone(currentPos, fromPointsYMax);\r\n var zMax = Cartesian3.clone(currentPos, fromPointsZMax);\r\n\r\n var numElements = positions.length;\r\n var i;\r\n for (i = 0; i < numElements; i += stride) {\r\n var x = positions[i] + center.x;\r\n var y = positions[i + 1] + center.y;\r\n var z = positions[i + 2] + center.z;\r\n\r\n currentPos.x = x;\r\n currentPos.y = y;\r\n currentPos.z = z;\r\n\r\n // Store points containing the the smallest and largest components\r\n if (x < xMin.x) {\r\n Cartesian3.clone(currentPos, xMin);\r\n }\r\n\r\n if (x > xMax.x) {\r\n Cartesian3.clone(currentPos, xMax);\r\n }\r\n\r\n if (y < yMin.y) {\r\n Cartesian3.clone(currentPos, yMin);\r\n }\r\n\r\n if (y > yMax.y) {\r\n Cartesian3.clone(currentPos, yMax);\r\n }\r\n\r\n if (z < zMin.z) {\r\n Cartesian3.clone(currentPos, zMin);\r\n }\r\n\r\n if (z > zMax.z) {\r\n Cartesian3.clone(currentPos, zMax);\r\n }\r\n }\r\n\r\n // Compute x-, y-, and z-spans (Squared distances b/n each component's min. and max.).\r\n var xSpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(xMax, xMin, fromPointsScratch)\r\n );\r\n var ySpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(yMax, yMin, fromPointsScratch)\r\n );\r\n var zSpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(zMax, zMin, fromPointsScratch)\r\n );\r\n\r\n // Set the diameter endpoints to the largest span.\r\n var diameter1 = xMin;\r\n var diameter2 = xMax;\r\n var maxSpan = xSpan;\r\n if (ySpan > maxSpan) {\r\n maxSpan = ySpan;\r\n diameter1 = yMin;\r\n diameter2 = yMax;\r\n }\r\n if (zSpan > maxSpan) {\r\n maxSpan = zSpan;\r\n diameter1 = zMin;\r\n diameter2 = zMax;\r\n }\r\n\r\n // Calculate the center of the initial sphere found by Ritter's algorithm\r\n var ritterCenter = fromPointsRitterCenter;\r\n ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;\r\n ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;\r\n ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;\r\n\r\n // Calculate the radius of the initial sphere found by Ritter's algorithm\r\n var radiusSquared = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(diameter2, ritterCenter, fromPointsScratch)\r\n );\r\n var ritterRadius = Math.sqrt(radiusSquared);\r\n\r\n // Find the center of the sphere found using the Naive method.\r\n var minBoxPt = fromPointsMinBoxPt;\r\n minBoxPt.x = xMin.x;\r\n minBoxPt.y = yMin.y;\r\n minBoxPt.z = zMin.z;\r\n\r\n var maxBoxPt = fromPointsMaxBoxPt;\r\n maxBoxPt.x = xMax.x;\r\n maxBoxPt.y = yMax.y;\r\n maxBoxPt.z = zMax.z;\r\n\r\n var naiveCenter = Cartesian3.midpoint(\r\n minBoxPt,\r\n maxBoxPt,\r\n fromPointsNaiveCenterScratch\r\n );\r\n\r\n // Begin 2nd pass to find naive radius and modify the ritter sphere.\r\n var naiveRadius = 0;\r\n for (i = 0; i < numElements; i += stride) {\r\n currentPos.x = positions[i] + center.x;\r\n currentPos.y = positions[i + 1] + center.y;\r\n currentPos.z = positions[i + 2] + center.z;\r\n\r\n // Find the furthest point from the naive center to calculate the naive radius.\r\n var r = Cartesian3.magnitude(\r\n Cartesian3.subtract(currentPos, naiveCenter, fromPointsScratch)\r\n );\r\n if (r > naiveRadius) {\r\n naiveRadius = r;\r\n }\r\n\r\n // Make adjustments to the Ritter Sphere to include all points.\r\n var oldCenterToPointSquared = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(currentPos, ritterCenter, fromPointsScratch)\r\n );\r\n if (oldCenterToPointSquared > radiusSquared) {\r\n var oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);\r\n // Calculate new radius to include the point that lies outside\r\n ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;\r\n radiusSquared = ritterRadius * ritterRadius;\r\n // Calculate center of new Ritter sphere\r\n var oldToNew = oldCenterToPoint - ritterRadius;\r\n ritterCenter.x =\r\n (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) /\r\n oldCenterToPoint;\r\n ritterCenter.y =\r\n (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) /\r\n oldCenterToPoint;\r\n ritterCenter.z =\r\n (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) /\r\n oldCenterToPoint;\r\n }\r\n }\r\n\r\n if (ritterRadius < naiveRadius) {\r\n Cartesian3.clone(ritterCenter, result.center);\r\n result.radius = ritterRadius;\r\n } else {\r\n Cartesian3.clone(naiveCenter, result.center);\r\n result.radius = naiveRadius;\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a tight-fitting bounding sphere enclosing a list of EncodedCartesian3s, where the points are\r\n * stored in parallel flat arrays in X, Y, Z, order. The bounding sphere is computed by running two\r\n * algorithms, a naive algorithm and Ritter's algorithm. The smaller of the two spheres is used to\r\n * ensure a tight fit.\r\n *\r\n * @param {Number[]} [positionsHigh] An array of high bits of the encoded cartesians that the bounding sphere will enclose. Each point\r\n * is formed from three elements in the array in the order X, Y, Z.\r\n * @param {Number[]} [positionsLow] An array of low bits of the encoded cartesians that the bounding sphere will enclose. Each point\r\n * is formed from three elements in the array in the order X, Y, Z.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if one was not provided.\r\n *\r\n * @see {@link http://blogs.agi.com/insight3d/index.php/2008/02/04/a-bounding/|Bounding Sphere computation article}\r\n */\r\nBoundingSphere.fromEncodedCartesianVertices = function (\r\n positionsHigh,\r\n positionsLow,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n if (\r\n !defined(positionsHigh) ||\r\n !defined(positionsLow) ||\r\n positionsHigh.length !== positionsLow.length ||\r\n positionsHigh.length === 0\r\n ) {\r\n result.center = Cartesian3.clone(Cartesian3.ZERO, result.center);\r\n result.radius = 0.0;\r\n return result;\r\n }\r\n\r\n var currentPos = fromPointsCurrentPos;\r\n currentPos.x = positionsHigh[0] + positionsLow[0];\r\n currentPos.y = positionsHigh[1] + positionsLow[1];\r\n currentPos.z = positionsHigh[2] + positionsLow[2];\r\n\r\n var xMin = Cartesian3.clone(currentPos, fromPointsXMin);\r\n var yMin = Cartesian3.clone(currentPos, fromPointsYMin);\r\n var zMin = Cartesian3.clone(currentPos, fromPointsZMin);\r\n\r\n var xMax = Cartesian3.clone(currentPos, fromPointsXMax);\r\n var yMax = Cartesian3.clone(currentPos, fromPointsYMax);\r\n var zMax = Cartesian3.clone(currentPos, fromPointsZMax);\r\n\r\n var numElements = positionsHigh.length;\r\n var i;\r\n for (i = 0; i < numElements; i += 3) {\r\n var x = positionsHigh[i] + positionsLow[i];\r\n var y = positionsHigh[i + 1] + positionsLow[i + 1];\r\n var z = positionsHigh[i + 2] + positionsLow[i + 2];\r\n\r\n currentPos.x = x;\r\n currentPos.y = y;\r\n currentPos.z = z;\r\n\r\n // Store points containing the the smallest and largest components\r\n if (x < xMin.x) {\r\n Cartesian3.clone(currentPos, xMin);\r\n }\r\n\r\n if (x > xMax.x) {\r\n Cartesian3.clone(currentPos, xMax);\r\n }\r\n\r\n if (y < yMin.y) {\r\n Cartesian3.clone(currentPos, yMin);\r\n }\r\n\r\n if (y > yMax.y) {\r\n Cartesian3.clone(currentPos, yMax);\r\n }\r\n\r\n if (z < zMin.z) {\r\n Cartesian3.clone(currentPos, zMin);\r\n }\r\n\r\n if (z > zMax.z) {\r\n Cartesian3.clone(currentPos, zMax);\r\n }\r\n }\r\n\r\n // Compute x-, y-, and z-spans (Squared distances b/n each component's min. and max.).\r\n var xSpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(xMax, xMin, fromPointsScratch)\r\n );\r\n var ySpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(yMax, yMin, fromPointsScratch)\r\n );\r\n var zSpan = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(zMax, zMin, fromPointsScratch)\r\n );\r\n\r\n // Set the diameter endpoints to the largest span.\r\n var diameter1 = xMin;\r\n var diameter2 = xMax;\r\n var maxSpan = xSpan;\r\n if (ySpan > maxSpan) {\r\n maxSpan = ySpan;\r\n diameter1 = yMin;\r\n diameter2 = yMax;\r\n }\r\n if (zSpan > maxSpan) {\r\n maxSpan = zSpan;\r\n diameter1 = zMin;\r\n diameter2 = zMax;\r\n }\r\n\r\n // Calculate the center of the initial sphere found by Ritter's algorithm\r\n var ritterCenter = fromPointsRitterCenter;\r\n ritterCenter.x = (diameter1.x + diameter2.x) * 0.5;\r\n ritterCenter.y = (diameter1.y + diameter2.y) * 0.5;\r\n ritterCenter.z = (diameter1.z + diameter2.z) * 0.5;\r\n\r\n // Calculate the radius of the initial sphere found by Ritter's algorithm\r\n var radiusSquared = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(diameter2, ritterCenter, fromPointsScratch)\r\n );\r\n var ritterRadius = Math.sqrt(radiusSquared);\r\n\r\n // Find the center of the sphere found using the Naive method.\r\n var minBoxPt = fromPointsMinBoxPt;\r\n minBoxPt.x = xMin.x;\r\n minBoxPt.y = yMin.y;\r\n minBoxPt.z = zMin.z;\r\n\r\n var maxBoxPt = fromPointsMaxBoxPt;\r\n maxBoxPt.x = xMax.x;\r\n maxBoxPt.y = yMax.y;\r\n maxBoxPt.z = zMax.z;\r\n\r\n var naiveCenter = Cartesian3.midpoint(\r\n minBoxPt,\r\n maxBoxPt,\r\n fromPointsNaiveCenterScratch\r\n );\r\n\r\n // Begin 2nd pass to find naive radius and modify the ritter sphere.\r\n var naiveRadius = 0;\r\n for (i = 0; i < numElements; i += 3) {\r\n currentPos.x = positionsHigh[i] + positionsLow[i];\r\n currentPos.y = positionsHigh[i + 1] + positionsLow[i + 1];\r\n currentPos.z = positionsHigh[i + 2] + positionsLow[i + 2];\r\n\r\n // Find the furthest point from the naive center to calculate the naive radius.\r\n var r = Cartesian3.magnitude(\r\n Cartesian3.subtract(currentPos, naiveCenter, fromPointsScratch)\r\n );\r\n if (r > naiveRadius) {\r\n naiveRadius = r;\r\n }\r\n\r\n // Make adjustments to the Ritter Sphere to include all points.\r\n var oldCenterToPointSquared = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(currentPos, ritterCenter, fromPointsScratch)\r\n );\r\n if (oldCenterToPointSquared > radiusSquared) {\r\n var oldCenterToPoint = Math.sqrt(oldCenterToPointSquared);\r\n // Calculate new radius to include the point that lies outside\r\n ritterRadius = (ritterRadius + oldCenterToPoint) * 0.5;\r\n radiusSquared = ritterRadius * ritterRadius;\r\n // Calculate center of new Ritter sphere\r\n var oldToNew = oldCenterToPoint - ritterRadius;\r\n ritterCenter.x =\r\n (ritterRadius * ritterCenter.x + oldToNew * currentPos.x) /\r\n oldCenterToPoint;\r\n ritterCenter.y =\r\n (ritterRadius * ritterCenter.y + oldToNew * currentPos.y) /\r\n oldCenterToPoint;\r\n ritterCenter.z =\r\n (ritterRadius * ritterCenter.z + oldToNew * currentPos.z) /\r\n oldCenterToPoint;\r\n }\r\n }\r\n\r\n if (ritterRadius < naiveRadius) {\r\n Cartesian3.clone(ritterCenter, result.center);\r\n result.radius = ritterRadius;\r\n } else {\r\n Cartesian3.clone(naiveCenter, result.center);\r\n result.radius = naiveRadius;\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a bounding sphere from the corner points of an axis-aligned bounding box. The sphere\r\n * tighly and fully encompases the box.\r\n *\r\n * @param {Cartesian3} [corner] The minimum height over the rectangle.\r\n * @param {Cartesian3} [oppositeCorner] The maximum height over the rectangle.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n *\r\n * @example\r\n * // Create a bounding sphere around the unit cube\r\n * var sphere = Cesium.BoundingSphere.fromCornerPoints(new Cesium.Cartesian3(-0.5, -0.5, -0.5), new Cesium.Cartesian3(0.5, 0.5, 0.5));\r\n */\r\nBoundingSphere.fromCornerPoints = function (corner, oppositeCorner, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"corner\", corner);\r\n Check.typeOf.object(\"oppositeCorner\", oppositeCorner);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n var center = Cartesian3.midpoint(corner, oppositeCorner, result.center);\r\n result.radius = Cartesian3.distance(center, oppositeCorner);\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a bounding sphere encompassing an ellipsoid.\r\n *\r\n * @param {Ellipsoid} ellipsoid The ellipsoid around which to create a bounding sphere.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n *\r\n * @example\r\n * var boundingSphere = Cesium.BoundingSphere.fromEllipsoid(ellipsoid);\r\n */\r\nBoundingSphere.fromEllipsoid = function (ellipsoid, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"ellipsoid\", ellipsoid);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n Cartesian3.clone(Cartesian3.ZERO, result.center);\r\n result.radius = ellipsoid.maximumRadius;\r\n return result;\r\n};\r\n\r\nvar fromBoundingSpheresScratch = new Cartesian3();\r\n\r\n/**\r\n * Computes a tight-fitting bounding sphere enclosing the provided array of bounding spheres.\r\n *\r\n * @param {BoundingSphere[]} [boundingSpheres] The array of bounding spheres.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.fromBoundingSpheres = function (boundingSpheres, result) {\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n if (!defined(boundingSpheres) || boundingSpheres.length === 0) {\r\n result.center = Cartesian3.clone(Cartesian3.ZERO, result.center);\r\n result.radius = 0.0;\r\n return result;\r\n }\r\n\r\n var length = boundingSpheres.length;\r\n if (length === 1) {\r\n return BoundingSphere.clone(boundingSpheres[0], result);\r\n }\r\n\r\n if (length === 2) {\r\n return BoundingSphere.union(boundingSpheres[0], boundingSpheres[1], result);\r\n }\r\n\r\n var positions = [];\r\n var i;\r\n for (i = 0; i < length; i++) {\r\n positions.push(boundingSpheres[i].center);\r\n }\r\n\r\n result = BoundingSphere.fromPoints(positions, result);\r\n\r\n var center = result.center;\r\n var radius = result.radius;\r\n for (i = 0; i < length; i++) {\r\n var tmp = boundingSpheres[i];\r\n radius = Math.max(\r\n radius,\r\n Cartesian3.distance(center, tmp.center, fromBoundingSpheresScratch) +\r\n tmp.radius\r\n );\r\n }\r\n result.radius = radius;\r\n\r\n return result;\r\n};\r\n\r\nvar fromOrientedBoundingBoxScratchU = new Cartesian3();\r\nvar fromOrientedBoundingBoxScratchV = new Cartesian3();\r\nvar fromOrientedBoundingBoxScratchW = new Cartesian3();\r\n\r\n/**\r\n * Computes a tight-fitting bounding sphere enclosing the provided oriented bounding box.\r\n *\r\n * @param {OrientedBoundingBox} orientedBoundingBox The oriented bounding box.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.fromOrientedBoundingBox = function (\r\n orientedBoundingBox,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"orientedBoundingBox\", orientedBoundingBox);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n var halfAxes = orientedBoundingBox.halfAxes;\r\n var u = Matrix3.getColumn(halfAxes, 0, fromOrientedBoundingBoxScratchU);\r\n var v = Matrix3.getColumn(halfAxes, 1, fromOrientedBoundingBoxScratchV);\r\n var w = Matrix3.getColumn(halfAxes, 2, fromOrientedBoundingBoxScratchW);\r\n\r\n Cartesian3.add(u, v, u);\r\n Cartesian3.add(u, w, u);\r\n\r\n result.center = Cartesian3.clone(orientedBoundingBox.center, result.center);\r\n result.radius = Cartesian3.magnitude(u);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a BoundingSphere instance.\r\n *\r\n * @param {BoundingSphere} sphere The bounding sphere to duplicate.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided. (Returns undefined if sphere is undefined)\r\n */\r\nBoundingSphere.clone = function (sphere, result) {\r\n if (!defined(sphere)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new BoundingSphere(sphere.center, sphere.radius);\r\n }\r\n\r\n result.center = Cartesian3.clone(sphere.center, result.center);\r\n result.radius = sphere.radius;\r\n return result;\r\n};\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nBoundingSphere.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {BoundingSphere} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nBoundingSphere.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var center = value.center;\r\n array[startingIndex++] = center.x;\r\n array[startingIndex++] = center.y;\r\n array[startingIndex++] = center.z;\r\n array[startingIndex] = value.radius;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {BoundingSphere} [result] The object into which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if one was not provided.\r\n */\r\nBoundingSphere.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n var center = result.center;\r\n center.x = array[startingIndex++];\r\n center.y = array[startingIndex++];\r\n center.z = array[startingIndex++];\r\n result.radius = array[startingIndex];\r\n return result;\r\n};\r\n\r\nvar unionScratch = new Cartesian3();\r\nvar unionScratchCenter = new Cartesian3();\r\n/**\r\n * Computes a bounding sphere that contains both the left and right bounding spheres.\r\n *\r\n * @param {BoundingSphere} left A sphere to enclose in a bounding sphere.\r\n * @param {BoundingSphere} right A sphere to enclose in a bounding sphere.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.union = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n var leftCenter = left.center;\r\n var leftRadius = left.radius;\r\n var rightCenter = right.center;\r\n var rightRadius = right.radius;\r\n\r\n var toRightCenter = Cartesian3.subtract(\r\n rightCenter,\r\n leftCenter,\r\n unionScratch\r\n );\r\n var centerSeparation = Cartesian3.magnitude(toRightCenter);\r\n\r\n if (leftRadius >= centerSeparation + rightRadius) {\r\n // Left sphere wins.\r\n left.clone(result);\r\n return result;\r\n }\r\n\r\n if (rightRadius >= centerSeparation + leftRadius) {\r\n // Right sphere wins.\r\n right.clone(result);\r\n return result;\r\n }\r\n\r\n // There are two tangent points, one on far side of each sphere.\r\n var halfDistanceBetweenTangentPoints =\r\n (leftRadius + centerSeparation + rightRadius) * 0.5;\r\n\r\n // Compute the center point halfway between the two tangent points.\r\n var center = Cartesian3.multiplyByScalar(\r\n toRightCenter,\r\n (-leftRadius + halfDistanceBetweenTangentPoints) / centerSeparation,\r\n unionScratchCenter\r\n );\r\n Cartesian3.add(center, leftCenter, center);\r\n Cartesian3.clone(center, result.center);\r\n result.radius = halfDistanceBetweenTangentPoints;\r\n\r\n return result;\r\n};\r\n\r\nvar expandScratch = new Cartesian3();\r\n/**\r\n * Computes a bounding sphere by enlarging the provided sphere to contain the provided point.\r\n *\r\n * @param {BoundingSphere} sphere A sphere to expand.\r\n * @param {Cartesian3} point A point to enclose in a bounding sphere.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.expand = function (sphere, point, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"sphere\", sphere);\r\n Check.typeOf.object(\"point\", point);\r\n //>>includeEnd('debug');\r\n\r\n result = BoundingSphere.clone(sphere, result);\r\n\r\n var radius = Cartesian3.magnitude(\r\n Cartesian3.subtract(point, result.center, expandScratch)\r\n );\r\n if (radius > result.radius) {\r\n result.radius = radius;\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines which side of a plane a sphere is located.\r\n *\r\n * @param {BoundingSphere} sphere The bounding sphere to test.\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire sphere is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire sphere is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the sphere\r\n * intersects the plane.\r\n */\r\nBoundingSphere.intersectPlane = function (sphere, plane) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"sphere\", sphere);\r\n Check.typeOf.object(\"plane\", plane);\r\n //>>includeEnd('debug');\r\n\r\n var center = sphere.center;\r\n var radius = sphere.radius;\r\n var normal = plane.normal;\r\n var distanceToPlane = Cartesian3.dot(normal, center) + plane.distance;\r\n\r\n if (distanceToPlane < -radius) {\r\n // The center point is negative side of the plane normal\r\n return Intersect.OUTSIDE;\r\n } else if (distanceToPlane < radius) {\r\n // The center point is positive side of the plane, but radius extends beyond it; partial overlap\r\n return Intersect.INTERSECTING;\r\n }\r\n return Intersect.INSIDE;\r\n};\r\n\r\n/**\r\n * Applies a 4x4 affine transformation matrix to a bounding sphere.\r\n *\r\n * @param {BoundingSphere} sphere The bounding sphere to apply the transformation to.\r\n * @param {Matrix4} transform The transformation matrix to apply to the bounding sphere.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.transform = function (sphere, transform, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"sphere\", sphere);\r\n Check.typeOf.object(\"transform\", transform);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n result.center = Matrix4.multiplyByPoint(\r\n transform,\r\n sphere.center,\r\n result.center\r\n );\r\n result.radius = Matrix4.getMaximumScale(transform) * sphere.radius;\r\n\r\n return result;\r\n};\r\n\r\nvar distanceSquaredToScratch = new Cartesian3();\r\n\r\n/**\r\n * Computes the estimated distance squared from the closest point on a bounding sphere to a point.\r\n *\r\n * @param {BoundingSphere} sphere The sphere.\r\n * @param {Cartesian3} cartesian The point\r\n * @returns {Number} The estimated distance squared from the bounding sphere to the point.\r\n *\r\n * @example\r\n * // Sort bounding spheres from back to front\r\n * spheres.sort(function(a, b) {\r\n * return Cesium.BoundingSphere.distanceSquaredTo(b, camera.positionWC) - Cesium.BoundingSphere.distanceSquaredTo(a, camera.positionWC);\r\n * });\r\n */\r\nBoundingSphere.distanceSquaredTo = function (sphere, cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"sphere\", sphere);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n var diff = Cartesian3.subtract(\r\n sphere.center,\r\n cartesian,\r\n distanceSquaredToScratch\r\n );\r\n return Cartesian3.magnitudeSquared(diff) - sphere.radius * sphere.radius;\r\n};\r\n\r\n/**\r\n * Applies a 4x4 affine transformation matrix to a bounding sphere where there is no scale\r\n * The transformation matrix is not verified to have a uniform scale of 1.\r\n * This method is faster than computing the general bounding sphere transform using {@link BoundingSphere.transform}.\r\n *\r\n * @param {BoundingSphere} sphere The bounding sphere to apply the transformation to.\r\n * @param {Matrix4} transform The transformation matrix to apply to the bounding sphere.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n *\r\n * @example\r\n * var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(positionOnEllipsoid);\r\n * var boundingSphere = new Cesium.BoundingSphere();\r\n * var newBoundingSphere = Cesium.BoundingSphere.transformWithoutScale(boundingSphere, modelMatrix);\r\n */\r\nBoundingSphere.transformWithoutScale = function (sphere, transform, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"sphere\", sphere);\r\n Check.typeOf.object(\"transform\", transform);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new BoundingSphere();\r\n }\r\n\r\n result.center = Matrix4.multiplyByPoint(\r\n transform,\r\n sphere.center,\r\n result.center\r\n );\r\n result.radius = sphere.radius;\r\n\r\n return result;\r\n};\r\n\r\nvar scratchCartesian3 = new Cartesian3();\r\n/**\r\n * The distances calculated by the vector from the center of the bounding sphere to position projected onto direction\r\n * plus/minus the radius of the bounding sphere.\r\n *
\r\n * If you imagine the infinite number of planes with normal direction, this computes the smallest distance to the\r\n * closest and farthest planes from position that intersect the bounding sphere.\r\n *\r\n * @param {BoundingSphere} sphere The bounding sphere to calculate the distance to.\r\n * @param {Cartesian3} position The position to calculate the distance from.\r\n * @param {Cartesian3} direction The direction from position.\r\n * @param {Interval} [result] A Interval to store the nearest and farthest distances.\r\n * @returns {Interval} The nearest and farthest distances on the bounding sphere from position in direction.\r\n */\r\nBoundingSphere.computePlaneDistances = function (\r\n sphere,\r\n position,\r\n direction,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"sphere\", sphere);\r\n Check.typeOf.object(\"position\", position);\r\n Check.typeOf.object(\"direction\", direction);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Interval();\r\n }\r\n\r\n var toCenter = Cartesian3.subtract(\r\n sphere.center,\r\n position,\r\n scratchCartesian3\r\n );\r\n var mag = Cartesian3.dot(direction, toCenter);\r\n\r\n result.start = mag - sphere.radius;\r\n result.stop = mag + sphere.radius;\r\n return result;\r\n};\r\n\r\nvar projectTo2DNormalScratch = new Cartesian3();\r\nvar projectTo2DEastScratch = new Cartesian3();\r\nvar projectTo2DNorthScratch = new Cartesian3();\r\nvar projectTo2DWestScratch = new Cartesian3();\r\nvar projectTo2DSouthScratch = new Cartesian3();\r\nvar projectTo2DCartographicScratch = new Cartographic();\r\nvar projectTo2DPositionsScratch = new Array(8);\r\nfor (var n = 0; n < 8; ++n) {\r\n projectTo2DPositionsScratch[n] = new Cartesian3();\r\n}\r\n\r\nvar projectTo2DProjection = new GeographicProjection();\r\n/**\r\n * Creates a bounding sphere in 2D from a bounding sphere in 3D world coordinates.\r\n *\r\n * @param {BoundingSphere} sphere The bounding sphere to transform to 2D.\r\n * @param {Object} [projection=GeographicProjection] The projection to 2D.\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.projectTo2D = function (sphere, projection, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"sphere\", sphere);\r\n //>>includeEnd('debug');\r\n\r\n projection = defaultValue(projection, projectTo2DProjection);\r\n\r\n var ellipsoid = projection.ellipsoid;\r\n var center = sphere.center;\r\n var radius = sphere.radius;\r\n\r\n var normal;\r\n if (Cartesian3.equals(center, Cartesian3.ZERO)) {\r\n // Bounding sphere is at the center. The geodetic surface normal is not\r\n // defined here so pick the x-axis as a fallback.\r\n normal = Cartesian3.clone(Cartesian3.UNIT_X, projectTo2DNormalScratch);\r\n } else {\r\n normal = ellipsoid.geodeticSurfaceNormal(center, projectTo2DNormalScratch);\r\n }\r\n var east = Cartesian3.cross(\r\n Cartesian3.UNIT_Z,\r\n normal,\r\n projectTo2DEastScratch\r\n );\r\n Cartesian3.normalize(east, east);\r\n var north = Cartesian3.cross(normal, east, projectTo2DNorthScratch);\r\n Cartesian3.normalize(north, north);\r\n\r\n Cartesian3.multiplyByScalar(normal, radius, normal);\r\n Cartesian3.multiplyByScalar(north, radius, north);\r\n Cartesian3.multiplyByScalar(east, radius, east);\r\n\r\n var south = Cartesian3.negate(north, projectTo2DSouthScratch);\r\n var west = Cartesian3.negate(east, projectTo2DWestScratch);\r\n\r\n var positions = projectTo2DPositionsScratch;\r\n\r\n // top NE corner\r\n var corner = positions[0];\r\n Cartesian3.add(normal, north, corner);\r\n Cartesian3.add(corner, east, corner);\r\n\r\n // top NW corner\r\n corner = positions[1];\r\n Cartesian3.add(normal, north, corner);\r\n Cartesian3.add(corner, west, corner);\r\n\r\n // top SW corner\r\n corner = positions[2];\r\n Cartesian3.add(normal, south, corner);\r\n Cartesian3.add(corner, west, corner);\r\n\r\n // top SE corner\r\n corner = positions[3];\r\n Cartesian3.add(normal, south, corner);\r\n Cartesian3.add(corner, east, corner);\r\n\r\n Cartesian3.negate(normal, normal);\r\n\r\n // bottom NE corner\r\n corner = positions[4];\r\n Cartesian3.add(normal, north, corner);\r\n Cartesian3.add(corner, east, corner);\r\n\r\n // bottom NW corner\r\n corner = positions[5];\r\n Cartesian3.add(normal, north, corner);\r\n Cartesian3.add(corner, west, corner);\r\n\r\n // bottom SW corner\r\n corner = positions[6];\r\n Cartesian3.add(normal, south, corner);\r\n Cartesian3.add(corner, west, corner);\r\n\r\n // bottom SE corner\r\n corner = positions[7];\r\n Cartesian3.add(normal, south, corner);\r\n Cartesian3.add(corner, east, corner);\r\n\r\n var length = positions.length;\r\n for (var i = 0; i < length; ++i) {\r\n var position = positions[i];\r\n Cartesian3.add(center, position, position);\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n position,\r\n projectTo2DCartographicScratch\r\n );\r\n projection.project(cartographic, position);\r\n }\r\n\r\n result = BoundingSphere.fromPoints(positions, result);\r\n\r\n // swizzle center components\r\n center = result.center;\r\n var x = center.x;\r\n var y = center.y;\r\n var z = center.z;\r\n center.x = z;\r\n center.y = x;\r\n center.z = y;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines whether or not a sphere is hidden from view by the occluder.\r\n *\r\n * @param {BoundingSphere} sphere The bounding sphere surrounding the occludee object.\r\n * @param {Occluder} occluder The occluder.\r\n * @returns {Boolean} true if the sphere is not visible; otherwise false.\r\n */\r\nBoundingSphere.isOccluded = function (sphere, occluder) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"sphere\", sphere);\r\n Check.typeOf.object(\"occluder\", occluder);\r\n //>>includeEnd('debug');\r\n return !occluder.isBoundingSphereVisible(sphere);\r\n};\r\n\r\n/**\r\n * Compares the provided BoundingSphere componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {BoundingSphere} [left] The first BoundingSphere.\r\n * @param {BoundingSphere} [right] The second BoundingSphere.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nBoundingSphere.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Cartesian3.equals(left.center, right.center) &&\r\n left.radius === right.radius)\r\n );\r\n};\r\n\r\n/**\r\n * Determines which side of a plane the sphere is located.\r\n *\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire sphere is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire sphere is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the sphere\r\n * intersects the plane.\r\n */\r\nBoundingSphere.prototype.intersectPlane = function (plane) {\r\n return BoundingSphere.intersectPlane(this, plane);\r\n};\r\n\r\n/**\r\n * Computes the estimated distance squared from the closest point on a bounding sphere to a point.\r\n *\r\n * @param {Cartesian3} cartesian The point\r\n * @returns {Number} The estimated distance squared from the bounding sphere to the point.\r\n *\r\n * @example\r\n * // Sort bounding spheres from back to front\r\n * spheres.sort(function(a, b) {\r\n * return b.distanceSquaredTo(camera.positionWC) - a.distanceSquaredTo(camera.positionWC);\r\n * });\r\n */\r\nBoundingSphere.prototype.distanceSquaredTo = function (cartesian) {\r\n return BoundingSphere.distanceSquaredTo(this, cartesian);\r\n};\r\n\r\n/**\r\n * The distances calculated by the vector from the center of the bounding sphere to position projected onto direction\r\n * plus/minus the radius of the bounding sphere.\r\n *
\r\n * If you imagine the infinite number of planes with normal direction, this computes the smallest distance to the\r\n * closest and farthest planes from position that intersect the bounding sphere.\r\n *\r\n * @param {Cartesian3} position The position to calculate the distance from.\r\n * @param {Cartesian3} direction The direction from position.\r\n * @param {Interval} [result] A Interval to store the nearest and farthest distances.\r\n * @returns {Interval} The nearest and farthest distances on the bounding sphere from position in direction.\r\n */\r\nBoundingSphere.prototype.computePlaneDistances = function (\r\n position,\r\n direction,\r\n result\r\n) {\r\n return BoundingSphere.computePlaneDistances(\r\n this,\r\n position,\r\n direction,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Determines whether or not a sphere is hidden from view by the occluder.\r\n *\r\n * @param {Occluder} occluder The occluder.\r\n * @returns {Boolean} true if the sphere is not visible; otherwise false.\r\n */\r\nBoundingSphere.prototype.isOccluded = function (occluder) {\r\n return BoundingSphere.isOccluded(this, occluder);\r\n};\r\n\r\n/**\r\n * Compares this BoundingSphere against the provided BoundingSphere componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {BoundingSphere} [right] The right hand side BoundingSphere.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nBoundingSphere.prototype.equals = function (right) {\r\n return BoundingSphere.equals(this, right);\r\n};\r\n\r\n/**\r\n * Duplicates this BoundingSphere instance.\r\n *\r\n * @param {BoundingSphere} [result] The object onto which to store the result.\r\n * @returns {BoundingSphere} The modified result parameter or a new BoundingSphere instance if none was provided.\r\n */\r\nBoundingSphere.prototype.clone = function (result) {\r\n return BoundingSphere.clone(this, result);\r\n};\r\n\r\n/**\r\n * Computes the radius of the BoundingSphere.\r\n * @returns {Number} The radius of the BoundingSphere.\r\n */\r\nBoundingSphere.prototype.volume = function () {\r\n var radius = this.radius;\r\n return volumeConstant * radius * radius * radius;\r\n};\r\nexport default BoundingSphere;\r\n","/**\r\n * @license\r\n *\r\n * Grauw URI utilities\r\n *\r\n * See: http://hg.grauw.nl/grauw-lib/file/tip/src/uri.js\r\n *\r\n * @author Laurens Holst (http://www.grauw.nl/)\r\n *\r\n * Copyright 2012 Laurens Holst\r\n *\r\n * Licensed under the Apache License, Version 2.0 (the \"License\");\r\n * you may not use this file except in compliance with the License.\r\n * You may obtain a copy of the License at\r\n *\r\n * http://www.apache.org/licenses/LICENSE-2.0\r\n *\r\n * Unless required by applicable law or agreed to in writing, software\r\n * distributed under the License is distributed on an \"AS IS\" BASIS,\r\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n * See the License for the specific language governing permissions and\r\n * limitations under the License.\r\n *\r\n */\r\n\r\n\t/**\r\n\t * Constructs a URI object.\r\n\t * @constructor\r\n\t * @class Implementation of URI parsing and base URI resolving algorithm in RFC 3986.\r\n\t * @param {string|URI} uri A string or URI object to create the object from.\r\n\t */\r\n\tfunction URI(uri) {\r\n\t\tif (uri instanceof URI) { // copy constructor\r\n\t\t\tthis.scheme = uri.scheme;\r\n\t\t\tthis.authority = uri.authority;\r\n\t\t\tthis.path = uri.path;\r\n\t\t\tthis.query = uri.query;\r\n\t\t\tthis.fragment = uri.fragment;\r\n\t\t} else if (uri) { // uri is URI string or cast to string\r\n\t\t\tvar c = parseRegex.exec(uri);\r\n\t\t\tthis.scheme = c[1];\r\n\t\t\tthis.authority = c[2];\r\n\t\t\tthis.path = c[3];\r\n\t\t\tthis.query = c[4];\r\n\t\t\tthis.fragment = c[5];\r\n\t\t}\r\n\t}\r\n\t// Initial values on the prototype\r\n\tURI.prototype.scheme = null;\r\n\tURI.prototype.authority = null;\r\n\tURI.prototype.path = '';\r\n\tURI.prototype.query = null;\r\n\tURI.prototype.fragment = null;\r\n\r\n\t// Regular expression from RFC 3986 appendix B\r\n\tvar parseRegex = new RegExp('^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\\\\?([^#]*))?(?:#(.*))?$');\r\n\r\n\t/**\r\n\t * Returns the scheme part of the URI.\r\n\t * In \"http://example.com:80/a/b?x#y\" this is \"http\".\r\n\t */\r\n\tURI.prototype.getScheme = function() {\r\n\t\treturn this.scheme;\r\n\t};\r\n\r\n\t/**\r\n\t * Returns the authority part of the URI.\r\n\t * In \"http://example.com:80/a/b?x#y\" this is \"example.com:80\".\r\n\t */\r\n\tURI.prototype.getAuthority = function() {\r\n\t\treturn this.authority;\r\n\t};\r\n\r\n\t/**\r\n\t * Returns the path part of the URI.\r\n\t * In \"http://example.com:80/a/b?x#y\" this is \"/a/b\".\r\n\t * In \"mailto:mike@example.com\" this is \"mike@example.com\".\r\n\t */\r\n\tURI.prototype.getPath = function() {\r\n\t\treturn this.path;\r\n\t};\r\n\r\n\t/**\r\n\t * Returns the query part of the URI.\r\n\t * In \"http://example.com:80/a/b?x#y\" this is \"x\".\r\n\t */\r\n\tURI.prototype.getQuery = function() {\r\n\t\treturn this.query;\r\n\t};\r\n\r\n\t/**\r\n\t * Returns the fragment part of the URI.\r\n\t * In \"http://example.com:80/a/b?x#y\" this is \"y\".\r\n\t */\r\n\tURI.prototype.getFragment = function() {\r\n\t\treturn this.fragment;\r\n\t};\r\n\r\n\t/**\r\n\t * Tests whether the URI is an absolute URI.\r\n\t * See RFC 3986 section 4.3.\r\n\t */\r\n\tURI.prototype.isAbsolute = function() {\r\n\t\treturn !!this.scheme && !this.fragment;\r\n\t};\r\n\r\n\t///**\r\n\t//* Extensive validation of the URI against the ABNF in RFC 3986\r\n\t//*/\r\n\t//URI.prototype.validate\r\n\r\n\t/**\r\n\t * Tests whether the URI is a same-document reference.\r\n\t * See RFC 3986 section 4.4.\r\n\t *\r\n\t * To perform more thorough comparison, you can normalise the URI objects.\r\n\t */\r\n\tURI.prototype.isSameDocumentAs = function(uri) {\r\n\t\treturn uri.scheme == this.scheme &&\r\n\t\t uri.authority == this.authority &&\r\n\t\t uri.path == this.path &&\r\n\t\t uri.query == this.query;\r\n\t};\r\n\r\n\t/**\r\n\t * Simple String Comparison of two URIs.\r\n\t * See RFC 3986 section 6.2.1.\r\n\t *\r\n\t * To perform more thorough comparison, you can normalise the URI objects.\r\n\t */\r\n\tURI.prototype.equals = function(uri) {\r\n\t\treturn this.isSameDocumentAs(uri) && uri.fragment == this.fragment;\r\n\t};\r\n\r\n\t/**\r\n\t * Normalizes the URI using syntax-based normalization.\r\n\t * This includes case normalization, percent-encoding normalization and path segment normalization.\r\n\t * XXX: Percent-encoding normalization does not escape characters that need to be escaped.\r\n\t * (Although that would not be a valid URI in the first place. See validate().)\r\n\t * See RFC 3986 section 6.2.2.\r\n\t */\r\n\tURI.prototype.normalize = function() {\r\n\t\tthis.removeDotSegments();\r\n\t\tif (this.scheme)\r\n\t\t\tthis.scheme = this.scheme.toLowerCase();\r\n\t\tif (this.authority)\r\n\t\t\tthis.authority = this.authority.replace(authorityRegex, replaceAuthority).\r\n\t\t\t\t\t\t\t\t\treplace(caseRegex, replaceCase);\r\n\t\tif (this.path)\r\n\t\t\tthis.path = this.path.replace(caseRegex, replaceCase);\r\n\t\tif (this.query)\r\n\t\t\tthis.query = this.query.replace(caseRegex, replaceCase);\r\n\t\tif (this.fragment)\r\n\t\t\tthis.fragment = this.fragment.replace(caseRegex, replaceCase);\r\n\t};\r\n\r\n\tvar caseRegex = /%[0-9a-z]{2}/gi;\r\n\tvar percentRegex = /[a-zA-Z0-9\\-\\._~]/;\r\n\tvar authorityRegex = /(.*@)?([^@:]*)(:.*)?/;\r\n\r\n\tfunction replaceCase(str) {\r\n\t\tvar dec = unescape(str);\r\n\t\treturn percentRegex.test(dec) ? dec : str.toUpperCase();\r\n\t}\r\n\r\n\tfunction replaceAuthority(str, p1, p2, p3) {\r\n\t\treturn (p1 || '') + p2.toLowerCase() + (p3 || '');\r\n\t}\r\n\r\n\t/**\r\n\t * Resolve a relative URI (this) against a base URI.\r\n\t * The base URI must be an absolute URI.\r\n\t * See RFC 3986 section 5.2\r\n\t */\r\n\tURI.prototype.resolve = function(baseURI) {\r\n\t\tvar uri = new URI();\r\n\t\tif (this.scheme) {\r\n\t\t\turi.scheme = this.scheme;\r\n\t\t\turi.authority = this.authority;\r\n\t\t\turi.path = this.path;\r\n\t\t\turi.query = this.query;\r\n\t\t} else {\r\n\t\t\turi.scheme = baseURI.scheme;\r\n\t\t\tif (this.authority) {\r\n\t\t\t\turi.authority = this.authority;\r\n\t\t\t\turi.path = this.path;\r\n\t\t\t\turi.query = this.query;\r\n\t\t\t} else {\r\n\t\t\t\turi.authority = baseURI.authority;\r\n\t\t\t\tif (this.path == '') {\r\n\t\t\t\t\turi.path = baseURI.path;\r\n\t\t\t\t\turi.query = this.query || baseURI.query;\r\n\t\t\t\t} else {\r\n\t\t\t\t\tif (this.path.charAt(0) == '/') {\r\n\t\t\t\t\t\turi.path = this.path;\r\n\t\t\t\t\t\turi.removeDotSegments();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tif (baseURI.authority && baseURI.path == '') {\r\n\t\t\t\t\t\t\turi.path = '/' + this.path;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\turi.path = baseURI.path.substring(0, baseURI.path.lastIndexOf('/') + 1) + this.path;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\turi.removeDotSegments();\r\n\t\t\t\t\t}\r\n\t\t\t\t\turi.query = this.query;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\turi.fragment = this.fragment;\r\n\t\treturn uri;\r\n\t};\r\n\r\n\t/**\r\n\t * Remove dot segments from path.\r\n\t * See RFC 3986 section 5.2.4\r\n\t * @private\r\n\t */\r\n\tURI.prototype.removeDotSegments = function() {\r\n\t\tvar input = this.path.split('/'),\r\n\t\t\toutput = [],\r\n\t\t\tsegment,\r\n\t\t\tabsPath = input[0] == '';\r\n\t\tif (absPath)\r\n\t\t\tinput.shift();\r\n\t\tvar sFirst = input[0] == '' ? input.shift() : null;\r\n\t\twhile (input.length) {\r\n\t\t\tsegment = input.shift();\r\n\t\t\tif (segment == '..') {\r\n\t\t\t\toutput.pop();\r\n\t\t\t} else if (segment != '.') {\r\n\t\t\t\toutput.push(segment);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (segment == '.' || segment == '..')\r\n\t\t\toutput.push('');\r\n\t\tif (absPath)\r\n\t\t\toutput.unshift('');\r\n\t\tthis.path = output.join('/');\r\n\t};\r\n\r\n\t// We don't like this function because it builds up a cache that is never cleared.\r\n//\t/**\r\n//\t * Resolves a relative URI against an absolute base URI.\r\n//\t * Convenience method.\r\n//\t * @param {String} uri the relative URI to resolve\r\n//\t * @param {String} baseURI the base URI (must be absolute) to resolve against\r\n//\t */\r\n//\tURI.resolve = function(sURI, sBaseURI) {\r\n//\t\tvar uri = cache[sURI] || (cache[sURI] = new URI(sURI));\r\n//\t\tvar baseURI = cache[sBaseURI] || (cache[sBaseURI] = new URI(sBaseURI));\r\n//\t\treturn uri.resolve(baseURI).toString();\r\n//\t};\r\n\r\n//\tvar cache = {};\r\n\r\n\t/**\r\n\t * Serialises the URI to a string.\r\n\t */\r\n\tURI.prototype.toString = function() {\r\n\t\tvar result = '';\r\n\t\tif (this.scheme)\r\n\t\t\tresult += this.scheme + ':';\r\n\t\tif (this.authority)\r\n\t\t\tresult += '//' + this.authority;\r\n\t\tresult += this.path;\r\n\t\tif (this.query)\r\n\t\t\tresult += '?' + this.query;\r\n\t\tif (this.fragment)\r\n\t\t\tresult += '#' + this.fragment;\r\n\t\treturn result;\r\n\t};\r\n\r\nexport default URI;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Given a relative Uri and a base Uri, returns the absolute Uri of the relative Uri.\r\n * @function\r\n *\r\n * @param {String} relative The relative Uri.\r\n * @param {String} [base] The base Uri.\r\n * @returns {String} The absolute Uri of the given relative Uri.\r\n *\r\n * @example\r\n * //absolute Uri will be \"https://test.com/awesome.png\";\r\n * var absoluteUri = Cesium.getAbsoluteUri('awesome.png', 'https://test.com');\r\n */\r\nfunction getAbsoluteUri(relative, base) {\r\n var documentObject;\r\n if (typeof document !== \"undefined\") {\r\n documentObject = document;\r\n }\r\n\r\n return getAbsoluteUri._implementation(relative, base, documentObject);\r\n}\r\n\r\ngetAbsoluteUri._implementation = function (relative, base, documentObject) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(relative)) {\r\n throw new DeveloperError(\"relative uri is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(base)) {\r\n if (typeof documentObject === \"undefined\") {\r\n return relative;\r\n }\r\n base = defaultValue(documentObject.baseURI, documentObject.location.href);\r\n }\r\n\r\n var baseUri = new Uri(base);\r\n var relativeUri = new Uri(relative);\r\n return relativeUri.resolve(baseUri).toString();\r\n};\r\nexport default getAbsoluteUri;\r\n","/**\r\n @license\r\n when.js - https://github.com/cujojs/when\r\n\r\n MIT License (c) copyright B Cavalier & J Hann\r\n\r\n * A lightweight CommonJS Promises/A and when() implementation\r\n * when is part of the cujo.js family of libraries (http://cujojs.com/)\r\n *\r\n * Licensed under the MIT License at:\r\n * http://www.opensource.org/licenses/mit-license.php\r\n *\r\n * @version 1.7.1\r\n */\r\n\r\n\tvar reduceArray, slice, undef;\r\n\r\n\t//\r\n\t// Public API\r\n\t//\r\n\r\n\twhen.defer = defer; // Create a deferred\r\n\twhen.resolve = resolve; // Create a resolved promise\r\n\twhen.reject = reject; // Create a rejected promise\r\n\r\n\twhen.join = join; // Join 2 or more promises\r\n\r\n\twhen.all = all; // Resolve a list of promises\r\n\twhen.map = map; // Array.map() for promises\r\n\twhen.reduce = reduce; // Array.reduce() for promises\r\n\r\n\twhen.any = any; // One-winner race\r\n\twhen.some = some; // Multi-winner race\r\n\r\n\twhen.chain = chain; // Make a promise trigger another resolver\r\n\r\n\twhen.isPromise = isPromise; // Determine if a thing is a promise\r\n\r\n\t/**\r\n\t * Register an observer for a promise or immediate value.\r\n\t *\r\n\t * @param {*} promiseOrValue\r\n\t * @param {function?} [onFulfilled] callback to be called when promiseOrValue is\r\n\t * successfully fulfilled. If promiseOrValue is an immediate value, callback\r\n\t * will be invoked immediately.\r\n\t * @param {function?} [onRejected] callback to be called when promiseOrValue is\r\n\t * rejected.\r\n\t * @param {function?} [onProgress] callback to be called when progress updates\r\n\t * are issued for promiseOrValue.\r\n\t * @returns {Promise} a new {@link Promise} that will complete with the return\r\n\t * value of callback or errback or the completion value of promiseOrValue if\r\n\t * callback and/or errback is not supplied.\r\n\t */\r\n\tfunction when(promiseOrValue, onFulfilled, onRejected, onProgress) {\r\n\t\t// Get a trusted promise for the input promiseOrValue, and then\r\n\t\t// register promise handlers\r\n\t\treturn resolve(promiseOrValue).then(onFulfilled, onRejected, onProgress);\r\n\t}\r\n\r\n\t/**\r\n\t * Returns promiseOrValue if promiseOrValue is a {@link Promise}, a new Promise if\r\n\t * promiseOrValue is a foreign promise, or a new, already-fulfilled {@link Promise}\r\n\t * whose value is promiseOrValue if promiseOrValue is an immediate value.\r\n\t *\r\n\t * @param {*} promiseOrValue\r\n\t * @returns Guaranteed to return a trusted Promise. If promiseOrValue is a when.js {@link Promise}\r\n\t * returns promiseOrValue, otherwise, returns a new, already-resolved, when.js {@link Promise}\r\n\t * whose resolution value is:\r\n\t * * the resolution value of promiseOrValue if it's a foreign promise, or\r\n\t * * promiseOrValue if it's a value\r\n\t */\r\n\tfunction resolve(promiseOrValue) {\r\n\t\tvar promise, deferred;\r\n\r\n\t\tif(promiseOrValue instanceof Promise) {\r\n\t\t\t// It's a when.js promise, so we trust it\r\n\t\t\tpromise = promiseOrValue;\r\n\r\n\t\t} else {\r\n\t\t\t// It's not a when.js promise. See if it's a foreign promise or a value.\r\n\t\t\tif(isPromise(promiseOrValue)) {\r\n\t\t\t\t// It's a thenable, but we don't know where it came from, so don't trust\r\n\t\t\t\t// its implementation entirely. Introduce a trusted middleman when.js promise\r\n\t\t\t\tdeferred = defer();\r\n\r\n\t\t\t\t// IMPORTANT: This is the only place when.js should ever call .then() on an\r\n\t\t\t\t// untrusted promise. Don't expose the return value to the untrusted promise\r\n\t\t\t\tpromiseOrValue.then(\r\n\t\t\t\t\tfunction(value) { deferred.resolve(value); },\r\n\t\t\t\t\tfunction(reason) { deferred.reject(reason); },\r\n\t\t\t\t\tfunction(update) { deferred.progress(update); }\r\n\t\t\t\t);\r\n\r\n\t\t\t\tpromise = deferred.promise;\r\n\r\n\t\t\t} else {\r\n\t\t\t\t// It's a value, not a promise. Create a resolved promise for it.\r\n\t\t\t\tpromise = fulfilled(promiseOrValue);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn promise;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns a rejected promise for the supplied promiseOrValue. The returned\r\n\t * promise will be rejected with:\r\n\t * - promiseOrValue, if it is a value, or\r\n\t * - if promiseOrValue is a promise\r\n\t * - promiseOrValue's value after it is fulfilled\r\n\t * - promiseOrValue's reason after it is rejected\r\n\t * @param {*} promiseOrValue the rejected value of the returned {@link Promise}\r\n\t * @returns {Promise} rejected {@link Promise}\r\n\t */\r\n\tfunction reject(promiseOrValue) {\r\n\t\treturn when(promiseOrValue, rejected);\r\n\t}\r\n\r\n\t/**\r\n\t * Trusted Promise constructor. A Promise created from this constructor is\r\n\t * a trusted when.js promise. Any other duck-typed promise is considered\r\n\t * untrusted.\r\n\t * @constructor\r\n\t * @name Promise\r\n\t */\r\n\tfunction Promise(then) {\r\n\t\tthis.then = then;\r\n\t}\r\n\r\n\tPromise.prototype = {\r\n\t\t/**\r\n\t\t * Register a callback that will be called when a promise is\r\n\t\t * fulfilled or rejected. Optionally also register a progress handler.\r\n\t\t * Shortcut for .then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress)\r\n\t\t * @param {function?} [onFulfilledOrRejected]\r\n\t\t * @param {function?} [onProgress]\r\n\t\t * @returns {Promise}\r\n\t\t */\r\n\t\talways: function(onFulfilledOrRejected, onProgress) {\r\n\t\t\treturn this.then(onFulfilledOrRejected, onFulfilledOrRejected, onProgress);\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Register a rejection handler. Shortcut for .then(undefined, onRejected)\r\n\t\t * @param {function?} onRejected\r\n\t\t * @returns {Promise}\r\n\t\t */\r\n\t\totherwise: function(onRejected) {\r\n\t\t\treturn this.then(undef, onRejected);\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Shortcut for .then(function() { return value; })\r\n\t\t * @param {*} value\r\n\t\t * @returns {Promise} a promise that:\r\n\t\t * - is fulfilled if value is not a promise, or\r\n\t\t * - if value is a promise, will fulfill with its value, or reject\r\n\t\t * with its reason.\r\n\t\t */\r\n\t\tyield: function(value) {\r\n\t\t\treturn this.then(function() {\r\n\t\t\t\treturn value;\r\n\t\t\t});\r\n\t\t},\r\n\r\n\t\t/**\r\n\t\t * Assumes that this promise will fulfill with an array, and arranges\r\n\t\t * for the onFulfilled to be called with the array as its argument list\r\n\t\t * i.e. onFulfilled.spread(undefined, array).\r\n\t\t * @param {function} onFulfilled function to receive spread arguments\r\n\t\t * @returns {Promise}\r\n\t\t */\r\n\t\tspread: function(onFulfilled) {\r\n\t\t\treturn this.then(function(array) {\r\n\t\t\t\t// array may contain promises, so resolve its contents.\r\n\t\t\t\treturn all(array, function(array) {\r\n\t\t\t\t\treturn onFulfilled.apply(undef, array);\r\n\t\t\t\t});\r\n\t\t\t});\r\n\t\t}\r\n\t};\r\n\r\n\t/**\r\n\t * Create an already-resolved promise for the supplied value\r\n\t * @private\r\n\t *\r\n\t * @param {*} value\r\n\t * @returns {Promise} fulfilled promise\r\n\t */\r\n\tfunction fulfilled(value) {\r\n\t\tvar p = new Promise(function(onFulfilled) {\r\n\t\t\t// TODO: Promises/A+ check typeof onFulfilled\r\n\t\t\ttry {\r\n\t\t\t\treturn resolve(onFulfilled ? onFulfilled(value) : value);\r\n\t\t\t} catch(e) {\r\n\t\t\t\treturn rejected(e);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn p;\r\n\t}\r\n\r\n\t/**\r\n\t * Create an already-rejected {@link Promise} with the supplied\r\n\t * rejection reason.\r\n\t * @private\r\n\t *\r\n\t * @param {*} reason\r\n\t * @returns {Promise} rejected promise\r\n\t */\r\n\tfunction rejected(reason) {\r\n\t\tvar p = new Promise(function(_, onRejected) {\r\n\t\t\t// TODO: Promises/A+ check typeof onRejected\r\n\t\t\ttry {\r\n\t\t\t\treturn onRejected ? resolve(onRejected(reason)) : rejected(reason);\r\n\t\t\t} catch(e) {\r\n\t\t\t\treturn rejected(e);\r\n\t\t\t}\r\n\t\t});\r\n\r\n\t\treturn p;\r\n\t}\r\n\r\n\t/**\r\n\t * Creates a new, Deferred with fully isolated resolver and promise parts,\r\n\t * either or both of which may be given out safely to consumers.\r\n\t * The Deferred itself has the full API: resolve, reject, progress, and\r\n\t * then. The resolver has resolve, reject, and progress. The promise\r\n\t * only has then.\r\n\t *\r\n\t * @returns {Deferred}\r\n\t */\r\n\tfunction defer() {\r\n\t\tvar deferred, promise, handlers, progressHandlers,\r\n\t\t\t_then, _progress, _resolve;\r\n\r\n\t\t/**\r\n\t\t * The promise for the new deferred\r\n\t\t * @type {Promise}\r\n\t\t */\r\n\t\tpromise = new Promise(then);\r\n\r\n\t\t/**\r\n\t\t * The full Deferred object, with {@link Promise} and {@link Resolver} parts\r\n\t\t * @class Deferred\r\n\t\t * @name Deferred\r\n\t\t */\r\n\t\tdeferred = {\r\n\t\t\tthen: then, // DEPRECATED: use deferred.promise.then\r\n\t\t\tresolve: promiseResolve,\r\n\t\t\treject: promiseReject,\r\n\t\t\t// TODO: Consider renaming progress() to notify()\r\n\t\t\tprogress: promiseProgress,\r\n\r\n\t\t\tpromise: promise,\r\n\r\n\t\t\tresolver: {\r\n\t\t\t\tresolve: promiseResolve,\r\n\t\t\t\treject: promiseReject,\r\n\t\t\t\tprogress: promiseProgress\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\thandlers = [];\r\n\t\tprogressHandlers = [];\r\n\r\n\t\t/**\r\n\t\t * Pre-resolution then() that adds the supplied callback, errback, and progback\r\n\t\t * functions to the registered listeners\r\n\t\t * @private\r\n\t\t *\r\n\t\t * @param {function?} [onFulfilled] resolution handler\r\n\t\t * @param {function?} [onRejected] rejection handler\r\n\t\t * @param {function?} [onProgress] progress handler\r\n\t\t */\r\n\t\t_then = function(onFulfilled, onRejected, onProgress) {\r\n\t\t\t// TODO: Promises/A+ check typeof onFulfilled, onRejected, onProgress\r\n\t\t\tvar deferred, progressHandler;\r\n\r\n\t\t\tdeferred = defer();\r\n\r\n\t\t\tprogressHandler = typeof onProgress === 'function'\r\n\t\t\t\t? function(update) {\r\n\t\t\t\t\ttry {\r\n\t\t\t\t\t\t// Allow progress handler to transform progress event\r\n\t\t\t\t\t\tdeferred.progress(onProgress(update));\r\n\t\t\t\t\t} catch(e) {\r\n\t\t\t\t\t\t// Use caught value as progress\r\n\t\t\t\t\t\tdeferred.progress(e);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\t: function(update) { deferred.progress(update); };\r\n\r\n\t\t\thandlers.push(function(promise) {\r\n\t\t\t\tpromise.then(onFulfilled, onRejected)\r\n\t\t\t\t\t.then(deferred.resolve, deferred.reject, progressHandler);\r\n\t\t\t});\r\n\r\n\t\t\tprogressHandlers.push(progressHandler);\r\n\r\n\t\t\treturn deferred.promise;\r\n\t\t};\r\n\r\n\t\t/**\r\n\t\t * Issue a progress event, notifying all progress listeners\r\n\t\t * @private\r\n\t\t * @param {*} update progress event payload to pass to all listeners\r\n\t\t */\r\n\t\t_progress = function(update) {\r\n\t\t\tprocessQueue(progressHandlers, update);\r\n\t\t\treturn update;\r\n\t\t};\r\n\r\n\t\t/**\r\n\t\t * Transition from pre-resolution state to post-resolution state, notifying\r\n\t\t * all listeners of the resolution or rejection\r\n\t\t * @private\r\n\t\t * @param {*} value the value of this deferred\r\n\t\t */\r\n\t\t_resolve = function(value) {\r\n\t\t\tvalue = resolve(value);\r\n\r\n\t\t\t// Replace _then with one that directly notifies with the result.\r\n\t\t\t_then = value.then;\r\n\t\t\t// Replace _resolve so that this Deferred can only be resolved once\r\n\t\t\t_resolve = resolve;\r\n\t\t\t// Make _progress a noop, to disallow progress for the resolved promise.\r\n\t\t\t_progress = noop;\r\n\r\n\t\t\t// Notify handlers\r\n\t\t\tprocessQueue(handlers, value);\r\n\r\n\t\t\t// Free progressHandlers array since we'll never issue progress events\r\n\t\t\tprogressHandlers = handlers = undef;\r\n\r\n\t\t\treturn value;\r\n\t\t};\r\n\r\n\t\treturn deferred;\r\n\r\n\t\t/**\r\n\t\t * Wrapper to allow _then to be replaced safely\r\n\t\t * @param {function?} [onFulfilled] resolution handler\r\n\t\t * @param {function?} [onRejected] rejection handler\r\n\t\t * @param {function?} [onProgress] progress handler\r\n\t\t * @returns {Promise} new promise\r\n\t\t */\r\n\t\tfunction then(onFulfilled, onRejected, onProgress) {\r\n\t\t\t// TODO: Promises/A+ check typeof onFulfilled, onRejected, onProgress\r\n\t\t\treturn _then(onFulfilled, onRejected, onProgress);\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Wrapper to allow _resolve to be replaced\r\n\t\t */\r\n\t\tfunction promiseResolve(val) {\r\n\t\t\treturn _resolve(val);\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Wrapper to allow _reject to be replaced\r\n\t\t */\r\n\t\tfunction promiseReject(err) {\r\n\t\t\treturn _resolve(rejected(err));\r\n\t\t}\r\n\r\n\t\t/**\r\n\t\t * Wrapper to allow _progress to be replaced\r\n\t\t */\r\n\t\tfunction promiseProgress(update) {\r\n\t\t\treturn _progress(update);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Determines if promiseOrValue is a promise or not. Uses the feature\r\n\t * test from http://wiki.commonjs.org/wiki/Promises/A to determine if\r\n\t * promiseOrValue is a promise.\r\n\t *\r\n\t * @param {*} promiseOrValue anything\r\n\t * @returns {boolean} true if promiseOrValue is a {@link Promise}\r\n\t */\r\n\tfunction isPromise(promiseOrValue) {\r\n\t\treturn promiseOrValue && typeof promiseOrValue.then === 'function';\r\n\t}\r\n\r\n\t/**\r\n\t * Initiates a competitive race, returning a promise that will resolve when\r\n\t * howMany of the supplied promisesOrValues have resolved, or will reject when\r\n\t * it becomes impossible for howMany to resolve, for example, when\r\n\t * (promisesOrValues.length - howMany) + 1 input promises reject.\r\n\t *\r\n\t * @param {Array} promisesOrValues array of anything, may contain a mix\r\n\t * of promises and values\r\n\t * @param howMany {number} number of promisesOrValues to resolve\r\n\t * @param {function?} [onFulfilled] resolution handler\r\n\t * @param {function?} [onRejected] rejection handler\r\n\t * @param {function?} [onProgress] progress handler\r\n\t * @returns {Promise} promise that will resolve to an array of howMany values that\r\n\t * resolved first, or will reject with an array of (promisesOrValues.length - howMany) + 1\r\n\t * rejection reasons.\r\n\t */\r\n\tfunction some(promisesOrValues, howMany, onFulfilled, onRejected, onProgress) {\r\n\r\n\t\tcheckCallbacks(2, arguments);\r\n\r\n\t\treturn when(promisesOrValues, function(promisesOrValues) {\r\n\r\n\t\t\tvar toResolve, toReject, values, reasons, deferred, fulfillOne, rejectOne, progress, len, i;\r\n\r\n\t\t\tlen = promisesOrValues.length >>> 0;\r\n\r\n\t\t\ttoResolve = Math.max(0, Math.min(howMany, len));\r\n\t\t\tvalues = [];\r\n\r\n\t\t\ttoReject = (len - toResolve) + 1;\r\n\t\t\treasons = [];\r\n\r\n\t\t\tdeferred = defer();\r\n\r\n\t\t\t// No items in the input, resolve immediately\r\n\t\t\tif (!toResolve) {\r\n\t\t\t\tdeferred.resolve(values);\r\n\r\n\t\t\t} else {\r\n\t\t\t\tprogress = deferred.progress;\r\n\r\n\t\t\t\trejectOne = function(reason) {\r\n\t\t\t\t\treasons.push(reason);\r\n\t\t\t\t\tif(!--toReject) {\r\n\t\t\t\t\t\tfulfillOne = rejectOne = noop;\r\n\t\t\t\t\t\tdeferred.reject(reasons);\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\r\n\t\t\t\tfulfillOne = function(val) {\r\n\t\t\t\t\t// This orders the values based on promise resolution order\r\n\t\t\t\t\t// Another strategy would be to use the original position of\r\n\t\t\t\t\t// the corresponding promise.\r\n\t\t\t\t\tvalues.push(val);\r\n\r\n\t\t\t\t\tif (!--toResolve) {\r\n\t\t\t\t\t\tfulfillOne = rejectOne = noop;\r\n\t\t\t\t\t\tdeferred.resolve(values);\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\r\n\t\t\t\tfor(i = 0; i < len; ++i) {\r\n\t\t\t\t\tif(i in promisesOrValues) {\r\n\t\t\t\t\t\twhen(promisesOrValues[i], fulfiller, rejecter, progress);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn deferred.then(onFulfilled, onRejected, onProgress);\r\n\r\n\t\t\tfunction rejecter(reason) {\r\n\t\t\t\trejectOne(reason);\r\n\t\t\t}\r\n\r\n\t\t\tfunction fulfiller(val) {\r\n\t\t\t\tfulfillOne(val);\r\n\t\t\t}\r\n\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Initiates a competitive race, returning a promise that will resolve when\r\n\t * any one of the supplied promisesOrValues has resolved or will reject when\r\n\t * *all* promisesOrValues have rejected.\r\n\t *\r\n\t * @param {Array|Promise} promisesOrValues array of anything, may contain a mix\r\n\t * of {@link Promise}s and values\r\n\t * @param {function?} [onFulfilled] resolution handler\r\n\t * @param {function?} [onRejected] rejection handler\r\n\t * @param {function?} [onProgress] progress handler\r\n\t * @returns {Promise} promise that will resolve to the value that resolved first, or\r\n\t * will reject with an array of all rejected inputs.\r\n\t */\r\n\tfunction any(promisesOrValues, onFulfilled, onRejected, onProgress) {\r\n\r\n\t\tfunction unwrapSingleResult(val) {\r\n\t\t\treturn onFulfilled ? onFulfilled(val[0]) : val[0];\r\n\t\t}\r\n\r\n\t\treturn some(promisesOrValues, 1, unwrapSingleResult, onRejected, onProgress);\r\n\t}\r\n\r\n\t/**\r\n\t * Return a promise that will resolve only once all the supplied promisesOrValues\r\n\t * have resolved. The resolution value of the returned promise will be an array\r\n\t * containing the resolution values of each of the promisesOrValues.\r\n\t * @memberOf when\r\n\t *\r\n\t * @param {Array|Promise} promisesOrValues array of anything, may contain a mix\r\n\t * of {@link Promise}s and values\r\n\t * @param {function?} [onFulfilled] resolution handler\r\n\t * @param {function?} [onRejected] rejection handler\r\n\t * @param {function?} [onProgress] progress handler\r\n\t * @returns {Promise}\r\n\t */\r\n\tfunction all(promisesOrValues, onFulfilled, onRejected, onProgress) {\r\n\t\tcheckCallbacks(1, arguments);\r\n\t\treturn map(promisesOrValues, identity).then(onFulfilled, onRejected, onProgress);\r\n\t}\r\n\r\n\t/**\r\n\t * Joins multiple promises into a single returned promise.\r\n\t * @returns {Promise} a promise that will fulfill when *all* the input promises\r\n\t * have fulfilled, or will reject when *any one* of the input promises rejects.\r\n\t */\r\n\tfunction join(/* ...promises */) {\r\n\t\treturn map(arguments, identity);\r\n\t}\r\n\r\n\t/**\r\n\t * Traditional map function, similar to `Array.prototype.map()`, but allows\r\n\t * input to contain {@link Promise}s and/or values, and mapFunc may return\r\n\t * either a value or a {@link Promise}\r\n\t *\r\n\t * @param {Array|Promise} promise array of anything, may contain a mix\r\n\t * of {@link Promise}s and values\r\n\t * @param {function} mapFunc mapping function mapFunc(value) which may return\r\n\t * either a {@link Promise} or value\r\n\t * @returns {Promise} a {@link Promise} that will resolve to an array containing\r\n\t * the mapped output values.\r\n\t */\r\n\tfunction map(promise, mapFunc) {\r\n\t\treturn when(promise, function(array) {\r\n\t\t\tvar results, len, toResolve, resolve, i, d;\r\n\r\n\t\t\t// Since we know the resulting length, we can preallocate the results\r\n\t\t\t// array to avoid array expansions.\r\n\t\t\ttoResolve = len = array.length >>> 0;\r\n\t\t\tresults = [];\r\n\t\t\td = defer();\r\n\r\n\t\t\tif(!toResolve) {\r\n\t\t\t\td.resolve(results);\r\n\t\t\t} else {\r\n\r\n\t\t\t\tresolve = function resolveOne(item, i) {\r\n\t\t\t\t\twhen(item, mapFunc).then(function(mapped) {\r\n\t\t\t\t\t\tresults[i] = mapped;\r\n\r\n\t\t\t\t\t\tif(!--toResolve) {\r\n\t\t\t\t\t\t\td.resolve(results);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}, d.reject);\r\n\t\t\t\t};\r\n\r\n\t\t\t\t// Since mapFunc may be async, get all invocations of it into flight\r\n\t\t\t\tfor(i = 0; i < len; i++) {\r\n\t\t\t\t\tif(i in array) {\r\n\t\t\t\t\t\tresolve(array[i], i);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\t--toResolve;\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t}\r\n\r\n\t\t\treturn d.promise;\r\n\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Traditional reduce function, similar to `Array.prototype.reduce()`, but\r\n\t * input may contain promises and/or values, and reduceFunc\r\n\t * may return either a value or a promise, *and* initialValue may\r\n\t * be a promise for the starting value.\r\n\t *\r\n\t * @param {Array|Promise} promise array or promise for an array of anything,\r\n\t * may contain a mix of promises and values.\r\n\t * @param {function} reduceFunc reduce function reduce(currentValue, nextValue, index, total),\r\n\t * where total is the total number of items being reduced, and will be the same\r\n\t * in each call to reduceFunc.\r\n\t * @returns {Promise} that will resolve to the final reduced value\r\n\t */\r\n\tfunction reduce(promise, reduceFunc /*, initialValue */) {\r\n\t\tvar args = slice.call(arguments, 1);\r\n\r\n\t\treturn when(promise, function(array) {\r\n\t\t\tvar total;\r\n\r\n\t\t\ttotal = array.length;\r\n\r\n\t\t\t// Wrap the supplied reduceFunc with one that handles promises and then\r\n\t\t\t// delegates to the supplied.\r\n\t\t\targs[0] = function (current, val, i) {\r\n\t\t\t\treturn when(current, function (c) {\r\n\t\t\t\t\treturn when(val, function (value) {\r\n\t\t\t\t\t\treturn reduceFunc(c, value, i, total);\r\n\t\t\t\t\t});\r\n\t\t\t\t});\r\n\t\t\t};\r\n\r\n\t\t\treturn reduceArray.apply(array, args);\r\n\t\t});\r\n\t}\r\n\r\n\t/**\r\n\t * Ensure that resolution of promiseOrValue will trigger resolver with the\r\n\t * value or reason of promiseOrValue, or instead with resolveValue if it is provided.\r\n\t *\r\n\t * @param promiseOrValue\r\n\t * @param {Object} resolver\r\n\t * @param {function} resolver.resolve\r\n\t * @param {function} resolver.reject\r\n\t * @param {*} [resolveValue]\r\n\t * @returns {Promise}\r\n\t */\r\n\tfunction chain(promiseOrValue, resolver, resolveValue) {\r\n\t\tvar useResolveValue = arguments.length > 2;\r\n\r\n\t\treturn when(promiseOrValue,\r\n\t\t\tfunction(val) {\r\n\t\t\t\tval = useResolveValue ? resolveValue : val;\r\n\t\t\t\tresolver.resolve(val);\r\n\t\t\t\treturn val;\r\n\t\t\t},\r\n\t\t\tfunction(reason) {\r\n\t\t\t\tresolver.reject(reason);\r\n\t\t\t\treturn rejected(reason);\r\n\t\t\t},\r\n\t\t\tresolver.progress\r\n\t\t);\r\n\t}\r\n\r\n\t//\r\n\t// Utility functions\r\n\t//\r\n\r\n\t/**\r\n\t * Apply all functions in queue to value\r\n\t * @param {Array} queue array of functions to execute\r\n\t * @param {*} value argument passed to each function\r\n\t */\r\n\tfunction processQueue(queue, value) {\r\n\t\tvar handler, i = 0;\r\n\r\n\t\twhile (handler = queue[i++]) {\r\n\t\t\thandler(value);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Helper that checks arrayOfCallbacks to ensure that each element is either\r\n\t * a function, or null or undefined.\r\n\t * @private\r\n\t * @param {number} start index at which to start checking items in arrayOfCallbacks\r\n\t * @param {Array} arrayOfCallbacks array to check\r\n\t * @throws {Error} if any element of arrayOfCallbacks is something other than\r\n\t * a functions, null, or undefined.\r\n\t */\r\n\tfunction checkCallbacks(start, arrayOfCallbacks) {\r\n\t\t// TODO: Promises/A+ update type checking and docs\r\n\t\tvar arg, i = arrayOfCallbacks.length;\r\n\r\n\t\twhile(i > start) {\r\n\t\t\targ = arrayOfCallbacks[--i];\r\n\r\n\t\t\tif (arg != null && typeof arg != 'function') {\r\n\t\t\t\tthrow new Error('arg '+i+' must be a function');\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * No-Op function used in method replacement\r\n\t * @private\r\n\t */\r\n\tfunction noop() {}\r\n\r\n\tslice = [].slice;\r\n\r\n\t// ES5 reduce implementation if native not available\r\n\t// See: http://es5.github.com/#x15.4.4.21 as there are many\r\n\t// specifics and edge cases.\r\n\treduceArray = [].reduce ||\r\n\t\tfunction(reduceFunc /*, initialValue */) {\r\n\t\t\t/*jshint maxcomplexity: 7*/\r\n\r\n\t\t\t// ES5 dictates that reduce.length === 1\r\n\r\n\t\t\t// This implementation deviates from ES5 spec in the following ways:\r\n\t\t\t// 1. It does not check if reduceFunc is a Callable\r\n\r\n\t\t\tvar arr, args, reduced, len, i;\r\n\r\n\t\t\ti = 0;\r\n\t\t\t// This generates a jshint warning, despite being valid\r\n\t\t\t// \"Missing 'new' prefix when invoking a constructor.\"\r\n\t\t\t// See https://github.com/jshint/jshint/issues/392\r\n\t\t\tarr = Object(this);\r\n\t\t\tlen = arr.length >>> 0;\r\n\t\t\targs = arguments;\r\n\r\n\t\t\t// If no initialValue, use first item of array (we know length !== 0 here)\r\n\t\t\t// and adjust i to start at second item\r\n\t\t\tif(args.length <= 1) {\r\n\t\t\t\t// Skip to the first real element in the array\r\n\t\t\t\tfor(;;) {\r\n\t\t\t\t\tif(i in arr) {\r\n\t\t\t\t\t\treduced = arr[i++];\r\n\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// If we reached the end of the array without finding any real\r\n\t\t\t\t\t// elements, it's a TypeError\r\n\t\t\t\t\tif(++i >= len) {\r\n\t\t\t\t\t\tthrow new TypeError();\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\t// If initialValue provided, use it\r\n\t\t\t\treduced = args[1];\r\n\t\t\t}\r\n\r\n\t\t\t// Do the actual reduce\r\n\t\t\tfor(;i < len; ++i) {\r\n\t\t\t\t// Skip holes\r\n\t\t\t\tif(i in arr) {\r\n\t\t\t\t\treduced = reduceFunc(reduced, arr[i], i, arr);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\treturn reduced;\r\n\t\t};\r\n\r\n\tfunction identity(x) {\r\n\t\treturn x;\r\n\t}\r\n\r\nexport default when;\r\n","import defaultValue from \"./defaultValue.js\";\r\n\r\n/**\r\n * Clones an object, returning a new object containing the same properties.\r\n *\r\n * @function\r\n *\r\n * @param {Object} object The object to clone.\r\n * @param {Boolean} [deep=false] If true, all properties will be deep cloned recursively.\r\n * @returns {Object} The cloned object.\r\n */\r\nfunction clone(object, deep) {\r\n if (object === null || typeof object !== \"object\") {\r\n return object;\r\n }\r\n\r\n deep = defaultValue(deep, false);\r\n\r\n var result = new object.constructor();\r\n for (var propertyName in object) {\r\n if (object.hasOwnProperty(propertyName)) {\r\n var value = object[propertyName];\r\n if (deep) {\r\n value = clone(value, deep);\r\n }\r\n result[propertyName] = value;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\nexport default clone;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * Merges two objects, copying their properties onto a new combined object. When two objects have the same\r\n * property, the value of the property on the first object is used. If either object is undefined,\r\n * it will be treated as an empty object.\r\n *\r\n * @example\r\n * var object1 = {\r\n * propOne : 1,\r\n * propTwo : {\r\n * value1 : 10\r\n * }\r\n * }\r\n * var object2 = {\r\n * propTwo : 2\r\n * }\r\n * var final = Cesium.combine(object1, object2);\r\n *\r\n * // final === {\r\n * // propOne : 1,\r\n * // propTwo : {\r\n * // value1 : 10\r\n * // }\r\n * // }\r\n *\r\n * @param {Object} [object1] The first object to merge.\r\n * @param {Object} [object2] The second object to merge.\r\n * @param {Boolean} [deep=false] Perform a recursive merge.\r\n * @returns {Object} The combined object containing all properties from both objects.\r\n *\r\n * @function\r\n */\r\nfunction combine(object1, object2, deep) {\r\n deep = defaultValue(deep, false);\r\n\r\n var result = {};\r\n\r\n var object1Defined = defined(object1);\r\n var object2Defined = defined(object2);\r\n var property;\r\n var object1Value;\r\n var object2Value;\r\n if (object1Defined) {\r\n for (property in object1) {\r\n if (object1.hasOwnProperty(property)) {\r\n object1Value = object1[property];\r\n if (\r\n object2Defined &&\r\n deep &&\r\n typeof object1Value === \"object\" &&\r\n object2.hasOwnProperty(property)\r\n ) {\r\n object2Value = object2[property];\r\n if (typeof object2Value === \"object\") {\r\n result[property] = combine(object1Value, object2Value, deep);\r\n } else {\r\n result[property] = object1Value;\r\n }\r\n } else {\r\n result[property] = object1Value;\r\n }\r\n }\r\n }\r\n }\r\n if (object2Defined) {\r\n for (property in object2) {\r\n if (\r\n object2.hasOwnProperty(property) &&\r\n !result.hasOwnProperty(property)\r\n ) {\r\n object2Value = object2[property];\r\n result[property] = object2Value;\r\n }\r\n }\r\n }\r\n return result;\r\n}\r\nexport default combine;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Given a URI, returns the base path of the URI.\r\n * @function\r\n *\r\n * @param {String} uri The Uri.\r\n * @param {Boolean} [includeQuery = false] Whether or not to include the query string and fragment form the uri\r\n * @returns {String} The base path of the Uri.\r\n *\r\n * @example\r\n * // basePath will be \"/Gallery/\";\r\n * var basePath = Cesium.getBaseUri('/Gallery/simple.czml?value=true&example=false');\r\n *\r\n * // basePath will be \"/Gallery/?value=true&example=false\";\r\n * var basePath = Cesium.getBaseUri('/Gallery/simple.czml?value=true&example=false', true);\r\n */\r\nfunction getBaseUri(uri, includeQuery) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(uri)) {\r\n throw new DeveloperError(\"uri is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var basePath = \"\";\r\n var i = uri.lastIndexOf(\"/\");\r\n if (i !== -1) {\r\n basePath = uri.substring(0, i + 1);\r\n }\r\n\r\n if (!includeQuery) {\r\n return basePath;\r\n }\r\n\r\n uri = new Uri(uri);\r\n if (defined(uri.query)) {\r\n basePath += \"?\" + uri.query;\r\n }\r\n if (defined(uri.fragment)) {\r\n basePath += \"#\" + uri.fragment;\r\n }\r\n\r\n return basePath;\r\n}\r\nexport default getBaseUri;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Given a URI, returns the extension of the URI.\r\n * @function getExtensionFromUri\r\n *\r\n * @param {String} uri The Uri.\r\n * @returns {String} The extension of the Uri.\r\n *\r\n * @example\r\n * //extension will be \"czml\";\r\n * var extension = Cesium.getExtensionFromUri('/Gallery/simple.czml?value=true&example=false');\r\n */\r\nfunction getExtensionFromUri(uri) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(uri)) {\r\n throw new DeveloperError(\"uri is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var uriObject = new Uri(uri);\r\n uriObject.normalize();\r\n var path = uriObject.path;\r\n var index = path.lastIndexOf(\"/\");\r\n if (index !== -1) {\r\n path = path.substr(index + 1);\r\n }\r\n index = path.lastIndexOf(\".\");\r\n if (index === -1) {\r\n path = \"\";\r\n } else {\r\n path = path.substr(index + 1);\r\n }\r\n return path;\r\n}\r\nexport default getExtensionFromUri;\r\n","import Check from \"./Check.js\";\r\n\r\nvar blobUriRegex = /^blob:/i;\r\n\r\n/**\r\n * Determines if the specified uri is a blob uri.\r\n *\r\n * @function isBlobUri\r\n *\r\n * @param {String} uri The uri to test.\r\n * @returns {Boolean} true when the uri is a blob uri; otherwise, false.\r\n *\r\n * @private\r\n */\r\nfunction isBlobUri(uri) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"uri\", uri);\r\n //>>includeEnd('debug');\r\n\r\n return blobUriRegex.test(uri);\r\n}\r\nexport default isBlobUri;\r\n","import defined from \"./defined.js\";\r\n\r\nvar a;\r\n\r\n/**\r\n * Given a URL, determine whether that URL is considered cross-origin to the current page.\r\n *\r\n * @private\r\n */\r\nfunction isCrossOriginUrl(url) {\r\n if (!defined(a)) {\r\n a = document.createElement(\"a\");\r\n }\r\n\r\n // copy window location into the anchor to get consistent results\r\n // when the port is default for the protocol (e.g. 80 for HTTP)\r\n a.href = window.location.href;\r\n\r\n // host includes both hostname and port if the port is not standard\r\n var host = a.host;\r\n var protocol = a.protocol;\r\n\r\n a.href = url;\r\n // IE only absolutizes href on get, not set\r\n // eslint-disable-next-line no-self-assign\r\n a.href = a.href;\r\n\r\n return protocol !== a.protocol || host !== a.host;\r\n}\r\nexport default isCrossOriginUrl;\r\n","import Check from \"./Check.js\";\r\n\r\nvar dataUriRegex = /^data:/i;\r\n\r\n/**\r\n * Determines if the specified uri is a data uri.\r\n *\r\n * @function isDataUri\r\n *\r\n * @param {String} uri The uri to test.\r\n * @returns {Boolean} true when the uri is a data uri; otherwise, false.\r\n *\r\n * @private\r\n */\r\nfunction isDataUri(uri) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"uri\", uri);\r\n //>>includeEnd('debug');\r\n\r\n return dataUriRegex.test(uri);\r\n}\r\nexport default isDataUri;\r\n","import when from \"../ThirdParty/when.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction loadAndExecuteScript(url) {\r\n var deferred = when.defer();\r\n var script = document.createElement(\"script\");\r\n script.async = true;\r\n script.src = url;\r\n\r\n var head = document.getElementsByTagName(\"head\")[0];\r\n script.onload = function () {\r\n script.onload = undefined;\r\n head.removeChild(script);\r\n deferred.resolve();\r\n };\r\n script.onerror = function (e) {\r\n deferred.reject(e);\r\n };\r\n\r\n head.appendChild(script);\r\n\r\n return deferred.promise;\r\n}\r\nexport default loadAndExecuteScript;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Converts an object representing a set of name/value pairs into a query string,\r\n * with names and values encoded properly for use in a URL. Values that are arrays\r\n * will produce multiple values with the same name.\r\n * @function objectToQuery\r\n *\r\n * @param {Object} obj The object containing data to encode.\r\n * @returns {String} An encoded query string.\r\n *\r\n *\r\n * @example\r\n * var str = Cesium.objectToQuery({\r\n * key1 : 'some value',\r\n * key2 : 'a/b',\r\n * key3 : ['x', 'y']\r\n * });\r\n *\r\n * @see queryToObject\r\n * // str will be:\r\n * // 'key1=some%20value&key2=a%2Fb&key3=x&key3=y'\r\n */\r\nfunction objectToQuery(obj) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(obj)) {\r\n throw new DeveloperError(\"obj is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var result = \"\";\r\n for (var propName in obj) {\r\n if (obj.hasOwnProperty(propName)) {\r\n var value = obj[propName];\r\n\r\n var part = encodeURIComponent(propName) + \"=\";\r\n if (Array.isArray(value)) {\r\n for (var i = 0, len = value.length; i < len; ++i) {\r\n result += part + encodeURIComponent(value[i]) + \"&\";\r\n }\r\n } else {\r\n result += part + encodeURIComponent(value) + \"&\";\r\n }\r\n }\r\n }\r\n\r\n // trim last &\r\n result = result.slice(0, -1);\r\n\r\n // This function used to replace %20 with + which is more compact and readable.\r\n // However, some servers didn't properly handle + as a space.\r\n // https://github.com/CesiumGS/cesium/issues/2192\r\n\r\n return result;\r\n}\r\nexport default objectToQuery;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Parses a query string into an object, where the keys and values of the object are the\r\n * name/value pairs from the query string, decoded. If a name appears multiple times,\r\n * the value in the object will be an array of values.\r\n * @function queryToObject\r\n *\r\n * @param {String} queryString The query string.\r\n * @returns {Object} An object containing the parameters parsed from the query string.\r\n *\r\n *\r\n * @example\r\n * var obj = Cesium.queryToObject('key1=some%20value&key2=a%2Fb&key3=x&key3=y');\r\n * // obj will be:\r\n * // {\r\n * // key1 : 'some value',\r\n * // key2 : 'a/b',\r\n * // key3 : ['x', 'y']\r\n * // }\r\n *\r\n * @see objectToQuery\r\n */\r\nfunction queryToObject(queryString) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(queryString)) {\r\n throw new DeveloperError(\"queryString is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var result = {};\r\n if (queryString === \"\") {\r\n return result;\r\n }\r\n var parts = queryString.replace(/\\+/g, \"%20\").split(/[&;]/);\r\n for (var i = 0, len = parts.length; i < len; ++i) {\r\n var subparts = parts[i].split(\"=\");\r\n\r\n var name = decodeURIComponent(subparts[0]);\r\n var value = subparts[1];\r\n if (defined(value)) {\r\n value = decodeURIComponent(value);\r\n } else {\r\n value = \"\";\r\n }\r\n\r\n var resultValue = result[name];\r\n if (typeof resultValue === \"string\") {\r\n // expand the single value to an array\r\n result[name] = [resultValue, value];\r\n } else if (Array.isArray(resultValue)) {\r\n resultValue.push(value);\r\n } else {\r\n result[name] = value;\r\n }\r\n }\r\n return result;\r\n}\r\nexport default queryToObject;\r\n","/**\r\n * State of the request.\r\n *\r\n * @enum {Number}\r\n */\r\nvar RequestState = {\r\n /**\r\n * Initial unissued state.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n UNISSUED: 0,\r\n\r\n /**\r\n * Issued but not yet active. Will become active when open slots are available.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n ISSUED: 1,\r\n\r\n /**\r\n * Actual http request has been sent.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n ACTIVE: 2,\r\n\r\n /**\r\n * Request completed successfully.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n RECEIVED: 3,\r\n\r\n /**\r\n * Request was cancelled, either explicitly or automatically because of low priority.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n CANCELLED: 4,\r\n\r\n /**\r\n * Request failed.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n FAILED: 5,\r\n};\r\nexport default Object.freeze(RequestState);\r\n","/**\r\n * An enum identifying the type of request. Used for finer grained logging and priority sorting.\r\n *\r\n * @enum {Number}\r\n */\r\nvar RequestType = {\r\n /**\r\n * Terrain request.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n TERRAIN: 0,\r\n\r\n /**\r\n * Imagery request.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n IMAGERY: 1,\r\n\r\n /**\r\n * 3D Tiles request.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n TILES3D: 2,\r\n\r\n /**\r\n * Other request.\r\n *\r\n * @type Number\r\n * @constant\r\n */\r\n OTHER: 3,\r\n};\r\nexport default Object.freeze(RequestType);\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport RequestState from \"./RequestState.js\";\r\nimport RequestType from \"./RequestType.js\";\r\n\r\n/**\r\n * Stores information for making a request. In general this does not need to be constructed directly.\r\n *\r\n * @alias Request\r\n * @constructor\r\n\r\n * @param {Object} [options] An object with the following properties:\r\n * @param {String} [options.url] The url to request.\r\n * @param {Request.RequestCallback} [options.requestFunction] The function that makes the actual data request.\r\n * @param {Request.CancelCallback} [options.cancelFunction] The function that is called when the request is cancelled.\r\n * @param {Request.PriorityCallback} [options.priorityFunction] The function that is called to update the request's priority, which occurs once per frame.\r\n * @param {Number} [options.priority=0.0] The initial priority of the request.\r\n * @param {Boolean} [options.throttle=false] Whether to throttle and prioritize the request. If false, the request will be sent immediately. If true, the request will be throttled and sent based on priority.\r\n * @param {Boolean} [options.throttleByServer=false] Whether to throttle the request by server.\r\n * @param {RequestType} [options.type=RequestType.OTHER] The type of request.\r\n */\r\nfunction Request(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var throttleByServer = defaultValue(options.throttleByServer, false);\r\n var throttle = defaultValue(options.throttle, false);\r\n\r\n /**\r\n * The URL to request.\r\n *\r\n * @type {String}\r\n */\r\n this.url = options.url;\r\n\r\n /**\r\n * The function that makes the actual data request.\r\n *\r\n * @type {Request.RequestCallback}\r\n */\r\n this.requestFunction = options.requestFunction;\r\n\r\n /**\r\n * The function that is called when the request is cancelled.\r\n *\r\n * @type {Request.CancelCallback}\r\n */\r\n this.cancelFunction = options.cancelFunction;\r\n\r\n /**\r\n * The function that is called to update the request's priority, which occurs once per frame.\r\n *\r\n * @type {Request.PriorityCallback}\r\n */\r\n this.priorityFunction = options.priorityFunction;\r\n\r\n /**\r\n * Priority is a unit-less value where lower values represent higher priority.\r\n * For world-based objects, this is usually the distance from the camera.\r\n * A request that does not have a priority function defaults to a priority of 0.\r\n *\r\n * If priorityFunction is defined, this value is updated every frame with the result of that call.\r\n *\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.priority = defaultValue(options.priority, 0.0);\r\n\r\n /**\r\n * Whether to throttle and prioritize the request. If false, the request will be sent immediately. If true, the\r\n * request will be throttled and sent based on priority.\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n this.throttle = throttle;\r\n\r\n /**\r\n * Whether to throttle the request by server. Browsers typically support about 6-8 parallel connections\r\n * for HTTP/1 servers, and an unlimited amount of connections for HTTP/2 servers. Setting this value\r\n * to true is preferable for requests going through HTTP/1 servers.\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n this.throttleByServer = throttleByServer;\r\n\r\n /**\r\n * Type of request.\r\n *\r\n * @type {RequestType}\r\n * @readonly\r\n *\r\n * @default RequestType.OTHER\r\n */\r\n this.type = defaultValue(options.type, RequestType.OTHER);\r\n\r\n /**\r\n * A key used to identify the server that a request is going to. It is derived from the url's authority and scheme.\r\n *\r\n * @type {String}\r\n *\r\n * @private\r\n */\r\n this.serverKey = undefined;\r\n\r\n /**\r\n * The current state of the request.\r\n *\r\n * @type {RequestState}\r\n * @readonly\r\n */\r\n this.state = RequestState.UNISSUED;\r\n\r\n /**\r\n * The requests's deferred promise.\r\n *\r\n * @type {Object}\r\n *\r\n * @private\r\n */\r\n this.deferred = undefined;\r\n\r\n /**\r\n * Whether the request was explicitly cancelled.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @private\r\n */\r\n this.cancelled = false;\r\n}\r\n\r\n/**\r\n * Mark the request as cancelled.\r\n *\r\n * @private\r\n */\r\nRequest.prototype.cancel = function () {\r\n this.cancelled = true;\r\n};\r\n\r\n/**\r\n * Duplicates a Request instance.\r\n *\r\n * @param {Request} [result] The object onto which to store the result.\r\n *\r\n * @returns {Request} The modified result parameter or a new Resource instance if one was not provided.\r\n */\r\nRequest.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new Request(this);\r\n }\r\n\r\n result.url = this.url;\r\n result.requestFunction = this.requestFunction;\r\n result.cancelFunction = this.cancelFunction;\r\n result.priorityFunction = this.priorityFunction;\r\n result.priority = this.priority;\r\n result.throttle = this.throttle;\r\n result.throttleByServer = this.throttleByServer;\r\n result.type = this.type;\r\n result.serverKey = this.serverKey;\r\n\r\n // These get defaulted because the cloned request hasn't been issued\r\n result.state = this.RequestState.UNISSUED;\r\n result.deferred = undefined;\r\n result.cancelled = false;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * The function that makes the actual data request.\r\n * @callback Request.RequestCallback\r\n * @returns {Promise} A promise for the requested data.\r\n */\r\n\r\n/**\r\n * The function that is called when the request is cancelled.\r\n * @callback Request.CancelCallback\r\n */\r\n\r\n/**\r\n * The function that is called to update the request's priority, which occurs once per frame.\r\n * @callback Request.PriorityCallback\r\n * @returns {Number} The updated priority value.\r\n */\r\nexport default Request;\r\n","/**\r\n * Parses the result of XMLHttpRequest's getAllResponseHeaders() method into\r\n * a dictionary.\r\n *\r\n * @function parseResponseHeaders\r\n *\r\n * @param {String} headerString The header string returned by getAllResponseHeaders(). The format is\r\n * described here: http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders()-method\r\n * @returns {Object} A dictionary of key/value pairs, where each key is the name of a header and the corresponding value\r\n * is that header's value.\r\n *\r\n * @private\r\n */\r\nfunction parseResponseHeaders(headerString) {\r\n var headers = {};\r\n\r\n if (!headerString) {\r\n return headers;\r\n }\r\n\r\n var headerPairs = headerString.split(\"\\u000d\\u000a\");\r\n\r\n for (var i = 0; i < headerPairs.length; ++i) {\r\n var headerPair = headerPairs[i];\r\n // Can't use split() here because it does the wrong thing\r\n // if the header value has the string \": \" in it.\r\n var index = headerPair.indexOf(\"\\u003a\\u0020\");\r\n if (index > 0) {\r\n var key = headerPair.substring(0, index);\r\n var val = headerPair.substring(index + 2);\r\n headers[key] = val;\r\n }\r\n }\r\n\r\n return headers;\r\n}\r\nexport default parseResponseHeaders;\r\n","import defined from \"./defined.js\";\r\nimport parseResponseHeaders from \"./parseResponseHeaders.js\";\r\n\r\n/**\r\n * An event that is raised when a request encounters an error.\r\n *\r\n * @constructor\r\n * @alias RequestErrorEvent\r\n *\r\n * @param {Number} [statusCode] The HTTP error status code, such as 404.\r\n * @param {Object} [response] The response included along with the error.\r\n * @param {String|Object} [responseHeaders] The response headers, represented either as an object literal or as a\r\n * string in the format returned by XMLHttpRequest's getAllResponseHeaders() function.\r\n */\r\nfunction RequestErrorEvent(statusCode, response, responseHeaders) {\r\n /**\r\n * The HTTP error status code, such as 404. If the error does not have a particular\r\n * HTTP code, this property will be undefined.\r\n *\r\n * @type {Number}\r\n */\r\n this.statusCode = statusCode;\r\n\r\n /**\r\n * The response included along with the error. If the error does not include a response,\r\n * this property will be undefined.\r\n *\r\n * @type {Object}\r\n */\r\n this.response = response;\r\n\r\n /**\r\n * The headers included in the response, represented as an object literal of key/value pairs.\r\n * If the error does not include any headers, this property will be undefined.\r\n *\r\n * @type {Object}\r\n */\r\n this.responseHeaders = responseHeaders;\r\n\r\n if (typeof this.responseHeaders === \"string\") {\r\n this.responseHeaders = parseResponseHeaders(this.responseHeaders);\r\n }\r\n}\r\n\r\n/**\r\n * Creates a string representing this RequestErrorEvent.\r\n * @memberof RequestErrorEvent\r\n *\r\n * @returns {String} A string representing the provided RequestErrorEvent.\r\n */\r\nRequestErrorEvent.prototype.toString = function () {\r\n var str = \"Request has failed.\";\r\n if (defined(this.statusCode)) {\r\n str += \" Status Code: \" + this.statusCode;\r\n }\r\n return str;\r\n};\r\nexport default RequestErrorEvent;\r\n","import Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * A generic utility class for managing subscribers for a particular event.\r\n * This class is usually instantiated inside of a container class and\r\n * exposed as a property for others to subscribe to.\r\n *\r\n * @alias Event\r\n * @constructor\r\n * @example\r\n * MyObject.prototype.myListener = function(arg1, arg2) {\r\n * this.myArg1Copy = arg1;\r\n * this.myArg2Copy = arg2;\r\n * }\r\n *\r\n * var myObjectInstance = new MyObject();\r\n * var evt = new Cesium.Event();\r\n * evt.addEventListener(MyObject.prototype.myListener, myObjectInstance);\r\n * evt.raiseEvent('1', '2');\r\n * evt.removeEventListener(MyObject.prototype.myListener);\r\n */\r\nfunction Event() {\r\n this._listeners = [];\r\n this._scopes = [];\r\n this._toRemove = [];\r\n this._insideRaiseEvent = false;\r\n}\r\n\r\nObject.defineProperties(Event.prototype, {\r\n /**\r\n * The number of listeners currently subscribed to the event.\r\n * @memberof Event.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n numberOfListeners: {\r\n get: function () {\r\n return this._listeners.length - this._toRemove.length;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Registers a callback function to be executed whenever the event is raised.\r\n * An optional scope can be provided to serve as the this pointer\r\n * in which the function will execute.\r\n *\r\n * @param {Function} listener The function to be executed when the event is raised.\r\n * @param {Object} [scope] An optional object scope to serve as the this\r\n * pointer in which the listener function will execute.\r\n * @returns {Event.RemoveCallback} A function that will remove this event listener when invoked.\r\n *\r\n * @see Event#raiseEvent\r\n * @see Event#removeEventListener\r\n */\r\nEvent.prototype.addEventListener = function (listener, scope) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.func(\"listener\", listener);\r\n //>>includeEnd('debug');\r\n\r\n this._listeners.push(listener);\r\n this._scopes.push(scope);\r\n\r\n var event = this;\r\n return function () {\r\n event.removeEventListener(listener, scope);\r\n };\r\n};\r\n\r\n/**\r\n * Unregisters a previously registered callback.\r\n *\r\n * @param {Function} listener The function to be unregistered.\r\n * @param {Object} [scope] The scope that was originally passed to addEventListener.\r\n * @returns {Boolean} true if the listener was removed; false if the listener and scope are not registered with the event.\r\n *\r\n * @see Event#addEventListener\r\n * @see Event#raiseEvent\r\n */\r\nEvent.prototype.removeEventListener = function (listener, scope) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.func(\"listener\", listener);\r\n //>>includeEnd('debug');\r\n\r\n var listeners = this._listeners;\r\n var scopes = this._scopes;\r\n\r\n var index = -1;\r\n for (var i = 0; i < listeners.length; i++) {\r\n if (listeners[i] === listener && scopes[i] === scope) {\r\n index = i;\r\n break;\r\n }\r\n }\r\n\r\n if (index !== -1) {\r\n if (this._insideRaiseEvent) {\r\n //In order to allow removing an event subscription from within\r\n //a callback, we don't actually remove the items here. Instead\r\n //remember the index they are at and undefined their value.\r\n this._toRemove.push(index);\r\n listeners[index] = undefined;\r\n scopes[index] = undefined;\r\n } else {\r\n listeners.splice(index, 1);\r\n scopes.splice(index, 1);\r\n }\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nfunction compareNumber(a, b) {\r\n return b - a;\r\n}\r\n\r\n/**\r\n * Raises the event by calling each registered listener with all supplied arguments.\r\n *\r\n * @param {...Object} arguments This method takes any number of parameters and passes them through to the listener functions.\r\n *\r\n * @see Event#addEventListener\r\n * @see Event#removeEventListener\r\n */\r\nEvent.prototype.raiseEvent = function () {\r\n this._insideRaiseEvent = true;\r\n\r\n var i;\r\n var listeners = this._listeners;\r\n var scopes = this._scopes;\r\n var length = listeners.length;\r\n\r\n for (i = 0; i < length; i++) {\r\n var listener = listeners[i];\r\n if (defined(listener)) {\r\n listeners[i].apply(scopes[i], arguments);\r\n }\r\n }\r\n\r\n //Actually remove items removed in removeEventListener.\r\n var toRemove = this._toRemove;\r\n length = toRemove.length;\r\n if (length > 0) {\r\n toRemove.sort(compareNumber);\r\n for (i = 0; i < length; i++) {\r\n var index = toRemove[i];\r\n listeners.splice(index, 1);\r\n scopes.splice(index, 1);\r\n }\r\n toRemove.length = 0;\r\n }\r\n\r\n this._insideRaiseEvent = false;\r\n};\r\n\r\n/**\r\n * A function that removes a listener.\r\n * @callback Event.RemoveCallback\r\n */\r\nexport default Event;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * Array implementation of a heap.\r\n *\r\n * @alias Heap\r\n * @constructor\r\n * @private\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Heap.ComparatorCallback} options.comparator The comparator to use for the heap. If comparator(a, b) is less than 0, sort a to a lower index than b, otherwise sort to a higher index.\r\n */\r\nfunction Heap(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.defined(\"options.comparator\", options.comparator);\r\n //>>includeEnd('debug');\r\n\r\n this._comparator = options.comparator;\r\n this._array = [];\r\n this._length = 0;\r\n this._maximumLength = undefined;\r\n}\r\n\r\nObject.defineProperties(Heap.prototype, {\r\n /**\r\n * Gets the length of the heap.\r\n *\r\n * @memberof Heap.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._length;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the internal array.\r\n *\r\n * @memberof Heap.prototype\r\n *\r\n * @type {Array}\r\n * @readonly\r\n */\r\n internalArray: {\r\n get: function () {\r\n return this._array;\r\n },\r\n },\r\n\r\n /**\r\n * Gets and sets the maximum length of the heap.\r\n *\r\n * @memberof Heap.prototype\r\n *\r\n * @type {Number}\r\n */\r\n maximumLength: {\r\n get: function () {\r\n return this._maximumLength;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"maximumLength\", value, 0);\r\n //>>includeEnd('debug');\r\n var originalLength = this._length;\r\n if (value < originalLength) {\r\n var array = this._array;\r\n // Remove trailing references\r\n for (var i = value; i < originalLength; ++i) {\r\n array[i] = undefined;\r\n }\r\n this._length = value;\r\n array.length = value;\r\n }\r\n this._maximumLength = value;\r\n },\r\n },\r\n\r\n /**\r\n * The comparator to use for the heap. If comparator(a, b) is less than 0, sort a to a lower index than b, otherwise sort to a higher index.\r\n *\r\n * @memberof Heap.prototype\r\n *\r\n * @type {Heap.ComparatorCallback}\r\n */\r\n comparator: {\r\n get: function () {\r\n return this._comparator;\r\n },\r\n },\r\n});\r\n\r\nfunction swap(array, a, b) {\r\n var temp = array[a];\r\n array[a] = array[b];\r\n array[b] = temp;\r\n}\r\n\r\n/**\r\n * Resizes the internal array of the heap.\r\n *\r\n * @param {Number} [length] The length to resize internal array to. Defaults to the current length of the heap.\r\n */\r\nHeap.prototype.reserve = function (length) {\r\n length = defaultValue(length, this._length);\r\n this._array.length = length;\r\n};\r\n\r\n/**\r\n * Update the heap so that index and all descendants satisfy the heap property.\r\n *\r\n * @param {Number} [index=0] The starting index to heapify from.\r\n */\r\nHeap.prototype.heapify = function (index) {\r\n index = defaultValue(index, 0);\r\n var length = this._length;\r\n var comparator = this._comparator;\r\n var array = this._array;\r\n var candidate = -1;\r\n var inserting = true;\r\n\r\n while (inserting) {\r\n var right = 2 * (index + 1);\r\n var left = right - 1;\r\n\r\n if (left < length && comparator(array[left], array[index]) < 0) {\r\n candidate = left;\r\n } else {\r\n candidate = index;\r\n }\r\n\r\n if (right < length && comparator(array[right], array[candidate]) < 0) {\r\n candidate = right;\r\n }\r\n if (candidate !== index) {\r\n swap(array, candidate, index);\r\n index = candidate;\r\n } else {\r\n inserting = false;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Resort the heap.\r\n */\r\nHeap.prototype.resort = function () {\r\n var length = this._length;\r\n for (var i = Math.ceil(length / 2); i >= 0; --i) {\r\n this.heapify(i);\r\n }\r\n};\r\n\r\n/**\r\n * Insert an element into the heap. If the length would grow greater than maximumLength\r\n * of the heap, extra elements are removed.\r\n *\r\n * @param {*} element The element to insert\r\n *\r\n * @return {*} The element that was removed from the heap if the heap is at full capacity.\r\n */\r\nHeap.prototype.insert = function (element) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"element\", element);\r\n //>>includeEnd('debug');\r\n\r\n var array = this._array;\r\n var comparator = this._comparator;\r\n var maximumLength = this._maximumLength;\r\n\r\n var index = this._length++;\r\n if (index < array.length) {\r\n array[index] = element;\r\n } else {\r\n array.push(element);\r\n }\r\n\r\n while (index !== 0) {\r\n var parent = Math.floor((index - 1) / 2);\r\n if (comparator(array[index], array[parent]) < 0) {\r\n swap(array, index, parent);\r\n index = parent;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n var removedElement;\r\n\r\n if (defined(maximumLength) && this._length > maximumLength) {\r\n removedElement = array[maximumLength];\r\n this._length = maximumLength;\r\n }\r\n\r\n return removedElement;\r\n};\r\n\r\n/**\r\n * Remove the element specified by index from the heap and return it.\r\n *\r\n * @param {Number} [index=0] The index to remove.\r\n * @returns {*} The specified element of the heap.\r\n */\r\nHeap.prototype.pop = function (index) {\r\n index = defaultValue(index, 0);\r\n if (this._length === 0) {\r\n return undefined;\r\n }\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.lessThan(\"index\", index, this._length);\r\n //>>includeEnd('debug');\r\n\r\n var array = this._array;\r\n var root = array[index];\r\n swap(array, index, --this._length);\r\n this.heapify(index);\r\n array[this._length] = undefined; // Remove trailing reference\r\n return root;\r\n};\r\n\r\n/**\r\n * The comparator to use for the heap.\r\n * @callback Heap.ComparatorCallback\r\n * @param {*} a An element in the heap.\r\n * @param {*} b An element in the heap.\r\n * @returns {Number} If the result of the comparison is less than 0, sort a to a lower index than b, otherwise sort to a higher index.\r\n */\r\nexport default Heap;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Event from \"./Event.js\";\r\nimport Heap from \"./Heap.js\";\r\nimport isBlobUri from \"./isBlobUri.js\";\r\nimport isDataUri from \"./isDataUri.js\";\r\nimport RequestState from \"./RequestState.js\";\r\n\r\nfunction sortRequests(a, b) {\r\n return a.priority - b.priority;\r\n}\r\n\r\nvar statistics = {\r\n numberOfAttemptedRequests: 0,\r\n numberOfActiveRequests: 0,\r\n numberOfCancelledRequests: 0,\r\n numberOfCancelledActiveRequests: 0,\r\n numberOfFailedRequests: 0,\r\n numberOfActiveRequestsEver: 0,\r\n lastNumberOfActiveRequests: 0,\r\n};\r\n\r\nvar priorityHeapLength = 20;\r\nvar requestHeap = new Heap({\r\n comparator: sortRequests,\r\n});\r\nrequestHeap.maximumLength = priorityHeapLength;\r\nrequestHeap.reserve(priorityHeapLength);\r\n\r\nvar activeRequests = [];\r\nvar numberOfActiveRequestsByServer = {};\r\n\r\nvar pageUri =\r\n typeof document !== \"undefined\" ? new Uri(document.location.href) : new Uri();\r\n\r\nvar requestCompletedEvent = new Event();\r\n\r\n/**\r\n * The request scheduler is used to track and constrain the number of active requests in order to prioritize incoming requests. The ability\r\n * to retain control over the number of requests in CesiumJS is important because due to events such as changes in the camera position,\r\n * a lot of new requests may be generated and a lot of in-flight requests may become redundant. The request scheduler manually constrains the\r\n * number of requests so that newer requests wait in a shorter queue and don't have to compete for bandwidth with requests that have expired.\r\n *\r\n * @namespace RequestScheduler\r\n *\r\n */\r\nfunction RequestScheduler() {}\r\n\r\n/**\r\n * The maximum number of simultaneous active requests. Un-throttled requests do not observe this limit.\r\n * @type {Number}\r\n * @default 50\r\n */\r\nRequestScheduler.maximumRequests = 50;\r\n\r\n/**\r\n * The maximum number of simultaneous active requests per server. Un-throttled requests or servers specifically\r\n * listed in {@link requestsByServer} do not observe this limit.\r\n * @type {Number}\r\n * @default 6\r\n */\r\nRequestScheduler.maximumRequestsPerServer = 6;\r\n\r\n/**\r\n * A per server key list of overrides to use for throttling instead of maximumRequestsPerServer\r\n * @type {Object}\r\n *\r\n * @example\r\n * RequestScheduler.requestsByServer = {\r\n * 'api.cesium.com:443': 18,\r\n * 'assets.cesium.com:443': 18\r\n * };\r\n */\r\nRequestScheduler.requestsByServer = {\r\n \"api.cesium.com:443\": 18,\r\n \"assets.cesium.com:443\": 18,\r\n};\r\n\r\n/**\r\n * Specifies if the request scheduler should throttle incoming requests, or let the browser queue requests under its control.\r\n * @type {Boolean}\r\n * @default true\r\n */\r\nRequestScheduler.throttleRequests = true;\r\n\r\n/**\r\n * When true, log statistics to the console every frame\r\n * @type {Boolean}\r\n * @default false\r\n * @private\r\n */\r\nRequestScheduler.debugShowStatistics = false;\r\n\r\n/**\r\n * An event that's raised when a request is completed. Event handlers are passed\r\n * the error object if the request fails.\r\n *\r\n * @type {Event}\r\n * @default Event()\r\n * @private\r\n */\r\nRequestScheduler.requestCompletedEvent = requestCompletedEvent;\r\n\r\nObject.defineProperties(RequestScheduler, {\r\n /**\r\n * Returns the statistics used by the request scheduler.\r\n *\r\n * @memberof RequestScheduler\r\n *\r\n * @type Object\r\n * @readonly\r\n * @private\r\n */\r\n statistics: {\r\n get: function () {\r\n return statistics;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum size of the priority heap. This limits the number of requests that are sorted by priority. Only applies to requests that are not yet active.\r\n *\r\n * @memberof RequestScheduler\r\n *\r\n * @type {Number}\r\n * @default 20\r\n * @private\r\n */\r\n priorityHeapLength: {\r\n get: function () {\r\n return priorityHeapLength;\r\n },\r\n set: function (value) {\r\n // If the new length shrinks the heap, need to cancel some of the requests.\r\n // Since this value is not intended to be tweaked regularly it is fine to just cancel the high priority requests.\r\n if (value < priorityHeapLength) {\r\n while (requestHeap.length > value) {\r\n var request = requestHeap.pop();\r\n cancelRequest(request);\r\n }\r\n }\r\n priorityHeapLength = value;\r\n requestHeap.maximumLength = value;\r\n requestHeap.reserve(value);\r\n },\r\n },\r\n});\r\n\r\nfunction updatePriority(request) {\r\n if (defined(request.priorityFunction)) {\r\n request.priority = request.priorityFunction();\r\n }\r\n}\r\n\r\nfunction serverHasOpenSlots(serverKey) {\r\n var maxRequests = defaultValue(\r\n RequestScheduler.requestsByServer[serverKey],\r\n RequestScheduler.maximumRequestsPerServer\r\n );\r\n return numberOfActiveRequestsByServer[serverKey] < maxRequests;\r\n}\r\n\r\nfunction issueRequest(request) {\r\n if (request.state === RequestState.UNISSUED) {\r\n request.state = RequestState.ISSUED;\r\n request.deferred = when.defer();\r\n }\r\n return request.deferred.promise;\r\n}\r\n\r\nfunction getRequestReceivedFunction(request) {\r\n return function (results) {\r\n if (request.state === RequestState.CANCELLED) {\r\n // If the data request comes back but the request is cancelled, ignore it.\r\n return;\r\n }\r\n // explicitly set to undefined to ensure GC of request response data. See #8843\r\n var deferred = request.deferred;\r\n\r\n --statistics.numberOfActiveRequests;\r\n --numberOfActiveRequestsByServer[request.serverKey];\r\n requestCompletedEvent.raiseEvent();\r\n request.state = RequestState.RECEIVED;\r\n request.deferred = undefined;\r\n\r\n deferred.resolve(results);\r\n };\r\n}\r\n\r\nfunction getRequestFailedFunction(request) {\r\n return function (error) {\r\n if (request.state === RequestState.CANCELLED) {\r\n // If the data request comes back but the request is cancelled, ignore it.\r\n return;\r\n }\r\n ++statistics.numberOfFailedRequests;\r\n --statistics.numberOfActiveRequests;\r\n --numberOfActiveRequestsByServer[request.serverKey];\r\n requestCompletedEvent.raiseEvent(error);\r\n request.state = RequestState.FAILED;\r\n request.deferred.reject(error);\r\n };\r\n}\r\n\r\nfunction startRequest(request) {\r\n var promise = issueRequest(request);\r\n request.state = RequestState.ACTIVE;\r\n activeRequests.push(request);\r\n ++statistics.numberOfActiveRequests;\r\n ++statistics.numberOfActiveRequestsEver;\r\n ++numberOfActiveRequestsByServer[request.serverKey];\r\n request\r\n .requestFunction()\r\n .then(getRequestReceivedFunction(request))\r\n .otherwise(getRequestFailedFunction(request));\r\n return promise;\r\n}\r\n\r\nfunction cancelRequest(request) {\r\n var active = request.state === RequestState.ACTIVE;\r\n request.state = RequestState.CANCELLED;\r\n ++statistics.numberOfCancelledRequests;\r\n // check that deferred has not been cleared since cancelRequest can be called\r\n // on a finished request, e.g. by clearForSpecs during tests\r\n if (defined(request.deferred)) {\r\n var deferred = request.deferred;\r\n request.deferred = undefined;\r\n deferred.reject();\r\n }\r\n\r\n if (active) {\r\n --statistics.numberOfActiveRequests;\r\n --numberOfActiveRequestsByServer[request.serverKey];\r\n ++statistics.numberOfCancelledActiveRequests;\r\n }\r\n\r\n if (defined(request.cancelFunction)) {\r\n request.cancelFunction();\r\n }\r\n}\r\n\r\n/**\r\n * Sort requests by priority and start requests.\r\n * @private\r\n */\r\nRequestScheduler.update = function () {\r\n var i;\r\n var request;\r\n\r\n // Loop over all active requests. Cancelled, failed, or received requests are removed from the array to make room for new requests.\r\n var removeCount = 0;\r\n var activeLength = activeRequests.length;\r\n for (i = 0; i < activeLength; ++i) {\r\n request = activeRequests[i];\r\n if (request.cancelled) {\r\n // Request was explicitly cancelled\r\n cancelRequest(request);\r\n }\r\n if (request.state !== RequestState.ACTIVE) {\r\n // Request is no longer active, remove from array\r\n ++removeCount;\r\n continue;\r\n }\r\n if (removeCount > 0) {\r\n // Shift back to fill in vacated slots from completed requests\r\n activeRequests[i - removeCount] = request;\r\n }\r\n }\r\n activeRequests.length -= removeCount;\r\n\r\n // Update priority of issued requests and resort the heap\r\n var issuedRequests = requestHeap.internalArray;\r\n var issuedLength = requestHeap.length;\r\n for (i = 0; i < issuedLength; ++i) {\r\n updatePriority(issuedRequests[i]);\r\n }\r\n requestHeap.resort();\r\n\r\n // Get the number of open slots and fill with the highest priority requests.\r\n // Un-throttled requests are automatically added to activeRequests, so activeRequests.length may exceed maximumRequests\r\n var openSlots = Math.max(\r\n RequestScheduler.maximumRequests - activeRequests.length,\r\n 0\r\n );\r\n var filledSlots = 0;\r\n while (filledSlots < openSlots && requestHeap.length > 0) {\r\n // Loop until all open slots are filled or the heap becomes empty\r\n request = requestHeap.pop();\r\n if (request.cancelled) {\r\n // Request was explicitly cancelled\r\n cancelRequest(request);\r\n continue;\r\n }\r\n\r\n if (request.throttleByServer && !serverHasOpenSlots(request.serverKey)) {\r\n // Open slots are available, but the request is throttled by its server. Cancel and try again later.\r\n cancelRequest(request);\r\n continue;\r\n }\r\n\r\n startRequest(request);\r\n ++filledSlots;\r\n }\r\n\r\n updateStatistics();\r\n};\r\n\r\n/**\r\n * Get the server key from a given url.\r\n *\r\n * @param {String} url The url.\r\n * @returns {String} The server key.\r\n * @private\r\n */\r\nRequestScheduler.getServerKey = function (url) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"url\", url);\r\n //>>includeEnd('debug');\r\n\r\n var uri = new Uri(url).resolve(pageUri);\r\n uri.normalize();\r\n var serverKey = uri.authority;\r\n if (!/:/.test(serverKey)) {\r\n // If the authority does not contain a port number, add port 443 for https or port 80 for http\r\n serverKey = serverKey + \":\" + (uri.scheme === \"https\" ? \"443\" : \"80\");\r\n }\r\n\r\n var length = numberOfActiveRequestsByServer[serverKey];\r\n if (!defined(length)) {\r\n numberOfActiveRequestsByServer[serverKey] = 0;\r\n }\r\n\r\n return serverKey;\r\n};\r\n\r\n/**\r\n * Issue a request. If request.throttle is false, the request is sent immediately. Otherwise the request will be\r\n * queued and sorted by priority before being sent.\r\n *\r\n * @param {Request} request The request object.\r\n *\r\n * @returns {Promise|undefined} A Promise for the requested data, or undefined if this request does not have high enough priority to be issued.\r\n *\r\n * @private\r\n */\r\nRequestScheduler.request = function (request) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"request\", request);\r\n Check.typeOf.string(\"request.url\", request.url);\r\n Check.typeOf.func(\"request.requestFunction\", request.requestFunction);\r\n //>>includeEnd('debug');\r\n\r\n if (isDataUri(request.url) || isBlobUri(request.url)) {\r\n requestCompletedEvent.raiseEvent();\r\n request.state = RequestState.RECEIVED;\r\n return request.requestFunction();\r\n }\r\n\r\n ++statistics.numberOfAttemptedRequests;\r\n\r\n if (!defined(request.serverKey)) {\r\n request.serverKey = RequestScheduler.getServerKey(request.url);\r\n }\r\n\r\n if (\r\n RequestScheduler.throttleRequests &&\r\n request.throttleByServer &&\r\n !serverHasOpenSlots(request.serverKey)\r\n ) {\r\n // Server is saturated. Try again later.\r\n return undefined;\r\n }\r\n\r\n if (!RequestScheduler.throttleRequests || !request.throttle) {\r\n return startRequest(request);\r\n }\r\n\r\n if (activeRequests.length >= RequestScheduler.maximumRequests) {\r\n // Active requests are saturated. Try again later.\r\n return undefined;\r\n }\r\n\r\n // Insert into the priority heap and see if a request was bumped off. If this request is the lowest\r\n // priority it will be returned.\r\n updatePriority(request);\r\n var removedRequest = requestHeap.insert(request);\r\n\r\n if (defined(removedRequest)) {\r\n if (removedRequest === request) {\r\n // Request does not have high enough priority to be issued\r\n return undefined;\r\n }\r\n // A previously issued request has been bumped off the priority heap, so cancel it\r\n cancelRequest(removedRequest);\r\n }\r\n\r\n return issueRequest(request);\r\n};\r\n\r\nfunction updateStatistics() {\r\n if (!RequestScheduler.debugShowStatistics) {\r\n return;\r\n }\r\n\r\n if (\r\n statistics.numberOfActiveRequests === 0 &&\r\n statistics.lastNumberOfActiveRequests > 0\r\n ) {\r\n if (statistics.numberOfAttemptedRequests > 0) {\r\n console.log(\r\n \"Number of attempted requests: \" + statistics.numberOfAttemptedRequests\r\n );\r\n statistics.numberOfAttemptedRequests = 0;\r\n }\r\n\r\n if (statistics.numberOfCancelledRequests > 0) {\r\n console.log(\r\n \"Number of cancelled requests: \" + statistics.numberOfCancelledRequests\r\n );\r\n statistics.numberOfCancelledRequests = 0;\r\n }\r\n\r\n if (statistics.numberOfCancelledActiveRequests > 0) {\r\n console.log(\r\n \"Number of cancelled active requests: \" +\r\n statistics.numberOfCancelledActiveRequests\r\n );\r\n statistics.numberOfCancelledActiveRequests = 0;\r\n }\r\n\r\n if (statistics.numberOfFailedRequests > 0) {\r\n console.log(\r\n \"Number of failed requests: \" + statistics.numberOfFailedRequests\r\n );\r\n statistics.numberOfFailedRequests = 0;\r\n }\r\n }\r\n\r\n statistics.lastNumberOfActiveRequests = statistics.numberOfActiveRequests;\r\n}\r\n\r\n/**\r\n * For testing only. Clears any requests that may not have completed from previous tests.\r\n *\r\n * @private\r\n */\r\nRequestScheduler.clearForSpecs = function () {\r\n while (requestHeap.length > 0) {\r\n var request = requestHeap.pop();\r\n cancelRequest(request);\r\n }\r\n var length = activeRequests.length;\r\n for (var i = 0; i < length; ++i) {\r\n cancelRequest(activeRequests[i]);\r\n }\r\n activeRequests.length = 0;\r\n numberOfActiveRequestsByServer = {};\r\n\r\n // Clear stats\r\n statistics.numberOfAttemptedRequests = 0;\r\n statistics.numberOfActiveRequests = 0;\r\n statistics.numberOfCancelledRequests = 0;\r\n statistics.numberOfCancelledActiveRequests = 0;\r\n statistics.numberOfFailedRequests = 0;\r\n statistics.numberOfActiveRequestsEver = 0;\r\n statistics.lastNumberOfActiveRequests = 0;\r\n};\r\n\r\n/**\r\n * For testing only.\r\n *\r\n * @private\r\n */\r\nRequestScheduler.numberOfActiveRequestsByServer = function (serverKey) {\r\n return numberOfActiveRequestsByServer[serverKey];\r\n};\r\n\r\n/**\r\n * For testing only.\r\n *\r\n * @private\r\n */\r\nRequestScheduler.requestHeap = requestHeap;\r\nexport default RequestScheduler;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * A singleton that contains all of the servers that are trusted. Credentials will be sent with\r\n * any requests to these servers.\r\n *\r\n * @namespace TrustedServers\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n */\r\nvar TrustedServers = {};\r\nvar _servers = {};\r\n\r\n/**\r\n * Adds a trusted server to the registry\r\n *\r\n * @param {String} host The host to be added.\r\n * @param {Number} port The port used to access the host.\r\n *\r\n * @example\r\n * // Add a trusted server\r\n * TrustedServers.add('my.server.com', 80);\r\n */\r\nTrustedServers.add = function (host, port) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(host)) {\r\n throw new DeveloperError(\"host is required.\");\r\n }\r\n if (!defined(port) || port <= 0) {\r\n throw new DeveloperError(\"port is required to be greater than 0.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var authority = host.toLowerCase() + \":\" + port;\r\n if (!defined(_servers[authority])) {\r\n _servers[authority] = true;\r\n }\r\n};\r\n\r\n/**\r\n * Removes a trusted server from the registry\r\n *\r\n * @param {String} host The host to be removed.\r\n * @param {Number} port The port used to access the host.\r\n *\r\n * @example\r\n * // Remove a trusted server\r\n * TrustedServers.remove('my.server.com', 80);\r\n */\r\nTrustedServers.remove = function (host, port) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(host)) {\r\n throw new DeveloperError(\"host is required.\");\r\n }\r\n if (!defined(port) || port <= 0) {\r\n throw new DeveloperError(\"port is required to be greater than 0.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var authority = host.toLowerCase() + \":\" + port;\r\n if (defined(_servers[authority])) {\r\n delete _servers[authority];\r\n }\r\n};\r\n\r\nfunction getAuthority(url) {\r\n var uri = new Uri(url);\r\n uri.normalize();\r\n\r\n // Removes username:password@ so we just have host[:port]\r\n var authority = uri.getAuthority();\r\n if (!defined(authority)) {\r\n return undefined; // Relative URL\r\n }\r\n\r\n if (authority.indexOf(\"@\") !== -1) {\r\n var parts = authority.split(\"@\");\r\n authority = parts[1];\r\n }\r\n\r\n // If the port is missing add one based on the scheme\r\n if (authority.indexOf(\":\") === -1) {\r\n var scheme = uri.getScheme();\r\n if (!defined(scheme)) {\r\n scheme = window.location.protocol;\r\n scheme = scheme.substring(0, scheme.length - 1);\r\n }\r\n if (scheme === \"http\") {\r\n authority += \":80\";\r\n } else if (scheme === \"https\") {\r\n authority += \":443\";\r\n } else {\r\n return undefined;\r\n }\r\n }\r\n\r\n return authority;\r\n}\r\n\r\n/**\r\n * Tests whether a server is trusted or not. The server must have been added with the port if it is included in the url.\r\n *\r\n * @param {String} url The url to be tested against the trusted list\r\n *\r\n * @returns {boolean} Returns true if url is trusted, false otherwise.\r\n *\r\n * @example\r\n * // Add server\r\n * TrustedServers.add('my.server.com', 81);\r\n *\r\n * // Check if server is trusted\r\n * if (TrustedServers.contains('https://my.server.com:81/path/to/file.png')) {\r\n * // my.server.com:81 is trusted\r\n * }\r\n * if (TrustedServers.contains('https://my.server.com/path/to/file.png')) {\r\n * // my.server.com isn't trusted\r\n * }\r\n */\r\nTrustedServers.contains = function (url) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(url)) {\r\n throw new DeveloperError(\"url is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n var authority = getAuthority(url);\r\n if (defined(authority) && defined(_servers[authority])) {\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Clears the registry\r\n *\r\n * @example\r\n * // Remove a trusted server\r\n * TrustedServers.clear();\r\n */\r\nTrustedServers.clear = function () {\r\n _servers = {};\r\n};\r\nexport default TrustedServers;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport appendForwardSlash from \"./appendForwardSlash.js\";\r\nimport Check from \"./Check.js\";\r\nimport clone from \"./clone.js\";\r\nimport combine from \"./combine.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport getAbsoluteUri from \"./getAbsoluteUri.js\";\r\nimport getBaseUri from \"./getBaseUri.js\";\r\nimport getExtensionFromUri from \"./getExtensionFromUri.js\";\r\nimport isBlobUri from \"./isBlobUri.js\";\r\nimport isCrossOriginUrl from \"./isCrossOriginUrl.js\";\r\nimport isDataUri from \"./isDataUri.js\";\r\nimport loadAndExecuteScript from \"./loadAndExecuteScript.js\";\r\nimport objectToQuery from \"./objectToQuery.js\";\r\nimport queryToObject from \"./queryToObject.js\";\r\nimport Request from \"./Request.js\";\r\nimport RequestErrorEvent from \"./RequestErrorEvent.js\";\r\nimport RequestScheduler from \"./RequestScheduler.js\";\r\nimport RequestState from \"./RequestState.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\nimport TrustedServers from \"./TrustedServers.js\";\r\n\r\nvar xhrBlobSupported = (function () {\r\n try {\r\n var xhr = new XMLHttpRequest();\r\n xhr.open(\"GET\", \"#\", true);\r\n xhr.responseType = \"blob\";\r\n return xhr.responseType === \"blob\";\r\n } catch (e) {\r\n return false;\r\n }\r\n})();\r\n\r\n/**\r\n * Parses a query string and returns the object equivalent.\r\n *\r\n * @param {Uri} uri The Uri with a query object.\r\n * @param {Resource} resource The Resource that will be assigned queryParameters.\r\n * @param {Boolean} merge If true, we'll merge with the resource's existing queryParameters. Otherwise they will be replaced.\r\n * @param {Boolean} preserveQueryParameters If true duplicate parameters will be concatenated into an array. If false, keys in uri will take precedence.\r\n *\r\n * @private\r\n */\r\nfunction parseQuery(uri, resource, merge, preserveQueryParameters) {\r\n var queryString = uri.query;\r\n if (!defined(queryString) || queryString.length === 0) {\r\n return {};\r\n }\r\n\r\n var query;\r\n // Special case we run into where the querystring is just a string, not key/value pairs\r\n if (queryString.indexOf(\"=\") === -1) {\r\n var result = {};\r\n result[queryString] = undefined;\r\n query = result;\r\n } else {\r\n query = queryToObject(queryString);\r\n }\r\n\r\n if (merge) {\r\n resource._queryParameters = combineQueryParameters(\r\n query,\r\n resource._queryParameters,\r\n preserveQueryParameters\r\n );\r\n } else {\r\n resource._queryParameters = query;\r\n }\r\n uri.query = undefined;\r\n}\r\n\r\n/**\r\n * Converts a query object into a string.\r\n *\r\n * @param {Uri} uri The Uri object that will have the query object set.\r\n * @param {Resource} resource The resource that has queryParameters\r\n *\r\n * @private\r\n */\r\nfunction stringifyQuery(uri, resource) {\r\n var queryObject = resource._queryParameters;\r\n\r\n var keys = Object.keys(queryObject);\r\n\r\n // We have 1 key with an undefined value, so this is just a string, not key/value pairs\r\n if (keys.length === 1 && !defined(queryObject[keys[0]])) {\r\n uri.query = keys[0];\r\n } else {\r\n uri.query = objectToQuery(queryObject);\r\n }\r\n}\r\n\r\n/**\r\n * Clones a value if it is defined, otherwise returns the default value\r\n *\r\n * @param {*} [val] The value to clone.\r\n * @param {*} [defaultVal] The default value.\r\n *\r\n * @returns {*} A clone of val or the defaultVal.\r\n *\r\n * @private\r\n */\r\nfunction defaultClone(val, defaultVal) {\r\n if (!defined(val)) {\r\n return defaultVal;\r\n }\r\n\r\n return defined(val.clone) ? val.clone() : clone(val);\r\n}\r\n\r\n/**\r\n * Checks to make sure the Resource isn't already being requested.\r\n *\r\n * @param {Request} request The request to check.\r\n *\r\n * @private\r\n */\r\nfunction checkAndResetRequest(request) {\r\n if (\r\n request.state === RequestState.ISSUED ||\r\n request.state === RequestState.ACTIVE\r\n ) {\r\n throw new RuntimeError(\"The Resource is already being fetched.\");\r\n }\r\n\r\n request.state = RequestState.UNISSUED;\r\n request.deferred = undefined;\r\n}\r\n\r\n/**\r\n * This combines a map of query parameters.\r\n *\r\n * @param {Object} q1 The first map of query parameters. Values in this map will take precedence if preserveQueryParameters is false.\r\n * @param {Object} q2 The second map of query parameters.\r\n * @param {Boolean} preserveQueryParameters If true duplicate parameters will be concatenated into an array. If false, keys in q1 will take precedence.\r\n *\r\n * @returns {Object} The combined map of query parameters.\r\n *\r\n * @example\r\n * var q1 = {\r\n * a: 1,\r\n * b: 2\r\n * };\r\n * var q2 = {\r\n * a: 3,\r\n * c: 4\r\n * };\r\n * var q3 = {\r\n * b: [5, 6],\r\n * d: 7\r\n * }\r\n *\r\n * // Returns\r\n * // {\r\n * // a: [1, 3],\r\n * // b: 2,\r\n * // c: 4\r\n * // };\r\n * combineQueryParameters(q1, q2, true);\r\n *\r\n * // Returns\r\n * // {\r\n * // a: 1,\r\n * // b: 2,\r\n * // c: 4\r\n * // };\r\n * combineQueryParameters(q1, q2, false);\r\n *\r\n * // Returns\r\n * // {\r\n * // a: 1,\r\n * // b: [2, 5, 6],\r\n * // d: 7\r\n * // };\r\n * combineQueryParameters(q1, q3, true);\r\n *\r\n * // Returns\r\n * // {\r\n * // a: 1,\r\n * // b: 2,\r\n * // d: 7\r\n * // };\r\n * combineQueryParameters(q1, q3, false);\r\n *\r\n * @private\r\n */\r\nfunction combineQueryParameters(q1, q2, preserveQueryParameters) {\r\n if (!preserveQueryParameters) {\r\n return combine(q1, q2);\r\n }\r\n\r\n var result = clone(q1, true);\r\n for (var param in q2) {\r\n if (q2.hasOwnProperty(param)) {\r\n var value = result[param];\r\n var q2Value = q2[param];\r\n if (defined(value)) {\r\n if (!Array.isArray(value)) {\r\n value = result[param] = [value];\r\n }\r\n\r\n result[param] = value.concat(q2Value);\r\n } else {\r\n result[param] = Array.isArray(q2Value) ? q2Value.slice() : q2Value;\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * A resource that includes the location and any other parameters we need to retrieve it or create derived resources. It also provides the ability to retry requests.\r\n *\r\n * @alias Resource\r\n * @constructor\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n *\r\n * @example\r\n * function refreshTokenRetryCallback(resource, error) {\r\n * if (error.statusCode === 403) {\r\n * // 403 status code means a new token should be generated\r\n * return getNewAccessToken()\r\n * .then(function(token) {\r\n * resource.queryParameters.access_token = token;\r\n * return true;\r\n * })\r\n * .otherwise(function() {\r\n * return false;\r\n * });\r\n * }\r\n *\r\n * return false;\r\n * }\r\n *\r\n * var resource = new Resource({\r\n * url: 'http://server.com/path/to/resource.json',\r\n * proxy: new DefaultProxy('/proxy/'),\r\n * headers: {\r\n * 'X-My-Header': 'valueOfHeader'\r\n * },\r\n * queryParameters: {\r\n * 'access_token': '123-435-456-000'\r\n * },\r\n * retryCallback: refreshTokenRetryCallback,\r\n * retryAttempts: 1\r\n * });\r\n */\r\nfunction Resource(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n if (typeof options === \"string\") {\r\n options = {\r\n url: options,\r\n };\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"options.url\", options.url);\r\n //>>includeEnd('debug');\r\n\r\n this._url = undefined;\r\n this._templateValues = defaultClone(options.templateValues, {});\r\n this._queryParameters = defaultClone(options.queryParameters, {});\r\n\r\n /**\r\n * Additional HTTP headers that will be sent with the request.\r\n *\r\n * @type {Object}\r\n */\r\n this.headers = defaultClone(options.headers, {});\r\n\r\n /**\r\n * A Request object that will be used. Intended for internal use only.\r\n *\r\n * @type {Request}\r\n */\r\n this.request = defaultValue(options.request, new Request());\r\n\r\n /**\r\n * A proxy to be used when loading the resource.\r\n *\r\n * @type {Proxy}\r\n */\r\n this.proxy = options.proxy;\r\n\r\n /**\r\n * Function to call when a request for this resource fails. If it returns true or a Promise that resolves to true, the request will be retried.\r\n *\r\n * @type {Function}\r\n */\r\n this.retryCallback = options.retryCallback;\r\n\r\n /**\r\n * The number of times the retryCallback should be called before giving up.\r\n *\r\n * @type {Number}\r\n */\r\n this.retryAttempts = defaultValue(options.retryAttempts, 0);\r\n this._retryCount = 0;\r\n\r\n var uri = new Uri(options.url);\r\n parseQuery(uri, this, true, true);\r\n\r\n // Remove the fragment as it's not sent with a request\r\n uri.fragment = undefined;\r\n\r\n this._url = uri.toString();\r\n}\r\n\r\n/**\r\n * A helper function to create a resource depending on whether we have a String or a Resource\r\n *\r\n * @param {Resource|String} resource A Resource or a String to use when creating a new Resource.\r\n *\r\n * @returns {Resource} If resource is a String, a Resource constructed with the url and options. Otherwise the resource parameter is returned.\r\n *\r\n * @private\r\n */\r\nResource.createIfNeeded = function (resource) {\r\n if (resource instanceof Resource) {\r\n // Keep existing request object. This function is used internally to duplicate a Resource, so that it can't\r\n // be modified outside of a class that holds it (eg. an imagery or terrain provider). Since the Request objects\r\n // are managed outside of the providers, by the tile loading code, we want to keep the request property the same so if it is changed\r\n // in the underlying tiling code the requests for this resource will use it.\r\n return resource.getDerivedResource({\r\n request: resource.request,\r\n });\r\n }\r\n\r\n if (typeof resource !== \"string\") {\r\n return resource;\r\n }\r\n\r\n return new Resource({\r\n url: resource,\r\n });\r\n};\r\n\r\nvar supportsImageBitmapOptionsPromise;\r\n/**\r\n * A helper function to check whether createImageBitmap supports passing ImageBitmapOptions.\r\n *\r\n * @returns {Promise} A promise that resolves to true if this browser supports creating an ImageBitmap with options.\r\n *\r\n * @private\r\n */\r\nResource.supportsImageBitmapOptions = function () {\r\n // Until the HTML folks figure out what to do about this, we need to actually try loading an image to\r\n // know if this browser supports passing options to the createImageBitmap function.\r\n // https://github.com/whatwg/html/pull/4248\r\n if (defined(supportsImageBitmapOptionsPromise)) {\r\n return supportsImageBitmapOptionsPromise;\r\n }\r\n\r\n if (typeof createImageBitmap !== \"function\") {\r\n supportsImageBitmapOptionsPromise = when.resolve(false);\r\n return supportsImageBitmapOptionsPromise;\r\n }\r\n\r\n var imageDataUri =\r\n \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQImWP4////fwAJ+wP9CNHoHgAAAABJRU5ErkJggg==\";\r\n\r\n supportsImageBitmapOptionsPromise = Resource.fetchBlob({\r\n url: imageDataUri,\r\n })\r\n .then(function (blob) {\r\n return createImageBitmap(blob, {\r\n imageOrientation: \"flipY\",\r\n premultiplyAlpha: \"none\",\r\n });\r\n })\r\n .then(function (imageBitmap) {\r\n return true;\r\n })\r\n .otherwise(function () {\r\n return false;\r\n });\r\n\r\n return supportsImageBitmapOptionsPromise;\r\n};\r\n\r\nObject.defineProperties(Resource, {\r\n /**\r\n * Returns true if blobs are supported.\r\n *\r\n * @memberof Resource\r\n * @type {Boolean}\r\n *\r\n * @readonly\r\n */\r\n isBlobSupported: {\r\n get: function () {\r\n return xhrBlobSupported;\r\n },\r\n },\r\n});\r\n\r\nObject.defineProperties(Resource.prototype, {\r\n /**\r\n * Query parameters appended to the url.\r\n *\r\n * @memberof Resource.prototype\r\n * @type {Object}\r\n *\r\n * @readonly\r\n */\r\n queryParameters: {\r\n get: function () {\r\n return this._queryParameters;\r\n },\r\n },\r\n\r\n /**\r\n * The key/value pairs used to replace template parameters in the url.\r\n *\r\n * @memberof Resource.prototype\r\n * @type {Object}\r\n *\r\n * @readonly\r\n */\r\n templateValues: {\r\n get: function () {\r\n return this._templateValues;\r\n },\r\n },\r\n\r\n /**\r\n * The url to the resource with template values replaced, query string appended and encoded by proxy if one was set.\r\n *\r\n * @memberof Resource.prototype\r\n * @type {String}\r\n */\r\n url: {\r\n get: function () {\r\n return this.getUrlComponent(true, true);\r\n },\r\n set: function (value) {\r\n var uri = new Uri(value);\r\n\r\n parseQuery(uri, this, false);\r\n\r\n // Remove the fragment as it's not sent with a request\r\n uri.fragment = undefined;\r\n\r\n this._url = uri.toString();\r\n },\r\n },\r\n\r\n /**\r\n * The file extension of the resource.\r\n *\r\n * @memberof Resource.prototype\r\n * @type {String}\r\n *\r\n * @readonly\r\n */\r\n extension: {\r\n get: function () {\r\n return getExtensionFromUri(this._url);\r\n },\r\n },\r\n\r\n /**\r\n * True if the Resource refers to a data URI.\r\n *\r\n * @memberof Resource.prototype\r\n * @type {Boolean}\r\n */\r\n isDataUri: {\r\n get: function () {\r\n return isDataUri(this._url);\r\n },\r\n },\r\n\r\n /**\r\n * True if the Resource refers to a blob URI.\r\n *\r\n * @memberof Resource.prototype\r\n * @type {Boolean}\r\n */\r\n isBlobUri: {\r\n get: function () {\r\n return isBlobUri(this._url);\r\n },\r\n },\r\n\r\n /**\r\n * True if the Resource refers to a cross origin URL.\r\n *\r\n * @memberof Resource.prototype\r\n * @type {Boolean}\r\n */\r\n isCrossOriginUrl: {\r\n get: function () {\r\n return isCrossOriginUrl(this._url);\r\n },\r\n },\r\n\r\n /**\r\n * True if the Resource has request headers. This is equivalent to checking if the headers property has any keys.\r\n *\r\n * @memberof Resource.prototype\r\n * @type {Boolean}\r\n */\r\n hasHeaders: {\r\n get: function () {\r\n return Object.keys(this.headers).length > 0;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Override Object#toString so that implicit string conversion gives the\r\n * complete URL represented by this Resource.\r\n *\r\n * @returns {String} The URL represented by this Resource\r\n */\r\nResource.prototype.toString = function () {\r\n return this.getUrlComponent(true, true);\r\n};\r\n\r\n/**\r\n * Returns the url, optional with the query string and processed by a proxy.\r\n *\r\n * @param {Boolean} [query=false] If true, the query string is included.\r\n * @param {Boolean} [proxy=false] If true, the url is processed by the proxy object, if defined.\r\n *\r\n * @returns {String} The url with all the requested components.\r\n */\r\nResource.prototype.getUrlComponent = function (query, proxy) {\r\n if (this.isDataUri) {\r\n return this._url;\r\n }\r\n\r\n var uri = new Uri(this._url);\r\n\r\n if (query) {\r\n stringifyQuery(uri, this);\r\n }\r\n\r\n // objectToQuery escapes the placeholders. Undo that.\r\n var url = uri.toString().replace(/%7B/g, \"{\").replace(/%7D/g, \"}\");\r\n\r\n var templateValues = this._templateValues;\r\n url = url.replace(/{(.*?)}/g, function (match, key) {\r\n var replacement = templateValues[key];\r\n if (defined(replacement)) {\r\n // use the replacement value from templateValues if there is one...\r\n return encodeURIComponent(replacement);\r\n }\r\n // otherwise leave it unchanged\r\n return match;\r\n });\r\n\r\n if (proxy && defined(this.proxy)) {\r\n url = this.proxy.getURL(url);\r\n }\r\n return url;\r\n};\r\n\r\n/**\r\n * Combines the specified object and the existing query parameters. This allows you to add many parameters at once,\r\n * as opposed to adding them one at a time to the queryParameters property. If a value is already set, it will be replaced with the new value.\r\n *\r\n * @param {Object} params The query parameters\r\n * @param {Boolean} [useAsDefault=false] If true the params will be used as the default values, so they will only be set if they are undefined.\r\n */\r\nResource.prototype.setQueryParameters = function (params, useAsDefault) {\r\n if (useAsDefault) {\r\n this._queryParameters = combineQueryParameters(\r\n this._queryParameters,\r\n params,\r\n false\r\n );\r\n } else {\r\n this._queryParameters = combineQueryParameters(\r\n params,\r\n this._queryParameters,\r\n false\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Combines the specified object and the existing query parameters. This allows you to add many parameters at once,\r\n * as opposed to adding them one at a time to the queryParameters property.\r\n *\r\n * @param {Object} params The query parameters\r\n */\r\nResource.prototype.appendQueryParameters = function (params) {\r\n this._queryParameters = combineQueryParameters(\r\n params,\r\n this._queryParameters,\r\n true\r\n );\r\n};\r\n\r\n/**\r\n * Combines the specified object and the existing template values. This allows you to add many values at once,\r\n * as opposed to adding them one at a time to the templateValues property. If a value is already set, it will become an array and the new value will be appended.\r\n *\r\n * @param {Object} template The template values\r\n * @param {Boolean} [useAsDefault=false] If true the values will be used as the default values, so they will only be set if they are undefined.\r\n */\r\nResource.prototype.setTemplateValues = function (template, useAsDefault) {\r\n if (useAsDefault) {\r\n this._templateValues = combine(this._templateValues, template);\r\n } else {\r\n this._templateValues = combine(template, this._templateValues);\r\n }\r\n};\r\n\r\n/**\r\n * Returns a resource relative to the current instance. All properties remain the same as the current instance unless overridden in options.\r\n *\r\n * @param {Object} options An object with the following properties\r\n * @param {String} [options.url] The url that will be resolved relative to the url of the current instance.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be combined with those of the current instance.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}). These will be combined with those of the current instance.\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The function to call when loading the resource fails.\r\n * @param {Number} [options.retryAttempts] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {Boolean} [options.preserveQueryParameters=false] If true, this will keep all query parameters from the current resource and derived resource. If false, derived parameters will replace those of the current resource.\r\n *\r\n * @returns {Resource} The resource derived from the current one.\r\n */\r\nResource.prototype.getDerivedResource = function (options) {\r\n var resource = this.clone();\r\n resource._retryCount = 0;\r\n\r\n if (defined(options.url)) {\r\n var uri = new Uri(options.url);\r\n\r\n var preserveQueryParameters = defaultValue(\r\n options.preserveQueryParameters,\r\n false\r\n );\r\n parseQuery(uri, resource, true, preserveQueryParameters);\r\n\r\n // Remove the fragment as it's not sent with a request\r\n uri.fragment = undefined;\r\n\r\n resource._url = uri.resolve(new Uri(getAbsoluteUri(this._url))).toString();\r\n }\r\n\r\n if (defined(options.queryParameters)) {\r\n resource._queryParameters = combine(\r\n options.queryParameters,\r\n resource._queryParameters\r\n );\r\n }\r\n if (defined(options.templateValues)) {\r\n resource._templateValues = combine(\r\n options.templateValues,\r\n resource.templateValues\r\n );\r\n }\r\n if (defined(options.headers)) {\r\n resource.headers = combine(options.headers, resource.headers);\r\n }\r\n if (defined(options.proxy)) {\r\n resource.proxy = options.proxy;\r\n }\r\n if (defined(options.request)) {\r\n resource.request = options.request;\r\n }\r\n if (defined(options.retryCallback)) {\r\n resource.retryCallback = options.retryCallback;\r\n }\r\n if (defined(options.retryAttempts)) {\r\n resource.retryAttempts = options.retryAttempts;\r\n }\r\n\r\n return resource;\r\n};\r\n\r\n/**\r\n * Called when a resource fails to load. This will call the retryCallback function if defined until retryAttempts is reached.\r\n *\r\n * @param {Error} [error] The error that was encountered.\r\n *\r\n * @returns {Promise} A promise to a boolean, that if true will cause the resource request to be retried.\r\n *\r\n * @private\r\n */\r\nResource.prototype.retryOnError = function (error) {\r\n var retryCallback = this.retryCallback;\r\n if (\r\n typeof retryCallback !== \"function\" ||\r\n this._retryCount >= this.retryAttempts\r\n ) {\r\n return when(false);\r\n }\r\n\r\n var that = this;\r\n return when(retryCallback(this, error)).then(function (result) {\r\n ++that._retryCount;\r\n\r\n return result;\r\n });\r\n};\r\n\r\n/**\r\n * Duplicates a Resource instance.\r\n *\r\n * @param {Resource} [result] The object onto which to store the result.\r\n *\r\n * @returns {Resource} The modified result parameter or a new Resource instance if one was not provided.\r\n */\r\nResource.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n result = new Resource({\r\n url: this._url,\r\n });\r\n }\r\n\r\n result._url = this._url;\r\n result._queryParameters = clone(this._queryParameters);\r\n result._templateValues = clone(this._templateValues);\r\n result.headers = clone(this.headers);\r\n result.proxy = this.proxy;\r\n result.retryCallback = this.retryCallback;\r\n result.retryAttempts = this.retryAttempts;\r\n result._retryCount = 0;\r\n result.request = this.request.clone();\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns the base path of the Resource.\r\n *\r\n * @param {Boolean} [includeQuery = false] Whether or not to include the query string and fragment form the uri\r\n *\r\n * @returns {String} The base URI of the resource\r\n */\r\nResource.prototype.getBaseUri = function (includeQuery) {\r\n return getBaseUri(this.getUrlComponent(includeQuery), includeQuery);\r\n};\r\n\r\n/**\r\n * Appends a forward slash to the URL.\r\n */\r\nResource.prototype.appendForwardSlash = function () {\r\n this._url = appendForwardSlash(this._url);\r\n};\r\n\r\n/**\r\n * Asynchronously loads the resource as raw binary data. Returns a promise that will resolve to\r\n * an ArrayBuffer once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @returns {Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n * @example\r\n * // load a single URL asynchronously\r\n * resource.fetchArrayBuffer().then(function(arrayBuffer) {\r\n * // use the data\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.fetchArrayBuffer = function () {\r\n return this.fetch({\r\n responseType: \"arraybuffer\",\r\n });\r\n};\r\n\r\n/**\r\n * Creates a Resource and calls fetchArrayBuffer() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @returns {Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.fetchArrayBuffer = function (options) {\r\n var resource = new Resource(options);\r\n return resource.fetchArrayBuffer();\r\n};\r\n\r\n/**\r\n * Asynchronously loads the given resource as a blob. Returns a promise that will resolve to\r\n * a Blob once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @returns {Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n * @example\r\n * // load a single URL asynchronously\r\n * resource.fetchBlob().then(function(blob) {\r\n * // use the data\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.fetchBlob = function () {\r\n return this.fetch({\r\n responseType: \"blob\",\r\n });\r\n};\r\n\r\n/**\r\n * Creates a Resource and calls fetchBlob() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @returns {Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.fetchBlob = function (options) {\r\n var resource = new Resource(options);\r\n return resource.fetchBlob();\r\n};\r\n\r\n/**\r\n * Asynchronously loads the given image resource. Returns a promise that will resolve to\r\n * an {@link https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap|ImageBitmap} if preferImageBitmap is true and the browser supports createImageBitmap or otherwise an\r\n * {@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement|Image} once loaded, or reject if the image failed to load.\r\n *\r\n * @param {Object} [options] An object with the following properties.\r\n * @param {Boolean} [options.preferBlob=false] If true, we will load the image via a blob.\r\n * @param {Boolean} [options.preferImageBitmap=false] If true, image will be decoded during fetch and an ImageBitmap is returned.\r\n * @param {Boolean} [options.flipY=false] If true, image will be vertically flipped during decode. Only applies if the browser supports createImageBitmap.\r\n * @returns {Promise.|Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * // load a single image asynchronously\r\n * resource.fetchImage().then(function(image) {\r\n * // use the loaded image\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * // load several images in parallel\r\n * when.all([resource1.fetchImage(), resource2.fetchImage()]).then(function(images) {\r\n * // images is an array containing all the loaded images\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.fetchImage = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var preferImageBitmap = defaultValue(options.preferImageBitmap, false);\r\n var preferBlob = defaultValue(options.preferBlob, false);\r\n var flipY = defaultValue(options.flipY, false);\r\n\r\n checkAndResetRequest(this.request);\r\n\r\n // We try to load the image normally if\r\n // 1. Blobs aren't supported\r\n // 2. It's a data URI\r\n // 3. It's a blob URI\r\n // 4. It doesn't have request headers and we preferBlob is false\r\n if (\r\n !xhrBlobSupported ||\r\n this.isDataUri ||\r\n this.isBlobUri ||\r\n (!this.hasHeaders && !preferBlob)\r\n ) {\r\n return fetchImage({\r\n resource: this,\r\n flipY: flipY,\r\n preferImageBitmap: preferImageBitmap,\r\n });\r\n }\r\n\r\n var blobPromise = this.fetchBlob();\r\n if (!defined(blobPromise)) {\r\n return;\r\n }\r\n\r\n var supportsImageBitmap;\r\n var useImageBitmap;\r\n var generatedBlobResource;\r\n var generatedBlob;\r\n return Resource.supportsImageBitmapOptions()\r\n .then(function (result) {\r\n supportsImageBitmap = result;\r\n useImageBitmap = supportsImageBitmap && preferImageBitmap;\r\n return blobPromise;\r\n })\r\n .then(function (blob) {\r\n if (!defined(blob)) {\r\n return;\r\n }\r\n generatedBlob = blob;\r\n if (useImageBitmap) {\r\n return Resource.createImageBitmapFromBlob(blob, {\r\n flipY: flipY,\r\n premultiplyAlpha: false,\r\n });\r\n }\r\n var blobUrl = window.URL.createObjectURL(blob);\r\n generatedBlobResource = new Resource({\r\n url: blobUrl,\r\n });\r\n\r\n return fetchImage({\r\n resource: generatedBlobResource,\r\n flipY: flipY,\r\n preferImageBitmap: false,\r\n });\r\n })\r\n .then(function (image) {\r\n if (!defined(image)) {\r\n return;\r\n }\r\n\r\n // The blob object may be needed for use by a TileDiscardPolicy,\r\n // so attach it to the image.\r\n image.blob = generatedBlob;\r\n\r\n if (useImageBitmap) {\r\n return image;\r\n }\r\n\r\n window.URL.revokeObjectURL(generatedBlobResource.url);\r\n return image;\r\n })\r\n .otherwise(function (error) {\r\n if (defined(generatedBlobResource)) {\r\n window.URL.revokeObjectURL(generatedBlobResource.url);\r\n }\r\n\r\n // If the blob load succeeded but the image decode failed, attach the blob\r\n // to the error object for use by a TileDiscardPolicy.\r\n // In particular, BingMapsImageryProvider uses this to detect the\r\n // zero-length response that is returned when a tile is not available.\r\n error.blob = generatedBlob;\r\n\r\n return when.reject(error);\r\n });\r\n};\r\n\r\n/**\r\n * Fetches an image and returns a promise to it.\r\n *\r\n * @param {Object} [options] An object with the following properties.\r\n * @param {Resource} [options.resource] Resource object that points to an image to fetch.\r\n * @param {Boolean} [options.preferImageBitmap] If true, image will be decoded during fetch and an ImageBitmap is returned.\r\n * @param {Boolean} [options.flipY] If true, image will be vertically flipped during decode. Only applies if the browser supports createImageBitmap.\r\n *\r\n * @private\r\n */\r\nfunction fetchImage(options) {\r\n var resource = options.resource;\r\n var flipY = options.flipY;\r\n var preferImageBitmap = options.preferImageBitmap;\r\n\r\n var request = resource.request;\r\n request.url = resource.url;\r\n request.requestFunction = function () {\r\n var crossOrigin = false;\r\n\r\n // data URIs can't have crossorigin set.\r\n if (!resource.isDataUri && !resource.isBlobUri) {\r\n crossOrigin = resource.isCrossOriginUrl;\r\n }\r\n\r\n var deferred = when.defer();\r\n Resource._Implementations.createImage(\r\n request,\r\n crossOrigin,\r\n deferred,\r\n flipY,\r\n preferImageBitmap\r\n );\r\n\r\n return deferred.promise;\r\n };\r\n\r\n var promise = RequestScheduler.request(request);\r\n if (!defined(promise)) {\r\n return;\r\n }\r\n\r\n return promise.otherwise(function (e) {\r\n // Don't retry cancelled or otherwise aborted requests\r\n if (request.state !== RequestState.FAILED) {\r\n return when.reject(e);\r\n }\r\n\r\n return resource.retryOnError(e).then(function (retry) {\r\n if (retry) {\r\n // Reset request so it can try again\r\n request.state = RequestState.UNISSUED;\r\n request.deferred = undefined;\r\n\r\n return fetchImage({\r\n resource: resource,\r\n flipY: flipY,\r\n preferImageBitmap: preferImageBitmap,\r\n });\r\n }\r\n\r\n return when.reject(e);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Creates a Resource and calls fetchImage() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Boolean} [options.flipY=false] Whether to vertically flip the image during fetch and decode. Only applies when requesting an image and the browser supports createImageBitmap.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {Boolean} [options.preferBlob=false] If true, we will load the image via a blob.\r\n * @param {Boolean} [options.preferImageBitmap=false] If true, image will be decoded during fetch and an ImageBitmap is returned.\r\n * @returns {Promise.|Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.fetchImage = function (options) {\r\n var resource = new Resource(options);\r\n return resource.fetchImage({\r\n flipY: options.flipY,\r\n preferBlob: options.preferBlob,\r\n preferImageBitmap: options.preferImageBitmap,\r\n });\r\n};\r\n\r\n/**\r\n * Asynchronously loads the given resource as text. Returns a promise that will resolve to\r\n * a String once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @returns {Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n * @example\r\n * // load text from a URL, setting a custom header\r\n * var resource = new Resource({\r\n * url: 'http://someUrl.com/someJson.txt',\r\n * headers: {\r\n * 'X-Custom-Header' : 'some value'\r\n * }\r\n * });\r\n * resource.fetchText().then(function(text) {\r\n * // Do something with the text\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest|XMLHttpRequest}\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.fetchText = function () {\r\n return this.fetch({\r\n responseType: \"text\",\r\n });\r\n};\r\n\r\n/**\r\n * Creates a Resource and calls fetchText() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @returns {Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.fetchText = function (options) {\r\n var resource = new Resource(options);\r\n return resource.fetchText();\r\n};\r\n\r\n// note: */* below is */* but that ends the comment block early\r\n/**\r\n * Asynchronously loads the given resource as JSON. Returns a promise that will resolve to\r\n * a JSON object once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled. This function\r\n * adds 'Accept: application/json,*/*;q=0.01' to the request headers, if not\r\n * already specified.\r\n *\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * resource.fetchJson().then(function(jsonData) {\r\n * // Do something with the JSON object\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.fetchJson = function () {\r\n var promise = this.fetch({\r\n responseType: \"text\",\r\n headers: {\r\n Accept: \"application/json,*/*;q=0.01\",\r\n },\r\n });\r\n\r\n if (!defined(promise)) {\r\n return undefined;\r\n }\r\n\r\n return promise.then(function (value) {\r\n if (!defined(value)) {\r\n return;\r\n }\r\n return JSON.parse(value);\r\n });\r\n};\r\n\r\n/**\r\n * Creates a Resource and calls fetchJson() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.fetchJson = function (options) {\r\n var resource = new Resource(options);\r\n return resource.fetchJson();\r\n};\r\n\r\n/**\r\n * Asynchronously loads the given resource as XML. Returns a promise that will resolve to\r\n * an XML Document once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @returns {Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * // load XML from a URL, setting a custom header\r\n * Cesium.loadXML('http://someUrl.com/someXML.xml', {\r\n * 'X-Custom-Header' : 'some value'\r\n * }).then(function(document) {\r\n * // Do something with the document\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest|XMLHttpRequest}\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.fetchXML = function () {\r\n return this.fetch({\r\n responseType: \"document\",\r\n overrideMimeType: \"text/xml\",\r\n });\r\n};\r\n\r\n/**\r\n * Creates a Resource and calls fetchXML() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @returns {Promise.|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.fetchXML = function (options) {\r\n var resource = new Resource(options);\r\n return resource.fetchXML();\r\n};\r\n\r\n/**\r\n * Requests a resource using JSONP.\r\n *\r\n * @param {String} [callbackParameterName='callback'] The callback parameter name that the server expects.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * // load a data asynchronously\r\n * resource.fetchJsonp().then(function(data) {\r\n * // use the loaded data\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.fetchJsonp = function (callbackParameterName) {\r\n callbackParameterName = defaultValue(callbackParameterName, \"callback\");\r\n\r\n checkAndResetRequest(this.request);\r\n\r\n //generate a unique function name\r\n var functionName;\r\n do {\r\n functionName = \"loadJsonp\" + Math.random().toString().substring(2, 8);\r\n } while (defined(window[functionName]));\r\n\r\n return fetchJsonp(this, callbackParameterName, functionName);\r\n};\r\n\r\nfunction fetchJsonp(resource, callbackParameterName, functionName) {\r\n var callbackQuery = {};\r\n callbackQuery[callbackParameterName] = functionName;\r\n resource.setQueryParameters(callbackQuery);\r\n\r\n var request = resource.request;\r\n request.url = resource.url;\r\n request.requestFunction = function () {\r\n var deferred = when.defer();\r\n\r\n //assign a function with that name in the global scope\r\n window[functionName] = function (data) {\r\n deferred.resolve(data);\r\n\r\n try {\r\n delete window[functionName];\r\n } catch (e) {\r\n window[functionName] = undefined;\r\n }\r\n };\r\n\r\n Resource._Implementations.loadAndExecuteScript(\r\n resource.url,\r\n functionName,\r\n deferred\r\n );\r\n return deferred.promise;\r\n };\r\n\r\n var promise = RequestScheduler.request(request);\r\n if (!defined(promise)) {\r\n return;\r\n }\r\n\r\n return promise.otherwise(function (e) {\r\n if (request.state !== RequestState.FAILED) {\r\n return when.reject(e);\r\n }\r\n\r\n return resource.retryOnError(e).then(function (retry) {\r\n if (retry) {\r\n // Reset request so it can try again\r\n request.state = RequestState.UNISSUED;\r\n request.deferred = undefined;\r\n\r\n return fetchJsonp(resource, callbackParameterName, functionName);\r\n }\r\n\r\n return when.reject(e);\r\n });\r\n });\r\n}\r\n\r\n/**\r\n * Creates a Resource from a URL and calls fetchJsonp() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {String} [options.callbackParameterName='callback'] The callback parameter name that the server expects.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.fetchJsonp = function (options) {\r\n var resource = new Resource(options);\r\n return resource.fetchJsonp(options.callbackParameterName);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nResource.prototype._makeRequest = function (options) {\r\n var resource = this;\r\n checkAndResetRequest(resource.request);\r\n\r\n var request = resource.request;\r\n request.url = resource.url;\r\n\r\n request.requestFunction = function () {\r\n var responseType = options.responseType;\r\n var headers = combine(options.headers, resource.headers);\r\n var overrideMimeType = options.overrideMimeType;\r\n var method = options.method;\r\n var data = options.data;\r\n var deferred = when.defer();\r\n var xhr = Resource._Implementations.loadWithXhr(\r\n resource.url,\r\n responseType,\r\n method,\r\n data,\r\n headers,\r\n deferred,\r\n overrideMimeType\r\n );\r\n if (defined(xhr) && defined(xhr.abort)) {\r\n request.cancelFunction = function () {\r\n xhr.abort();\r\n };\r\n }\r\n return deferred.promise;\r\n };\r\n\r\n var promise = RequestScheduler.request(request);\r\n if (!defined(promise)) {\r\n return;\r\n }\r\n\r\n return promise\r\n .then(function (data) {\r\n // explicitly set to undefined to ensure GC of request response data. See #8843\r\n request.cancelFunction = undefined;\r\n return data;\r\n })\r\n .otherwise(function (e) {\r\n request.cancelFunction = undefined;\r\n if (request.state !== RequestState.FAILED) {\r\n return when.reject(e);\r\n }\r\n\r\n return resource.retryOnError(e).then(function (retry) {\r\n if (retry) {\r\n // Reset request so it can try again\r\n request.state = RequestState.UNISSUED;\r\n request.deferred = undefined;\r\n\r\n return resource.fetch(options);\r\n }\r\n\r\n return when.reject(e);\r\n });\r\n });\r\n};\r\n\r\nvar dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/;\r\n\r\nfunction decodeDataUriText(isBase64, data) {\r\n var result = decodeURIComponent(data);\r\n if (isBase64) {\r\n return atob(result);\r\n }\r\n return result;\r\n}\r\n\r\nfunction decodeDataUriArrayBuffer(isBase64, data) {\r\n var byteString = decodeDataUriText(isBase64, data);\r\n var buffer = new ArrayBuffer(byteString.length);\r\n var view = new Uint8Array(buffer);\r\n for (var i = 0; i < byteString.length; i++) {\r\n view[i] = byteString.charCodeAt(i);\r\n }\r\n return buffer;\r\n}\r\n\r\nfunction decodeDataUri(dataUriRegexResult, responseType) {\r\n responseType = defaultValue(responseType, \"\");\r\n var mimeType = dataUriRegexResult[1];\r\n var isBase64 = !!dataUriRegexResult[2];\r\n var data = dataUriRegexResult[3];\r\n\r\n switch (responseType) {\r\n case \"\":\r\n case \"text\":\r\n return decodeDataUriText(isBase64, data);\r\n case \"arraybuffer\":\r\n return decodeDataUriArrayBuffer(isBase64, data);\r\n case \"blob\":\r\n var buffer = decodeDataUriArrayBuffer(isBase64, data);\r\n return new Blob([buffer], {\r\n type: mimeType,\r\n });\r\n case \"document\":\r\n var parser = new DOMParser();\r\n return parser.parseFromString(\r\n decodeDataUriText(isBase64, data),\r\n mimeType\r\n );\r\n case \"json\":\r\n return JSON.parse(decodeDataUriText(isBase64, data));\r\n default:\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\"Unhandled responseType: \" + responseType);\r\n //>>includeEnd('debug');\r\n }\r\n}\r\n\r\n/**\r\n * Asynchronously loads the given resource. Returns a promise that will resolve to\r\n * the result once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled. It's recommended that you use\r\n * the more specific functions eg. fetchJson, fetchBlob, etc.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * resource.fetch()\r\n * .then(function(body) {\r\n * // use the data\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.fetch = function (options) {\r\n options = defaultClone(options, {});\r\n options.method = \"GET\";\r\n\r\n return this._makeRequest(options);\r\n};\r\n\r\n/**\r\n * Creates a Resource from a URL and calls fetch() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.fetch = function (options) {\r\n var resource = new Resource(options);\r\n return resource.fetch({\r\n // Make copy of just the needed fields because headers can be passed to both the constructor and to fetch\r\n responseType: options.responseType,\r\n overrideMimeType: options.overrideMimeType,\r\n });\r\n};\r\n\r\n/**\r\n * Asynchronously deletes the given resource. Returns a promise that will resolve to\r\n * the result once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * resource.delete()\r\n * .then(function(body) {\r\n * // use the data\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.delete = function (options) {\r\n options = defaultClone(options, {});\r\n options.method = \"DELETE\";\r\n\r\n return this._makeRequest(options);\r\n};\r\n\r\n/**\r\n * Creates a Resource from a URL and calls delete() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.data] Data that is posted with the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.delete = function (options) {\r\n var resource = new Resource(options);\r\n return resource.delete({\r\n // Make copy of just the needed fields because headers can be passed to both the constructor and to fetch\r\n responseType: options.responseType,\r\n overrideMimeType: options.overrideMimeType,\r\n data: options.data,\r\n });\r\n};\r\n\r\n/**\r\n * Asynchronously gets headers the given resource. Returns a promise that will resolve to\r\n * the result once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * resource.head()\r\n * .then(function(headers) {\r\n * // use the data\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.head = function (options) {\r\n options = defaultClone(options, {});\r\n options.method = \"HEAD\";\r\n\r\n return this._makeRequest(options);\r\n};\r\n\r\n/**\r\n * Creates a Resource from a URL and calls head() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.head = function (options) {\r\n var resource = new Resource(options);\r\n return resource.head({\r\n // Make copy of just the needed fields because headers can be passed to both the constructor and to fetch\r\n responseType: options.responseType,\r\n overrideMimeType: options.overrideMimeType,\r\n });\r\n};\r\n\r\n/**\r\n * Asynchronously gets options the given resource. Returns a promise that will resolve to\r\n * the result once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * resource.options()\r\n * .then(function(headers) {\r\n * // use the data\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.options = function (options) {\r\n options = defaultClone(options, {});\r\n options.method = \"OPTIONS\";\r\n\r\n return this._makeRequest(options);\r\n};\r\n\r\n/**\r\n * Creates a Resource from a URL and calls options() on it.\r\n *\r\n * @param {String|Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.options = function (options) {\r\n var resource = new Resource(options);\r\n return resource.options({\r\n // Make copy of just the needed fields because headers can be passed to both the constructor and to fetch\r\n responseType: options.responseType,\r\n overrideMimeType: options.overrideMimeType,\r\n });\r\n};\r\n\r\n/**\r\n * Asynchronously posts data to the given resource. Returns a promise that will resolve to\r\n * the result once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @param {Object} data Data that is posted with the resource.\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Object} [options.data] Data that is posted with the resource.\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * resource.post(data)\r\n * .then(function(result) {\r\n * // use the result\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.post = function (data, options) {\r\n Check.defined(\"data\", data);\r\n\r\n options = defaultClone(options, {});\r\n options.method = \"POST\";\r\n options.data = data;\r\n\r\n return this._makeRequest(options);\r\n};\r\n\r\n/**\r\n * Creates a Resource from a URL and calls post() on it.\r\n *\r\n * @param {Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} options.data Data that is posted with the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.post = function (options) {\r\n var resource = new Resource(options);\r\n return resource.post(options.data, {\r\n // Make copy of just the needed fields because headers can be passed to both the constructor and to post\r\n responseType: options.responseType,\r\n overrideMimeType: options.overrideMimeType,\r\n });\r\n};\r\n\r\n/**\r\n * Asynchronously puts data to the given resource. Returns a promise that will resolve to\r\n * the result once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @param {Object} data Data that is posted with the resource.\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * resource.put(data)\r\n * .then(function(result) {\r\n * // use the result\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.put = function (data, options) {\r\n Check.defined(\"data\", data);\r\n\r\n options = defaultClone(options, {});\r\n options.method = \"PUT\";\r\n options.data = data;\r\n\r\n return this._makeRequest(options);\r\n};\r\n\r\n/**\r\n * Creates a Resource from a URL and calls put() on it.\r\n *\r\n * @param {Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} options.data Data that is posted with the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.put = function (options) {\r\n var resource = new Resource(options);\r\n return resource.put(options.data, {\r\n // Make copy of just the needed fields because headers can be passed to both the constructor and to post\r\n responseType: options.responseType,\r\n overrideMimeType: options.overrideMimeType,\r\n });\r\n};\r\n\r\n/**\r\n * Asynchronously patches data to the given resource. Returns a promise that will resolve to\r\n * the result once loaded, or reject if the resource failed to load. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @param {Object} data Data that is posted with the resource.\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {Object} [options.headers] Additional HTTP headers to send with the request, if any.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n *\r\n * @example\r\n * resource.patch(data)\r\n * .then(function(result) {\r\n * // use the result\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nResource.prototype.patch = function (data, options) {\r\n Check.defined(\"data\", data);\r\n\r\n options = defaultClone(options, {});\r\n options.method = \"PATCH\";\r\n options.data = data;\r\n\r\n return this._makeRequest(options);\r\n};\r\n\r\n/**\r\n * Creates a Resource from a URL and calls patch() on it.\r\n *\r\n * @param {Object} options A url or an object with the following properties\r\n * @param {String} options.url The url of the resource.\r\n * @param {Object} options.data Data that is posted with the resource.\r\n * @param {Object} [options.queryParameters] An object containing query parameters that will be sent when retrieving the resource.\r\n * @param {Object} [options.templateValues] Key/Value pairs that are used to replace template values (eg. {x}).\r\n * @param {Object} [options.headers={}] Additional HTTP headers that will be sent.\r\n * @param {Proxy} [options.proxy] A proxy to be used when loading the resource.\r\n * @param {Resource.RetryCallback} [options.retryCallback] The Function to call when a request for this resource fails. If it returns true, the request will be retried.\r\n * @param {Number} [options.retryAttempts=0] The number of times the retryCallback should be called before giving up.\r\n * @param {Request} [options.request] A Request object that will be used. Intended for internal use only.\r\n * @param {String} [options.responseType] The type of response. This controls the type of item returned.\r\n * @param {String} [options.overrideMimeType] Overrides the MIME type returned by the server.\r\n * @returns {Promise.<*>|undefined} a promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n */\r\nResource.patch = function (options) {\r\n var resource = new Resource(options);\r\n return resource.patch(options.data, {\r\n // Make copy of just the needed fields because headers can be passed to both the constructor and to post\r\n responseType: options.responseType,\r\n overrideMimeType: options.overrideMimeType,\r\n });\r\n};\r\n\r\n/**\r\n * Contains implementations of functions that can be replaced for testing\r\n *\r\n * @private\r\n */\r\nResource._Implementations = {};\r\n\r\nfunction loadImageElement(url, crossOrigin, deferred) {\r\n var image = new Image();\r\n\r\n image.onload = function () {\r\n deferred.resolve(image);\r\n };\r\n\r\n image.onerror = function (e) {\r\n deferred.reject(e);\r\n };\r\n\r\n if (crossOrigin) {\r\n if (TrustedServers.contains(url)) {\r\n image.crossOrigin = \"use-credentials\";\r\n } else {\r\n image.crossOrigin = \"\";\r\n }\r\n }\r\n\r\n image.src = url;\r\n}\r\n\r\nResource._Implementations.createImage = function (\r\n request,\r\n crossOrigin,\r\n deferred,\r\n flipY,\r\n preferImageBitmap\r\n) {\r\n var url = request.url;\r\n // Passing an Image to createImageBitmap will force it to run on the main thread\r\n // since DOM elements don't exist on workers. We convert it to a blob so it's non-blocking.\r\n // See:\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=1044102#c38\r\n // https://bugs.chromium.org/p/chromium/issues/detail?id=580202#c10\r\n Resource.supportsImageBitmapOptions()\r\n .then(function (supportsImageBitmap) {\r\n // We can only use ImageBitmap if we can flip on decode.\r\n // See: https://github.com/CesiumGS/cesium/pull/7579#issuecomment-466146898\r\n if (!(supportsImageBitmap && preferImageBitmap)) {\r\n loadImageElement(url, crossOrigin, deferred);\r\n return;\r\n }\r\n var responseType = \"blob\";\r\n var method = \"GET\";\r\n var xhrDeferred = when.defer();\r\n var xhr = Resource._Implementations.loadWithXhr(\r\n url,\r\n responseType,\r\n method,\r\n undefined,\r\n undefined,\r\n xhrDeferred,\r\n undefined,\r\n undefined,\r\n undefined\r\n );\r\n\r\n if (defined(xhr) && defined(xhr.abort)) {\r\n request.cancelFunction = function () {\r\n xhr.abort();\r\n };\r\n }\r\n return xhrDeferred.promise\r\n .then(function (blob) {\r\n if (!defined(blob)) {\r\n deferred.reject(\r\n new RuntimeError(\r\n \"Successfully retrieved \" +\r\n url +\r\n \" but it contained no content.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n return Resource.createImageBitmapFromBlob(blob, {\r\n flipY: flipY,\r\n premultiplyAlpha: false,\r\n });\r\n })\r\n .then(deferred.resolve);\r\n })\r\n .otherwise(deferred.reject);\r\n};\r\n\r\n/**\r\n * Wrapper for createImageBitmap\r\n *\r\n * @private\r\n */\r\nResource.createImageBitmapFromBlob = function (blob, options) {\r\n Check.defined(\"options\", options);\r\n Check.typeOf.bool(\"options.flipY\", options.flipY);\r\n Check.typeOf.bool(\"options.premultiplyAlpha\", options.premultiplyAlpha);\r\n\r\n return createImageBitmap(blob, {\r\n imageOrientation: options.flipY ? \"flipY\" : \"none\",\r\n premultiplyAlpha: options.premultiplyAlpha ? \"premultiply\" : \"none\",\r\n });\r\n};\r\n\r\nfunction decodeResponse(loadWithHttpResponse, responseType) {\r\n switch (responseType) {\r\n case \"text\":\r\n return loadWithHttpResponse.toString(\"utf8\");\r\n case \"json\":\r\n return JSON.parse(loadWithHttpResponse.toString(\"utf8\"));\r\n default:\r\n return new Uint8Array(loadWithHttpResponse).buffer;\r\n }\r\n}\r\n\r\nfunction loadWithHttpRequest(\r\n url,\r\n responseType,\r\n method,\r\n data,\r\n headers,\r\n deferred,\r\n overrideMimeType\r\n) {\r\n // Note: only the 'json' and 'text' responseTypes transforms the loaded buffer\r\n /* eslint-disable no-undef */\r\n var URL = require(\"url\").parse(url);\r\n var http = URL.protocol === \"https:\" ? require(\"https\") : require(\"http\");\r\n var zlib = require(\"zlib\");\r\n /* eslint-enable no-undef */\r\n\r\n var options = {\r\n protocol: URL.protocol,\r\n hostname: URL.hostname,\r\n port: URL.port,\r\n path: URL.path,\r\n query: URL.query,\r\n method: method,\r\n headers: headers,\r\n };\r\n\r\n http\r\n .request(options)\r\n .on(\"response\", function (res) {\r\n if (res.statusCode < 200 || res.statusCode >= 300) {\r\n deferred.reject(\r\n new RequestErrorEvent(res.statusCode, res, res.headers)\r\n );\r\n return;\r\n }\r\n\r\n var chunkArray = [];\r\n res.on(\"data\", function (chunk) {\r\n chunkArray.push(chunk);\r\n });\r\n\r\n res.on(\"end\", function () {\r\n // eslint-disable-next-line no-undef\r\n var result = Buffer.concat(chunkArray);\r\n if (res.headers[\"content-encoding\"] === \"gzip\") {\r\n zlib.gunzip(result, function (error, resultUnzipped) {\r\n if (error) {\r\n deferred.reject(\r\n new RuntimeError(\"Error decompressing response.\")\r\n );\r\n } else {\r\n deferred.resolve(decodeResponse(resultUnzipped, responseType));\r\n }\r\n });\r\n } else {\r\n deferred.resolve(decodeResponse(result, responseType));\r\n }\r\n });\r\n })\r\n .on(\"error\", function (e) {\r\n deferred.reject(new RequestErrorEvent());\r\n })\r\n .end();\r\n}\r\n\r\nvar noXMLHttpRequest = typeof XMLHttpRequest === \"undefined\";\r\nResource._Implementations.loadWithXhr = function (\r\n url,\r\n responseType,\r\n method,\r\n data,\r\n headers,\r\n deferred,\r\n overrideMimeType\r\n) {\r\n var dataUriRegexResult = dataUriRegex.exec(url);\r\n if (dataUriRegexResult !== null) {\r\n deferred.resolve(decodeDataUri(dataUriRegexResult, responseType));\r\n return;\r\n }\r\n\r\n if (noXMLHttpRequest) {\r\n loadWithHttpRequest(\r\n url,\r\n responseType,\r\n method,\r\n data,\r\n headers,\r\n deferred,\r\n overrideMimeType\r\n );\r\n return;\r\n }\r\n\r\n var xhr = new XMLHttpRequest();\r\n\r\n if (TrustedServers.contains(url)) {\r\n xhr.withCredentials = true;\r\n }\r\n\r\n xhr.open(method, url, true);\r\n\r\n if (defined(overrideMimeType) && defined(xhr.overrideMimeType)) {\r\n xhr.overrideMimeType(overrideMimeType);\r\n }\r\n\r\n if (defined(headers)) {\r\n for (var key in headers) {\r\n if (headers.hasOwnProperty(key)) {\r\n xhr.setRequestHeader(key, headers[key]);\r\n }\r\n }\r\n }\r\n\r\n if (defined(responseType)) {\r\n xhr.responseType = responseType;\r\n }\r\n\r\n // While non-standard, file protocol always returns a status of 0 on success\r\n var localFile = false;\r\n if (typeof url === \"string\") {\r\n localFile =\r\n url.indexOf(\"file://\") === 0 ||\r\n (typeof window !== \"undefined\" && window.location.origin === \"file://\");\r\n }\r\n\r\n xhr.onload = function () {\r\n if (\r\n (xhr.status < 200 || xhr.status >= 300) &&\r\n !(localFile && xhr.status === 0)\r\n ) {\r\n deferred.reject(\r\n new RequestErrorEvent(\r\n xhr.status,\r\n xhr.response,\r\n xhr.getAllResponseHeaders()\r\n )\r\n );\r\n return;\r\n }\r\n\r\n var response = xhr.response;\r\n var browserResponseType = xhr.responseType;\r\n\r\n if (method === \"HEAD\" || method === \"OPTIONS\") {\r\n var responseHeaderString = xhr.getAllResponseHeaders();\r\n var splitHeaders = responseHeaderString.trim().split(/[\\r\\n]+/);\r\n\r\n var responseHeaders = {};\r\n splitHeaders.forEach(function (line) {\r\n var parts = line.split(\": \");\r\n var header = parts.shift();\r\n responseHeaders[header] = parts.join(\": \");\r\n });\r\n\r\n deferred.resolve(responseHeaders);\r\n return;\r\n }\r\n\r\n //All modern browsers will go into either the first or second if block or last else block.\r\n //Other code paths support older browsers that either do not support the supplied responseType\r\n //or do not support the xhr.response property.\r\n if (xhr.status === 204) {\r\n // accept no content\r\n deferred.resolve();\r\n } else if (\r\n defined(response) &&\r\n (!defined(responseType) || browserResponseType === responseType)\r\n ) {\r\n deferred.resolve(response);\r\n } else if (responseType === \"json\" && typeof response === \"string\") {\r\n try {\r\n deferred.resolve(JSON.parse(response));\r\n } catch (e) {\r\n deferred.reject(e);\r\n }\r\n } else if (\r\n (browserResponseType === \"\" || browserResponseType === \"document\") &&\r\n defined(xhr.responseXML) &&\r\n xhr.responseXML.hasChildNodes()\r\n ) {\r\n deferred.resolve(xhr.responseXML);\r\n } else if (\r\n (browserResponseType === \"\" || browserResponseType === \"text\") &&\r\n defined(xhr.responseText)\r\n ) {\r\n deferred.resolve(xhr.responseText);\r\n } else {\r\n deferred.reject(\r\n new RuntimeError(\"Invalid XMLHttpRequest response type.\")\r\n );\r\n }\r\n };\r\n\r\n xhr.onerror = function (e) {\r\n deferred.reject(new RequestErrorEvent());\r\n };\r\n\r\n xhr.send(data);\r\n\r\n return xhr;\r\n};\r\n\r\nResource._Implementations.loadAndExecuteScript = function (\r\n url,\r\n functionName,\r\n deferred\r\n) {\r\n return loadAndExecuteScript(url, functionName).otherwise(deferred.reject);\r\n};\r\n\r\n/**\r\n * The default implementations\r\n *\r\n * @private\r\n */\r\nResource._DefaultImplementations = {};\r\nResource._DefaultImplementations.createImage =\r\n Resource._Implementations.createImage;\r\nResource._DefaultImplementations.loadWithXhr =\r\n Resource._Implementations.loadWithXhr;\r\nResource._DefaultImplementations.loadAndExecuteScript =\r\n Resource._Implementations.loadAndExecuteScript;\r\n\r\n/**\r\n * A resource instance initialized to the current browser location\r\n *\r\n * @type {Resource}\r\n * @constant\r\n */\r\nResource.DEFAULT = Object.freeze(\r\n new Resource({\r\n url:\r\n typeof document === \"undefined\"\r\n ? \"\"\r\n : document.location.href.split(\"?\")[0],\r\n })\r\n);\r\n\r\n/**\r\n * A function that returns the value of the property.\r\n * @callback Resource.RetryCallback\r\n *\r\n * @param {Resource} [resource] The resource that failed to load.\r\n * @param {Error} [error] The error that occurred during the loading of the resource.\r\n * @returns {Boolean|Promise} If true or a promise that resolved to true, the resource will be retried. Otherwise the failure will be returned.\r\n */\r\nexport default Resource;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport getAbsoluteUri from \"./getAbsoluteUri.js\";\r\nimport Resource from \"./Resource.js\";\r\n\r\n/*global CESIUM_BASE_URL*/\r\n\r\nvar cesiumScriptRegex = /((?:.*\\/)|^)Cesium\\.js(?:\\?|\\#|$)/;\r\nfunction getBaseUrlFromCesiumScript() {\r\n var scripts = document.getElementsByTagName(\"script\");\r\n for (var i = 0, len = scripts.length; i < len; ++i) {\r\n var src = scripts[i].getAttribute(\"src\");\r\n var result = cesiumScriptRegex.exec(src);\r\n if (result !== null) {\r\n return result[1];\r\n }\r\n }\r\n return undefined;\r\n}\r\n\r\nvar a;\r\nfunction tryMakeAbsolute(url) {\r\n if (typeof document === \"undefined\") {\r\n //Node.js and Web Workers. In both cases, the URL will already be absolute.\r\n return url;\r\n }\r\n\r\n if (!defined(a)) {\r\n a = document.createElement(\"a\");\r\n }\r\n a.href = url;\r\n\r\n // IE only absolutizes href on get, not set\r\n // eslint-disable-next-line no-self-assign\r\n a.href = a.href;\r\n return a.href;\r\n}\r\n\r\nvar baseResource;\r\nfunction getCesiumBaseUrl() {\r\n if (defined(baseResource)) {\r\n return baseResource;\r\n }\r\n\r\n var baseUrlString;\r\n if (typeof CESIUM_BASE_URL !== \"undefined\") {\r\n baseUrlString = CESIUM_BASE_URL;\r\n } else if (\r\n typeof define === \"object\" &&\r\n defined(define.amd) &&\r\n !define.amd.toUrlUndefined &&\r\n defined(require.toUrl)\r\n ) {\r\n baseUrlString = getAbsoluteUri(\r\n \"..\",\r\n buildModuleUrl(\"Core/buildModuleUrl.js\")\r\n );\r\n } else {\r\n baseUrlString = getBaseUrlFromCesiumScript();\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(baseUrlString)) {\r\n throw new DeveloperError(\r\n \"Unable to determine Cesium base URL automatically, try defining a global variable called CESIUM_BASE_URL.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n baseResource = new Resource({\r\n url: tryMakeAbsolute(baseUrlString),\r\n });\r\n baseResource.appendForwardSlash();\r\n\r\n return baseResource;\r\n}\r\n\r\nfunction buildModuleUrlFromRequireToUrl(moduleID) {\r\n //moduleID will be non-relative, so require it relative to this module, in Core.\r\n return tryMakeAbsolute(require.toUrl(\"../\" + moduleID));\r\n}\r\n\r\nfunction buildModuleUrlFromBaseUrl(moduleID) {\r\n var resource = getCesiumBaseUrl().getDerivedResource({\r\n url: moduleID,\r\n });\r\n return resource.url;\r\n}\r\n\r\nvar implementation;\r\n\r\n/**\r\n * Given a relative URL under the Cesium base URL, returns an absolute URL.\r\n * @function\r\n *\r\n * @param {String} relativeUrl The relative path.\r\n * @returns {String} The absolutely URL representation of the provided path.\r\n *\r\n * @example\r\n * var viewer = new Cesium.Viewer(\"cesiumContainer\", {\r\n * imageryProvider: new Cesium.TileMapServiceImageryProvider({\r\n * url: Cesium.buildModuleUrl(\"Assets/Textures/NaturalEarthII\"),\r\n * }),\r\n * baseLayerPicker: false,\r\n * });\r\n */\r\nfunction buildModuleUrl(relativeUrl) {\r\n if (!defined(implementation)) {\r\n //select implementation\r\n if (\r\n typeof define === \"object\" &&\r\n defined(define.amd) &&\r\n !define.amd.toUrlUndefined &&\r\n defined(require.toUrl)\r\n ) {\r\n implementation = buildModuleUrlFromRequireToUrl;\r\n } else {\r\n implementation = buildModuleUrlFromBaseUrl;\r\n }\r\n }\r\n\r\n var url = implementation(relativeUrl);\r\n return url;\r\n}\r\n\r\n// exposed for testing\r\nbuildModuleUrl._cesiumScriptRegex = cesiumScriptRegex;\r\nbuildModuleUrl._buildModuleUrlFromBaseUrl = buildModuleUrlFromBaseUrl;\r\nbuildModuleUrl._clearBaseResource = function () {\r\n baseResource = undefined;\r\n};\r\n\r\n/**\r\n * Sets the base URL for resolving modules.\r\n * @param {String} value The new base URL.\r\n */\r\nbuildModuleUrl.setBaseUrl = function (value) {\r\n baseResource = Resource.DEFAULT.getDerivedResource({\r\n url: value,\r\n });\r\n};\r\n\r\n/**\r\n * Gets the base URL for resolving modules.\r\n */\r\nbuildModuleUrl.getCesiumBaseUrl = getCesiumBaseUrl;\r\n\r\nexport default buildModuleUrl;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * A 2D Cartesian point.\r\n * @alias Cartesian2\r\n * @constructor\r\n *\r\n * @param {Number} [x=0.0] The X component.\r\n * @param {Number} [y=0.0] The Y component.\r\n *\r\n * @see Cartesian3\r\n * @see Cartesian4\r\n * @see Packable\r\n */\r\nfunction Cartesian2(x, y) {\r\n /**\r\n * The X component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.x = defaultValue(x, 0.0);\r\n\r\n /**\r\n * The Y component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.y = defaultValue(y, 0.0);\r\n}\r\n\r\n/**\r\n * Creates a Cartesian2 instance from x and y coordinates.\r\n *\r\n * @param {Number} x The x coordinate.\r\n * @param {Number} y The y coordinate.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.\r\n */\r\nCartesian2.fromElements = function (x, y, result) {\r\n if (!defined(result)) {\r\n return new Cartesian2(x, y);\r\n }\r\n\r\n result.x = x;\r\n result.y = y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a Cartesian2 instance.\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian to duplicate.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. (Returns undefined if cartesian is undefined)\r\n */\r\nCartesian2.clone = function (cartesian, result) {\r\n if (!defined(cartesian)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new Cartesian2(cartesian.x, cartesian.y);\r\n }\r\n\r\n result.x = cartesian.x;\r\n result.y = cartesian.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Cartesian2 instance from an existing Cartesian3. This simply takes the\r\n * x and y properties of the Cartesian3 and drops z.\r\n * @function\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian3 instance to create a Cartesian2 instance from.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.\r\n */\r\nCartesian2.fromCartesian3 = Cartesian2.clone;\r\n\r\n/**\r\n * Creates a Cartesian2 instance from an existing Cartesian4. This simply takes the\r\n * x and y properties of the Cartesian4 and drops z and w.\r\n * @function\r\n *\r\n * @param {Cartesian4} cartesian The Cartesian4 instance to create a Cartesian2 instance from.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.\r\n */\r\nCartesian2.fromCartesian4 = Cartesian2.clone;\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nCartesian2.packedLength = 2;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Cartesian2} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCartesian2.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.x;\r\n array[startingIndex] = value.y;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Cartesian2} [result] The object into which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.\r\n */\r\nCartesian2.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian2();\r\n }\r\n result.x = array[startingIndex++];\r\n result.y = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Flattens an array of Cartesian2s into and array of components.\r\n *\r\n * @param {Cartesian2[]} array The array of cartesians to pack.\r\n * @param {Number[]} [result] The array onto which to store the result. If this is a typed array, it must have array.length * 2 components, else a {@link DeveloperError} will be thrown. If it is a regular array, it will be resized to have (array.length * 2) elements.\r\n\r\n * @returns {Number[]} The packed array.\r\n */\r\nCartesian2.packArray = function (array, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n var length = array.length;\r\n var resultLength = length * 2;\r\n if (!defined(result)) {\r\n result = new Array(resultLength);\r\n } else if (!Array.isArray(result) && result.length !== resultLength) {\r\n throw new DeveloperError(\r\n \"If result is a typed array, it must have exactly array.length * 2 elements\"\r\n );\r\n } else if (result.length !== resultLength) {\r\n result.length = resultLength;\r\n }\r\n\r\n for (var i = 0; i < length; ++i) {\r\n Cartesian2.pack(array[i], result, i * 2);\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Unpacks an array of cartesian components into and array of Cartesian2s.\r\n *\r\n * @param {Number[]} array The array of components to unpack.\r\n * @param {Cartesian2[]} [result] The array onto which to store the result.\r\n * @returns {Cartesian2[]} The unpacked array.\r\n */\r\nCartesian2.unpackArray = function (array, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n Check.typeOf.number.greaterThanOrEquals(\"array.length\", array.length, 2);\r\n if (array.length % 2 !== 0) {\r\n throw new DeveloperError(\"array length must be a multiple of 2.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = array.length;\r\n if (!defined(result)) {\r\n result = new Array(length / 2);\r\n } else {\r\n result.length = length / 2;\r\n }\r\n\r\n for (var i = 0; i < length; i += 2) {\r\n var index = i / 2;\r\n result[index] = Cartesian2.unpack(array, i, result[index]);\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Cartesian2 from two consecutive elements in an array.\r\n * @function\r\n *\r\n * @param {Number[]} array The array whose two consecutive elements correspond to the x and y components, respectively.\r\n * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to the x component.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.\r\n *\r\n * @example\r\n * // Create a Cartesian2 with (1.0, 2.0)\r\n * var v = [1.0, 2.0];\r\n * var p = Cesium.Cartesian2.fromArray(v);\r\n *\r\n * // Create a Cartesian2 with (1.0, 2.0) using an offset into an array\r\n * var v2 = [0.0, 0.0, 1.0, 2.0];\r\n * var p2 = Cesium.Cartesian2.fromArray(v2, 2);\r\n */\r\nCartesian2.fromArray = Cartesian2.unpack;\r\n\r\n/**\r\n * Computes the value of the maximum component for the supplied Cartesian.\r\n *\r\n * @param {Cartesian2} cartesian The cartesian to use.\r\n * @returns {Number} The value of the maximum component.\r\n */\r\nCartesian2.maximumComponent = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return Math.max(cartesian.x, cartesian.y);\r\n};\r\n\r\n/**\r\n * Computes the value of the minimum component for the supplied Cartesian.\r\n *\r\n * @param {Cartesian2} cartesian The cartesian to use.\r\n * @returns {Number} The value of the minimum component.\r\n */\r\nCartesian2.minimumComponent = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return Math.min(cartesian.x, cartesian.y);\r\n};\r\n\r\n/**\r\n * Compares two Cartesians and computes a Cartesian which contains the minimum components of the supplied Cartesians.\r\n *\r\n * @param {Cartesian2} first A cartesian to compare.\r\n * @param {Cartesian2} second A cartesian to compare.\r\n * @param {Cartesian2} result The object into which to store the result.\r\n * @returns {Cartesian2} A cartesian with the minimum components.\r\n */\r\nCartesian2.minimumByComponent = function (first, second, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"first\", first);\r\n Check.typeOf.object(\"second\", second);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.min(first.x, second.x);\r\n result.y = Math.min(first.y, second.y);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares two Cartesians and computes a Cartesian which contains the maximum components of the supplied Cartesians.\r\n *\r\n * @param {Cartesian2} first A cartesian to compare.\r\n * @param {Cartesian2} second A cartesian to compare.\r\n * @param {Cartesian2} result The object into which to store the result.\r\n * @returns {Cartesian2} A cartesian with the maximum components.\r\n */\r\nCartesian2.maximumByComponent = function (first, second, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"first\", first);\r\n Check.typeOf.object(\"second\", second);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.max(first.x, second.x);\r\n result.y = Math.max(first.y, second.y);\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the provided Cartesian's squared magnitude.\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian instance whose squared magnitude is to be computed.\r\n * @returns {Number} The squared magnitude.\r\n */\r\nCartesian2.magnitudeSquared = function (cartesian) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n return cartesian.x * cartesian.x + cartesian.y * cartesian.y;\r\n};\r\n\r\n/**\r\n * Computes the Cartesian's magnitude (length).\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian instance whose magnitude is to be computed.\r\n * @returns {Number} The magnitude.\r\n */\r\nCartesian2.magnitude = function (cartesian) {\r\n return Math.sqrt(Cartesian2.magnitudeSquared(cartesian));\r\n};\r\n\r\nvar distanceScratch = new Cartesian2();\r\n\r\n/**\r\n * Computes the distance between two points.\r\n *\r\n * @param {Cartesian2} left The first point to compute the distance from.\r\n * @param {Cartesian2} right The second point to compute the distance to.\r\n * @returns {Number} The distance between two points.\r\n *\r\n * @example\r\n * // Returns 1.0\r\n * var d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(2.0, 0.0));\r\n */\r\nCartesian2.distance = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian2.subtract(left, right, distanceScratch);\r\n return Cartesian2.magnitude(distanceScratch);\r\n};\r\n\r\n/**\r\n * Computes the squared distance between two points. Comparing squared distances\r\n * using this function is more efficient than comparing distances using {@link Cartesian2#distance}.\r\n *\r\n * @param {Cartesian2} left The first point to compute the distance from.\r\n * @param {Cartesian2} right The second point to compute the distance to.\r\n * @returns {Number} The distance between two points.\r\n *\r\n * @example\r\n * // Returns 4.0, not 2.0\r\n * var d = Cesium.Cartesian2.distance(new Cesium.Cartesian2(1.0, 0.0), new Cesium.Cartesian2(3.0, 0.0));\r\n */\r\nCartesian2.distanceSquared = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian2.subtract(left, right, distanceScratch);\r\n return Cartesian2.magnitudeSquared(distanceScratch);\r\n};\r\n\r\n/**\r\n * Computes the normalized form of the supplied Cartesian.\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian to be normalized.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.normalize = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var magnitude = Cartesian2.magnitude(cartesian);\r\n\r\n result.x = cartesian.x / magnitude;\r\n result.y = cartesian.y / magnitude;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (isNaN(result.x) || isNaN(result.y)) {\r\n throw new DeveloperError(\"normalized result is not a number\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the dot (scalar) product of two Cartesians.\r\n *\r\n * @param {Cartesian2} left The first Cartesian.\r\n * @param {Cartesian2} right The second Cartesian.\r\n * @returns {Number} The dot product.\r\n */\r\nCartesian2.dot = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n return left.x * right.x + left.y * right.y;\r\n};\r\n\r\n/**\r\n * Computes the magnitude of the cross product that would result from implicitly setting the Z coordinate of the input vectors to 0\r\n *\r\n * @param {Cartesian2} left The first Cartesian.\r\n * @param {Cartesian2} right The second Cartesian.\r\n * @returns {Number} The cross product.\r\n */\r\nCartesian2.cross = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n return left.x * right.y - left.y * right.x;\r\n};\r\n\r\n/**\r\n * Computes the componentwise product of two Cartesians.\r\n *\r\n * @param {Cartesian2} left The first Cartesian.\r\n * @param {Cartesian2} right The second Cartesian.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.multiplyComponents = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x * right.x;\r\n result.y = left.y * right.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise quotient of two Cartesians.\r\n *\r\n * @param {Cartesian2} left The first Cartesian.\r\n * @param {Cartesian2} right The second Cartesian.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.divideComponents = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x / right.x;\r\n result.y = left.y / right.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise sum of two Cartesians.\r\n *\r\n * @param {Cartesian2} left The first Cartesian.\r\n * @param {Cartesian2} right The second Cartesian.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.add = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x + right.x;\r\n result.y = left.y + right.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise difference of two Cartesians.\r\n *\r\n * @param {Cartesian2} left The first Cartesian.\r\n * @param {Cartesian2} right The second Cartesian.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.subtract = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x - right.x;\r\n result.y = left.y - right.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Multiplies the provided Cartesian componentwise by the provided scalar.\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian to be scaled.\r\n * @param {Number} scalar The scalar to multiply with.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.multiplyByScalar = function (cartesian, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = cartesian.x * scalar;\r\n result.y = cartesian.y * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Divides the provided Cartesian componentwise by the provided scalar.\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian to be divided.\r\n * @param {Number} scalar The scalar to divide by.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.divideByScalar = function (cartesian, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = cartesian.x / scalar;\r\n result.y = cartesian.y / scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Negates the provided Cartesian.\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian to be negated.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.negate = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = -cartesian.x;\r\n result.y = -cartesian.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the absolute value of the provided Cartesian.\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian whose absolute value is to be computed.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.abs = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Math.abs(cartesian.x);\r\n result.y = Math.abs(cartesian.y);\r\n return result;\r\n};\r\n\r\nvar lerpScratch = new Cartesian2();\r\n/**\r\n * Computes the linear interpolation or extrapolation at t using the provided cartesians.\r\n *\r\n * @param {Cartesian2} start The value corresponding to t at 0.0.\r\n * @param {Cartesian2} end The value corresponding to t at 1.0.\r\n * @param {Number} t The point along t at which to interpolate.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nCartesian2.lerp = function (start, end, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"start\", start);\r\n Check.typeOf.object(\"end\", end);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian2.multiplyByScalar(end, t, lerpScratch);\r\n result = Cartesian2.multiplyByScalar(start, 1.0 - t, result);\r\n return Cartesian2.add(lerpScratch, result, result);\r\n};\r\n\r\nvar angleBetweenScratch = new Cartesian2();\r\nvar angleBetweenScratch2 = new Cartesian2();\r\n/**\r\n * Returns the angle, in radians, between the provided Cartesians.\r\n *\r\n * @param {Cartesian2} left The first Cartesian.\r\n * @param {Cartesian2} right The second Cartesian.\r\n * @returns {Number} The angle between the Cartesians.\r\n */\r\nCartesian2.angleBetween = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n Cartesian2.normalize(left, angleBetweenScratch);\r\n Cartesian2.normalize(right, angleBetweenScratch2);\r\n return CesiumMath.acosClamped(\r\n Cartesian2.dot(angleBetweenScratch, angleBetweenScratch2)\r\n );\r\n};\r\n\r\nvar mostOrthogonalAxisScratch = new Cartesian2();\r\n/**\r\n * Returns the axis that is most orthogonal to the provided Cartesian.\r\n *\r\n * @param {Cartesian2} cartesian The Cartesian on which to find the most orthogonal axis.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The most orthogonal axis.\r\n */\r\nCartesian2.mostOrthogonalAxis = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var f = Cartesian2.normalize(cartesian, mostOrthogonalAxisScratch);\r\n Cartesian2.abs(f, f);\r\n\r\n if (f.x <= f.y) {\r\n result = Cartesian2.clone(Cartesian2.UNIT_X, result);\r\n } else {\r\n result = Cartesian2.clone(Cartesian2.UNIT_Y, result);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided Cartesians componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Cartesian2} [left] The first Cartesian.\r\n * @param {Cartesian2} [right] The second Cartesian.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCartesian2.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.x === right.x &&\r\n left.y === right.y)\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCartesian2.equalsArray = function (cartesian, array, offset) {\r\n return cartesian.x === array[offset] && cartesian.y === array[offset + 1];\r\n};\r\n\r\n/**\r\n * Compares the provided Cartesians componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {Cartesian2} [left] The first Cartesian.\r\n * @param {Cartesian2} [right] The second Cartesian.\r\n * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nCartesian2.equalsEpsilon = function (\r\n left,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n CesiumMath.equalsEpsilon(\r\n left.x,\r\n right.x,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n left.y,\r\n right.y,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ))\r\n );\r\n};\r\n\r\n/**\r\n * An immutable Cartesian2 instance initialized to (0.0, 0.0).\r\n *\r\n * @type {Cartesian2}\r\n * @constant\r\n */\r\nCartesian2.ZERO = Object.freeze(new Cartesian2(0.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian2 instance initialized to (1.0, 0.0).\r\n *\r\n * @type {Cartesian2}\r\n * @constant\r\n */\r\nCartesian2.UNIT_X = Object.freeze(new Cartesian2(1.0, 0.0));\r\n\r\n/**\r\n * An immutable Cartesian2 instance initialized to (0.0, 1.0).\r\n *\r\n * @type {Cartesian2}\r\n * @constant\r\n */\r\nCartesian2.UNIT_Y = Object.freeze(new Cartesian2(0.0, 1.0));\r\n\r\n/**\r\n * Duplicates this Cartesian2 instance.\r\n *\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided.\r\n */\r\nCartesian2.prototype.clone = function (result) {\r\n return Cartesian2.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this Cartesian against the provided Cartesian componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Cartesian2} [right] The right hand side Cartesian.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nCartesian2.prototype.equals = function (right) {\r\n return Cartesian2.equals(this, right);\r\n};\r\n\r\n/**\r\n * Compares this Cartesian against the provided Cartesian componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {Cartesian2} [right] The right hand side Cartesian.\r\n * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if they are within the provided epsilon, false otherwise.\r\n */\r\nCartesian2.prototype.equalsEpsilon = function (\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return Cartesian2.equalsEpsilon(\r\n this,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n );\r\n};\r\n\r\n/**\r\n * Creates a string representing this Cartesian in the format '(x, y)'.\r\n *\r\n * @returns {String} A string representing the provided Cartesian in the format '(x, y)'.\r\n */\r\nCartesian2.prototype.toString = function () {\r\n return \"(\" + this.x + \", \" + this.y + \")\";\r\n};\r\nexport default Cartesian2;\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport GeographicProjection from \"./GeographicProjection.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\n\r\n/**\r\n * A tiling scheme for geometry referenced to a simple {@link GeographicProjection} where\r\n * longitude and latitude are directly mapped to X and Y. This projection is commonly\r\n * known as geographic, equirectangular, equidistant cylindrical, or plate carrée.\r\n *\r\n * @alias GeographicTilingScheme\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid whose surface is being tiled. Defaults to\r\n * the WGS84 ellipsoid.\r\n * @param {Rectangle} [options.rectangle=Rectangle.MAX_VALUE] The rectangle, in radians, covered by the tiling scheme.\r\n * @param {Number} [options.numberOfLevelZeroTilesX=2] The number of tiles in the X direction at level zero of\r\n * the tile tree.\r\n * @param {Number} [options.numberOfLevelZeroTilesY=1] The number of tiles in the Y direction at level zero of\r\n * the tile tree.\r\n */\r\nfunction GeographicTilingScheme(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n this._rectangle = defaultValue(options.rectangle, Rectangle.MAX_VALUE);\r\n this._projection = new GeographicProjection(this._ellipsoid);\r\n this._numberOfLevelZeroTilesX = defaultValue(\r\n options.numberOfLevelZeroTilesX,\r\n 2\r\n );\r\n this._numberOfLevelZeroTilesY = defaultValue(\r\n options.numberOfLevelZeroTilesY,\r\n 1\r\n );\r\n}\r\n\r\nObject.defineProperties(GeographicTilingScheme.prototype, {\r\n /**\r\n * Gets the ellipsoid that is tiled by this tiling scheme.\r\n * @memberof GeographicTilingScheme.prototype\r\n * @type {Ellipsoid}\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the rectangle, in radians, covered by this tiling scheme.\r\n * @memberof GeographicTilingScheme.prototype\r\n * @type {Rectangle}\r\n */\r\n rectangle: {\r\n get: function () {\r\n return this._rectangle;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the map projection used by this tiling scheme.\r\n * @memberof GeographicTilingScheme.prototype\r\n * @type {MapProjection}\r\n */\r\n projection: {\r\n get: function () {\r\n return this._projection;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the total number of tiles in the X direction at a specified level-of-detail.\r\n *\r\n * @param {Number} level The level-of-detail.\r\n * @returns {Number} The number of tiles in the X direction at the given level.\r\n */\r\nGeographicTilingScheme.prototype.getNumberOfXTilesAtLevel = function (level) {\r\n return this._numberOfLevelZeroTilesX << level;\r\n};\r\n\r\n/**\r\n * Gets the total number of tiles in the Y direction at a specified level-of-detail.\r\n *\r\n * @param {Number} level The level-of-detail.\r\n * @returns {Number} The number of tiles in the Y direction at the given level.\r\n */\r\nGeographicTilingScheme.prototype.getNumberOfYTilesAtLevel = function (level) {\r\n return this._numberOfLevelZeroTilesY << level;\r\n};\r\n\r\n/**\r\n * Transforms a rectangle specified in geodetic radians to the native coordinate system\r\n * of this tiling scheme.\r\n *\r\n * @param {Rectangle} rectangle The rectangle to transform.\r\n * @param {Rectangle} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the native rectangle if 'result'\r\n * is undefined.\r\n */\r\nGeographicTilingScheme.prototype.rectangleToNativeRectangle = function (\r\n rectangle,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n var west = CesiumMath.toDegrees(rectangle.west);\r\n var south = CesiumMath.toDegrees(rectangle.south);\r\n var east = CesiumMath.toDegrees(rectangle.east);\r\n var north = CesiumMath.toDegrees(rectangle.north);\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(west, south, east, north);\r\n }\r\n\r\n result.west = west;\r\n result.south = south;\r\n result.east = east;\r\n result.north = north;\r\n return result;\r\n};\r\n\r\n/**\r\n * Converts tile x, y coordinates and level to a rectangle expressed in the native coordinates\r\n * of the tiling scheme.\r\n *\r\n * @param {Number} x The integer x coordinate of the tile.\r\n * @param {Number} y The integer y coordinate of the tile.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Object} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the rectangle\r\n * if 'result' is undefined.\r\n */\r\nGeographicTilingScheme.prototype.tileXYToNativeRectangle = function (\r\n x,\r\n y,\r\n level,\r\n result\r\n) {\r\n var rectangleRadians = this.tileXYToRectangle(x, y, level, result);\r\n rectangleRadians.west = CesiumMath.toDegrees(rectangleRadians.west);\r\n rectangleRadians.south = CesiumMath.toDegrees(rectangleRadians.south);\r\n rectangleRadians.east = CesiumMath.toDegrees(rectangleRadians.east);\r\n rectangleRadians.north = CesiumMath.toDegrees(rectangleRadians.north);\r\n return rectangleRadians;\r\n};\r\n\r\n/**\r\n * Converts tile x, y coordinates and level to a cartographic rectangle in radians.\r\n *\r\n * @param {Number} x The integer x coordinate of the tile.\r\n * @param {Number} y The integer y coordinate of the tile.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Object} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the rectangle\r\n * if 'result' is undefined.\r\n */\r\nGeographicTilingScheme.prototype.tileXYToRectangle = function (\r\n x,\r\n y,\r\n level,\r\n result\r\n) {\r\n var rectangle = this._rectangle;\r\n\r\n var xTiles = this.getNumberOfXTilesAtLevel(level);\r\n var yTiles = this.getNumberOfYTilesAtLevel(level);\r\n\r\n var xTileWidth = rectangle.width / xTiles;\r\n var west = x * xTileWidth + rectangle.west;\r\n var east = (x + 1) * xTileWidth + rectangle.west;\r\n\r\n var yTileHeight = rectangle.height / yTiles;\r\n var north = rectangle.north - y * yTileHeight;\r\n var south = rectangle.north - (y + 1) * yTileHeight;\r\n\r\n if (!defined(result)) {\r\n result = new Rectangle(west, south, east, north);\r\n }\r\n\r\n result.west = west;\r\n result.south = south;\r\n result.east = east;\r\n result.north = north;\r\n return result;\r\n};\r\n\r\n/**\r\n * Calculates the tile x, y coordinates of the tile containing\r\n * a given cartographic position.\r\n *\r\n * @param {Cartographic} position The position.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Cartesian2} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Cartesian2} The specified 'result', or a new object containing the tile x, y coordinates\r\n * if 'result' is undefined.\r\n */\r\nGeographicTilingScheme.prototype.positionToTileXY = function (\r\n position,\r\n level,\r\n result\r\n) {\r\n var rectangle = this._rectangle;\r\n if (!Rectangle.contains(rectangle, position)) {\r\n // outside the bounds of the tiling scheme\r\n return undefined;\r\n }\r\n\r\n var xTiles = this.getNumberOfXTilesAtLevel(level);\r\n var yTiles = this.getNumberOfYTilesAtLevel(level);\r\n\r\n var xTileWidth = rectangle.width / xTiles;\r\n var yTileHeight = rectangle.height / yTiles;\r\n\r\n var longitude = position.longitude;\r\n if (rectangle.east < rectangle.west) {\r\n longitude += CesiumMath.TWO_PI;\r\n }\r\n\r\n var xTileCoordinate = ((longitude - rectangle.west) / xTileWidth) | 0;\r\n if (xTileCoordinate >= xTiles) {\r\n xTileCoordinate = xTiles - 1;\r\n }\r\n\r\n var yTileCoordinate =\r\n ((rectangle.north - position.latitude) / yTileHeight) | 0;\r\n if (yTileCoordinate >= yTiles) {\r\n yTileCoordinate = yTiles - 1;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Cartesian2(xTileCoordinate, yTileCoordinate);\r\n }\r\n\r\n result.x = xTileCoordinate;\r\n result.y = yTileCoordinate;\r\n return result;\r\n};\r\nexport default GeographicTilingScheme;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport buildModuleUrl from \"./buildModuleUrl.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport GeographicTilingScheme from \"./GeographicTilingScheme.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Resource from \"./Resource.js\";\r\n\r\nvar scratchDiagonalCartesianNE = new Cartesian3();\r\nvar scratchDiagonalCartesianSW = new Cartesian3();\r\nvar scratchDiagonalCartographic = new Cartographic();\r\nvar scratchCenterCartesian = new Cartesian3();\r\nvar scratchSurfaceCartesian = new Cartesian3();\r\n\r\nvar scratchBoundingSphere = new BoundingSphere();\r\nvar tilingScheme = new GeographicTilingScheme();\r\nvar scratchCorners = [\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n];\r\nvar scratchTileXY = new Cartesian2();\r\n\r\n/**\r\n * A collection of functions for approximating terrain height\r\n * @private\r\n */\r\nvar ApproximateTerrainHeights = {};\r\n\r\n/**\r\n * Initializes the minimum and maximum terrain heights\r\n * @return {Promise}\r\n */\r\nApproximateTerrainHeights.initialize = function () {\r\n var initPromise = ApproximateTerrainHeights._initPromise;\r\n if (defined(initPromise)) {\r\n return initPromise;\r\n }\r\n\r\n initPromise = Resource.fetchJson(\r\n buildModuleUrl(\"Assets/approximateTerrainHeights.json\")\r\n ).then(function (json) {\r\n ApproximateTerrainHeights._terrainHeights = json;\r\n });\r\n ApproximateTerrainHeights._initPromise = initPromise;\r\n\r\n return initPromise;\r\n};\r\n\r\n/**\r\n * Computes the minimum and maximum terrain heights for a given rectangle\r\n * @param {Rectangle} rectangle The bounding rectangle\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid\r\n * @return {{minimumTerrainHeight: Number, maximumTerrainHeight: Number}}\r\n */\r\nApproximateTerrainHeights.getMinimumMaximumHeights = function (\r\n rectangle,\r\n ellipsoid\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"rectangle\", rectangle);\r\n if (!defined(ApproximateTerrainHeights._terrainHeights)) {\r\n throw new DeveloperError(\r\n \"You must call ApproximateTerrainHeights.initialize and wait for the promise to resolve before using this function\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n\r\n var xyLevel = getTileXYLevel(rectangle);\r\n\r\n // Get the terrain min/max for that tile\r\n var minTerrainHeight = ApproximateTerrainHeights._defaultMinTerrainHeight;\r\n var maxTerrainHeight = ApproximateTerrainHeights._defaultMaxTerrainHeight;\r\n if (defined(xyLevel)) {\r\n var key = xyLevel.level + \"-\" + xyLevel.x + \"-\" + xyLevel.y;\r\n var heights = ApproximateTerrainHeights._terrainHeights[key];\r\n if (defined(heights)) {\r\n minTerrainHeight = heights[0];\r\n maxTerrainHeight = heights[1];\r\n }\r\n\r\n // Compute min by taking the center of the NE->SW diagonal and finding distance to the surface\r\n ellipsoid.cartographicToCartesian(\r\n Rectangle.northeast(rectangle, scratchDiagonalCartographic),\r\n scratchDiagonalCartesianNE\r\n );\r\n ellipsoid.cartographicToCartesian(\r\n Rectangle.southwest(rectangle, scratchDiagonalCartographic),\r\n scratchDiagonalCartesianSW\r\n );\r\n\r\n Cartesian3.midpoint(\r\n scratchDiagonalCartesianSW,\r\n scratchDiagonalCartesianNE,\r\n scratchCenterCartesian\r\n );\r\n var surfacePosition = ellipsoid.scaleToGeodeticSurface(\r\n scratchCenterCartesian,\r\n scratchSurfaceCartesian\r\n );\r\n if (defined(surfacePosition)) {\r\n var distance = Cartesian3.distance(\r\n scratchCenterCartesian,\r\n surfacePosition\r\n );\r\n minTerrainHeight = Math.min(minTerrainHeight, -distance);\r\n } else {\r\n minTerrainHeight = ApproximateTerrainHeights._defaultMinTerrainHeight;\r\n }\r\n }\r\n\r\n minTerrainHeight = Math.max(\r\n ApproximateTerrainHeights._defaultMinTerrainHeight,\r\n minTerrainHeight\r\n );\r\n\r\n return {\r\n minimumTerrainHeight: minTerrainHeight,\r\n maximumTerrainHeight: maxTerrainHeight,\r\n };\r\n};\r\n\r\n/**\r\n * Computes the bounding sphere based on the tile heights in the rectangle\r\n * @param {Rectangle} rectangle The bounding rectangle\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid\r\n * @return {BoundingSphere} The result bounding sphere\r\n */\r\nApproximateTerrainHeights.getBoundingSphere = function (rectangle, ellipsoid) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"rectangle\", rectangle);\r\n if (!defined(ApproximateTerrainHeights._terrainHeights)) {\r\n throw new DeveloperError(\r\n \"You must call ApproximateTerrainHeights.initialize and wait for the promise to resolve before using this function\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n\r\n var xyLevel = getTileXYLevel(rectangle);\r\n\r\n // Get the terrain max for that tile\r\n var maxTerrainHeight = ApproximateTerrainHeights._defaultMaxTerrainHeight;\r\n if (defined(xyLevel)) {\r\n var key = xyLevel.level + \"-\" + xyLevel.x + \"-\" + xyLevel.y;\r\n var heights = ApproximateTerrainHeights._terrainHeights[key];\r\n if (defined(heights)) {\r\n maxTerrainHeight = heights[1];\r\n }\r\n }\r\n\r\n var result = BoundingSphere.fromRectangle3D(rectangle, ellipsoid, 0.0);\r\n BoundingSphere.fromRectangle3D(\r\n rectangle,\r\n ellipsoid,\r\n maxTerrainHeight,\r\n scratchBoundingSphere\r\n );\r\n\r\n return BoundingSphere.union(result, scratchBoundingSphere, result);\r\n};\r\n\r\nfunction getTileXYLevel(rectangle) {\r\n Cartographic.fromRadians(\r\n rectangle.east,\r\n rectangle.north,\r\n 0.0,\r\n scratchCorners[0]\r\n );\r\n Cartographic.fromRadians(\r\n rectangle.west,\r\n rectangle.north,\r\n 0.0,\r\n scratchCorners[1]\r\n );\r\n Cartographic.fromRadians(\r\n rectangle.east,\r\n rectangle.south,\r\n 0.0,\r\n scratchCorners[2]\r\n );\r\n Cartographic.fromRadians(\r\n rectangle.west,\r\n rectangle.south,\r\n 0.0,\r\n scratchCorners[3]\r\n );\r\n\r\n // Determine which tile the bounding rectangle is in\r\n var lastLevelX = 0,\r\n lastLevelY = 0;\r\n var currentX = 0,\r\n currentY = 0;\r\n var maxLevel = ApproximateTerrainHeights._terrainHeightsMaxLevel;\r\n var i;\r\n for (i = 0; i <= maxLevel; ++i) {\r\n var failed = false;\r\n for (var j = 0; j < 4; ++j) {\r\n var corner = scratchCorners[j];\r\n tilingScheme.positionToTileXY(corner, i, scratchTileXY);\r\n if (j === 0) {\r\n currentX = scratchTileXY.x;\r\n currentY = scratchTileXY.y;\r\n } else if (currentX !== scratchTileXY.x || currentY !== scratchTileXY.y) {\r\n failed = true;\r\n break;\r\n }\r\n }\r\n\r\n if (failed) {\r\n break;\r\n }\r\n\r\n lastLevelX = currentX;\r\n lastLevelY = currentY;\r\n }\r\n\r\n if (i === 0) {\r\n return undefined;\r\n }\r\n\r\n return {\r\n x: lastLevelX,\r\n y: lastLevelY,\r\n level: i > maxLevel ? maxLevel : i - 1,\r\n };\r\n}\r\n\r\nApproximateTerrainHeights._terrainHeightsMaxLevel = 6;\r\nApproximateTerrainHeights._defaultMaxTerrainHeight = 9000.0;\r\nApproximateTerrainHeights._defaultMinTerrainHeight = -100000.0;\r\nApproximateTerrainHeights._terrainHeights = undefined;\r\nApproximateTerrainHeights._initPromise = undefined;\r\n\r\nObject.defineProperties(ApproximateTerrainHeights, {\r\n /**\r\n * Determines if the terrain heights are initialized and ready to use. To initialize the terrain heights,\r\n * call {@link ApproximateTerrainHeights#initialize} and wait for the returned promise to resolve.\r\n * @type {Boolean}\r\n * @readonly\r\n * @memberof ApproximateTerrainHeights\r\n */\r\n initialized: {\r\n get: function () {\r\n return defined(ApproximateTerrainHeights._terrainHeights);\r\n },\r\n },\r\n});\r\nexport default ApproximateTerrainHeights;\r\n","/*! @license DOMPurify | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.0.8/LICENSE */\r\n\r\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\r\n\r\nvar hasOwnProperty = Object.hasOwnProperty,\r\n setPrototypeOf = Object.setPrototypeOf,\r\n isFrozen = Object.isFrozen;\r\nvar freeze = Object.freeze,\r\n seal = Object.seal,\r\n create = Object.create; // eslint-disable-line import/no-mutable-exports\r\n\r\nvar _ref = typeof Reflect !== 'undefined' && Reflect,\r\n apply = _ref.apply,\r\n construct = _ref.construct;\r\n\r\nif (!apply) {\r\n apply = function apply(fun, thisValue, args) {\r\n return fun.apply(thisValue, args);\r\n };\r\n}\r\n\r\nif (!freeze) {\r\n freeze = function freeze(x) {\r\n return x;\r\n };\r\n}\r\n\r\nif (!seal) {\r\n seal = function seal(x) {\r\n return x;\r\n };\r\n}\r\n\r\nif (!construct) {\r\n construct = function construct(Func, args) {\r\n return new (Function.prototype.bind.apply(Func, [null].concat(_toConsumableArray(args))))();\r\n };\r\n}\r\n\r\nvar arrayForEach = unapply(Array.prototype.forEach);\r\nvar arrayPop = unapply(Array.prototype.pop);\r\nvar arrayPush = unapply(Array.prototype.push);\r\n\r\nvar stringToLowerCase = unapply(String.prototype.toLowerCase);\r\nvar stringMatch = unapply(String.prototype.match);\r\nvar stringReplace = unapply(String.prototype.replace);\r\nvar stringIndexOf = unapply(String.prototype.indexOf);\r\nvar stringTrim = unapply(String.prototype.trim);\r\n\r\nvar regExpTest = unapply(RegExp.prototype.test);\r\n\r\nvar typeErrorCreate = unconstruct(TypeError);\r\n\r\nfunction unapply(func) {\r\n return function (thisArg) {\r\n for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\r\n args[_key - 1] = arguments[_key];\r\n }\r\n\r\n return apply(func, thisArg, args);\r\n };\r\n}\r\n\r\nfunction unconstruct(func) {\r\n return function () {\r\n for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\r\n args[_key2] = arguments[_key2];\r\n }\r\n\r\n return construct(func, args);\r\n };\r\n}\r\n\r\n/* Add properties to a lookup table */\r\nfunction addToSet(set, array) {\r\n if (setPrototypeOf) {\r\n // Make 'in' and truthy checks like Boolean(set.constructor)\r\n // independent of any properties defined on Object.prototype.\r\n // Prevent prototype setters from intercepting set as a this value.\r\n setPrototypeOf(set, null);\r\n }\r\n\r\n var l = array.length;\r\n while (l--) {\r\n var element = array[l];\r\n if (typeof element === 'string') {\r\n var lcElement = stringToLowerCase(element);\r\n if (lcElement !== element) {\r\n // Config presets (e.g. tags.js, attrs.js) are immutable.\r\n if (!isFrozen(array)) {\r\n array[l] = lcElement;\r\n }\r\n\r\n element = lcElement;\r\n }\r\n }\r\n\r\n set[element] = true;\r\n }\r\n\r\n return set;\r\n}\r\n\r\n/* Shallow clone an object */\r\nfunction clone(object) {\r\n var newObject = create(null);\r\n\r\n var property = void 0;\r\n for (property in object) {\r\n if (apply(hasOwnProperty, object, [property])) {\r\n newObject[property] = object[property];\r\n }\r\n }\r\n\r\n return newObject;\r\n}\r\n\r\nvar html = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\r\n\r\n// SVG\r\nvar svg = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'video', 'view', 'vkern']);\r\n\r\nvar svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\r\n\r\nvar mathMl = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover']);\r\n\r\nvar text = freeze(['#text']);\r\n\r\nvar html$1 = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'playsinline', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns']);\r\n\r\nvar svg$1 = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\r\n\r\nvar mathMl$1 = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\r\n\r\nvar xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\r\n\r\n// eslint-disable-next-line unicorn/better-regex\r\nvar MUSTACHE_EXPR = seal(/\\{\\{[\\s\\S]*|[\\s\\S]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\r\nvar ERB_EXPR = seal(/<%[\\s\\S]*|[\\s\\S]*%>/gm);\r\nvar DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]/); // eslint-disable-line no-useless-escape\r\nvar ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\r\nvar IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\r\n);\r\nvar IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\r\nvar ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\r\n);\r\n\r\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\r\n\r\nfunction _toConsumableArray$1(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\r\n\r\nvar getGlobal = function getGlobal() {\r\n return typeof window === 'undefined' ? null : window;\r\n};\r\n\r\n/**\r\n * Creates a no-op policy for internal use only.\r\n * Don't export this function outside this module!\r\n * @param {?TrustedTypePolicyFactory} trustedTypes The policy factory.\r\n * @param {Document} document The document object (to determine policy name suffix)\r\n * @return {?TrustedTypePolicy} The policy created (or null, if Trusted Types\r\n * are not supported).\r\n */\r\nvar _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, document) {\r\n if ((typeof trustedTypes === 'undefined' ? 'undefined' : _typeof(trustedTypes)) !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\r\n return null;\r\n }\r\n\r\n // Allow the callers to control the unique policy name\r\n // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\r\n // Policy creation with duplicate names throws in Trusted Types.\r\n var suffix = null;\r\n var ATTR_NAME = 'data-tt-policy-suffix';\r\n if (document.currentScript && document.currentScript.hasAttribute(ATTR_NAME)) {\r\n suffix = document.currentScript.getAttribute(ATTR_NAME);\r\n }\r\n\r\n var policyName = 'dompurify' + (suffix ? '#' + suffix : '');\r\n\r\n try {\r\n return trustedTypes.createPolicy(policyName, {\r\n createHTML: function createHTML(html$$1) {\r\n return html$$1;\r\n }\r\n });\r\n } catch (_) {\r\n // Policy creation failed (most likely another DOMPurify script has\r\n // already run). Skip creating the policy, as this will only cause errors\r\n // if TT are enforced.\r\n console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\r\n return null;\r\n }\r\n};\r\n\r\nfunction createDOMPurify() {\r\n var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\r\n\r\n var DOMPurify = function DOMPurify(root) {\r\n return createDOMPurify(root);\r\n };\r\n\r\n /**\r\n * Version label, exposed for easier checks\r\n * if DOMPurify is up to date or not\r\n */\r\n DOMPurify.version = '2.2.2';\r\n\r\n /**\r\n * Array of elements that DOMPurify removed during sanitation.\r\n * Empty if nothing was removed.\r\n */\r\n DOMPurify.removed = [];\r\n\r\n if (!window || !window.document || window.document.nodeType !== 9) {\r\n // Not running in a browser, provide a factory function\r\n // so that you can pass your own Window\r\n DOMPurify.isSupported = false;\r\n\r\n return DOMPurify;\r\n }\r\n\r\n var originalDocument = window.document;\r\n\r\n var document = window.document;\r\n var DocumentFragment = window.DocumentFragment,\r\n HTMLTemplateElement = window.HTMLTemplateElement,\r\n Node = window.Node,\r\n NodeFilter = window.NodeFilter,\r\n _window$NamedNodeMap = window.NamedNodeMap,\r\n NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,\r\n Text = window.Text,\r\n Comment = window.Comment,\r\n DOMParser = window.DOMParser,\r\n trustedTypes = window.trustedTypes;\r\n\r\n // As per issue #47, the web-components registry is inherited by a\r\n // new document created via createHTMLDocument. As per the spec\r\n // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\r\n // a new empty registry is used when creating a template contents owner\r\n // document, so we use that as our parent document to ensure nothing\r\n // is inherited.\r\n\r\n if (typeof HTMLTemplateElement === 'function') {\r\n var template = document.createElement('template');\r\n if (template.content && template.content.ownerDocument) {\r\n document = template.content.ownerDocument;\r\n }\r\n }\r\n\r\n var trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, originalDocument);\r\n var emptyHTML = trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML('') : '';\r\n\r\n var _document = document,\r\n implementation = _document.implementation,\r\n createNodeIterator = _document.createNodeIterator,\r\n getElementsByTagName = _document.getElementsByTagName,\r\n createDocumentFragment = _document.createDocumentFragment;\r\n var importNode = originalDocument.importNode;\r\n\r\n\r\n var documentMode = {};\r\n try {\r\n documentMode = clone(document).documentMode ? document.documentMode : {};\r\n } catch (_) {}\r\n\r\n var hooks = {};\r\n\r\n /**\r\n * Expose whether this browser supports running the full DOMPurify.\r\n */\r\n DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && documentMode !== 9;\r\n\r\n var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,\r\n ERB_EXPR$$1 = ERB_EXPR,\r\n DATA_ATTR$$1 = DATA_ATTR,\r\n ARIA_ATTR$$1 = ARIA_ATTR,\r\n IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,\r\n ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;\r\n var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;\r\n\r\n /**\r\n * We consider the elements and attributes below to be safe. Ideally\r\n * don't add any new ones but feel free to remove unwanted ones.\r\n */\r\n\r\n /* allowed element names */\r\n\r\n var ALLOWED_TAGS = null;\r\n var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1(html), _toConsumableArray$1(svg), _toConsumableArray$1(svgFilters), _toConsumableArray$1(mathMl), _toConsumableArray$1(text)));\r\n\r\n /* Allowed attribute names */\r\n var ALLOWED_ATTR = null;\r\n var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray$1(html$1), _toConsumableArray$1(svg$1), _toConsumableArray$1(mathMl$1), _toConsumableArray$1(xml)));\r\n\r\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\r\n var FORBID_TAGS = null;\r\n\r\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\r\n var FORBID_ATTR = null;\r\n\r\n /* Decide if ARIA attributes are okay */\r\n var ALLOW_ARIA_ATTR = true;\r\n\r\n /* Decide if custom data attributes are okay */\r\n var ALLOW_DATA_ATTR = true;\r\n\r\n /* Decide if unknown protocols are okay */\r\n var ALLOW_UNKNOWN_PROTOCOLS = false;\r\n\r\n /* Output should be safe for common template engines.\r\n * This means, DOMPurify removes data attributes, mustaches and ERB\r\n */\r\n var SAFE_FOR_TEMPLATES = false;\r\n\r\n /* Decide if document with ... should be returned */\r\n var WHOLE_DOCUMENT = false;\r\n\r\n /* Track whether config is already set on this instance of DOMPurify. */\r\n var SET_CONFIG = false;\r\n\r\n /* Decide if all elements (e.g. style, script) must be children of\r\n * document.body. By default, browsers might move them to document.head */\r\n var FORCE_BODY = false;\r\n\r\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\r\n * string (or a TrustedHTML object if Trusted Types are supported).\r\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\r\n */\r\n var RETURN_DOM = false;\r\n\r\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\r\n * string (or a TrustedHTML object if Trusted Types are supported) */\r\n var RETURN_DOM_FRAGMENT = false;\r\n\r\n /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM\r\n * `Node` is imported into the current `Document`. If this flag is not enabled the\r\n * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by\r\n * DOMPurify.\r\n *\r\n * This defaults to `true` starting DOMPurify 2.2.0. Note that setting it to `false`\r\n * might cause XSS from attacks hidden in closed shadowroots in case the browser\r\n * supports Declarative Shadow: DOM https://web.dev/declarative-shadow-dom/\r\n */\r\n var RETURN_DOM_IMPORT = true;\r\n\r\n /* Try to return a Trusted Type object instead of a string, return a string in\r\n * case Trusted Types are not supported */\r\n var RETURN_TRUSTED_TYPE = false;\r\n\r\n /* Output should be free from DOM clobbering attacks? */\r\n var SANITIZE_DOM = true;\r\n\r\n /* Keep element content when removing element? */\r\n var KEEP_CONTENT = true;\r\n\r\n /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\r\n * of importing it into a new Document and returning a sanitized copy */\r\n var IN_PLACE = false;\r\n\r\n /* Allow usage of profiles like html, svg and mathMl */\r\n var USE_PROFILES = {};\r\n\r\n /* Tags to ignore content of when KEEP_CONTENT is true */\r\n var FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\r\n\r\n /* Tags that are safe for data: URIs */\r\n var DATA_URI_TAGS = null;\r\n var DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\r\n\r\n /* Attributes safe for values like \"javascript:\" */\r\n var URI_SAFE_ATTRIBUTES = null;\r\n var DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);\r\n\r\n /* Keep a reference to config to pass to hooks */\r\n var CONFIG = null;\r\n\r\n /* Ideally, do not touch anything below this line */\r\n /* ______________________________________________ */\r\n\r\n var formElement = document.createElement('form');\r\n\r\n /**\r\n * _parseConfig\r\n *\r\n * @param {Object} cfg optional config literal\r\n */\r\n // eslint-disable-next-line complexity\r\n var _parseConfig = function _parseConfig(cfg) {\r\n if (CONFIG && CONFIG === cfg) {\r\n return;\r\n }\r\n\r\n /* Shield configuration object from tampering */\r\n if (!cfg || (typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {\r\n cfg = {};\r\n }\r\n\r\n /* Shield configuration object from prototype pollution */\r\n cfg = clone(cfg);\r\n\r\n /* Set configuration parameters */\r\n ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;\r\n ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;\r\n URI_SAFE_ATTRIBUTES = 'ADD_URI_SAFE_ATTR' in cfg ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR) : DEFAULT_URI_SAFE_ATTRIBUTES;\r\n DATA_URI_TAGS = 'ADD_DATA_URI_TAGS' in cfg ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS) : DEFAULT_DATA_URI_TAGS;\r\n FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};\r\n FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};\r\n USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;\r\n ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\r\n ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\r\n ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\r\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\r\n WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\r\n RETURN_DOM = cfg.RETURN_DOM || false; // Default false\r\n RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\r\n RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT !== false; // Default true\r\n RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\r\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\r\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\r\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\r\n IN_PLACE = cfg.IN_PLACE || false; // Default false\r\n IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;\r\n if (SAFE_FOR_TEMPLATES) {\r\n ALLOW_DATA_ATTR = false;\r\n }\r\n\r\n if (RETURN_DOM_FRAGMENT) {\r\n RETURN_DOM = true;\r\n }\r\n\r\n /* Parse profile info */\r\n if (USE_PROFILES) {\r\n ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray$1(text)));\r\n ALLOWED_ATTR = [];\r\n if (USE_PROFILES.html === true) {\r\n addToSet(ALLOWED_TAGS, html);\r\n addToSet(ALLOWED_ATTR, html$1);\r\n }\r\n\r\n if (USE_PROFILES.svg === true) {\r\n addToSet(ALLOWED_TAGS, svg);\r\n addToSet(ALLOWED_ATTR, svg$1);\r\n addToSet(ALLOWED_ATTR, xml);\r\n }\r\n\r\n if (USE_PROFILES.svgFilters === true) {\r\n addToSet(ALLOWED_TAGS, svgFilters);\r\n addToSet(ALLOWED_ATTR, svg$1);\r\n addToSet(ALLOWED_ATTR, xml);\r\n }\r\n\r\n if (USE_PROFILES.mathMl === true) {\r\n addToSet(ALLOWED_TAGS, mathMl);\r\n addToSet(ALLOWED_ATTR, mathMl$1);\r\n addToSet(ALLOWED_ATTR, xml);\r\n }\r\n }\r\n\r\n /* Merge configuration parameters */\r\n if (cfg.ADD_TAGS) {\r\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\r\n ALLOWED_TAGS = clone(ALLOWED_TAGS);\r\n }\r\n\r\n addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);\r\n }\r\n\r\n if (cfg.ADD_ATTR) {\r\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\r\n ALLOWED_ATTR = clone(ALLOWED_ATTR);\r\n }\r\n\r\n addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);\r\n }\r\n\r\n if (cfg.ADD_URI_SAFE_ATTR) {\r\n addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);\r\n }\r\n\r\n /* Add #text in case KEEP_CONTENT is set to true */\r\n if (KEEP_CONTENT) {\r\n ALLOWED_TAGS['#text'] = true;\r\n }\r\n\r\n /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\r\n if (WHOLE_DOCUMENT) {\r\n addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\r\n }\r\n\r\n /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\r\n if (ALLOWED_TAGS.table) {\r\n addToSet(ALLOWED_TAGS, ['tbody']);\r\n delete FORBID_TAGS.tbody;\r\n }\r\n\r\n // Prevent further manipulation of configuration.\r\n // Not available in IE8, Safari 5, etc.\r\n if (freeze) {\r\n freeze(cfg);\r\n }\r\n\r\n CONFIG = cfg;\r\n };\r\n\r\n /**\r\n * _forceRemove\r\n *\r\n * @param {Node} node a DOM node\r\n */\r\n var _forceRemove = function _forceRemove(node) {\r\n arrayPush(DOMPurify.removed, { element: node });\r\n try {\r\n node.parentNode.removeChild(node);\r\n } catch (_) {\r\n node.outerHTML = emptyHTML;\r\n }\r\n };\r\n\r\n /**\r\n * _removeAttribute\r\n *\r\n * @param {String} name an Attribute name\r\n * @param {Node} node a DOM node\r\n */\r\n var _removeAttribute = function _removeAttribute(name, node) {\r\n try {\r\n arrayPush(DOMPurify.removed, {\r\n attribute: node.getAttributeNode(name),\r\n from: node\r\n });\r\n } catch (_) {\r\n arrayPush(DOMPurify.removed, {\r\n attribute: null,\r\n from: node\r\n });\r\n }\r\n\r\n node.removeAttribute(name);\r\n };\r\n\r\n /**\r\n * _initDocument\r\n *\r\n * @param {String} dirty a string of dirty markup\r\n * @return {Document} a DOM, filled with the dirty markup\r\n */\r\n var _initDocument = function _initDocument(dirty) {\r\n /* Create a HTML document */\r\n var doc = void 0;\r\n var leadingWhitespace = void 0;\r\n\r\n if (FORCE_BODY) {\r\n dirty = '' + dirty;\r\n } else {\r\n /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\r\n var matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\r\n leadingWhitespace = matches && matches[0];\r\n }\r\n\r\n var dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\r\n /* Use the DOMParser API by default, fallback later if needs be */\r\n try {\r\n doc = new DOMParser().parseFromString(dirtyPayload, 'text/html');\r\n } catch (_) {}\r\n\r\n /* Use createHTMLDocument in case DOMParser is not available */\r\n if (!doc || !doc.documentElement) {\r\n doc = implementation.createHTMLDocument('');\r\n var _doc = doc,\r\n body = _doc.body;\r\n\r\n body.parentNode.removeChild(body.parentNode.firstElementChild);\r\n body.outerHTML = dirtyPayload;\r\n }\r\n\r\n if (dirty && leadingWhitespace) {\r\n doc.body.insertBefore(document.createTextNode(leadingWhitespace), doc.body.childNodes[0] || null);\r\n }\r\n\r\n /* Work on whole document or just its body */\r\n return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\r\n };\r\n\r\n /**\r\n * _createIterator\r\n *\r\n * @param {Document} root document/fragment to create iterator for\r\n * @return {Iterator} iterator instance\r\n */\r\n var _createIterator = function _createIterator(root) {\r\n return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {\r\n return NodeFilter.FILTER_ACCEPT;\r\n }, false);\r\n };\r\n\r\n /**\r\n * _isClobbered\r\n *\r\n * @param {Node} elm element to check for clobbering attacks\r\n * @return {Boolean} true if clobbered, false if safe\r\n */\r\n var _isClobbered = function _isClobbered(elm) {\r\n if (elm instanceof Text || elm instanceof Comment) {\r\n return false;\r\n }\r\n\r\n if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function' || typeof elm.namespaceURI !== 'string') {\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n /**\r\n * _isNode\r\n *\r\n * @param {Node} obj object to check whether it's a DOM node\r\n * @return {Boolean} true is object is a DOM node\r\n */\r\n var _isNode = function _isNode(object) {\r\n return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? object instanceof Node : object && (typeof object === 'undefined' ? 'undefined' : _typeof(object)) === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string';\r\n };\r\n\r\n /**\r\n * _executeHook\r\n * Execute user configurable hooks\r\n *\r\n * @param {String} entryPoint Name of the hook's entry point\r\n * @param {Node} currentNode node to work on with the hook\r\n * @param {Object} data additional hook parameters\r\n */\r\n var _executeHook = function _executeHook(entryPoint, currentNode, data) {\r\n if (!hooks[entryPoint]) {\r\n return;\r\n }\r\n\r\n arrayForEach(hooks[entryPoint], function (hook) {\r\n hook.call(DOMPurify, currentNode, data, CONFIG);\r\n });\r\n };\r\n\r\n /**\r\n * _sanitizeElements\r\n *\r\n * @protect nodeName\r\n * @protect textContent\r\n * @protect removeChild\r\n *\r\n * @param {Node} currentNode to check for permission to exist\r\n * @return {Boolean} true if node was killed, false if left alive\r\n */\r\n var _sanitizeElements = function _sanitizeElements(currentNode) {\r\n var content = void 0;\r\n\r\n /* Execute a hook if present */\r\n _executeHook('beforeSanitizeElements', currentNode, null);\r\n\r\n /* Check if element is clobbered or can clobber */\r\n if (_isClobbered(currentNode)) {\r\n _forceRemove(currentNode);\r\n return true;\r\n }\r\n\r\n /* Check if tagname contains Unicode */\r\n if (stringMatch(currentNode.nodeName, /[\\u0080-\\uFFFF]/)) {\r\n _forceRemove(currentNode);\r\n return true;\r\n }\r\n\r\n /* Now let's check the element's type and name */\r\n var tagName = stringToLowerCase(currentNode.nodeName);\r\n\r\n /* Execute a hook if present */\r\n _executeHook('uponSanitizeElement', currentNode, {\r\n tagName: tagName,\r\n allowedTags: ALLOWED_TAGS\r\n });\r\n\r\n /* Take care of an mXSS pattern using p, br inside svg, math */\r\n if ((tagName === 'svg' || tagName === 'math') && currentNode.querySelectorAll('p, br, form, table').length !== 0) {\r\n _forceRemove(currentNode);\r\n return true;\r\n }\r\n\r\n /* Detect mXSS attempts abusing namespace confusion */\r\n if (!_isNode(currentNode.firstElementChild) && (!_isNode(currentNode.content) || !_isNode(currentNode.content.firstElementChild)) && regExpTest(/<[!/\\w]/g, currentNode.innerHTML) && regExpTest(/<[!/\\w]/g, currentNode.textContent)) {\r\n _forceRemove(currentNode);\r\n return true;\r\n }\r\n\r\n /* Remove element if anything forbids its presence */\r\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\r\n /* Keep content except for bad-listed elements */\r\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {\r\n try {\r\n var htmlToInsert = currentNode.innerHTML;\r\n currentNode.insertAdjacentHTML('AfterEnd', trustedTypesPolicy ? trustedTypesPolicy.createHTML(htmlToInsert) : htmlToInsert);\r\n } catch (_) {}\r\n }\r\n\r\n _forceRemove(currentNode);\r\n return true;\r\n }\r\n\r\n /* Remove in case a noscript/noembed XSS is suspected */\r\n if ((tagName === 'noscript' || tagName === 'noembed') && regExpTest(/<\\/no(script|embed)/i, currentNode.innerHTML)) {\r\n _forceRemove(currentNode);\r\n return true;\r\n }\r\n\r\n /* Sanitize element content to be template-safe */\r\n if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {\r\n /* Get the element's text content */\r\n content = currentNode.textContent;\r\n content = stringReplace(content, MUSTACHE_EXPR$$1, ' ');\r\n content = stringReplace(content, ERB_EXPR$$1, ' ');\r\n if (currentNode.textContent !== content) {\r\n arrayPush(DOMPurify.removed, { element: currentNode.cloneNode() });\r\n currentNode.textContent = content;\r\n }\r\n }\r\n\r\n /* Execute a hook if present */\r\n _executeHook('afterSanitizeElements', currentNode, null);\r\n\r\n return false;\r\n };\r\n\r\n /**\r\n * _isValidAttribute\r\n *\r\n * @param {string} lcTag Lowercase tag name of containing element.\r\n * @param {string} lcName Lowercase attribute name.\r\n * @param {string} value Attribute value.\r\n * @return {Boolean} Returns true if `value` is valid, otherwise false.\r\n */\r\n // eslint-disable-next-line complexity\r\n var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\r\n /* Make sure attribute cannot clobber */\r\n if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\r\n return false;\r\n }\r\n\r\n /* Allow valid data-* attributes: At least one character after \"-\"\r\n (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\r\n XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\r\n We don't need to check the value; it's always URI safe. */\r\n if (ALLOW_DATA_ATTR && regExpTest(DATA_ATTR$$1, lcName)) ; else if (ALLOW_ARIA_ATTR && regExpTest(ARIA_ATTR$$1, lcName)) ; else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\r\n return false;\r\n\r\n /* Check value is safe. First, is attr inert? If so, is safe */\r\n } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') && lcTag !== 'script' && stringIndexOf(value, 'data:') === 0 && DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS && !regExpTest(IS_SCRIPT_OR_DATA$$1, stringReplace(value, ATTR_WHITESPACE$$1, ''))) ; else if (!value) ; else {\r\n return false;\r\n }\r\n\r\n return true;\r\n };\r\n\r\n /**\r\n * _sanitizeAttributes\r\n *\r\n * @protect attributes\r\n * @protect nodeName\r\n * @protect removeAttribute\r\n * @protect setAttribute\r\n *\r\n * @param {Node} currentNode to sanitize\r\n */\r\n var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\r\n var attr = void 0;\r\n var value = void 0;\r\n var lcName = void 0;\r\n var l = void 0;\r\n /* Execute a hook if present */\r\n _executeHook('beforeSanitizeAttributes', currentNode, null);\r\n\r\n var attributes = currentNode.attributes;\r\n\r\n /* Check if we have attributes; if not we might have a text node */\r\n\r\n if (!attributes) {\r\n return;\r\n }\r\n\r\n var hookEvent = {\r\n attrName: '',\r\n attrValue: '',\r\n keepAttr: true,\r\n allowedAttributes: ALLOWED_ATTR\r\n };\r\n l = attributes.length;\r\n\r\n /* Go backwards over all attributes; safely remove bad ones */\r\n while (l--) {\r\n attr = attributes[l];\r\n var _attr = attr,\r\n name = _attr.name,\r\n namespaceURI = _attr.namespaceURI;\r\n\r\n value = stringTrim(attr.value);\r\n lcName = stringToLowerCase(name);\r\n\r\n /* Execute a hook if present */\r\n hookEvent.attrName = lcName;\r\n hookEvent.attrValue = value;\r\n hookEvent.keepAttr = true;\r\n hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\r\n _executeHook('uponSanitizeAttribute', currentNode, hookEvent);\r\n value = hookEvent.attrValue;\r\n /* Did the hooks approve of the attribute? */\r\n if (hookEvent.forceKeepAttr) {\r\n continue;\r\n }\r\n\r\n /* Remove attribute */\r\n _removeAttribute(name, currentNode);\r\n\r\n /* Did the hooks approve of the attribute? */\r\n if (!hookEvent.keepAttr) {\r\n continue;\r\n }\r\n\r\n /* Work around a security issue in jQuery 3.0 */\r\n if (regExpTest(/\\/>/i, value)) {\r\n _removeAttribute(name, currentNode);\r\n continue;\r\n }\r\n\r\n /* Sanitize attribute content to be template-safe */\r\n if (SAFE_FOR_TEMPLATES) {\r\n value = stringReplace(value, MUSTACHE_EXPR$$1, ' ');\r\n value = stringReplace(value, ERB_EXPR$$1, ' ');\r\n }\r\n\r\n /* Is `value` valid for this attribute? */\r\n var lcTag = currentNode.nodeName.toLowerCase();\r\n if (!_isValidAttribute(lcTag, lcName, value)) {\r\n continue;\r\n }\r\n\r\n /* Handle invalid data-* attribute set by try-catching it */\r\n try {\r\n if (namespaceURI) {\r\n currentNode.setAttributeNS(namespaceURI, name, value);\r\n } else {\r\n /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\r\n currentNode.setAttribute(name, value);\r\n }\r\n\r\n arrayPop(DOMPurify.removed);\r\n } catch (_) {}\r\n }\r\n\r\n /* Execute a hook if present */\r\n _executeHook('afterSanitizeAttributes', currentNode, null);\r\n };\r\n\r\n /**\r\n * _sanitizeShadowDOM\r\n *\r\n * @param {DocumentFragment} fragment to iterate over recursively\r\n */\r\n var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\r\n var shadowNode = void 0;\r\n var shadowIterator = _createIterator(fragment);\r\n\r\n /* Execute a hook if present */\r\n _executeHook('beforeSanitizeShadowDOM', fragment, null);\r\n\r\n while (shadowNode = shadowIterator.nextNode()) {\r\n /* Execute a hook if present */\r\n _executeHook('uponSanitizeShadowNode', shadowNode, null);\r\n\r\n /* Sanitize tags and elements */\r\n if (_sanitizeElements(shadowNode)) {\r\n continue;\r\n }\r\n\r\n /* Deep shadow DOM detected */\r\n if (shadowNode.content instanceof DocumentFragment) {\r\n _sanitizeShadowDOM(shadowNode.content);\r\n }\r\n\r\n /* Check attributes, sanitize if necessary */\r\n _sanitizeAttributes(shadowNode);\r\n }\r\n\r\n /* Execute a hook if present */\r\n _executeHook('afterSanitizeShadowDOM', fragment, null);\r\n };\r\n\r\n /**\r\n * Sanitize\r\n * Public method providing core sanitation functionality\r\n *\r\n * @param {String|Node} dirty string or DOM node\r\n * @param {Object} configuration object\r\n */\r\n // eslint-disable-next-line complexity\r\n DOMPurify.sanitize = function (dirty, cfg) {\r\n var body = void 0;\r\n var importedNode = void 0;\r\n var currentNode = void 0;\r\n var oldNode = void 0;\r\n var returnNode = void 0;\r\n /* Make sure we have a string to sanitize.\r\n DO NOT return early, as this will return the wrong type if\r\n the user has requested a DOM object rather than a string */\r\n if (!dirty) {\r\n dirty = '';\r\n }\r\n\r\n /* Stringify, in case dirty is an object */\r\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\r\n // eslint-disable-next-line no-negated-condition\r\n if (typeof dirty.toString !== 'function') {\r\n throw typeErrorCreate('toString is not a function');\r\n } else {\r\n dirty = dirty.toString();\r\n if (typeof dirty !== 'string') {\r\n throw typeErrorCreate('dirty is not a string, aborting');\r\n }\r\n }\r\n }\r\n\r\n /* Check we can run. Otherwise fall back or ignore */\r\n if (!DOMPurify.isSupported) {\r\n if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {\r\n if (typeof dirty === 'string') {\r\n return window.toStaticHTML(dirty);\r\n }\r\n\r\n if (_isNode(dirty)) {\r\n return window.toStaticHTML(dirty.outerHTML);\r\n }\r\n }\r\n\r\n return dirty;\r\n }\r\n\r\n /* Assign config vars */\r\n if (!SET_CONFIG) {\r\n _parseConfig(cfg);\r\n }\r\n\r\n /* Clean up removed elements */\r\n DOMPurify.removed = [];\r\n\r\n /* Check if dirty is correctly typed for IN_PLACE */\r\n if (typeof dirty === 'string') {\r\n IN_PLACE = false;\r\n }\r\n\r\n if (IN_PLACE) ; else if (dirty instanceof Node) {\r\n /* If dirty is a DOM element, append to an empty document to avoid\r\n elements being stripped by the parser */\r\n body = _initDocument('');\r\n importedNode = body.ownerDocument.importNode(dirty, true);\r\n if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {\r\n /* Node is already a body, use as is */\r\n body = importedNode;\r\n } else if (importedNode.nodeName === 'HTML') {\r\n body = importedNode;\r\n } else {\r\n // eslint-disable-next-line unicorn/prefer-node-append\r\n body.appendChild(importedNode);\r\n }\r\n } else {\r\n /* Exit directly if we have nothing to do */\r\n if (!RETURN_DOM && !SAFE_FOR_TEMPLATES && !WHOLE_DOCUMENT &&\r\n // eslint-disable-next-line unicorn/prefer-includes\r\n dirty.indexOf('<') === -1) {\r\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\r\n }\r\n\r\n /* Initialize the document to work on */\r\n body = _initDocument(dirty);\r\n\r\n /* Check we have a DOM node from the data */\r\n if (!body) {\r\n return RETURN_DOM ? null : emptyHTML;\r\n }\r\n }\r\n\r\n /* Remove first element node (ours) if FORCE_BODY is set */\r\n if (body && FORCE_BODY) {\r\n _forceRemove(body.firstChild);\r\n }\r\n\r\n /* Get node iterator */\r\n var nodeIterator = _createIterator(IN_PLACE ? dirty : body);\r\n\r\n /* Now start iterating over the created document */\r\n while (currentNode = nodeIterator.nextNode()) {\r\n /* Fix IE's strange behavior with manipulated textNodes #89 */\r\n if (currentNode.nodeType === 3 && currentNode === oldNode) {\r\n continue;\r\n }\r\n\r\n /* Sanitize tags and elements */\r\n if (_sanitizeElements(currentNode)) {\r\n continue;\r\n }\r\n\r\n /* Shadow DOM detected, sanitize it */\r\n if (currentNode.content instanceof DocumentFragment) {\r\n _sanitizeShadowDOM(currentNode.content);\r\n }\r\n\r\n /* Check attributes, sanitize if necessary */\r\n _sanitizeAttributes(currentNode);\r\n\r\n oldNode = currentNode;\r\n }\r\n\r\n oldNode = null;\r\n\r\n /* If we sanitized `dirty` in-place, return it. */\r\n if (IN_PLACE) {\r\n return dirty;\r\n }\r\n\r\n /* Return sanitized string or DOM */\r\n if (RETURN_DOM) {\r\n if (RETURN_DOM_FRAGMENT) {\r\n returnNode = createDocumentFragment.call(body.ownerDocument);\r\n\r\n while (body.firstChild) {\r\n // eslint-disable-next-line unicorn/prefer-node-append\r\n returnNode.appendChild(body.firstChild);\r\n }\r\n } else {\r\n returnNode = body;\r\n }\r\n\r\n if (RETURN_DOM_IMPORT) {\r\n /*\r\n AdoptNode() is not used because internal state is not reset\r\n (e.g. the past names map of a HTMLFormElement), this is safe\r\n in theory but we would rather not risk another attack vector.\r\n The state that is cloned by importNode() is explicitly defined\r\n by the specs.\r\n */\r\n returnNode = importNode.call(originalDocument, returnNode, true);\r\n }\r\n\r\n return returnNode;\r\n }\r\n\r\n var serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\r\n\r\n /* Sanitize final string template-safe */\r\n if (SAFE_FOR_TEMPLATES) {\r\n serializedHTML = stringReplace(serializedHTML, MUSTACHE_EXPR$$1, ' ');\r\n serializedHTML = stringReplace(serializedHTML, ERB_EXPR$$1, ' ');\r\n }\r\n\r\n return trustedTypesPolicy && RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\r\n };\r\n\r\n /**\r\n * Public method to set the configuration once\r\n * setConfig\r\n *\r\n * @param {Object} cfg configuration object\r\n */\r\n DOMPurify.setConfig = function (cfg) {\r\n _parseConfig(cfg);\r\n SET_CONFIG = true;\r\n };\r\n\r\n /**\r\n * Public method to remove the configuration\r\n * clearConfig\r\n *\r\n */\r\n DOMPurify.clearConfig = function () {\r\n CONFIG = null;\r\n SET_CONFIG = false;\r\n };\r\n\r\n /**\r\n * Public method to check if an attribute value is valid.\r\n * Uses last set config, if any. Otherwise, uses config defaults.\r\n * isValidAttribute\r\n *\r\n * @param {string} tag Tag name of containing element.\r\n * @param {string} attr Attribute name.\r\n * @param {string} value Attribute value.\r\n * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.\r\n */\r\n DOMPurify.isValidAttribute = function (tag, attr, value) {\r\n /* Initialize shared config vars if necessary. */\r\n if (!CONFIG) {\r\n _parseConfig({});\r\n }\r\n\r\n var lcTag = stringToLowerCase(tag);\r\n var lcName = stringToLowerCase(attr);\r\n return _isValidAttribute(lcTag, lcName, value);\r\n };\r\n\r\n /**\r\n * AddHook\r\n * Public method to add DOMPurify hooks\r\n *\r\n * @param {String} entryPoint entry point for the hook to add\r\n * @param {Function} hookFunction function to execute\r\n */\r\n DOMPurify.addHook = function (entryPoint, hookFunction) {\r\n if (typeof hookFunction !== 'function') {\r\n return;\r\n }\r\n\r\n hooks[entryPoint] = hooks[entryPoint] || [];\r\n arrayPush(hooks[entryPoint], hookFunction);\r\n };\r\n\r\n /**\r\n * RemoveHook\r\n * Public method to remove a DOMPurify hook at a given entryPoint\r\n * (pops it from the stack of hooks if more are present)\r\n *\r\n * @param {String} entryPoint entry point for the hook to remove\r\n */\r\n DOMPurify.removeHook = function (entryPoint) {\r\n if (hooks[entryPoint]) {\r\n arrayPop(hooks[entryPoint]);\r\n }\r\n };\r\n\r\n /**\r\n * RemoveHooks\r\n * Public method to remove all DOMPurify hooks at a given entryPoint\r\n *\r\n * @param {String} entryPoint entry point for the hooks to remove\r\n */\r\n DOMPurify.removeHooks = function (entryPoint) {\r\n if (hooks[entryPoint]) {\r\n hooks[entryPoint] = [];\r\n }\r\n };\r\n\r\n /**\r\n * RemoveAllHooks\r\n * Public method to remove all DOMPurify hooks\r\n *\r\n */\r\n DOMPurify.removeAllHooks = function () {\r\n hooks = {};\r\n };\r\n\r\n return DOMPurify;\r\n}\r\n\r\nvar purify = createDOMPurify();\r\n\r\nexport default purify;\r\n//# sourceMappingURL=purify.es.js.map\r\n","import DOMPurify from \"../ThirdParty/purify.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\nvar nextCreditId = 0;\r\nvar creditToId = {};\r\n\r\n/**\r\n * A credit contains data pertaining to how to display attributions/credits for certain content on the screen.\r\n * @param {String} html An string representing an html code snippet\r\n * @param {Boolean} [showOnScreen=false] If true, the credit will be visible in the main credit container. Otherwise, it will appear in a popover\r\n *\r\n * @alias Credit\r\n * @constructor\r\n *\r\n * @exception {DeveloperError} html is required.\r\n *\r\n * @example\r\n * //Create a credit with a tooltip, image and link\r\n * var credit = new Cesium.Credit('');\r\n */\r\nfunction Credit(html, showOnScreen) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"html\", html);\r\n //>>includeEnd('debug');\r\n var id;\r\n var key = html;\r\n\r\n if (defined(creditToId[key])) {\r\n id = creditToId[key];\r\n } else {\r\n id = nextCreditId++;\r\n creditToId[key] = id;\r\n }\r\n\r\n showOnScreen = defaultValue(showOnScreen, false);\r\n\r\n // Credits are immutable so generate an id to use to optimize equal()\r\n this._id = id;\r\n this._html = html;\r\n this._showOnScreen = showOnScreen;\r\n this._element = undefined;\r\n}\r\n\r\nObject.defineProperties(Credit.prototype, {\r\n /**\r\n * The credit content\r\n * @memberof Credit.prototype\r\n * @type {String}\r\n * @readonly\r\n */\r\n html: {\r\n get: function () {\r\n return this._html;\r\n },\r\n },\r\n\r\n /**\r\n * @memberof Credit.prototype\r\n * @type {Number}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n\r\n /**\r\n * Whether the credit should be displayed on screen or in a lightbox\r\n * @memberof Credit.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n showOnScreen: {\r\n get: function () {\r\n return this._showOnScreen;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the credit element\r\n * @memberof Credit.prototype\r\n * @type {HTMLElement}\r\n * @readonly\r\n */\r\n element: {\r\n get: function () {\r\n if (!defined(this._element)) {\r\n var html = DOMPurify.sanitize(this._html);\r\n\r\n var div = document.createElement(\"div\");\r\n div._creditId = this._id;\r\n div.style.display = \"inline\";\r\n div.innerHTML = html;\r\n\r\n var links = div.querySelectorAll(\"a\");\r\n for (var i = 0; i < links.length; i++) {\r\n links[i].setAttribute(\"target\", \"_blank\");\r\n }\r\n\r\n this._element = div;\r\n }\r\n return this._element;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Returns true if the credits are equal\r\n *\r\n * @param {Credit} left The first credit\r\n * @param {Credit} right The second credit\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCredit.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) && defined(right) && left._id === right._id)\r\n );\r\n};\r\n\r\n/**\r\n * Returns true if the credits are equal\r\n *\r\n * @param {Credit} credit The credit to compare to.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCredit.prototype.equals = function (credit) {\r\n return Credit.equals(this, credit);\r\n};\r\n\r\n/**\r\n * @private\r\n * @param attribution\r\n * @return {Credit}\r\n */\r\nCredit.getIonCredit = function (attribution) {\r\n var showOnScreen =\r\n defined(attribution.collapsible) && !attribution.collapsible;\r\n var credit = new Credit(attribution.html, showOnScreen);\r\n\r\n credit._isIon = credit.html.indexOf(\"ion-credit.png\") !== -1;\r\n return credit;\r\n};\r\n\r\n/**\r\n * Duplicates a Credit instance.\r\n *\r\n * @param {Credit} [credit] The Credit to duplicate.\r\n * @returns {Credit} A new Credit instance that is a duplicate of the one provided. (Returns undefined if the credit is undefined)\r\n */\r\nCredit.clone = function (credit) {\r\n if (defined(credit)) {\r\n return new Credit(credit.html, credit.showOnScreen);\r\n }\r\n};\r\nexport default Credit;\r\n","/**\r\n * The encoding that is used for a heightmap\r\n *\r\n * @enum {Number}\r\n */\r\nvar HeightmapEncoding = {\r\n /**\r\n * No encoding\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NONE: 0,\r\n\r\n /**\r\n * LERC encoding\r\n *\r\n * @type {Number}\r\n * @constant\r\n *\r\n * @see {@link https://github.com/Esri/lerc|The LERC specification}\r\n */\r\n LERC: 1,\r\n};\r\nexport default Object.freeze(HeightmapEncoding);\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Intersect from \"./Intersect.js\";\r\n\r\n/**\r\n * Creates an instance of an AxisAlignedBoundingBox from the minimum and maximum points along the x, y, and z axes.\r\n * @alias AxisAlignedBoundingBox\r\n * @constructor\r\n *\r\n * @param {Cartesian3} [minimum=Cartesian3.ZERO] The minimum point along the x, y, and z axes.\r\n * @param {Cartesian3} [maximum=Cartesian3.ZERO] The maximum point along the x, y, and z axes.\r\n * @param {Cartesian3} [center] The center of the box; automatically computed if not supplied.\r\n *\r\n * @see BoundingSphere\r\n * @see BoundingRectangle\r\n */\r\nfunction AxisAlignedBoundingBox(minimum, maximum, center) {\r\n /**\r\n * The minimum point defining the bounding box.\r\n * @type {Cartesian3}\r\n * @default {@link Cartesian3.ZERO}\r\n */\r\n this.minimum = Cartesian3.clone(defaultValue(minimum, Cartesian3.ZERO));\r\n\r\n /**\r\n * The maximum point defining the bounding box.\r\n * @type {Cartesian3}\r\n * @default {@link Cartesian3.ZERO}\r\n */\r\n this.maximum = Cartesian3.clone(defaultValue(maximum, Cartesian3.ZERO));\r\n\r\n //If center was not defined, compute it.\r\n if (!defined(center)) {\r\n center = Cartesian3.midpoint(this.minimum, this.maximum, new Cartesian3());\r\n } else {\r\n center = Cartesian3.clone(center);\r\n }\r\n\r\n /**\r\n * The center point of the bounding box.\r\n * @type {Cartesian3}\r\n */\r\n this.center = center;\r\n}\r\n\r\n/**\r\n * Computes an instance of an AxisAlignedBoundingBox. The box is determined by\r\n * finding the points spaced the farthest apart on the x, y, and z axes.\r\n *\r\n * @param {Cartesian3[]} positions List of points that the bounding box will enclose. Each point must have a x, y, and z properties.\r\n * @param {AxisAlignedBoundingBox} [result] The object onto which to store the result.\r\n * @returns {AxisAlignedBoundingBox} The modified result parameter or a new AxisAlignedBoundingBox instance if one was not provided.\r\n *\r\n * @example\r\n * // Compute an axis aligned bounding box enclosing two points.\r\n * var box = Cesium.AxisAlignedBoundingBox.fromPoints([new Cesium.Cartesian3(2, 0, 0), new Cesium.Cartesian3(-2, 0, 0)]);\r\n */\r\nAxisAlignedBoundingBox.fromPoints = function (positions, result) {\r\n if (!defined(result)) {\r\n result = new AxisAlignedBoundingBox();\r\n }\r\n\r\n if (!defined(positions) || positions.length === 0) {\r\n result.minimum = Cartesian3.clone(Cartesian3.ZERO, result.minimum);\r\n result.maximum = Cartesian3.clone(Cartesian3.ZERO, result.maximum);\r\n result.center = Cartesian3.clone(Cartesian3.ZERO, result.center);\r\n return result;\r\n }\r\n\r\n var minimumX = positions[0].x;\r\n var minimumY = positions[0].y;\r\n var minimumZ = positions[0].z;\r\n\r\n var maximumX = positions[0].x;\r\n var maximumY = positions[0].y;\r\n var maximumZ = positions[0].z;\r\n\r\n var length = positions.length;\r\n for (var i = 1; i < length; i++) {\r\n var p = positions[i];\r\n var x = p.x;\r\n var y = p.y;\r\n var z = p.z;\r\n\r\n minimumX = Math.min(x, minimumX);\r\n maximumX = Math.max(x, maximumX);\r\n minimumY = Math.min(y, minimumY);\r\n maximumY = Math.max(y, maximumY);\r\n minimumZ = Math.min(z, minimumZ);\r\n maximumZ = Math.max(z, maximumZ);\r\n }\r\n\r\n var minimum = result.minimum;\r\n minimum.x = minimumX;\r\n minimum.y = minimumY;\r\n minimum.z = minimumZ;\r\n\r\n var maximum = result.maximum;\r\n maximum.x = maximumX;\r\n maximum.y = maximumY;\r\n maximum.z = maximumZ;\r\n\r\n result.center = Cartesian3.midpoint(minimum, maximum, result.center);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a AxisAlignedBoundingBox instance.\r\n *\r\n * @param {AxisAlignedBoundingBox} box The bounding box to duplicate.\r\n * @param {AxisAlignedBoundingBox} [result] The object onto which to store the result.\r\n * @returns {AxisAlignedBoundingBox} The modified result parameter or a new AxisAlignedBoundingBox instance if none was provided. (Returns undefined if box is undefined)\r\n */\r\nAxisAlignedBoundingBox.clone = function (box, result) {\r\n if (!defined(box)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new AxisAlignedBoundingBox(box.minimum, box.maximum, box.center);\r\n }\r\n\r\n result.minimum = Cartesian3.clone(box.minimum, result.minimum);\r\n result.maximum = Cartesian3.clone(box.maximum, result.maximum);\r\n result.center = Cartesian3.clone(box.center, result.center);\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided AxisAlignedBoundingBox componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {AxisAlignedBoundingBox} [left] The first AxisAlignedBoundingBox.\r\n * @param {AxisAlignedBoundingBox} [right] The second AxisAlignedBoundingBox.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nAxisAlignedBoundingBox.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Cartesian3.equals(left.center, right.center) &&\r\n Cartesian3.equals(left.minimum, right.minimum) &&\r\n Cartesian3.equals(left.maximum, right.maximum))\r\n );\r\n};\r\n\r\nvar intersectScratch = new Cartesian3();\r\n/**\r\n * Determines which side of a plane a box is located.\r\n *\r\n * @param {AxisAlignedBoundingBox} box The bounding box to test.\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the box\r\n * intersects the plane.\r\n */\r\nAxisAlignedBoundingBox.intersectPlane = function (box, plane) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"box\", box);\r\n Check.defined(\"plane\", plane);\r\n //>>includeEnd('debug');\r\n\r\n intersectScratch = Cartesian3.subtract(\r\n box.maximum,\r\n box.minimum,\r\n intersectScratch\r\n );\r\n var h = Cartesian3.multiplyByScalar(intersectScratch, 0.5, intersectScratch); //The positive half diagonal\r\n var normal = plane.normal;\r\n var e =\r\n h.x * Math.abs(normal.x) +\r\n h.y * Math.abs(normal.y) +\r\n h.z * Math.abs(normal.z);\r\n var s = Cartesian3.dot(box.center, normal) + plane.distance; //signed distance from center\r\n\r\n if (s - e > 0) {\r\n return Intersect.INSIDE;\r\n }\r\n\r\n if (s + e < 0) {\r\n //Not in front because normals point inward\r\n return Intersect.OUTSIDE;\r\n }\r\n\r\n return Intersect.INTERSECTING;\r\n};\r\n\r\n/**\r\n * Duplicates this AxisAlignedBoundingBox instance.\r\n *\r\n * @param {AxisAlignedBoundingBox} [result] The object onto which to store the result.\r\n * @returns {AxisAlignedBoundingBox} The modified result parameter or a new AxisAlignedBoundingBox instance if one was not provided.\r\n */\r\nAxisAlignedBoundingBox.prototype.clone = function (result) {\r\n return AxisAlignedBoundingBox.clone(this, result);\r\n};\r\n\r\n/**\r\n * Determines which side of a plane this box is located.\r\n *\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the box\r\n * intersects the plane.\r\n */\r\nAxisAlignedBoundingBox.prototype.intersectPlane = function (plane) {\r\n return AxisAlignedBoundingBox.intersectPlane(this, plane);\r\n};\r\n\r\n/**\r\n * Compares this AxisAlignedBoundingBox against the provided AxisAlignedBoundingBox componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {AxisAlignedBoundingBox} [right] The right hand side AxisAlignedBoundingBox.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nAxisAlignedBoundingBox.prototype.equals = function (right) {\r\n return AxisAlignedBoundingBox.equals(this, right);\r\n};\r\nexport default AxisAlignedBoundingBox;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\n\r\n/**\r\n * Determine whether or not other objects are visible or hidden behind the visible horizon defined by\r\n * an {@link Ellipsoid} and a camera position. The ellipsoid is assumed to be located at the\r\n * origin of the coordinate system. This class uses the algorithm described in the\r\n * {@link https://cesium.com/blog/2013/04/25/Horizon-culling/|Horizon Culling} blog post.\r\n *\r\n * @alias EllipsoidalOccluder\r\n *\r\n * @param {Ellipsoid} ellipsoid The ellipsoid to use as an occluder.\r\n * @param {Cartesian3} [cameraPosition] The coordinate of the viewer/camera. If this parameter is not\r\n * specified, {@link EllipsoidalOccluder#cameraPosition} must be called before\r\n * testing visibility.\r\n *\r\n * @constructor\r\n *\r\n * @example\r\n * // Construct an ellipsoidal occluder with radii 1.0, 1.1, and 0.9.\r\n * var cameraPosition = new Cesium.Cartesian3(5.0, 6.0, 7.0);\r\n * var occluderEllipsoid = new Cesium.Ellipsoid(1.0, 1.1, 0.9);\r\n * var occluder = new Cesium.EllipsoidalOccluder(occluderEllipsoid, cameraPosition);\r\n *\r\n * @private\r\n */\r\nfunction EllipsoidalOccluder(ellipsoid, cameraPosition) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"ellipsoid\", ellipsoid);\r\n //>>includeEnd('debug');\r\n\r\n this._ellipsoid = ellipsoid;\r\n this._cameraPosition = new Cartesian3();\r\n this._cameraPositionInScaledSpace = new Cartesian3();\r\n this._distanceToLimbInScaledSpaceSquared = 0.0;\r\n\r\n // cameraPosition fills in the above values\r\n if (defined(cameraPosition)) {\r\n this.cameraPosition = cameraPosition;\r\n }\r\n}\r\n\r\nObject.defineProperties(EllipsoidalOccluder.prototype, {\r\n /**\r\n * Gets the occluding ellipsoid.\r\n * @memberof EllipsoidalOccluder.prototype\r\n * @type {Ellipsoid}\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n /**\r\n * Gets or sets the position of the camera.\r\n * @memberof EllipsoidalOccluder.prototype\r\n * @type {Cartesian3}\r\n */\r\n cameraPosition: {\r\n get: function () {\r\n return this._cameraPosition;\r\n },\r\n set: function (cameraPosition) {\r\n // See https://cesium.com/blog/2013/04/25/Horizon-culling/\r\n var ellipsoid = this._ellipsoid;\r\n var cv = ellipsoid.transformPositionToScaledSpace(\r\n cameraPosition,\r\n this._cameraPositionInScaledSpace\r\n );\r\n var vhMagnitudeSquared = Cartesian3.magnitudeSquared(cv) - 1.0;\r\n\r\n Cartesian3.clone(cameraPosition, this._cameraPosition);\r\n this._cameraPositionInScaledSpace = cv;\r\n this._distanceToLimbInScaledSpaceSquared = vhMagnitudeSquared;\r\n },\r\n },\r\n});\r\n\r\nvar scratchCartesian = new Cartesian3();\r\n\r\n/**\r\n * Determines whether or not a point, the occludee, is hidden from view by the occluder.\r\n *\r\n * @param {Cartesian3} occludee The point to test for visibility.\r\n * @returns {Boolean} true if the occludee is visible; otherwise false.\r\n *\r\n * @example\r\n * var cameraPosition = new Cesium.Cartesian3(0, 0, 2.5);\r\n * var ellipsoid = new Cesium.Ellipsoid(1.0, 1.1, 0.9);\r\n * var occluder = new Cesium.EllipsoidalOccluder(ellipsoid, cameraPosition);\r\n * var point = new Cesium.Cartesian3(0, -3, -3);\r\n * occluder.isPointVisible(point); //returns true\r\n */\r\nEllipsoidalOccluder.prototype.isPointVisible = function (occludee) {\r\n var ellipsoid = this._ellipsoid;\r\n var occludeeScaledSpacePosition = ellipsoid.transformPositionToScaledSpace(\r\n occludee,\r\n scratchCartesian\r\n );\r\n return isScaledSpacePointVisible(\r\n occludeeScaledSpacePosition,\r\n this._cameraPositionInScaledSpace,\r\n this._distanceToLimbInScaledSpaceSquared\r\n );\r\n};\r\n\r\n/**\r\n * Determines whether or not a point expressed in the ellipsoid scaled space, is hidden from view by the\r\n * occluder. To transform a Cartesian X, Y, Z position in the coordinate system aligned with the ellipsoid\r\n * into the scaled space, call {@link Ellipsoid#transformPositionToScaledSpace}.\r\n *\r\n * @param {Cartesian3} occludeeScaledSpacePosition The point to test for visibility, represented in the scaled space.\r\n * @returns {Boolean} true if the occludee is visible; otherwise false.\r\n *\r\n * @example\r\n * var cameraPosition = new Cesium.Cartesian3(0, 0, 2.5);\r\n * var ellipsoid = new Cesium.Ellipsoid(1.0, 1.1, 0.9);\r\n * var occluder = new Cesium.EllipsoidalOccluder(ellipsoid, cameraPosition);\r\n * var point = new Cesium.Cartesian3(0, -3, -3);\r\n * var scaledSpacePoint = ellipsoid.transformPositionToScaledSpace(point);\r\n * occluder.isScaledSpacePointVisible(scaledSpacePoint); //returns true\r\n */\r\nEllipsoidalOccluder.prototype.isScaledSpacePointVisible = function (\r\n occludeeScaledSpacePosition\r\n) {\r\n return isScaledSpacePointVisible(\r\n occludeeScaledSpacePosition,\r\n this._cameraPositionInScaledSpace,\r\n this._distanceToLimbInScaledSpaceSquared\r\n );\r\n};\r\n\r\nvar scratchCameraPositionInScaledSpaceShrunk = new Cartesian3();\r\n\r\n/**\r\n * Similar to {@link EllipsoidalOccluder#isScaledSpacePointVisible} except tests against an\r\n * ellipsoid that has been shrunk by the minimum height when the minimum height is below\r\n * the ellipsoid. This is intended to be used with points generated by\r\n * {@link EllipsoidalOccluder#computeHorizonCullingPointPossiblyUnderEllipsoid} or\r\n * {@link EllipsoidalOccluder#computeHorizonCullingPointFromVerticesPossiblyUnderEllipsoid}.\r\n *\r\n * @param {Cartesian3} occludeeScaledSpacePosition The point to test for visibility, represented in the scaled space of the possibly-shrunk ellipsoid.\r\n * @returns {Boolean} true if the occludee is visible; otherwise false.\r\n */\r\nEllipsoidalOccluder.prototype.isScaledSpacePointVisiblePossiblyUnderEllipsoid = function (\r\n occludeeScaledSpacePosition,\r\n minimumHeight\r\n) {\r\n var ellipsoid = this._ellipsoid;\r\n var vhMagnitudeSquared;\r\n var cv;\r\n\r\n if (\r\n defined(minimumHeight) &&\r\n minimumHeight < 0.0 &&\r\n ellipsoid.minimumRadius > -minimumHeight\r\n ) {\r\n // This code is similar to the cameraPosition setter, but unrolled for performance because it will be called a lot.\r\n cv = scratchCameraPositionInScaledSpaceShrunk;\r\n cv.x = this._cameraPosition.x / (ellipsoid.radii.x + minimumHeight);\r\n cv.y = this._cameraPosition.y / (ellipsoid.radii.y + minimumHeight);\r\n cv.z = this._cameraPosition.z / (ellipsoid.radii.z + minimumHeight);\r\n vhMagnitudeSquared = cv.x * cv.x + cv.y * cv.y + cv.z * cv.z - 1.0;\r\n } else {\r\n cv = this._cameraPositionInScaledSpace;\r\n vhMagnitudeSquared = this._distanceToLimbInScaledSpaceSquared;\r\n }\r\n\r\n return isScaledSpacePointVisible(\r\n occludeeScaledSpacePosition,\r\n cv,\r\n vhMagnitudeSquared\r\n );\r\n};\r\n\r\n/**\r\n * Computes a point that can be used for horizon culling from a list of positions. If the point is below\r\n * the horizon, all of the positions are guaranteed to be below the horizon as well. The returned point\r\n * is expressed in the ellipsoid-scaled space and is suitable for use with\r\n * {@link EllipsoidalOccluder#isScaledSpacePointVisible}.\r\n *\r\n * @param {Cartesian3} directionToPoint The direction that the computed point will lie along.\r\n * A reasonable direction to use is the direction from the center of the ellipsoid to\r\n * the center of the bounding sphere computed from the positions. The direction need not\r\n * be normalized.\r\n * @param {Cartesian3[]} positions The positions from which to compute the horizon culling point. The positions\r\n * must be expressed in a reference frame centered at the ellipsoid and aligned with the\r\n * ellipsoid's axes.\r\n * @param {Cartesian3} [result] The instance on which to store the result instead of allocating a new instance.\r\n * @returns {Cartesian3} The computed horizon culling point, expressed in the ellipsoid-scaled space.\r\n */\r\nEllipsoidalOccluder.prototype.computeHorizonCullingPoint = function (\r\n directionToPoint,\r\n positions,\r\n result\r\n) {\r\n return computeHorizonCullingPointFromPositions(\r\n this._ellipsoid,\r\n directionToPoint,\r\n positions,\r\n result\r\n );\r\n};\r\n\r\nvar scratchEllipsoidShrunk = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\n\r\n/**\r\n * Similar to {@link EllipsoidalOccluder#computeHorizonCullingPoint} except computes the culling\r\n * point relative to an ellipsoid that has been shrunk by the minimum height when the minimum height is below\r\n * the ellipsoid. The returned point is expressed in the possibly-shrunk ellipsoid-scaled space and is suitable\r\n * for use with {@link EllipsoidalOccluder#isScaledSpacePointVisiblePossiblyUnderEllipsoid}.\r\n *\r\n * @param {Cartesian3} directionToPoint The direction that the computed point will lie along.\r\n * A reasonable direction to use is the direction from the center of the ellipsoid to\r\n * the center of the bounding sphere computed from the positions. The direction need not\r\n * be normalized.\r\n * @param {Cartesian3[]} positions The positions from which to compute the horizon culling point. The positions\r\n * must be expressed in a reference frame centered at the ellipsoid and aligned with the\r\n * ellipsoid's axes.\r\n * @param {Number} [minimumHeight] The minimum height of all positions. If this value is undefined, all positions are assumed to be above the ellipsoid.\r\n * @param {Cartesian3} [result] The instance on which to store the result instead of allocating a new instance.\r\n * @returns {Cartesian3} The computed horizon culling point, expressed in the possibly-shrunk ellipsoid-scaled space.\r\n */\r\nEllipsoidalOccluder.prototype.computeHorizonCullingPointPossiblyUnderEllipsoid = function (\r\n directionToPoint,\r\n positions,\r\n minimumHeight,\r\n result\r\n) {\r\n var possiblyShrunkEllipsoid = getPossiblyShrunkEllipsoid(\r\n this._ellipsoid,\r\n minimumHeight,\r\n scratchEllipsoidShrunk\r\n );\r\n return computeHorizonCullingPointFromPositions(\r\n possiblyShrunkEllipsoid,\r\n directionToPoint,\r\n positions,\r\n result\r\n );\r\n};\r\n/**\r\n * Computes a point that can be used for horizon culling from a list of positions. If the point is below\r\n * the horizon, all of the positions are guaranteed to be below the horizon as well. The returned point\r\n * is expressed in the ellipsoid-scaled space and is suitable for use with\r\n * {@link EllipsoidalOccluder#isScaledSpacePointVisible}.\r\n *\r\n * @param {Cartesian3} directionToPoint The direction that the computed point will lie along.\r\n * A reasonable direction to use is the direction from the center of the ellipsoid to\r\n * the center of the bounding sphere computed from the positions. The direction need not\r\n * be normalized.\r\n * @param {Number[]} vertices The vertices from which to compute the horizon culling point. The positions\r\n * must be expressed in a reference frame centered at the ellipsoid and aligned with the\r\n * ellipsoid's axes.\r\n * @param {Number} [stride=3]\r\n * @param {Cartesian3} [center=Cartesian3.ZERO]\r\n * @param {Cartesian3} [result] The instance on which to store the result instead of allocating a new instance.\r\n * @returns {Cartesian3} The computed horizon culling point, expressed in the ellipsoid-scaled space.\r\n */\r\nEllipsoidalOccluder.prototype.computeHorizonCullingPointFromVertices = function (\r\n directionToPoint,\r\n vertices,\r\n stride,\r\n center,\r\n result\r\n) {\r\n return computeHorizonCullingPointFromVertices(\r\n this._ellipsoid,\r\n directionToPoint,\r\n vertices,\r\n stride,\r\n center,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Similar to {@link EllipsoidalOccluder#computeHorizonCullingPointFromVertices} except computes the culling\r\n * point relative to an ellipsoid that has been shrunk by the minimum height when the minimum height is below\r\n * the ellipsoid. The returned point is expressed in the possibly-shrunk ellipsoid-scaled space and is suitable\r\n * for use with {@link EllipsoidalOccluder#isScaledSpacePointVisiblePossiblyUnderEllipsoid}.\r\n *\r\n * @param {Cartesian3} directionToPoint The direction that the computed point will lie along.\r\n * A reasonable direction to use is the direction from the center of the ellipsoid to\r\n * the center of the bounding sphere computed from the positions. The direction need not\r\n * be normalized.\r\n * @param {Number[]} vertices The vertices from which to compute the horizon culling point. The positions\r\n * must be expressed in a reference frame centered at the ellipsoid and aligned with the\r\n * ellipsoid's axes.\r\n * @param {Number} [stride=3]\r\n * @param {Cartesian3} [center=Cartesian3.ZERO]\r\n * @param {Number} [minimumHeight] The minimum height of all vertices. If this value is undefined, all vertices are assumed to be above the ellipsoid.\r\n * @param {Cartesian3} [result] The instance on which to store the result instead of allocating a new instance.\r\n * @returns {Cartesian3} The computed horizon culling point, expressed in the possibly-shrunk ellipsoid-scaled space.\r\n */\r\nEllipsoidalOccluder.prototype.computeHorizonCullingPointFromVerticesPossiblyUnderEllipsoid = function (\r\n directionToPoint,\r\n vertices,\r\n stride,\r\n center,\r\n minimumHeight,\r\n result\r\n) {\r\n var possiblyShrunkEllipsoid = getPossiblyShrunkEllipsoid(\r\n this._ellipsoid,\r\n minimumHeight,\r\n scratchEllipsoidShrunk\r\n );\r\n return computeHorizonCullingPointFromVertices(\r\n possiblyShrunkEllipsoid,\r\n directionToPoint,\r\n vertices,\r\n stride,\r\n center,\r\n result\r\n );\r\n};\r\n\r\nvar subsampleScratch = [];\r\n\r\n/**\r\n * Computes a point that can be used for horizon culling of a rectangle. If the point is below\r\n * the horizon, the ellipsoid-conforming rectangle is guaranteed to be below the horizon as well.\r\n * The returned point is expressed in the ellipsoid-scaled space and is suitable for use with\r\n * {@link EllipsoidalOccluder#isScaledSpacePointVisible}.\r\n *\r\n * @param {Rectangle} rectangle The rectangle for which to compute the horizon culling point.\r\n * @param {Ellipsoid} ellipsoid The ellipsoid on which the rectangle is defined. This may be different from\r\n * the ellipsoid used by this instance for occlusion testing.\r\n * @param {Cartesian3} [result] The instance on which to store the result instead of allocating a new instance.\r\n * @returns {Cartesian3} The computed horizon culling point, expressed in the ellipsoid-scaled space.\r\n */\r\nEllipsoidalOccluder.prototype.computeHorizonCullingPointFromRectangle = function (\r\n rectangle,\r\n ellipsoid,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n var positions = Rectangle.subsample(\r\n rectangle,\r\n ellipsoid,\r\n 0.0,\r\n subsampleScratch\r\n );\r\n var bs = BoundingSphere.fromPoints(positions);\r\n\r\n // If the bounding sphere center is too close to the center of the occluder, it doesn't make\r\n // sense to try to horizon cull it.\r\n if (Cartesian3.magnitude(bs.center) < 0.1 * ellipsoid.minimumRadius) {\r\n return undefined;\r\n }\r\n\r\n return this.computeHorizonCullingPoint(bs.center, positions, result);\r\n};\r\n\r\nvar scratchEllipsoidShrunkRadii = new Cartesian3();\r\n\r\nfunction getPossiblyShrunkEllipsoid(ellipsoid, minimumHeight, result) {\r\n if (\r\n defined(minimumHeight) &&\r\n minimumHeight < 0.0 &&\r\n ellipsoid.minimumRadius > -minimumHeight\r\n ) {\r\n var ellipsoidShrunkRadii = Cartesian3.fromElements(\r\n ellipsoid.radii.x + minimumHeight,\r\n ellipsoid.radii.y + minimumHeight,\r\n ellipsoid.radii.z + minimumHeight,\r\n scratchEllipsoidShrunkRadii\r\n );\r\n ellipsoid = Ellipsoid.fromCartesian3(ellipsoidShrunkRadii, result);\r\n }\r\n return ellipsoid;\r\n}\r\n\r\nfunction computeHorizonCullingPointFromPositions(\r\n ellipsoid,\r\n directionToPoint,\r\n positions,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"directionToPoint\", directionToPoint);\r\n Check.defined(\"positions\", positions);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n var scaledSpaceDirectionToPoint = computeScaledSpaceDirectionToPoint(\r\n ellipsoid,\r\n directionToPoint\r\n );\r\n var resultMagnitude = 0.0;\r\n\r\n for (var i = 0, len = positions.length; i < len; ++i) {\r\n var position = positions[i];\r\n var candidateMagnitude = computeMagnitude(\r\n ellipsoid,\r\n position,\r\n scaledSpaceDirectionToPoint\r\n );\r\n if (candidateMagnitude < 0.0) {\r\n // all points should face the same direction, but this one doesn't, so return undefined\r\n return undefined;\r\n }\r\n resultMagnitude = Math.max(resultMagnitude, candidateMagnitude);\r\n }\r\n\r\n return magnitudeToPoint(scaledSpaceDirectionToPoint, resultMagnitude, result);\r\n}\r\n\r\nvar positionScratch = new Cartesian3();\r\n\r\nfunction computeHorizonCullingPointFromVertices(\r\n ellipsoid,\r\n directionToPoint,\r\n vertices,\r\n stride,\r\n center,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"directionToPoint\", directionToPoint);\r\n Check.defined(\"vertices\", vertices);\r\n Check.typeOf.number(\"stride\", stride);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n stride = defaultValue(stride, 3);\r\n center = defaultValue(center, Cartesian3.ZERO);\r\n var scaledSpaceDirectionToPoint = computeScaledSpaceDirectionToPoint(\r\n ellipsoid,\r\n directionToPoint\r\n );\r\n var resultMagnitude = 0.0;\r\n\r\n for (var i = 0, len = vertices.length; i < len; i += stride) {\r\n positionScratch.x = vertices[i] + center.x;\r\n positionScratch.y = vertices[i + 1] + center.y;\r\n positionScratch.z = vertices[i + 2] + center.z;\r\n\r\n var candidateMagnitude = computeMagnitude(\r\n ellipsoid,\r\n positionScratch,\r\n scaledSpaceDirectionToPoint\r\n );\r\n if (candidateMagnitude < 0.0) {\r\n // all points should face the same direction, but this one doesn't, so return undefined\r\n return undefined;\r\n }\r\n resultMagnitude = Math.max(resultMagnitude, candidateMagnitude);\r\n }\r\n\r\n return magnitudeToPoint(scaledSpaceDirectionToPoint, resultMagnitude, result);\r\n}\r\n\r\nfunction isScaledSpacePointVisible(\r\n occludeeScaledSpacePosition,\r\n cameraPositionInScaledSpace,\r\n distanceToLimbInScaledSpaceSquared\r\n) {\r\n // See https://cesium.com/blog/2013/04/25/Horizon-culling/\r\n var cv = cameraPositionInScaledSpace;\r\n var vhMagnitudeSquared = distanceToLimbInScaledSpaceSquared;\r\n var vt = Cartesian3.subtract(\r\n occludeeScaledSpacePosition,\r\n cv,\r\n scratchCartesian\r\n );\r\n var vtDotVc = -Cartesian3.dot(vt, cv);\r\n // If vhMagnitudeSquared < 0 then we are below the surface of the ellipsoid and\r\n // in this case, set the culling plane to be on V.\r\n var isOccluded =\r\n vhMagnitudeSquared < 0\r\n ? vtDotVc > 0\r\n : vtDotVc > vhMagnitudeSquared &&\r\n (vtDotVc * vtDotVc) / Cartesian3.magnitudeSquared(vt) >\r\n vhMagnitudeSquared;\r\n return !isOccluded;\r\n}\r\n\r\nvar scaledSpaceScratch = new Cartesian3();\r\nvar directionScratch = new Cartesian3();\r\n\r\nfunction computeMagnitude(ellipsoid, position, scaledSpaceDirectionToPoint) {\r\n var scaledSpacePosition = ellipsoid.transformPositionToScaledSpace(\r\n position,\r\n scaledSpaceScratch\r\n );\r\n var magnitudeSquared = Cartesian3.magnitudeSquared(scaledSpacePosition);\r\n var magnitude = Math.sqrt(magnitudeSquared);\r\n var direction = Cartesian3.divideByScalar(\r\n scaledSpacePosition,\r\n magnitude,\r\n directionScratch\r\n );\r\n\r\n // For the purpose of this computation, points below the ellipsoid are consider to be on it instead.\r\n magnitudeSquared = Math.max(1.0, magnitudeSquared);\r\n magnitude = Math.max(1.0, magnitude);\r\n\r\n var cosAlpha = Cartesian3.dot(direction, scaledSpaceDirectionToPoint);\r\n var sinAlpha = Cartesian3.magnitude(\r\n Cartesian3.cross(direction, scaledSpaceDirectionToPoint, direction)\r\n );\r\n var cosBeta = 1.0 / magnitude;\r\n var sinBeta = Math.sqrt(magnitudeSquared - 1.0) * cosBeta;\r\n\r\n return 1.0 / (cosAlpha * cosBeta - sinAlpha * sinBeta);\r\n}\r\n\r\nfunction magnitudeToPoint(\r\n scaledSpaceDirectionToPoint,\r\n resultMagnitude,\r\n result\r\n) {\r\n // The horizon culling point is undefined if there were no positions from which to compute it,\r\n // the directionToPoint is pointing opposite all of the positions, or if we computed NaN or infinity.\r\n if (\r\n resultMagnitude <= 0.0 ||\r\n resultMagnitude === 1.0 / 0.0 ||\r\n resultMagnitude !== resultMagnitude\r\n ) {\r\n return undefined;\r\n }\r\n\r\n return Cartesian3.multiplyByScalar(\r\n scaledSpaceDirectionToPoint,\r\n resultMagnitude,\r\n result\r\n );\r\n}\r\n\r\nvar directionToPointScratch = new Cartesian3();\r\n\r\nfunction computeScaledSpaceDirectionToPoint(ellipsoid, directionToPoint) {\r\n if (Cartesian3.equals(directionToPoint, Cartesian3.ZERO)) {\r\n return directionToPoint;\r\n }\r\n\r\n ellipsoid.transformPositionToScaledSpace(\r\n directionToPoint,\r\n directionToPointScratch\r\n );\r\n return Cartesian3.normalize(directionToPointScratch, directionToPointScratch);\r\n}\r\nexport default EllipsoidalOccluder;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * Defines functions for 2nd order polynomial functions of one variable with only real coefficients.\r\n *\r\n * @namespace QuadraticRealPolynomial\r\n */\r\nvar QuadraticRealPolynomial = {};\r\n\r\n/**\r\n * Provides the discriminant of the quadratic equation from the supplied coefficients.\r\n *\r\n * @param {Number} a The coefficient of the 2nd order monomial.\r\n * @param {Number} b The coefficient of the 1st order monomial.\r\n * @param {Number} c The coefficient of the 0th order monomial.\r\n * @returns {Number} The value of the discriminant.\r\n */\r\nQuadraticRealPolynomial.computeDiscriminant = function (a, b, c) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof a !== \"number\") {\r\n throw new DeveloperError(\"a is a required number.\");\r\n }\r\n if (typeof b !== \"number\") {\r\n throw new DeveloperError(\"b is a required number.\");\r\n }\r\n if (typeof c !== \"number\") {\r\n throw new DeveloperError(\"c is a required number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var discriminant = b * b - 4.0 * a * c;\r\n return discriminant;\r\n};\r\n\r\nfunction addWithCancellationCheck(left, right, tolerance) {\r\n var difference = left + right;\r\n if (\r\n CesiumMath.sign(left) !== CesiumMath.sign(right) &&\r\n Math.abs(difference / Math.max(Math.abs(left), Math.abs(right))) < tolerance\r\n ) {\r\n return 0.0;\r\n }\r\n\r\n return difference;\r\n}\r\n\r\n/**\r\n * Provides the real valued roots of the quadratic polynomial with the provided coefficients.\r\n *\r\n * @param {Number} a The coefficient of the 2nd order monomial.\r\n * @param {Number} b The coefficient of the 1st order monomial.\r\n * @param {Number} c The coefficient of the 0th order monomial.\r\n * @returns {Number[]} The real valued roots.\r\n */\r\nQuadraticRealPolynomial.computeRealRoots = function (a, b, c) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof a !== \"number\") {\r\n throw new DeveloperError(\"a is a required number.\");\r\n }\r\n if (typeof b !== \"number\") {\r\n throw new DeveloperError(\"b is a required number.\");\r\n }\r\n if (typeof c !== \"number\") {\r\n throw new DeveloperError(\"c is a required number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var ratio;\r\n if (a === 0.0) {\r\n if (b === 0.0) {\r\n // Constant function: c = 0.\r\n return [];\r\n }\r\n\r\n // Linear function: b * x + c = 0.\r\n return [-c / b];\r\n } else if (b === 0.0) {\r\n if (c === 0.0) {\r\n // 2nd order monomial: a * x^2 = 0.\r\n return [0.0, 0.0];\r\n }\r\n\r\n var cMagnitude = Math.abs(c);\r\n var aMagnitude = Math.abs(a);\r\n\r\n if (\r\n cMagnitude < aMagnitude &&\r\n cMagnitude / aMagnitude < CesiumMath.EPSILON14\r\n ) {\r\n // c ~= 0.0.\r\n // 2nd order monomial: a * x^2 = 0.\r\n return [0.0, 0.0];\r\n } else if (\r\n cMagnitude > aMagnitude &&\r\n aMagnitude / cMagnitude < CesiumMath.EPSILON14\r\n ) {\r\n // a ~= 0.0.\r\n // Constant function: c = 0.\r\n return [];\r\n }\r\n\r\n // a * x^2 + c = 0\r\n ratio = -c / a;\r\n\r\n if (ratio < 0.0) {\r\n // Both roots are complex.\r\n return [];\r\n }\r\n\r\n // Both roots are real.\r\n var root = Math.sqrt(ratio);\r\n return [-root, root];\r\n } else if (c === 0.0) {\r\n // a * x^2 + b * x = 0\r\n ratio = -b / a;\r\n if (ratio < 0.0) {\r\n return [ratio, 0.0];\r\n }\r\n\r\n return [0.0, ratio];\r\n }\r\n\r\n // a * x^2 + b * x + c = 0\r\n var b2 = b * b;\r\n var four_ac = 4.0 * a * c;\r\n var radicand = addWithCancellationCheck(b2, -four_ac, CesiumMath.EPSILON14);\r\n\r\n if (radicand < 0.0) {\r\n // Both roots are complex.\r\n return [];\r\n }\r\n\r\n var q =\r\n -0.5 *\r\n addWithCancellationCheck(\r\n b,\r\n CesiumMath.sign(b) * Math.sqrt(radicand),\r\n CesiumMath.EPSILON14\r\n );\r\n if (b > 0.0) {\r\n return [q / a, c / q];\r\n }\r\n\r\n return [c / q, q / a];\r\n};\r\nexport default QuadraticRealPolynomial;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\nimport QuadraticRealPolynomial from \"./QuadraticRealPolynomial.js\";\r\n\r\n/**\r\n * Defines functions for 3rd order polynomial functions of one variable with only real coefficients.\r\n *\r\n * @namespace CubicRealPolynomial\r\n */\r\nvar CubicRealPolynomial = {};\r\n\r\n/**\r\n * Provides the discriminant of the cubic equation from the supplied coefficients.\r\n *\r\n * @param {Number} a The coefficient of the 3rd order monomial.\r\n * @param {Number} b The coefficient of the 2nd order monomial.\r\n * @param {Number} c The coefficient of the 1st order monomial.\r\n * @param {Number} d The coefficient of the 0th order monomial.\r\n * @returns {Number} The value of the discriminant.\r\n */\r\nCubicRealPolynomial.computeDiscriminant = function (a, b, c, d) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof a !== \"number\") {\r\n throw new DeveloperError(\"a is a required number.\");\r\n }\r\n if (typeof b !== \"number\") {\r\n throw new DeveloperError(\"b is a required number.\");\r\n }\r\n if (typeof c !== \"number\") {\r\n throw new DeveloperError(\"c is a required number.\");\r\n }\r\n if (typeof d !== \"number\") {\r\n throw new DeveloperError(\"d is a required number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var a2 = a * a;\r\n var b2 = b * b;\r\n var c2 = c * c;\r\n var d2 = d * d;\r\n\r\n var discriminant =\r\n 18.0 * a * b * c * d +\r\n b2 * c2 -\r\n 27.0 * a2 * d2 -\r\n 4.0 * (a * c2 * c + b2 * b * d);\r\n return discriminant;\r\n};\r\n\r\nfunction computeRealRoots(a, b, c, d) {\r\n var A = a;\r\n var B = b / 3.0;\r\n var C = c / 3.0;\r\n var D = d;\r\n\r\n var AC = A * C;\r\n var BD = B * D;\r\n var B2 = B * B;\r\n var C2 = C * C;\r\n var delta1 = A * C - B2;\r\n var delta2 = A * D - B * C;\r\n var delta3 = B * D - C2;\r\n\r\n var discriminant = 4.0 * delta1 * delta3 - delta2 * delta2;\r\n var temp;\r\n var temp1;\r\n\r\n if (discriminant < 0.0) {\r\n var ABar;\r\n var CBar;\r\n var DBar;\r\n\r\n if (B2 * BD >= AC * C2) {\r\n ABar = A;\r\n CBar = delta1;\r\n DBar = -2.0 * B * delta1 + A * delta2;\r\n } else {\r\n ABar = D;\r\n CBar = delta3;\r\n DBar = -D * delta2 + 2.0 * C * delta3;\r\n }\r\n\r\n var s = DBar < 0.0 ? -1.0 : 1.0; // This is not Math.Sign()!\r\n var temp0 = -s * Math.abs(ABar) * Math.sqrt(-discriminant);\r\n temp1 = -DBar + temp0;\r\n\r\n var x = temp1 / 2.0;\r\n var p = x < 0.0 ? -Math.pow(-x, 1.0 / 3.0) : Math.pow(x, 1.0 / 3.0);\r\n var q = temp1 === temp0 ? -p : -CBar / p;\r\n\r\n temp = CBar <= 0.0 ? p + q : -DBar / (p * p + q * q + CBar);\r\n\r\n if (B2 * BD >= AC * C2) {\r\n return [(temp - B) / A];\r\n }\r\n\r\n return [-D / (temp + C)];\r\n }\r\n\r\n var CBarA = delta1;\r\n var DBarA = -2.0 * B * delta1 + A * delta2;\r\n\r\n var CBarD = delta3;\r\n var DBarD = -D * delta2 + 2.0 * C * delta3;\r\n\r\n var squareRootOfDiscriminant = Math.sqrt(discriminant);\r\n var halfSquareRootOf3 = Math.sqrt(3.0) / 2.0;\r\n\r\n var theta = Math.abs(Math.atan2(A * squareRootOfDiscriminant, -DBarA) / 3.0);\r\n temp = 2.0 * Math.sqrt(-CBarA);\r\n var cosine = Math.cos(theta);\r\n temp1 = temp * cosine;\r\n var temp3 = temp * (-cosine / 2.0 - halfSquareRootOf3 * Math.sin(theta));\r\n\r\n var numeratorLarge = temp1 + temp3 > 2.0 * B ? temp1 - B : temp3 - B;\r\n var denominatorLarge = A;\r\n\r\n var root1 = numeratorLarge / denominatorLarge;\r\n\r\n theta = Math.abs(Math.atan2(D * squareRootOfDiscriminant, -DBarD) / 3.0);\r\n temp = 2.0 * Math.sqrt(-CBarD);\r\n cosine = Math.cos(theta);\r\n temp1 = temp * cosine;\r\n temp3 = temp * (-cosine / 2.0 - halfSquareRootOf3 * Math.sin(theta));\r\n\r\n var numeratorSmall = -D;\r\n var denominatorSmall = temp1 + temp3 < 2.0 * C ? temp1 + C : temp3 + C;\r\n\r\n var root3 = numeratorSmall / denominatorSmall;\r\n\r\n var E = denominatorLarge * denominatorSmall;\r\n var F =\r\n -numeratorLarge * denominatorSmall - denominatorLarge * numeratorSmall;\r\n var G = numeratorLarge * numeratorSmall;\r\n\r\n var root2 = (C * F - B * G) / (-B * F + C * E);\r\n\r\n if (root1 <= root2) {\r\n if (root1 <= root3) {\r\n if (root2 <= root3) {\r\n return [root1, root2, root3];\r\n }\r\n return [root1, root3, root2];\r\n }\r\n return [root3, root1, root2];\r\n }\r\n if (root1 <= root3) {\r\n return [root2, root1, root3];\r\n }\r\n if (root2 <= root3) {\r\n return [root2, root3, root1];\r\n }\r\n return [root3, root2, root1];\r\n}\r\n\r\n/**\r\n * Provides the real valued roots of the cubic polynomial with the provided coefficients.\r\n *\r\n * @param {Number} a The coefficient of the 3rd order monomial.\r\n * @param {Number} b The coefficient of the 2nd order monomial.\r\n * @param {Number} c The coefficient of the 1st order monomial.\r\n * @param {Number} d The coefficient of the 0th order monomial.\r\n * @returns {Number[]} The real valued roots.\r\n */\r\nCubicRealPolynomial.computeRealRoots = function (a, b, c, d) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof a !== \"number\") {\r\n throw new DeveloperError(\"a is a required number.\");\r\n }\r\n if (typeof b !== \"number\") {\r\n throw new DeveloperError(\"b is a required number.\");\r\n }\r\n if (typeof c !== \"number\") {\r\n throw new DeveloperError(\"c is a required number.\");\r\n }\r\n if (typeof d !== \"number\") {\r\n throw new DeveloperError(\"d is a required number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var roots;\r\n var ratio;\r\n if (a === 0.0) {\r\n // Quadratic function: b * x^2 + c * x + d = 0.\r\n return QuadraticRealPolynomial.computeRealRoots(b, c, d);\r\n } else if (b === 0.0) {\r\n if (c === 0.0) {\r\n if (d === 0.0) {\r\n // 3rd order monomial: a * x^3 = 0.\r\n return [0.0, 0.0, 0.0];\r\n }\r\n\r\n // a * x^3 + d = 0\r\n ratio = -d / a;\r\n var root =\r\n ratio < 0.0 ? -Math.pow(-ratio, 1.0 / 3.0) : Math.pow(ratio, 1.0 / 3.0);\r\n return [root, root, root];\r\n } else if (d === 0.0) {\r\n // x * (a * x^2 + c) = 0.\r\n roots = QuadraticRealPolynomial.computeRealRoots(a, 0, c);\r\n\r\n // Return the roots in ascending order.\r\n if (roots.Length === 0) {\r\n return [0.0];\r\n }\r\n return [roots[0], 0.0, roots[1]];\r\n }\r\n\r\n // Deflated cubic polynomial: a * x^3 + c * x + d= 0.\r\n return computeRealRoots(a, 0, c, d);\r\n } else if (c === 0.0) {\r\n if (d === 0.0) {\r\n // x^2 * (a * x + b) = 0.\r\n ratio = -b / a;\r\n if (ratio < 0.0) {\r\n return [ratio, 0.0, 0.0];\r\n }\r\n return [0.0, 0.0, ratio];\r\n }\r\n // a * x^3 + b * x^2 + d = 0.\r\n return computeRealRoots(a, b, 0, d);\r\n } else if (d === 0.0) {\r\n // x * (a * x^2 + b * x + c) = 0\r\n roots = QuadraticRealPolynomial.computeRealRoots(a, b, c);\r\n\r\n // Return the roots in ascending order.\r\n if (roots.length === 0) {\r\n return [0.0];\r\n } else if (roots[1] <= 0.0) {\r\n return [roots[0], roots[1], 0.0];\r\n } else if (roots[0] >= 0.0) {\r\n return [0.0, roots[0], roots[1]];\r\n }\r\n return [roots[0], 0.0, roots[1]];\r\n }\r\n\r\n return computeRealRoots(a, b, c, d);\r\n};\r\nexport default CubicRealPolynomial;\r\n","import CubicRealPolynomial from \"./CubicRealPolynomial.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport QuadraticRealPolynomial from \"./QuadraticRealPolynomial.js\";\r\n\r\n/**\r\n * Defines functions for 4th order polynomial functions of one variable with only real coefficients.\r\n *\r\n * @namespace QuarticRealPolynomial\r\n */\r\nvar QuarticRealPolynomial = {};\r\n\r\n/**\r\n * Provides the discriminant of the quartic equation from the supplied coefficients.\r\n *\r\n * @param {Number} a The coefficient of the 4th order monomial.\r\n * @param {Number} b The coefficient of the 3rd order monomial.\r\n * @param {Number} c The coefficient of the 2nd order monomial.\r\n * @param {Number} d The coefficient of the 1st order monomial.\r\n * @param {Number} e The coefficient of the 0th order monomial.\r\n * @returns {Number} The value of the discriminant.\r\n */\r\nQuarticRealPolynomial.computeDiscriminant = function (a, b, c, d, e) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof a !== \"number\") {\r\n throw new DeveloperError(\"a is a required number.\");\r\n }\r\n if (typeof b !== \"number\") {\r\n throw new DeveloperError(\"b is a required number.\");\r\n }\r\n if (typeof c !== \"number\") {\r\n throw new DeveloperError(\"c is a required number.\");\r\n }\r\n if (typeof d !== \"number\") {\r\n throw new DeveloperError(\"d is a required number.\");\r\n }\r\n if (typeof e !== \"number\") {\r\n throw new DeveloperError(\"e is a required number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var a2 = a * a;\r\n var a3 = a2 * a;\r\n var b2 = b * b;\r\n var b3 = b2 * b;\r\n var c2 = c * c;\r\n var c3 = c2 * c;\r\n var d2 = d * d;\r\n var d3 = d2 * d;\r\n var e2 = e * e;\r\n var e3 = e2 * e;\r\n\r\n var discriminant =\r\n b2 * c2 * d2 -\r\n 4.0 * b3 * d3 -\r\n 4.0 * a * c3 * d2 +\r\n 18 * a * b * c * d3 -\r\n 27.0 * a2 * d2 * d2 +\r\n 256.0 * a3 * e3 +\r\n e *\r\n (18.0 * b3 * c * d -\r\n 4.0 * b2 * c3 +\r\n 16.0 * a * c2 * c2 -\r\n 80.0 * a * b * c2 * d -\r\n 6.0 * a * b2 * d2 +\r\n 144.0 * a2 * c * d2) +\r\n e2 *\r\n (144.0 * a * b2 * c -\r\n 27.0 * b2 * b2 -\r\n 128.0 * a2 * c2 -\r\n 192.0 * a2 * b * d);\r\n return discriminant;\r\n};\r\n\r\nfunction original(a3, a2, a1, a0) {\r\n var a3Squared = a3 * a3;\r\n\r\n var p = a2 - (3.0 * a3Squared) / 8.0;\r\n var q = a1 - (a2 * a3) / 2.0 + (a3Squared * a3) / 8.0;\r\n var r =\r\n a0 -\r\n (a1 * a3) / 4.0 +\r\n (a2 * a3Squared) / 16.0 -\r\n (3.0 * a3Squared * a3Squared) / 256.0;\r\n\r\n // Find the roots of the cubic equations: h^6 + 2 p h^4 + (p^2 - 4 r) h^2 - q^2 = 0.\r\n var cubicRoots = CubicRealPolynomial.computeRealRoots(\r\n 1.0,\r\n 2.0 * p,\r\n p * p - 4.0 * r,\r\n -q * q\r\n );\r\n\r\n if (cubicRoots.length > 0) {\r\n var temp = -a3 / 4.0;\r\n\r\n // Use the largest positive root.\r\n var hSquared = cubicRoots[cubicRoots.length - 1];\r\n\r\n if (Math.abs(hSquared) < CesiumMath.EPSILON14) {\r\n // y^4 + p y^2 + r = 0.\r\n var roots = QuadraticRealPolynomial.computeRealRoots(1.0, p, r);\r\n\r\n if (roots.length === 2) {\r\n var root0 = roots[0];\r\n var root1 = roots[1];\r\n\r\n var y;\r\n if (root0 >= 0.0 && root1 >= 0.0) {\r\n var y0 = Math.sqrt(root0);\r\n var y1 = Math.sqrt(root1);\r\n\r\n return [temp - y1, temp - y0, temp + y0, temp + y1];\r\n } else if (root0 >= 0.0 && root1 < 0.0) {\r\n y = Math.sqrt(root0);\r\n return [temp - y, temp + y];\r\n } else if (root0 < 0.0 && root1 >= 0.0) {\r\n y = Math.sqrt(root1);\r\n return [temp - y, temp + y];\r\n }\r\n }\r\n return [];\r\n } else if (hSquared > 0.0) {\r\n var h = Math.sqrt(hSquared);\r\n\r\n var m = (p + hSquared - q / h) / 2.0;\r\n var n = (p + hSquared + q / h) / 2.0;\r\n\r\n // Now solve the two quadratic factors: (y^2 + h y + m)(y^2 - h y + n);\r\n var roots1 = QuadraticRealPolynomial.computeRealRoots(1.0, h, m);\r\n var roots2 = QuadraticRealPolynomial.computeRealRoots(1.0, -h, n);\r\n\r\n if (roots1.length !== 0) {\r\n roots1[0] += temp;\r\n roots1[1] += temp;\r\n\r\n if (roots2.length !== 0) {\r\n roots2[0] += temp;\r\n roots2[1] += temp;\r\n\r\n if (roots1[1] <= roots2[0]) {\r\n return [roots1[0], roots1[1], roots2[0], roots2[1]];\r\n } else if (roots2[1] <= roots1[0]) {\r\n return [roots2[0], roots2[1], roots1[0], roots1[1]];\r\n } else if (roots1[0] >= roots2[0] && roots1[1] <= roots2[1]) {\r\n return [roots2[0], roots1[0], roots1[1], roots2[1]];\r\n } else if (roots2[0] >= roots1[0] && roots2[1] <= roots1[1]) {\r\n return [roots1[0], roots2[0], roots2[1], roots1[1]];\r\n } else if (roots1[0] > roots2[0] && roots1[0] < roots2[1]) {\r\n return [roots2[0], roots1[0], roots2[1], roots1[1]];\r\n }\r\n return [roots1[0], roots2[0], roots1[1], roots2[1]];\r\n }\r\n return roots1;\r\n }\r\n\r\n if (roots2.length !== 0) {\r\n roots2[0] += temp;\r\n roots2[1] += temp;\r\n\r\n return roots2;\r\n }\r\n return [];\r\n }\r\n }\r\n return [];\r\n}\r\n\r\nfunction neumark(a3, a2, a1, a0) {\r\n var a1Squared = a1 * a1;\r\n var a2Squared = a2 * a2;\r\n var a3Squared = a3 * a3;\r\n\r\n var p = -2.0 * a2;\r\n var q = a1 * a3 + a2Squared - 4.0 * a0;\r\n var r = a3Squared * a0 - a1 * a2 * a3 + a1Squared;\r\n\r\n var cubicRoots = CubicRealPolynomial.computeRealRoots(1.0, p, q, r);\r\n\r\n if (cubicRoots.length > 0) {\r\n // Use the most positive root\r\n var y = cubicRoots[0];\r\n\r\n var temp = a2 - y;\r\n var tempSquared = temp * temp;\r\n\r\n var g1 = a3 / 2.0;\r\n var h1 = temp / 2.0;\r\n\r\n var m = tempSquared - 4.0 * a0;\r\n var mError = tempSquared + 4.0 * Math.abs(a0);\r\n\r\n var n = a3Squared - 4.0 * y;\r\n var nError = a3Squared + 4.0 * Math.abs(y);\r\n\r\n var g2;\r\n var h2;\r\n\r\n if (y < 0.0 || m * nError < n * mError) {\r\n var squareRootOfN = Math.sqrt(n);\r\n g2 = squareRootOfN / 2.0;\r\n h2 = squareRootOfN === 0.0 ? 0.0 : (a3 * h1 - a1) / squareRootOfN;\r\n } else {\r\n var squareRootOfM = Math.sqrt(m);\r\n g2 = squareRootOfM === 0.0 ? 0.0 : (a3 * h1 - a1) / squareRootOfM;\r\n h2 = squareRootOfM / 2.0;\r\n }\r\n\r\n var G;\r\n var g;\r\n if (g1 === 0.0 && g2 === 0.0) {\r\n G = 0.0;\r\n g = 0.0;\r\n } else if (CesiumMath.sign(g1) === CesiumMath.sign(g2)) {\r\n G = g1 + g2;\r\n g = y / G;\r\n } else {\r\n g = g1 - g2;\r\n G = y / g;\r\n }\r\n\r\n var H;\r\n var h;\r\n if (h1 === 0.0 && h2 === 0.0) {\r\n H = 0.0;\r\n h = 0.0;\r\n } else if (CesiumMath.sign(h1) === CesiumMath.sign(h2)) {\r\n H = h1 + h2;\r\n h = a0 / H;\r\n } else {\r\n h = h1 - h2;\r\n H = a0 / h;\r\n }\r\n\r\n // Now solve the two quadratic factors: (y^2 + G y + H)(y^2 + g y + h);\r\n var roots1 = QuadraticRealPolynomial.computeRealRoots(1.0, G, H);\r\n var roots2 = QuadraticRealPolynomial.computeRealRoots(1.0, g, h);\r\n\r\n if (roots1.length !== 0) {\r\n if (roots2.length !== 0) {\r\n if (roots1[1] <= roots2[0]) {\r\n return [roots1[0], roots1[1], roots2[0], roots2[1]];\r\n } else if (roots2[1] <= roots1[0]) {\r\n return [roots2[0], roots2[1], roots1[0], roots1[1]];\r\n } else if (roots1[0] >= roots2[0] && roots1[1] <= roots2[1]) {\r\n return [roots2[0], roots1[0], roots1[1], roots2[1]];\r\n } else if (roots2[0] >= roots1[0] && roots2[1] <= roots1[1]) {\r\n return [roots1[0], roots2[0], roots2[1], roots1[1]];\r\n } else if (roots1[0] > roots2[0] && roots1[0] < roots2[1]) {\r\n return [roots2[0], roots1[0], roots2[1], roots1[1]];\r\n }\r\n return [roots1[0], roots2[0], roots1[1], roots2[1]];\r\n }\r\n return roots1;\r\n }\r\n if (roots2.length !== 0) {\r\n return roots2;\r\n }\r\n }\r\n return [];\r\n}\r\n\r\n/**\r\n * Provides the real valued roots of the quartic polynomial with the provided coefficients.\r\n *\r\n * @param {Number} a The coefficient of the 4th order monomial.\r\n * @param {Number} b The coefficient of the 3rd order monomial.\r\n * @param {Number} c The coefficient of the 2nd order monomial.\r\n * @param {Number} d The coefficient of the 1st order monomial.\r\n * @param {Number} e The coefficient of the 0th order monomial.\r\n * @returns {Number[]} The real valued roots.\r\n */\r\nQuarticRealPolynomial.computeRealRoots = function (a, b, c, d, e) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof a !== \"number\") {\r\n throw new DeveloperError(\"a is a required number.\");\r\n }\r\n if (typeof b !== \"number\") {\r\n throw new DeveloperError(\"b is a required number.\");\r\n }\r\n if (typeof c !== \"number\") {\r\n throw new DeveloperError(\"c is a required number.\");\r\n }\r\n if (typeof d !== \"number\") {\r\n throw new DeveloperError(\"d is a required number.\");\r\n }\r\n if (typeof e !== \"number\") {\r\n throw new DeveloperError(\"e is a required number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (Math.abs(a) < CesiumMath.EPSILON15) {\r\n return CubicRealPolynomial.computeRealRoots(b, c, d, e);\r\n }\r\n var a3 = b / a;\r\n var a2 = c / a;\r\n var a1 = d / a;\r\n var a0 = e / a;\r\n\r\n var k = a3 < 0.0 ? 1 : 0;\r\n k += a2 < 0.0 ? k + 1 : k;\r\n k += a1 < 0.0 ? k + 1 : k;\r\n k += a0 < 0.0 ? k + 1 : k;\r\n\r\n switch (k) {\r\n case 0:\r\n return original(a3, a2, a1, a0);\r\n case 1:\r\n return neumark(a3, a2, a1, a0);\r\n case 2:\r\n return neumark(a3, a2, a1, a0);\r\n case 3:\r\n return original(a3, a2, a1, a0);\r\n case 4:\r\n return original(a3, a2, a1, a0);\r\n case 5:\r\n return neumark(a3, a2, a1, a0);\r\n case 6:\r\n return original(a3, a2, a1, a0);\r\n case 7:\r\n return original(a3, a2, a1, a0);\r\n case 8:\r\n return neumark(a3, a2, a1, a0);\r\n case 9:\r\n return original(a3, a2, a1, a0);\r\n case 10:\r\n return original(a3, a2, a1, a0);\r\n case 11:\r\n return neumark(a3, a2, a1, a0);\r\n case 12:\r\n return original(a3, a2, a1, a0);\r\n case 13:\r\n return original(a3, a2, a1, a0);\r\n case 14:\r\n return original(a3, a2, a1, a0);\r\n case 15:\r\n return original(a3, a2, a1, a0);\r\n default:\r\n return undefined;\r\n }\r\n};\r\nexport default QuarticRealPolynomial;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * Represents a ray that extends infinitely from the provided origin in the provided direction.\r\n * @alias Ray\r\n * @constructor\r\n *\r\n * @param {Cartesian3} [origin=Cartesian3.ZERO] The origin of the ray.\r\n * @param {Cartesian3} [direction=Cartesian3.ZERO] The direction of the ray.\r\n */\r\nfunction Ray(origin, direction) {\r\n direction = Cartesian3.clone(defaultValue(direction, Cartesian3.ZERO));\r\n if (!Cartesian3.equals(direction, Cartesian3.ZERO)) {\r\n Cartesian3.normalize(direction, direction);\r\n }\r\n\r\n /**\r\n * The origin of the ray.\r\n * @type {Cartesian3}\r\n * @default {@link Cartesian3.ZERO}\r\n */\r\n this.origin = Cartesian3.clone(defaultValue(origin, Cartesian3.ZERO));\r\n\r\n /**\r\n * The direction of the ray.\r\n * @type {Cartesian3}\r\n */\r\n this.direction = direction;\r\n}\r\n\r\n/**\r\n * Duplicates a Ray instance.\r\n *\r\n * @param {Ray} ray The ray to duplicate.\r\n * @param {Ray} [result] The object onto which to store the result.\r\n * @returns {Ray} The modified result parameter or a new Ray instance if one was not provided. (Returns undefined if ray is undefined)\r\n */\r\nRay.clone = function (ray, result) {\r\n if (!defined(ray)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new Ray(ray.origin, ray.direction);\r\n }\r\n result.origin = Cartesian3.clone(ray.origin);\r\n result.direction = Cartesian3.clone(ray.direction);\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the point along the ray given by r(t) = o + t*d,\r\n * where o is the origin of the ray and d is the direction.\r\n *\r\n * @param {Ray} ray The ray.\r\n * @param {Number} t A scalar value.\r\n * @param {Cartesian3} [result] The object in which the result will be stored.\r\n * @returns {Cartesian3} The modified result parameter, or a new instance if none was provided.\r\n *\r\n * @example\r\n * //Get the first intersection point of a ray and an ellipsoid.\r\n * var intersection = Cesium.IntersectionTests.rayEllipsoid(ray, ellipsoid);\r\n * var point = Cesium.Ray.getPoint(ray, intersection.start);\r\n */\r\nRay.getPoint = function (ray, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"ray\", ray);\r\n Check.typeOf.number(\"t\", t);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n result = Cartesian3.multiplyByScalar(ray.direction, t, result);\r\n return Cartesian3.add(ray.origin, result, result);\r\n};\r\nexport default Ray;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Interval from \"./Interval.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport QuadraticRealPolynomial from \"./QuadraticRealPolynomial.js\";\r\nimport QuarticRealPolynomial from \"./QuarticRealPolynomial.js\";\r\nimport Ray from \"./Ray.js\";\r\n\r\n/**\r\n * Functions for computing the intersection between geometries such as rays, planes, triangles, and ellipsoids.\r\n *\r\n * @namespace IntersectionTests\r\n */\r\nvar IntersectionTests = {};\r\n\r\n/**\r\n * Computes the intersection of a ray and a plane.\r\n *\r\n * @param {Ray} ray The ray.\r\n * @param {Plane} plane The plane.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The intersection point or undefined if there is no intersections.\r\n */\r\nIntersectionTests.rayPlane = function (ray, plane, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(ray)) {\r\n throw new DeveloperError(\"ray is required.\");\r\n }\r\n if (!defined(plane)) {\r\n throw new DeveloperError(\"plane is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n var origin = ray.origin;\r\n var direction = ray.direction;\r\n var normal = plane.normal;\r\n var denominator = Cartesian3.dot(normal, direction);\r\n\r\n if (Math.abs(denominator) < CesiumMath.EPSILON15) {\r\n // Ray is parallel to plane. The ray may be in the polygon's plane.\r\n return undefined;\r\n }\r\n\r\n var t = (-plane.distance - Cartesian3.dot(normal, origin)) / denominator;\r\n\r\n if (t < 0) {\r\n return undefined;\r\n }\r\n\r\n result = Cartesian3.multiplyByScalar(direction, t, result);\r\n return Cartesian3.add(origin, result, result);\r\n};\r\n\r\nvar scratchEdge0 = new Cartesian3();\r\nvar scratchEdge1 = new Cartesian3();\r\nvar scratchPVec = new Cartesian3();\r\nvar scratchTVec = new Cartesian3();\r\nvar scratchQVec = new Cartesian3();\r\n\r\n/**\r\n * Computes the intersection of a ray and a triangle as a parametric distance along the input ray. The result is negative when the triangle is behind the ray.\r\n *\r\n * Implements {@link https://cadxfem.org/inf/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf|\r\n * Fast Minimum Storage Ray/Triangle Intersection} by Tomas Moller and Ben Trumbore.\r\n *\r\n * @memberof IntersectionTests\r\n *\r\n * @param {Ray} ray The ray.\r\n * @param {Cartesian3} p0 The first vertex of the triangle.\r\n * @param {Cartesian3} p1 The second vertex of the triangle.\r\n * @param {Cartesian3} p2 The third vertex of the triangle.\r\n * @param {Boolean} [cullBackFaces=false] If true, will only compute an intersection with the front face of the triangle\r\n * and return undefined for intersections with the back face.\r\n * @returns {Number} The intersection as a parametric distance along the ray, or undefined if there is no intersection.\r\n */\r\nIntersectionTests.rayTriangleParametric = function (\r\n ray,\r\n p0,\r\n p1,\r\n p2,\r\n cullBackFaces\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(ray)) {\r\n throw new DeveloperError(\"ray is required.\");\r\n }\r\n if (!defined(p0)) {\r\n throw new DeveloperError(\"p0 is required.\");\r\n }\r\n if (!defined(p1)) {\r\n throw new DeveloperError(\"p1 is required.\");\r\n }\r\n if (!defined(p2)) {\r\n throw new DeveloperError(\"p2 is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n cullBackFaces = defaultValue(cullBackFaces, false);\r\n\r\n var origin = ray.origin;\r\n var direction = ray.direction;\r\n\r\n var edge0 = Cartesian3.subtract(p1, p0, scratchEdge0);\r\n var edge1 = Cartesian3.subtract(p2, p0, scratchEdge1);\r\n\r\n var p = Cartesian3.cross(direction, edge1, scratchPVec);\r\n var det = Cartesian3.dot(edge0, p);\r\n\r\n var tvec;\r\n var q;\r\n\r\n var u;\r\n var v;\r\n var t;\r\n\r\n if (cullBackFaces) {\r\n if (det < CesiumMath.EPSILON6) {\r\n return undefined;\r\n }\r\n\r\n tvec = Cartesian3.subtract(origin, p0, scratchTVec);\r\n u = Cartesian3.dot(tvec, p);\r\n if (u < 0.0 || u > det) {\r\n return undefined;\r\n }\r\n\r\n q = Cartesian3.cross(tvec, edge0, scratchQVec);\r\n\r\n v = Cartesian3.dot(direction, q);\r\n if (v < 0.0 || u + v > det) {\r\n return undefined;\r\n }\r\n\r\n t = Cartesian3.dot(edge1, q) / det;\r\n } else {\r\n if (Math.abs(det) < CesiumMath.EPSILON6) {\r\n return undefined;\r\n }\r\n var invDet = 1.0 / det;\r\n\r\n tvec = Cartesian3.subtract(origin, p0, scratchTVec);\r\n u = Cartesian3.dot(tvec, p) * invDet;\r\n if (u < 0.0 || u > 1.0) {\r\n return undefined;\r\n }\r\n\r\n q = Cartesian3.cross(tvec, edge0, scratchQVec);\r\n\r\n v = Cartesian3.dot(direction, q) * invDet;\r\n if (v < 0.0 || u + v > 1.0) {\r\n return undefined;\r\n }\r\n\r\n t = Cartesian3.dot(edge1, q) * invDet;\r\n }\r\n\r\n return t;\r\n};\r\n\r\n/**\r\n * Computes the intersection of a ray and a triangle as a Cartesian3 coordinate.\r\n *\r\n * Implements {@link https://cadxfem.org/inf/Fast%20MinimumStorage%20RayTriangle%20Intersection.pdf|\r\n * Fast Minimum Storage Ray/Triangle Intersection} by Tomas Moller and Ben Trumbore.\r\n *\r\n * @memberof IntersectionTests\r\n *\r\n * @param {Ray} ray The ray.\r\n * @param {Cartesian3} p0 The first vertex of the triangle.\r\n * @param {Cartesian3} p1 The second vertex of the triangle.\r\n * @param {Cartesian3} p2 The third vertex of the triangle.\r\n * @param {Boolean} [cullBackFaces=false] If true, will only compute an intersection with the front face of the triangle\r\n * and return undefined for intersections with the back face.\r\n * @param {Cartesian3} [result] The Cartesian3 onto which to store the result.\r\n * @returns {Cartesian3} The intersection point or undefined if there is no intersections.\r\n */\r\nIntersectionTests.rayTriangle = function (\r\n ray,\r\n p0,\r\n p1,\r\n p2,\r\n cullBackFaces,\r\n result\r\n) {\r\n var t = IntersectionTests.rayTriangleParametric(\r\n ray,\r\n p0,\r\n p1,\r\n p2,\r\n cullBackFaces\r\n );\r\n if (!defined(t) || t < 0.0) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n Cartesian3.multiplyByScalar(ray.direction, t, result);\r\n return Cartesian3.add(ray.origin, result, result);\r\n};\r\n\r\nvar scratchLineSegmentTriangleRay = new Ray();\r\n\r\n/**\r\n * Computes the intersection of a line segment and a triangle.\r\n * @memberof IntersectionTests\r\n *\r\n * @param {Cartesian3} v0 The an end point of the line segment.\r\n * @param {Cartesian3} v1 The other end point of the line segment.\r\n * @param {Cartesian3} p0 The first vertex of the triangle.\r\n * @param {Cartesian3} p1 The second vertex of the triangle.\r\n * @param {Cartesian3} p2 The third vertex of the triangle.\r\n * @param {Boolean} [cullBackFaces=false] If true, will only compute an intersection with the front face of the triangle\r\n * and return undefined for intersections with the back face.\r\n * @param {Cartesian3} [result] The Cartesian3 onto which to store the result.\r\n * @returns {Cartesian3} The intersection point or undefined if there is no intersections.\r\n */\r\nIntersectionTests.lineSegmentTriangle = function (\r\n v0,\r\n v1,\r\n p0,\r\n p1,\r\n p2,\r\n cullBackFaces,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(v0)) {\r\n throw new DeveloperError(\"v0 is required.\");\r\n }\r\n if (!defined(v1)) {\r\n throw new DeveloperError(\"v1 is required.\");\r\n }\r\n if (!defined(p0)) {\r\n throw new DeveloperError(\"p0 is required.\");\r\n }\r\n if (!defined(p1)) {\r\n throw new DeveloperError(\"p1 is required.\");\r\n }\r\n if (!defined(p2)) {\r\n throw new DeveloperError(\"p2 is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var ray = scratchLineSegmentTriangleRay;\r\n Cartesian3.clone(v0, ray.origin);\r\n Cartesian3.subtract(v1, v0, ray.direction);\r\n Cartesian3.normalize(ray.direction, ray.direction);\r\n\r\n var t = IntersectionTests.rayTriangleParametric(\r\n ray,\r\n p0,\r\n p1,\r\n p2,\r\n cullBackFaces\r\n );\r\n if (!defined(t) || t < 0.0 || t > Cartesian3.distance(v0, v1)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n Cartesian3.multiplyByScalar(ray.direction, t, result);\r\n return Cartesian3.add(ray.origin, result, result);\r\n};\r\n\r\nfunction solveQuadratic(a, b, c, result) {\r\n var det = b * b - 4.0 * a * c;\r\n if (det < 0.0) {\r\n return undefined;\r\n } else if (det > 0.0) {\r\n var denom = 1.0 / (2.0 * a);\r\n var disc = Math.sqrt(det);\r\n var root0 = (-b + disc) * denom;\r\n var root1 = (-b - disc) * denom;\r\n\r\n if (root0 < root1) {\r\n result.root0 = root0;\r\n result.root1 = root1;\r\n } else {\r\n result.root0 = root1;\r\n result.root1 = root0;\r\n }\r\n\r\n return result;\r\n }\r\n\r\n var root = -b / (2.0 * a);\r\n if (root === 0.0) {\r\n return undefined;\r\n }\r\n\r\n result.root0 = result.root1 = root;\r\n return result;\r\n}\r\n\r\nvar raySphereRoots = {\r\n root0: 0.0,\r\n root1: 0.0,\r\n};\r\n\r\nfunction raySphere(ray, sphere, result) {\r\n if (!defined(result)) {\r\n result = new Interval();\r\n }\r\n\r\n var origin = ray.origin;\r\n var direction = ray.direction;\r\n\r\n var center = sphere.center;\r\n var radiusSquared = sphere.radius * sphere.radius;\r\n\r\n var diff = Cartesian3.subtract(origin, center, scratchPVec);\r\n\r\n var a = Cartesian3.dot(direction, direction);\r\n var b = 2.0 * Cartesian3.dot(direction, diff);\r\n var c = Cartesian3.magnitudeSquared(diff) - radiusSquared;\r\n\r\n var roots = solveQuadratic(a, b, c, raySphereRoots);\r\n if (!defined(roots)) {\r\n return undefined;\r\n }\r\n\r\n result.start = roots.root0;\r\n result.stop = roots.root1;\r\n return result;\r\n}\r\n\r\n/**\r\n * Computes the intersection points of a ray with a sphere.\r\n * @memberof IntersectionTests\r\n *\r\n * @param {Ray} ray The ray.\r\n * @param {BoundingSphere} sphere The sphere.\r\n * @param {Interval} [result] The result onto which to store the result.\r\n * @returns {Interval} The interval containing scalar points along the ray or undefined if there are no intersections.\r\n */\r\nIntersectionTests.raySphere = function (ray, sphere, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(ray)) {\r\n throw new DeveloperError(\"ray is required.\");\r\n }\r\n if (!defined(sphere)) {\r\n throw new DeveloperError(\"sphere is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n result = raySphere(ray, sphere, result);\r\n if (!defined(result) || result.stop < 0.0) {\r\n return undefined;\r\n }\r\n\r\n result.start = Math.max(result.start, 0.0);\r\n return result;\r\n};\r\n\r\nvar scratchLineSegmentRay = new Ray();\r\n\r\n/**\r\n * Computes the intersection points of a line segment with a sphere.\r\n * @memberof IntersectionTests\r\n *\r\n * @param {Cartesian3} p0 An end point of the line segment.\r\n * @param {Cartesian3} p1 The other end point of the line segment.\r\n * @param {BoundingSphere} sphere The sphere.\r\n * @param {Interval} [result] The result onto which to store the result.\r\n * @returns {Interval} The interval containing scalar points along the ray or undefined if there are no intersections.\r\n */\r\nIntersectionTests.lineSegmentSphere = function (p0, p1, sphere, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(p0)) {\r\n throw new DeveloperError(\"p0 is required.\");\r\n }\r\n if (!defined(p1)) {\r\n throw new DeveloperError(\"p1 is required.\");\r\n }\r\n if (!defined(sphere)) {\r\n throw new DeveloperError(\"sphere is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var ray = scratchLineSegmentRay;\r\n Cartesian3.clone(p0, ray.origin);\r\n var direction = Cartesian3.subtract(p1, p0, ray.direction);\r\n\r\n var maxT = Cartesian3.magnitude(direction);\r\n Cartesian3.normalize(direction, direction);\r\n\r\n result = raySphere(ray, sphere, result);\r\n if (!defined(result) || result.stop < 0.0 || result.start > maxT) {\r\n return undefined;\r\n }\r\n\r\n result.start = Math.max(result.start, 0.0);\r\n result.stop = Math.min(result.stop, maxT);\r\n return result;\r\n};\r\n\r\nvar scratchQ = new Cartesian3();\r\nvar scratchW = new Cartesian3();\r\n\r\n/**\r\n * Computes the intersection points of a ray with an ellipsoid.\r\n *\r\n * @param {Ray} ray The ray.\r\n * @param {Ellipsoid} ellipsoid The ellipsoid.\r\n * @returns {Interval} The interval containing scalar points along the ray or undefined if there are no intersections.\r\n */\r\nIntersectionTests.rayEllipsoid = function (ray, ellipsoid) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(ray)) {\r\n throw new DeveloperError(\"ray is required.\");\r\n }\r\n if (!defined(ellipsoid)) {\r\n throw new DeveloperError(\"ellipsoid is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var inverseRadii = ellipsoid.oneOverRadii;\r\n var q = Cartesian3.multiplyComponents(inverseRadii, ray.origin, scratchQ);\r\n var w = Cartesian3.multiplyComponents(inverseRadii, ray.direction, scratchW);\r\n\r\n var q2 = Cartesian3.magnitudeSquared(q);\r\n var qw = Cartesian3.dot(q, w);\r\n\r\n var difference, w2, product, discriminant, temp;\r\n\r\n if (q2 > 1.0) {\r\n // Outside ellipsoid.\r\n if (qw >= 0.0) {\r\n // Looking outward or tangent (0 intersections).\r\n return undefined;\r\n }\r\n\r\n // qw < 0.0.\r\n var qw2 = qw * qw;\r\n difference = q2 - 1.0; // Positively valued.\r\n w2 = Cartesian3.magnitudeSquared(w);\r\n product = w2 * difference;\r\n\r\n if (qw2 < product) {\r\n // Imaginary roots (0 intersections).\r\n return undefined;\r\n } else if (qw2 > product) {\r\n // Distinct roots (2 intersections).\r\n discriminant = qw * qw - product;\r\n temp = -qw + Math.sqrt(discriminant); // Avoid cancellation.\r\n var root0 = temp / w2;\r\n var root1 = difference / temp;\r\n if (root0 < root1) {\r\n return new Interval(root0, root1);\r\n }\r\n\r\n return {\r\n start: root1,\r\n stop: root0,\r\n };\r\n }\r\n // qw2 == product. Repeated roots (2 intersections).\r\n var root = Math.sqrt(difference / w2);\r\n return new Interval(root, root);\r\n } else if (q2 < 1.0) {\r\n // Inside ellipsoid (2 intersections).\r\n difference = q2 - 1.0; // Negatively valued.\r\n w2 = Cartesian3.magnitudeSquared(w);\r\n product = w2 * difference; // Negatively valued.\r\n\r\n discriminant = qw * qw - product;\r\n temp = -qw + Math.sqrt(discriminant); // Positively valued.\r\n return new Interval(0.0, temp / w2);\r\n }\r\n // q2 == 1.0. On ellipsoid.\r\n if (qw < 0.0) {\r\n // Looking inward.\r\n w2 = Cartesian3.magnitudeSquared(w);\r\n return new Interval(0.0, -qw / w2);\r\n }\r\n\r\n // qw >= 0.0. Looking outward or tangent.\r\n return undefined;\r\n};\r\n\r\nfunction addWithCancellationCheck(left, right, tolerance) {\r\n var difference = left + right;\r\n if (\r\n CesiumMath.sign(left) !== CesiumMath.sign(right) &&\r\n Math.abs(difference / Math.max(Math.abs(left), Math.abs(right))) < tolerance\r\n ) {\r\n return 0.0;\r\n }\r\n\r\n return difference;\r\n}\r\n\r\nfunction quadraticVectorExpression(A, b, c, x, w) {\r\n var xSquared = x * x;\r\n var wSquared = w * w;\r\n\r\n var l2 = (A[Matrix3.COLUMN1ROW1] - A[Matrix3.COLUMN2ROW2]) * wSquared;\r\n var l1 =\r\n w *\r\n (x *\r\n addWithCancellationCheck(\r\n A[Matrix3.COLUMN1ROW0],\r\n A[Matrix3.COLUMN0ROW1],\r\n CesiumMath.EPSILON15\r\n ) +\r\n b.y);\r\n var l0 =\r\n A[Matrix3.COLUMN0ROW0] * xSquared +\r\n A[Matrix3.COLUMN2ROW2] * wSquared +\r\n x * b.x +\r\n c;\r\n\r\n var r1 =\r\n wSquared *\r\n addWithCancellationCheck(\r\n A[Matrix3.COLUMN2ROW1],\r\n A[Matrix3.COLUMN1ROW2],\r\n CesiumMath.EPSILON15\r\n );\r\n var r0 =\r\n w *\r\n (x *\r\n addWithCancellationCheck(A[Matrix3.COLUMN2ROW0], A[Matrix3.COLUMN0ROW2]) +\r\n b.z);\r\n\r\n var cosines;\r\n var solutions = [];\r\n if (r0 === 0.0 && r1 === 0.0) {\r\n cosines = QuadraticRealPolynomial.computeRealRoots(l2, l1, l0);\r\n if (cosines.length === 0) {\r\n return solutions;\r\n }\r\n\r\n var cosine0 = cosines[0];\r\n var sine0 = Math.sqrt(Math.max(1.0 - cosine0 * cosine0, 0.0));\r\n solutions.push(new Cartesian3(x, w * cosine0, w * -sine0));\r\n solutions.push(new Cartesian3(x, w * cosine0, w * sine0));\r\n\r\n if (cosines.length === 2) {\r\n var cosine1 = cosines[1];\r\n var sine1 = Math.sqrt(Math.max(1.0 - cosine1 * cosine1, 0.0));\r\n solutions.push(new Cartesian3(x, w * cosine1, w * -sine1));\r\n solutions.push(new Cartesian3(x, w * cosine1, w * sine1));\r\n }\r\n\r\n return solutions;\r\n }\r\n\r\n var r0Squared = r0 * r0;\r\n var r1Squared = r1 * r1;\r\n var l2Squared = l2 * l2;\r\n var r0r1 = r0 * r1;\r\n\r\n var c4 = l2Squared + r1Squared;\r\n var c3 = 2.0 * (l1 * l2 + r0r1);\r\n var c2 = 2.0 * l0 * l2 + l1 * l1 - r1Squared + r0Squared;\r\n var c1 = 2.0 * (l0 * l1 - r0r1);\r\n var c0 = l0 * l0 - r0Squared;\r\n\r\n if (c4 === 0.0 && c3 === 0.0 && c2 === 0.0 && c1 === 0.0) {\r\n return solutions;\r\n }\r\n\r\n cosines = QuarticRealPolynomial.computeRealRoots(c4, c3, c2, c1, c0);\r\n var length = cosines.length;\r\n if (length === 0) {\r\n return solutions;\r\n }\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var cosine = cosines[i];\r\n var cosineSquared = cosine * cosine;\r\n var sineSquared = Math.max(1.0 - cosineSquared, 0.0);\r\n var sine = Math.sqrt(sineSquared);\r\n\r\n //var left = l2 * cosineSquared + l1 * cosine + l0;\r\n var left;\r\n if (CesiumMath.sign(l2) === CesiumMath.sign(l0)) {\r\n left = addWithCancellationCheck(\r\n l2 * cosineSquared + l0,\r\n l1 * cosine,\r\n CesiumMath.EPSILON12\r\n );\r\n } else if (CesiumMath.sign(l0) === CesiumMath.sign(l1 * cosine)) {\r\n left = addWithCancellationCheck(\r\n l2 * cosineSquared,\r\n l1 * cosine + l0,\r\n CesiumMath.EPSILON12\r\n );\r\n } else {\r\n left = addWithCancellationCheck(\r\n l2 * cosineSquared + l1 * cosine,\r\n l0,\r\n CesiumMath.EPSILON12\r\n );\r\n }\r\n\r\n var right = addWithCancellationCheck(r1 * cosine, r0, CesiumMath.EPSILON15);\r\n var product = left * right;\r\n\r\n if (product < 0.0) {\r\n solutions.push(new Cartesian3(x, w * cosine, w * sine));\r\n } else if (product > 0.0) {\r\n solutions.push(new Cartesian3(x, w * cosine, w * -sine));\r\n } else if (sine !== 0.0) {\r\n solutions.push(new Cartesian3(x, w * cosine, w * -sine));\r\n solutions.push(new Cartesian3(x, w * cosine, w * sine));\r\n ++i;\r\n } else {\r\n solutions.push(new Cartesian3(x, w * cosine, w * sine));\r\n }\r\n }\r\n\r\n return solutions;\r\n}\r\n\r\nvar firstAxisScratch = new Cartesian3();\r\nvar secondAxisScratch = new Cartesian3();\r\nvar thirdAxisScratch = new Cartesian3();\r\nvar referenceScratch = new Cartesian3();\r\nvar bCart = new Cartesian3();\r\nvar bScratch = new Matrix3();\r\nvar btScratch = new Matrix3();\r\nvar diScratch = new Matrix3();\r\nvar dScratch = new Matrix3();\r\nvar cScratch = new Matrix3();\r\nvar tempMatrix = new Matrix3();\r\nvar aScratch = new Matrix3();\r\nvar sScratch = new Cartesian3();\r\nvar closestScratch = new Cartesian3();\r\nvar surfPointScratch = new Cartographic();\r\n\r\n/**\r\n * Provides the point along the ray which is nearest to the ellipsoid.\r\n *\r\n * @param {Ray} ray The ray.\r\n * @param {Ellipsoid} ellipsoid The ellipsoid.\r\n * @returns {Cartesian3} The nearest planetodetic point on the ray.\r\n */\r\nIntersectionTests.grazingAltitudeLocation = function (ray, ellipsoid) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(ray)) {\r\n throw new DeveloperError(\"ray is required.\");\r\n }\r\n if (!defined(ellipsoid)) {\r\n throw new DeveloperError(\"ellipsoid is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var position = ray.origin;\r\n var direction = ray.direction;\r\n\r\n if (!Cartesian3.equals(position, Cartesian3.ZERO)) {\r\n var normal = ellipsoid.geodeticSurfaceNormal(position, firstAxisScratch);\r\n if (Cartesian3.dot(direction, normal) >= 0.0) {\r\n // The location provided is the closest point in altitude\r\n return position;\r\n }\r\n }\r\n\r\n var intersects = defined(this.rayEllipsoid(ray, ellipsoid));\r\n\r\n // Compute the scaled direction vector.\r\n var f = ellipsoid.transformPositionToScaledSpace(direction, firstAxisScratch);\r\n\r\n // Constructs a basis from the unit scaled direction vector. Construct its rotation and transpose.\r\n var firstAxis = Cartesian3.normalize(f, f);\r\n var reference = Cartesian3.mostOrthogonalAxis(f, referenceScratch);\r\n var secondAxis = Cartesian3.normalize(\r\n Cartesian3.cross(reference, firstAxis, secondAxisScratch),\r\n secondAxisScratch\r\n );\r\n var thirdAxis = Cartesian3.normalize(\r\n Cartesian3.cross(firstAxis, secondAxis, thirdAxisScratch),\r\n thirdAxisScratch\r\n );\r\n var B = bScratch;\r\n B[0] = firstAxis.x;\r\n B[1] = firstAxis.y;\r\n B[2] = firstAxis.z;\r\n B[3] = secondAxis.x;\r\n B[4] = secondAxis.y;\r\n B[5] = secondAxis.z;\r\n B[6] = thirdAxis.x;\r\n B[7] = thirdAxis.y;\r\n B[8] = thirdAxis.z;\r\n\r\n var B_T = Matrix3.transpose(B, btScratch);\r\n\r\n // Get the scaling matrix and its inverse.\r\n var D_I = Matrix3.fromScale(ellipsoid.radii, diScratch);\r\n var D = Matrix3.fromScale(ellipsoid.oneOverRadii, dScratch);\r\n\r\n var C = cScratch;\r\n C[0] = 0.0;\r\n C[1] = -direction.z;\r\n C[2] = direction.y;\r\n C[3] = direction.z;\r\n C[4] = 0.0;\r\n C[5] = -direction.x;\r\n C[6] = -direction.y;\r\n C[7] = direction.x;\r\n C[8] = 0.0;\r\n\r\n var temp = Matrix3.multiply(\r\n Matrix3.multiply(B_T, D, tempMatrix),\r\n C,\r\n tempMatrix\r\n );\r\n var A = Matrix3.multiply(Matrix3.multiply(temp, D_I, aScratch), B, aScratch);\r\n var b = Matrix3.multiplyByVector(temp, position, bCart);\r\n\r\n // Solve for the solutions to the expression in standard form:\r\n var solutions = quadraticVectorExpression(\r\n A,\r\n Cartesian3.negate(b, firstAxisScratch),\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n );\r\n\r\n var s;\r\n var altitude;\r\n var length = solutions.length;\r\n if (length > 0) {\r\n var closest = Cartesian3.clone(Cartesian3.ZERO, closestScratch);\r\n var maximumValue = Number.NEGATIVE_INFINITY;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n s = Matrix3.multiplyByVector(\r\n D_I,\r\n Matrix3.multiplyByVector(B, solutions[i], sScratch),\r\n sScratch\r\n );\r\n var v = Cartesian3.normalize(\r\n Cartesian3.subtract(s, position, referenceScratch),\r\n referenceScratch\r\n );\r\n var dotProduct = Cartesian3.dot(v, direction);\r\n\r\n if (dotProduct > maximumValue) {\r\n maximumValue = dotProduct;\r\n closest = Cartesian3.clone(s, closest);\r\n }\r\n }\r\n\r\n var surfacePoint = ellipsoid.cartesianToCartographic(\r\n closest,\r\n surfPointScratch\r\n );\r\n maximumValue = CesiumMath.clamp(maximumValue, 0.0, 1.0);\r\n altitude =\r\n Cartesian3.magnitude(\r\n Cartesian3.subtract(closest, position, referenceScratch)\r\n ) * Math.sqrt(1.0 - maximumValue * maximumValue);\r\n altitude = intersects ? -altitude : altitude;\r\n surfacePoint.height = altitude;\r\n return ellipsoid.cartographicToCartesian(surfacePoint, new Cartesian3());\r\n }\r\n\r\n return undefined;\r\n};\r\n\r\nvar lineSegmentPlaneDifference = new Cartesian3();\r\n\r\n/**\r\n * Computes the intersection of a line segment and a plane.\r\n *\r\n * @param {Cartesian3} endPoint0 An end point of the line segment.\r\n * @param {Cartesian3} endPoint1 The other end point of the line segment.\r\n * @param {Plane} plane The plane.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The intersection point or undefined if there is no intersection.\r\n *\r\n * @example\r\n * var origin = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);\r\n * var normal = ellipsoid.geodeticSurfaceNormal(origin);\r\n * var plane = Cesium.Plane.fromPointNormal(origin, normal);\r\n *\r\n * var p0 = new Cesium.Cartesian3(...);\r\n * var p1 = new Cesium.Cartesian3(...);\r\n *\r\n * // find the intersection of the line segment from p0 to p1 and the tangent plane at origin.\r\n * var intersection = Cesium.IntersectionTests.lineSegmentPlane(p0, p1, plane);\r\n */\r\nIntersectionTests.lineSegmentPlane = function (\r\n endPoint0,\r\n endPoint1,\r\n plane,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(endPoint0)) {\r\n throw new DeveloperError(\"endPoint0 is required.\");\r\n }\r\n if (!defined(endPoint1)) {\r\n throw new DeveloperError(\"endPoint1 is required.\");\r\n }\r\n if (!defined(plane)) {\r\n throw new DeveloperError(\"plane is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n var difference = Cartesian3.subtract(\r\n endPoint1,\r\n endPoint0,\r\n lineSegmentPlaneDifference\r\n );\r\n var normal = plane.normal;\r\n var nDotDiff = Cartesian3.dot(normal, difference);\r\n\r\n // check if the segment and plane are parallel\r\n if (Math.abs(nDotDiff) < CesiumMath.EPSILON6) {\r\n return undefined;\r\n }\r\n\r\n var nDotP0 = Cartesian3.dot(normal, endPoint0);\r\n var t = -(plane.distance + nDotP0) / nDotDiff;\r\n\r\n // intersection only if t is in [0, 1]\r\n if (t < 0.0 || t > 1.0) {\r\n return undefined;\r\n }\r\n\r\n // intersection is endPoint0 + t * (endPoint1 - endPoint0)\r\n Cartesian3.multiplyByScalar(difference, t, result);\r\n Cartesian3.add(endPoint0, result, result);\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the intersection of a triangle and a plane\r\n *\r\n * @param {Cartesian3} p0 First point of the triangle\r\n * @param {Cartesian3} p1 Second point of the triangle\r\n * @param {Cartesian3} p2 Third point of the triangle\r\n * @param {Plane} plane Intersection plane\r\n * @returns {Object} An object with properties positions and indices, which are arrays that represent three triangles that do not cross the plane. (Undefined if no intersection exists)\r\n *\r\n * @example\r\n * var origin = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);\r\n * var normal = ellipsoid.geodeticSurfaceNormal(origin);\r\n * var plane = Cesium.Plane.fromPointNormal(origin, normal);\r\n *\r\n * var p0 = new Cesium.Cartesian3(...);\r\n * var p1 = new Cesium.Cartesian3(...);\r\n * var p2 = new Cesium.Cartesian3(...);\r\n *\r\n * // convert the triangle composed of points (p0, p1, p2) to three triangles that don't cross the plane\r\n * var triangles = Cesium.IntersectionTests.trianglePlaneIntersection(p0, p1, p2, plane);\r\n */\r\nIntersectionTests.trianglePlaneIntersection = function (p0, p1, p2, plane) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(p0) || !defined(p1) || !defined(p2) || !defined(plane)) {\r\n throw new DeveloperError(\"p0, p1, p2, and plane are required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var planeNormal = plane.normal;\r\n var planeD = plane.distance;\r\n var p0Behind = Cartesian3.dot(planeNormal, p0) + planeD < 0.0;\r\n var p1Behind = Cartesian3.dot(planeNormal, p1) + planeD < 0.0;\r\n var p2Behind = Cartesian3.dot(planeNormal, p2) + planeD < 0.0;\r\n // Given these dots products, the calls to lineSegmentPlaneIntersection\r\n // always have defined results.\r\n\r\n var numBehind = 0;\r\n numBehind += p0Behind ? 1 : 0;\r\n numBehind += p1Behind ? 1 : 0;\r\n numBehind += p2Behind ? 1 : 0;\r\n\r\n var u1, u2;\r\n if (numBehind === 1 || numBehind === 2) {\r\n u1 = new Cartesian3();\r\n u2 = new Cartesian3();\r\n }\r\n\r\n if (numBehind === 1) {\r\n if (p0Behind) {\r\n IntersectionTests.lineSegmentPlane(p0, p1, plane, u1);\r\n IntersectionTests.lineSegmentPlane(p0, p2, plane, u2);\r\n\r\n return {\r\n positions: [p0, p1, p2, u1, u2],\r\n indices: [\r\n // Behind\r\n 0,\r\n 3,\r\n 4,\r\n\r\n // In front\r\n 1,\r\n 2,\r\n 4,\r\n 1,\r\n 4,\r\n 3,\r\n ],\r\n };\r\n } else if (p1Behind) {\r\n IntersectionTests.lineSegmentPlane(p1, p2, plane, u1);\r\n IntersectionTests.lineSegmentPlane(p1, p0, plane, u2);\r\n\r\n return {\r\n positions: [p0, p1, p2, u1, u2],\r\n indices: [\r\n // Behind\r\n 1,\r\n 3,\r\n 4,\r\n\r\n // In front\r\n 2,\r\n 0,\r\n 4,\r\n 2,\r\n 4,\r\n 3,\r\n ],\r\n };\r\n } else if (p2Behind) {\r\n IntersectionTests.lineSegmentPlane(p2, p0, plane, u1);\r\n IntersectionTests.lineSegmentPlane(p2, p1, plane, u2);\r\n\r\n return {\r\n positions: [p0, p1, p2, u1, u2],\r\n indices: [\r\n // Behind\r\n 2,\r\n 3,\r\n 4,\r\n\r\n // In front\r\n 0,\r\n 1,\r\n 4,\r\n 0,\r\n 4,\r\n 3,\r\n ],\r\n };\r\n }\r\n } else if (numBehind === 2) {\r\n if (!p0Behind) {\r\n IntersectionTests.lineSegmentPlane(p1, p0, plane, u1);\r\n IntersectionTests.lineSegmentPlane(p2, p0, plane, u2);\r\n\r\n return {\r\n positions: [p0, p1, p2, u1, u2],\r\n indices: [\r\n // Behind\r\n 1,\r\n 2,\r\n 4,\r\n 1,\r\n 4,\r\n 3,\r\n\r\n // In front\r\n 0,\r\n 3,\r\n 4,\r\n ],\r\n };\r\n } else if (!p1Behind) {\r\n IntersectionTests.lineSegmentPlane(p2, p1, plane, u1);\r\n IntersectionTests.lineSegmentPlane(p0, p1, plane, u2);\r\n\r\n return {\r\n positions: [p0, p1, p2, u1, u2],\r\n indices: [\r\n // Behind\r\n 2,\r\n 0,\r\n 4,\r\n 2,\r\n 4,\r\n 3,\r\n\r\n // In front\r\n 1,\r\n 3,\r\n 4,\r\n ],\r\n };\r\n } else if (!p2Behind) {\r\n IntersectionTests.lineSegmentPlane(p0, p2, plane, u1);\r\n IntersectionTests.lineSegmentPlane(p1, p2, plane, u2);\r\n\r\n return {\r\n positions: [p0, p1, p2, u1, u2],\r\n indices: [\r\n // Behind\r\n 0,\r\n 1,\r\n 4,\r\n 0,\r\n 4,\r\n 3,\r\n\r\n // In front\r\n 2,\r\n 3,\r\n 4,\r\n ],\r\n };\r\n }\r\n }\r\n\r\n // if numBehind is 3, the triangle is completely behind the plane;\r\n // otherwise, it is completely in front (numBehind is 0).\r\n return undefined;\r\n};\r\nexport default IntersectionTests;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\n\r\n/**\r\n * A plane in Hessian Normal Form defined by\r\n *
\r\n * ax + by + cz + d = 0\r\n * 
\r\n * where (a, b, c) is the plane's normal, d is the signed\r\n * distance to the plane, and (x, y, z) is any point on\r\n * the plane.\r\n *\r\n * @alias Plane\r\n * @constructor\r\n *\r\n * @param {Cartesian3} normal The plane's normal (normalized).\r\n * @param {Number} distance The shortest distance from the origin to the plane. The sign of\r\n * distance determines which side of the plane the origin\r\n * is on. If distance is positive, the origin is in the half-space\r\n * in the direction of the normal; if negative, the origin is in the half-space\r\n * opposite to the normal; if zero, the plane passes through the origin.\r\n *\r\n * @example\r\n * // The plane x=0\r\n * var plane = new Cesium.Plane(Cesium.Cartesian3.UNIT_X, 0.0);\r\n *\r\n * @exception {DeveloperError} Normal must be normalized\r\n */\r\nfunction Plane(normal, distance) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"normal\", normal);\r\n if (\r\n !CesiumMath.equalsEpsilon(\r\n Cartesian3.magnitude(normal),\r\n 1.0,\r\n CesiumMath.EPSILON6\r\n )\r\n ) {\r\n throw new DeveloperError(\"normal must be normalized.\");\r\n }\r\n Check.typeOf.number(\"distance\", distance);\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * The plane's normal.\r\n *\r\n * @type {Cartesian3}\r\n */\r\n this.normal = Cartesian3.clone(normal);\r\n\r\n /**\r\n * The shortest distance from the origin to the plane. The sign of\r\n * distance determines which side of the plane the origin\r\n * is on. If distance is positive, the origin is in the half-space\r\n * in the direction of the normal; if negative, the origin is in the half-space\r\n * opposite to the normal; if zero, the plane passes through the origin.\r\n *\r\n * @type {Number}\r\n */\r\n this.distance = distance;\r\n}\r\n\r\n/**\r\n * Creates a plane from a normal and a point on the plane.\r\n *\r\n * @param {Cartesian3} point The point on the plane.\r\n * @param {Cartesian3} normal The plane's normal (normalized).\r\n * @param {Plane} [result] The object onto which to store the result.\r\n * @returns {Plane} A new plane instance or the modified result parameter.\r\n *\r\n * @example\r\n * var point = Cesium.Cartesian3.fromDegrees(-72.0, 40.0);\r\n * var normal = ellipsoid.geodeticSurfaceNormal(point);\r\n * var tangentPlane = Cesium.Plane.fromPointNormal(point, normal);\r\n *\r\n * @exception {DeveloperError} Normal must be normalized\r\n */\r\nPlane.fromPointNormal = function (point, normal, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"point\", point);\r\n Check.typeOf.object(\"normal\", normal);\r\n if (\r\n !CesiumMath.equalsEpsilon(\r\n Cartesian3.magnitude(normal),\r\n 1.0,\r\n CesiumMath.EPSILON6\r\n )\r\n ) {\r\n throw new DeveloperError(\"normal must be normalized.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var distance = -Cartesian3.dot(normal, point);\r\n\r\n if (!defined(result)) {\r\n return new Plane(normal, distance);\r\n }\r\n\r\n Cartesian3.clone(normal, result.normal);\r\n result.distance = distance;\r\n return result;\r\n};\r\n\r\nvar scratchNormal = new Cartesian3();\r\n/**\r\n * Creates a plane from the general equation\r\n *\r\n * @param {Cartesian4} coefficients The plane's normal (normalized).\r\n * @param {Plane} [result] The object onto which to store the result.\r\n * @returns {Plane} A new plane instance or the modified result parameter.\r\n *\r\n * @exception {DeveloperError} Normal must be normalized\r\n */\r\nPlane.fromCartesian4 = function (coefficients, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"coefficients\", coefficients);\r\n //>>includeEnd('debug');\r\n\r\n var normal = Cartesian3.fromCartesian4(coefficients, scratchNormal);\r\n var distance = coefficients.w;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !CesiumMath.equalsEpsilon(\r\n Cartesian3.magnitude(normal),\r\n 1.0,\r\n CesiumMath.EPSILON6\r\n )\r\n ) {\r\n throw new DeveloperError(\"normal must be normalized.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Plane(normal, distance);\r\n }\r\n Cartesian3.clone(normal, result.normal);\r\n result.distance = distance;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the signed shortest distance of a point to a plane.\r\n * The sign of the distance determines which side of the plane the point\r\n * is on. If the distance is positive, the point is in the half-space\r\n * in the direction of the normal; if negative, the point is in the half-space\r\n * opposite to the normal; if zero, the plane passes through the point.\r\n *\r\n * @param {Plane} plane The plane.\r\n * @param {Cartesian3} point The point.\r\n * @returns {Number} The signed shortest distance of the point to the plane.\r\n */\r\nPlane.getPointDistance = function (plane, point) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"plane\", plane);\r\n Check.typeOf.object(\"point\", point);\r\n //>>includeEnd('debug');\r\n\r\n return Cartesian3.dot(plane.normal, point) + plane.distance;\r\n};\r\n\r\nvar scratchCartesian = new Cartesian3();\r\n/**\r\n * Projects a point onto the plane.\r\n * @param {Plane} plane The plane to project the point onto\r\n * @param {Cartesian3} point The point to project onto the plane\r\n * @param {Cartesian3} [result] The result point. If undefined, a new Cartesian3 will be created.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.\r\n */\r\nPlane.projectPointOntoPlane = function (plane, point, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"plane\", plane);\r\n Check.typeOf.object(\"point\", point);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n // projectedPoint = point - (normal.point + scale) * normal\r\n var pointDistance = Plane.getPointDistance(plane, point);\r\n var scaledNormal = Cartesian3.multiplyByScalar(\r\n plane.normal,\r\n pointDistance,\r\n scratchCartesian\r\n );\r\n\r\n return Cartesian3.subtract(point, scaledNormal, result);\r\n};\r\n\r\nvar scratchInverseTranspose = new Matrix4();\r\nvar scratchPlaneCartesian4 = new Cartesian4();\r\nvar scratchTransformNormal = new Cartesian3();\r\n/**\r\n * Transforms the plane by the given transformation matrix.\r\n *\r\n * @param {Plane} plane The plane.\r\n * @param {Matrix4} transform The transformation matrix.\r\n * @param {Plane} [result] The object into which to store the result.\r\n * @returns {Plane} The plane transformed by the given transformation matrix.\r\n */\r\nPlane.transform = function (plane, transform, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"plane\", plane);\r\n Check.typeOf.object(\"transform\", transform);\r\n //>>includeEnd('debug');\r\n\r\n var normal = plane.normal;\r\n var distance = plane.distance;\r\n var inverseTranspose = Matrix4.inverseTranspose(\r\n transform,\r\n scratchInverseTranspose\r\n );\r\n var planeAsCartesian4 = Cartesian4.fromElements(\r\n normal.x,\r\n normal.y,\r\n normal.z,\r\n distance,\r\n scratchPlaneCartesian4\r\n );\r\n planeAsCartesian4 = Matrix4.multiplyByVector(\r\n inverseTranspose,\r\n planeAsCartesian4,\r\n planeAsCartesian4\r\n );\r\n\r\n // Convert the transformed plane to Hessian Normal Form\r\n var transformedNormal = Cartesian3.fromCartesian4(\r\n planeAsCartesian4,\r\n scratchTransformNormal\r\n );\r\n\r\n planeAsCartesian4 = Cartesian4.divideByScalar(\r\n planeAsCartesian4,\r\n Cartesian3.magnitude(transformedNormal),\r\n planeAsCartesian4\r\n );\r\n\r\n return Plane.fromCartesian4(planeAsCartesian4, result);\r\n};\r\n\r\n/**\r\n * Duplicates a Plane instance.\r\n *\r\n * @param {Plane} plane The plane to duplicate.\r\n * @param {Plane} [result] The object onto which to store the result.\r\n * @returns {Plane} The modified result parameter or a new Plane instance if one was not provided.\r\n */\r\nPlane.clone = function (plane, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"plane\", plane);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Plane(plane.normal, plane.distance);\r\n }\r\n\r\n Cartesian3.clone(plane.normal, result.normal);\r\n result.distance = plane.distance;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided Planes by normal and distance and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Plane} left The first plane.\r\n * @param {Plane} right The second plane.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPlane.equals = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n return (\r\n left.distance === right.distance &&\r\n Cartesian3.equals(left.normal, right.normal)\r\n );\r\n};\r\n\r\n/**\r\n * A constant initialized to the XY plane passing through the origin, with normal in positive Z.\r\n *\r\n * @type {Plane}\r\n * @constant\r\n */\r\nPlane.ORIGIN_XY_PLANE = Object.freeze(new Plane(Cartesian3.UNIT_Z, 0.0));\r\n\r\n/**\r\n * A constant initialized to the YZ plane passing through the origin, with normal in positive X.\r\n *\r\n * @type {Plane}\r\n * @constant\r\n */\r\nPlane.ORIGIN_YZ_PLANE = Object.freeze(new Plane(Cartesian3.UNIT_X, 0.0));\r\n\r\n/**\r\n * A constant initialized to the ZX plane passing through the origin, with normal in positive Y.\r\n *\r\n * @type {Plane}\r\n * @constant\r\n */\r\nPlane.ORIGIN_ZX_PLANE = Object.freeze(new Plane(Cartesian3.UNIT_Y, 0.0));\r\nexport default Plane;\r\n","import Check from \"./Check.js\";\r\n\r\n/**\r\n * Finds an item in a sorted array.\r\n *\r\n * @function\r\n * @param {Array} array The sorted array to search.\r\n * @param {*} itemToFind The item to find in the array.\r\n * @param {binarySearchComparator} comparator The function to use to compare the item to\r\n * elements in the array.\r\n * @returns {Number} The index of itemToFind in the array, if it exists. If itemToFind\r\n * does not exist, the return value is a negative number which is the bitwise complement (~)\r\n * of the index before which the itemToFind should be inserted in order to maintain the\r\n * sorted order of the array.\r\n *\r\n * @example\r\n * // Create a comparator function to search through an array of numbers.\r\n * function comparator(a, b) {\r\n * return a - b;\r\n * };\r\n * var numbers = [0, 2, 4, 6, 8];\r\n * var index = Cesium.binarySearch(numbers, 6, comparator); // 3\r\n */\r\nfunction binarySearch(array, itemToFind, comparator) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n Check.defined(\"itemToFind\", itemToFind);\r\n Check.defined(\"comparator\", comparator);\r\n //>>includeEnd('debug');\r\n\r\n var low = 0;\r\n var high = array.length - 1;\r\n var i;\r\n var comparison;\r\n\r\n while (low <= high) {\r\n i = ~~((low + high) / 2);\r\n comparison = comparator(array[i], itemToFind);\r\n if (comparison < 0) {\r\n low = i + 1;\r\n continue;\r\n }\r\n if (comparison > 0) {\r\n high = i - 1;\r\n continue;\r\n }\r\n return i;\r\n }\r\n return ~(high + 1);\r\n}\r\n\r\n/**\r\n * A function used to compare two items while performing a binary search.\r\n * @callback binarySearchComparator\r\n *\r\n * @param {*} a An item in the array.\r\n * @param {*} b The item being searched for.\r\n * @returns {Number} Returns a negative value if a is less than b,\r\n * a positive value if a is greater than b, or\r\n * 0 if a is equal to b.\r\n *\r\n * @example\r\n * function compareNumbers(a, b) {\r\n * return a - b;\r\n * }\r\n */\r\nexport default binarySearch;\r\n","/**\r\n * A set of Earth Orientation Parameters (EOP) sampled at a time.\r\n *\r\n * @alias EarthOrientationParametersSample\r\n * @constructor\r\n *\r\n * @param {Number} xPoleWander The pole wander about the X axis, in radians.\r\n * @param {Number} yPoleWander The pole wander about the Y axis, in radians.\r\n * @param {Number} xPoleOffset The offset to the Celestial Intermediate Pole (CIP) about the X axis, in radians.\r\n * @param {Number} yPoleOffset The offset to the Celestial Intermediate Pole (CIP) about the Y axis, in radians.\r\n * @param {Number} ut1MinusUtc The difference in time standards, UT1 - UTC, in seconds.\r\n *\r\n * @private\r\n */\r\nfunction EarthOrientationParametersSample(\r\n xPoleWander,\r\n yPoleWander,\r\n xPoleOffset,\r\n yPoleOffset,\r\n ut1MinusUtc\r\n) {\r\n /**\r\n * The pole wander about the X axis, in radians.\r\n * @type {Number}\r\n */\r\n this.xPoleWander = xPoleWander;\r\n\r\n /**\r\n * The pole wander about the Y axis, in radians.\r\n * @type {Number}\r\n */\r\n this.yPoleWander = yPoleWander;\r\n\r\n /**\r\n * The offset to the Celestial Intermediate Pole (CIP) about the X axis, in radians.\r\n * @type {Number}\r\n */\r\n this.xPoleOffset = xPoleOffset;\r\n\r\n /**\r\n * The offset to the Celestial Intermediate Pole (CIP) about the Y axis, in radians.\r\n * @type {Number}\r\n */\r\n this.yPoleOffset = yPoleOffset;\r\n\r\n /**\r\n * The difference in time standards, UT1 - UTC, in seconds.\r\n * @type {Number}\r\n */\r\n this.ut1MinusUtc = ut1MinusUtc;\r\n}\r\nexport default EarthOrientationParametersSample;\r\n","/**\r\n@license\r\nsprintf.js from the php.js project - https://github.com/kvz/phpjs\r\nDirectly from https://github.com/kvz/phpjs/blob/master/functions/strings/sprintf.js\r\n\r\nphp.js is copyright 2012 Kevin van Zonneveld.\r\n\r\nPortions copyright Brett Zamir (http://brett-zamir.me), Kevin van Zonneveld\r\n(http://kevin.vanzonneveld.net), Onno Marsman, Theriault, Michael White\r\n(http://getsprink.com), Waldo Malqui Silva, Paulo Freitas, Jack, Jonas\r\nRaoni Soares Silva (http://www.jsfromhell.com), Philip Peterson, Legaev\r\nAndrey, Ates Goral (http://magnetiq.com), Alex, Ratheous, Martijn Wieringa,\r\nRafa? Kukawski (http://blog.kukawski.pl), lmeyrick\r\n(https://sourceforge.net/projects/bcmath-js/), Nate, Philippe Baumann,\r\nEnrique Gonzalez, Webtoolkit.info (http://www.webtoolkit.info/), Carlos R.\r\nL. Rodrigues (http://www.jsfromhell.com), Ash Searle\r\n(http://hexmen.com/blog/), Jani Hartikainen, travc, Ole Vrijenhoek,\r\nErkekjetter, Michael Grier, Rafa? Kukawski (http://kukawski.pl), Johnny\r\nMast (http://www.phpvrouwen.nl), T.Wild, d3x,\r\nhttp://stackoverflow.com/questions/57803/how-to-convert-decimal-to-hex-in-javascript,\r\nRafa? Kukawski (http://blog.kukawski.pl/), stag019, pilus, WebDevHobo\r\n(http://webdevhobo.blogspot.com/), marrtins, GeekFG\r\n(http://geekfg.blogspot.com), Andrea Giammarchi\r\n(http://webreflection.blogspot.com), Arpad Ray (mailto:arpad@php.net),\r\ngorthaur, Paul Smith, Tim de Koning (http://www.kingsquare.nl), Joris, Oleg\r\nEremeev, Steve Hilder, majak, gettimeofday, KELAN, Josh Fraser\r\n(http://onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/),\r\nMarc Palau, Martin\r\n(http://www.erlenwiese.de/), Breaking Par Consulting Inc\r\n(http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CFB006C45F7),\r\nChris, Mirek Slugen, saulius, Alfonso Jimenez\r\n(http://www.alfonsojimenez.com), Diplom@t (http://difane.com/), felix,\r\nMailfaker (http://www.weedem.fr/), Tyler Akins (http://rumkin.com), Caio\r\nAriede (http://caioariede.com), Robin, Kankrelune\r\n(http://www.webfaktory.info/), Karol Kowalski, Imgen Tata\r\n(http://www.myipdf.com/), mdsjack (http://www.mdsjack.bo.it), Dreamer,\r\nFelix Geisendoerfer (http://www.debuggable.com/felix), Lars Fischer, AJ,\r\nDavid, Aman Gupta, Michael White, Public Domain\r\n(http://www.json.org/json2.js), Steven Levithan\r\n(http://blog.stevenlevithan.com), Sakimori, Pellentesque Malesuada,\r\nThunder.m, Dj (http://phpjs.org/functions/htmlentities:425#comment_134018),\r\nSteve Clay, David James, Francois, class_exists, nobbler, T. Wild, Itsacon\r\n(http://www.itsacon.net/), date, Ole Vrijenhoek (http://www.nervous.nl/),\r\nFox, Raphael (Ao RUDLER), Marco, noname, Mateusz \"loonquawl\" Zalega, Frank\r\nForte, Arno, ger, mktime, john (http://www.jd-tech.net), Nick Kolosov\r\n(http://sammy.ru), marc andreu, Scott Cariss, Douglas Crockford\r\n(http://javascript.crockford.com), madipta, Slawomir Kaniecki,\r\nReverseSyntax, Nathan, Alex Wilson, kenneth, Bayron Guevara, Adam Wallner\r\n(http://web2.bitbaro.hu/), paulo kuong, jmweb, Lincoln Ramsay, djmix,\r\nPyerre, Jon Hohle, Thiago Mata (http://thiagomata.blog.com), lmeyrick\r\n(https://sourceforge.net/projects/bcmath-js/this.), Linuxworld, duncan,\r\nGilbert, Sanjoy Roy, Shingo, sankai, Oskar Larsson H?gfeldt\r\n(http://oskar-lh.name/), Denny Wardhana, 0m3r, Everlasto, Subhasis Deb,\r\njosh, jd, Pier Paolo Ramon (http://www.mastersoup.com/), P, merabi, Soren\r\nHansen, Eugene Bulkin (http://doubleaw.com/), Der Simon\r\n(http://innerdom.sourceforge.net/), echo is bad, Ozh, XoraX\r\n(http://www.xorax.info), EdorFaus, JB, J A R, Marc Jansen, Francesco, LH,\r\nStoyan Kyosev (http://www.svest.org/), nord_ua, omid\r\n(http://phpjs.org/functions/380:380#comment_137122), Brad Touesnard, MeEtc\r\n(http://yass.meetcweb.com), Peter-Paul Koch\r\n(http://www.quirksmode.org/js/beat.html), Olivier Louvignes\r\n(http://mg-crea.com/), T0bsn, Tim Wiel, Bryan Elliott, Jalal Berrami,\r\nMartin, JT, David Randall, Thomas Beaucourt (http://www.webapp.fr), taith,\r\nvlado houba, Pierre-Luc Paour, Kristof Coomans (SCK-CEN Belgian Nucleair\r\nResearch Centre), Martin Pool, Kirk Strobeck, Rick Waldron, Brant Messenger\r\n(http://www.brantmessenger.com/), Devan Penner-Woelk, Saulo Vallory, Wagner\r\nB. Soares, Artur Tchernychev, Valentina De Rosa, Jason Wong\r\n(http://carrot.org/), Christoph, Daniel Esteban, strftime, Mick@el, rezna,\r\nSimon Willison (http://simonwillison.net), Anton Ongson, Gabriel Paderni,\r\nMarco van Oort, penutbutterjelly, Philipp Lenssen, Bjorn Roesbeke\r\n(http://www.bjornroesbeke.be/), Bug?, Eric Nagel, Tomasz Wesolowski,\r\nEvertjan Garretsen, Bobby Drake, Blues (http://tech.bluesmoon.info/), Luke\r\nGodfrey, Pul, uestla, Alan C, Ulrich, Rafal Kukawski, Yves Sucaet,\r\nsowberry, Norman \"zEh\" Fuchs, hitwork, Zahlii, johnrembo, Nick Callen,\r\nSteven Levithan (stevenlevithan.com), ejsanders, Scott Baker, Brian Tafoya\r\n(http://www.premasolutions.com/), Philippe Jausions\r\n(http://pear.php.net/user/jausions), Aidan Lister\r\n(http://aidanlister.com/), Rob, e-mike, HKM, ChaosNo1, metjay, strcasecmp,\r\nstrcmp, Taras Bogach, jpfle, Alexander Ermolaev\r\n(http://snippets.dzone.com/user/AlexanderErmolaev), DxGx, kilops, Orlando,\r\ndptr1988, Le Torbi, James (http://www.james-bell.co.uk/), Pedro Tainha\r\n(http://www.pedrotainha.com), James, Arnout Kazemier\r\n(http://www.3rd-Eden.com), Chris McMacken, gabriel paderni, Yannoo,\r\nFGFEmperor, baris ozdil, Tod Gentille, Greg Frazier, jakes, 3D-GRAF, Allan\r\nJensen (http://www.winternet.no), Howard Yeend, Benjamin Lupton, davook,\r\ndaniel airton wermann (http://wermann.com.br), Atli T¨®r, Maximusya, Ryan\r\nW Tenney (http://ryan.10e.us), Alexander M Beedie, fearphage\r\n(http://http/my.opera.com/fearphage/), Nathan Sepulveda, Victor, Matteo,\r\nBilly, stensi, Cord, Manish, T.J. Leahy, Riddler\r\n(http://www.frontierwebdev.com/), Rafa? Kukawski, FremyCompany, Matt\r\nBradley, Tim de Koning, Luis Salazar (http://www.freaky-media.com/), Diogo\r\nResende, Rival, Andrej Pavlovic, Garagoth, Le Torbi\r\n(http://www.letorbi.de/), Dino, Josep Sanz (http://www.ws3.es/), rem,\r\nRussell Walker (http://www.nbill.co.uk/), Jamie Beck\r\n(http://www.terabit.ca/), setcookie, Michael, YUI Library:\r\nhttp://developer.yahoo.com/yui/docs/YAHOO.util.DateLocale.html, Blues at\r\nhttp://hacks.bluesmoon.info/strftime/strftime.js, Ben\r\n(http://benblume.co.uk/), DtTvB\r\n(http://dt.in.th/2008-09-16.string-length-in-bytes.html), Andreas, William,\r\nmeo, incidence, Cagri Ekin, Amirouche, Amir Habibi\r\n(http://www.residence-mixte.com/), Luke Smith (http://lucassmith.name),\r\nKheang Hok Chin (http://www.distantia.ca/), Jay Klehr, Lorenzo Pisani,\r\nTony, Yen-Wei Liu, Greenseed, mk.keck, Leslie Hoare, dude, booeyOH, Ben\r\nBryan\r\n\r\nLicensed under the MIT (MIT-LICENSE.txt) license.\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a\r\ncopy of this software and associated documentation files (the\r\n\"Software\"), to deal in the Software without restriction, including\r\nwithout limitation the rights to use, copy, modify, merge, publish,\r\ndistribute, sublicense, and/or sell copies of the Software, and to\r\npermit persons to whom the Software is furnished to do so, subject to\r\nthe following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included\r\nin all copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r\nIN NO EVENT SHALL KEVIN VAN ZONNEVELD BE LIABLE FOR ANY CLAIM, DAMAGES\r\nOR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\r\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\r\nOTHER DEALINGS IN THE SOFTWARE.\r\n*/\r\n\r\nfunction sprintf () {\r\n // http://kevin.vanzonneveld.net\r\n // + original by: Ash Searle (http://hexmen.com/blog/)\r\n // + namespaced by: Michael White (http://getsprink.com)\r\n // + tweaked by: Jack\r\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\r\n // + input by: Paulo Freitas\r\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\r\n // + input by: Brett Zamir (http://brett-zamir.me)\r\n // + improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)\r\n // + improved by: Dj\r\n // + improved by: Allidylls\r\n // * example 1: sprintf(\"%01.2f\", 123.1);\r\n // * returns 1: 123.10\r\n // * example 2: sprintf(\"[%10s]\", 'monkey');\r\n // * returns 2: '[ monkey]'\r\n // * example 3: sprintf(\"[%'#10s]\", 'monkey');\r\n // * returns 3: '[####monkey]'\r\n // * example 4: sprintf(\"%d\", 123456789012345);\r\n // * returns 4: '123456789012345'\r\n var regex = /%%|%(\\d+\\$)?([-+\\'#0 ]*)(\\*\\d+\\$|\\*|\\d+)?(\\.(\\*\\d+\\$|\\*|\\d+))?([scboxXuideEfFgG])/g;\r\n var a = arguments,\r\n i = 0,\r\n format = a[i++];\r\n\r\n // pad()\r\n var pad = function (str, len, chr, leftJustify) {\r\n if (!chr) {\r\n chr = ' ';\r\n }\r\n\r\n var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr);\r\n return leftJustify ? str + padding : padding + str;\r\n };\r\n\r\n // justify()\r\n var justify = function (value, prefix, leftJustify, minWidth, zeroPad, customPadChar) {\r\n var diff = minWidth - value.length;\r\n if (diff > 0) {\r\n if (leftJustify || !zeroPad) {\r\n value = pad(value, minWidth, customPadChar, leftJustify);\r\n } else {\r\n value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length);\r\n }\r\n }\r\n return value;\r\n };\r\n\r\n // formatBaseX()\r\n var formatBaseX = function (value, base, prefix, leftJustify, minWidth, precision, zeroPad) {\r\n // Note: casts negative numbers to positive ones\r\n var number = value >>> 0;\r\n prefix = prefix && number && {\r\n '2': '0b',\r\n '8': '0',\r\n '16': '0x'\r\n }[base] || '';\r\n value = prefix + pad(number.toString(base), precision || 0, '0', false);\r\n return justify(value, prefix, leftJustify, minWidth, zeroPad);\r\n };\r\n\r\n // formatString()\r\n var formatString = function (value, leftJustify, minWidth, precision, zeroPad, customPadChar) {\r\n if (precision != null) {\r\n value = value.slice(0, precision);\r\n }\r\n return justify(value, '', leftJustify, minWidth, zeroPad, customPadChar);\r\n };\r\n\r\n // doFormat()\r\n var doFormat = function (substring, valueIndex, flags, minWidth, _, precision, type) {\r\n var number;\r\n var prefix;\r\n var method;\r\n var textTransform;\r\n var value;\r\n\r\n if (substring == '%%') {\r\n return '%';\r\n }\r\n\r\n // parse flags\r\n var leftJustify = false,\r\n positivePrefix = '',\r\n zeroPad = false,\r\n prefixBaseX = false,\r\n customPadChar = ' ';\r\n var flagsl = flags.length;\r\n for (var j = 0; flags && j < flagsl; j++) {\r\n switch (flags.charAt(j)) {\r\n case ' ':\r\n positivePrefix = ' ';\r\n break;\r\n case '+':\r\n positivePrefix = '+';\r\n break;\r\n case '-':\r\n leftJustify = true;\r\n break;\r\n case \"'\":\r\n customPadChar = flags.charAt(j + 1);\r\n break;\r\n case '0':\r\n zeroPad = true;\r\n break;\r\n case '#':\r\n prefixBaseX = true;\r\n break;\r\n }\r\n }\r\n\r\n // parameters may be null, undefined, empty-string or real valued\r\n // we want to ignore null, undefined and empty-string values\r\n if (!minWidth) {\r\n minWidth = 0;\r\n } else if (minWidth == '*') {\r\n minWidth = +a[i++];\r\n } else if (minWidth.charAt(0) == '*') {\r\n minWidth = +a[minWidth.slice(1, -1)];\r\n } else {\r\n minWidth = +minWidth;\r\n }\r\n\r\n // Note: undocumented perl feature:\r\n if (minWidth < 0) {\r\n minWidth = -minWidth;\r\n leftJustify = true;\r\n }\r\n\r\n if (!isFinite(minWidth)) {\r\n throw new Error('sprintf: (minimum-)width must be finite');\r\n }\r\n\r\n if (!precision) {\r\n precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : undefined;\r\n } else if (precision == '*') {\r\n precision = +a[i++];\r\n } else if (precision.charAt(0) == '*') {\r\n precision = +a[precision.slice(1, -1)];\r\n } else {\r\n precision = +precision;\r\n }\r\n\r\n // grab value using valueIndex if required?\r\n value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++];\r\n\r\n switch (type) {\r\n case 's':\r\n return formatString(String(value), leftJustify, minWidth, precision, zeroPad, customPadChar);\r\n case 'c':\r\n return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad);\r\n case 'b':\r\n return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad);\r\n case 'o':\r\n return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad);\r\n case 'x':\r\n return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad);\r\n case 'X':\r\n return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad).toUpperCase();\r\n case 'u':\r\n return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad);\r\n case 'i':\r\n case 'd':\r\n number = +value || 0;\r\n number = Math.round(number - number % 1); // Plain Math.round doesn't just truncate\r\n prefix = number < 0 ? '-' : positivePrefix;\r\n value = prefix + pad(String(Math.abs(number)), precision, '0', false);\r\n return justify(value, prefix, leftJustify, minWidth, zeroPad);\r\n case 'e':\r\n case 'E':\r\n case 'f': // Should handle locales (as per setlocale)\r\n case 'F':\r\n case 'g':\r\n case 'G':\r\n number = +value;\r\n prefix = number < 0 ? '-' : positivePrefix;\r\n method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())];\r\n textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2];\r\n value = prefix + Math.abs(number)[method](precision);\r\n return justify(value, prefix, leftJustify, minWidth, zeroPad)[textTransform]();\r\n default:\r\n return substring;\r\n }\r\n };\r\n\r\n return format.replace(regex, doFormat);\r\n}\r\n\r\nexport default sprintf;\r\n","/**\r\n * Represents a Gregorian date in a more precise format than the JavaScript Date object.\r\n * In addition to submillisecond precision, this object can also represent leap seconds.\r\n * @alias GregorianDate\r\n * @constructor\r\n *\r\n * @param {Number} [year] The year as a whole number.\r\n * @param {Number} [month] The month as a whole number with range [1, 12].\r\n * @param {Number} [day] The day of the month as a whole number starting at 1.\r\n * @param {Number} [hour] The hour as a whole number with range [0, 23].\r\n * @param {Number} [minute] The minute of the hour as a whole number with range [0, 59].\r\n * @param {Number} [second] The second of the minute as a whole number with range [0, 60], with 60 representing a leap second.\r\n * @param {Number} [millisecond] The millisecond of the second as a floating point number with range [0.0, 1000.0).\r\n * @param {Boolean} [isLeapSecond] Whether this time is during a leap second.\r\n *\r\n * @see JulianDate#toGregorianDate\r\n */\r\nfunction GregorianDate(\r\n year,\r\n month,\r\n day,\r\n hour,\r\n minute,\r\n second,\r\n millisecond,\r\n isLeapSecond\r\n) {\r\n /**\r\n * Gets or sets the year as a whole number.\r\n * @type {Number}\r\n */\r\n this.year = year;\r\n /**\r\n * Gets or sets the month as a whole number with range [1, 12].\r\n * @type {Number}\r\n */\r\n this.month = month;\r\n /**\r\n * Gets or sets the day of the month as a whole number starting at 1.\r\n * @type {Number}\r\n */\r\n this.day = day;\r\n /**\r\n * Gets or sets the hour as a whole number with range [0, 23].\r\n * @type {Number}\r\n */\r\n this.hour = hour;\r\n /**\r\n * Gets or sets the minute of the hour as a whole number with range [0, 59].\r\n * @type {Number}\r\n */\r\n this.minute = minute;\r\n /**\r\n * Gets or sets the second of the minute as a whole number with range [0, 60], with 60 representing a leap second.\r\n * @type {Number}\r\n */\r\n this.second = second;\r\n /**\r\n * Gets or sets the millisecond of the second as a floating point number with range [0.0, 1000.0).\r\n * @type {Number}\r\n */\r\n this.millisecond = millisecond;\r\n /**\r\n * Gets or sets whether this time is during a leap second.\r\n * @type {Boolean}\r\n */\r\n this.isLeapSecond = isLeapSecond;\r\n}\r\nexport default GregorianDate;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Determines if a given date is a leap year.\r\n *\r\n * @function isLeapYear\r\n *\r\n * @param {Number} year The year to be tested.\r\n * @returns {Boolean} True if year is a leap year.\r\n *\r\n * @example\r\n * var leapYear = Cesium.isLeapYear(2000); // true\r\n */\r\nfunction isLeapYear(year) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (year === null || isNaN(year)) {\r\n throw new DeveloperError(\"year is required and must be a number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;\r\n}\r\nexport default isLeapYear;\r\n","/**\r\n * Describes a single leap second, which is constructed from a {@link JulianDate} and a\r\n * numerical offset representing the number of seconds TAI is ahead of the UTC time standard.\r\n * @alias LeapSecond\r\n * @constructor\r\n *\r\n * @param {JulianDate} [date] A Julian date representing the time of the leap second.\r\n * @param {Number} [offset] The cumulative number of seconds that TAI is ahead of UTC at the provided date.\r\n */\r\nfunction LeapSecond(date, offset) {\r\n /**\r\n * Gets or sets the date at which this leap second occurs.\r\n * @type {JulianDate}\r\n */\r\n this.julianDate = date;\r\n\r\n /**\r\n * Gets or sets the cumulative number of seconds between the UTC and TAI time standards at the time\r\n * of this leap second.\r\n * @type {Number}\r\n */\r\n this.offset = offset;\r\n}\r\nexport default LeapSecond;\r\n","/**\r\n * Constants for time conversions like those done by {@link JulianDate}.\r\n *\r\n * @namespace TimeConstants\r\n *\r\n * @see JulianDate\r\n *\r\n * @private\r\n */\r\nvar TimeConstants = {\r\n /**\r\n * The number of seconds in one millisecond: 0.001\r\n * @type {Number}\r\n * @constant\r\n */\r\n SECONDS_PER_MILLISECOND: 0.001,\r\n\r\n /**\r\n * The number of seconds in one minute: 60.\r\n * @type {Number}\r\n * @constant\r\n */\r\n SECONDS_PER_MINUTE: 60.0,\r\n\r\n /**\r\n * The number of minutes in one hour: 60.\r\n * @type {Number}\r\n * @constant\r\n */\r\n MINUTES_PER_HOUR: 60.0,\r\n\r\n /**\r\n * The number of hours in one day: 24.\r\n * @type {Number}\r\n * @constant\r\n */\r\n HOURS_PER_DAY: 24.0,\r\n\r\n /**\r\n * The number of seconds in one hour: 3600.\r\n * @type {Number}\r\n * @constant\r\n */\r\n SECONDS_PER_HOUR: 3600.0,\r\n\r\n /**\r\n * The number of minutes in one day: 1440.\r\n * @type {Number}\r\n * @constant\r\n */\r\n MINUTES_PER_DAY: 1440.0,\r\n\r\n /**\r\n * The number of seconds in one day, ignoring leap seconds: 86400.\r\n * @type {Number}\r\n * @constant\r\n */\r\n SECONDS_PER_DAY: 86400.0,\r\n\r\n /**\r\n * The number of days in one Julian century: 36525.\r\n * @type {Number}\r\n * @constant\r\n */\r\n DAYS_PER_JULIAN_CENTURY: 36525.0,\r\n\r\n /**\r\n * One trillionth of a second.\r\n * @type {Number}\r\n * @constant\r\n */\r\n PICOSECOND: 0.000000001,\r\n\r\n /**\r\n * The number of days to subtract from a Julian date to determine the\r\n * modified Julian date, which gives the number of days since midnight\r\n * on November 17, 1858.\r\n * @type {Number}\r\n * @constant\r\n */\r\n MODIFIED_JULIAN_DATE_DIFFERENCE: 2400000.5,\r\n};\r\nexport default Object.freeze(TimeConstants);\r\n","/**\r\n * Provides the type of time standards which JulianDate can take as input.\r\n *\r\n * @enum {Number}\r\n *\r\n * @see JulianDate\r\n */\r\nvar TimeStandard = {\r\n /**\r\n * Represents the coordinated Universal Time (UTC) time standard.\r\n *\r\n * UTC is related to TAI according to the relationship\r\n * UTC = TAI - deltaT where deltaT is the number of leap\r\n * seconds which have been introduced as of the time in TAI.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n UTC: 0,\r\n\r\n /**\r\n * Represents the International Atomic Time (TAI) time standard.\r\n * TAI is the principal time standard to which the other time standards are related.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n TAI: 1,\r\n};\r\nexport default Object.freeze(TimeStandard);\r\n","import sprintf from \"../ThirdParty/sprintf.js\";\r\nimport binarySearch from \"./binarySearch.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport GregorianDate from \"./GregorianDate.js\";\r\nimport isLeapYear from \"./isLeapYear.js\";\r\nimport LeapSecond from \"./LeapSecond.js\";\r\nimport TimeConstants from \"./TimeConstants.js\";\r\nimport TimeStandard from \"./TimeStandard.js\";\r\n\r\nvar gregorianDateScratch = new GregorianDate();\r\nvar daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\r\nvar daysInLeapFeburary = 29;\r\n\r\nfunction compareLeapSecondDates(leapSecond, dateToFind) {\r\n return JulianDate.compare(leapSecond.julianDate, dateToFind.julianDate);\r\n}\r\n\r\n// we don't really need a leap second instance, anything with a julianDate property will do\r\nvar binarySearchScratchLeapSecond = new LeapSecond();\r\n\r\nfunction convertUtcToTai(julianDate) {\r\n //Even though julianDate is in UTC, we'll treat it as TAI and\r\n //search the leap second table for it.\r\n binarySearchScratchLeapSecond.julianDate = julianDate;\r\n var leapSeconds = JulianDate.leapSeconds;\r\n var index = binarySearch(\r\n leapSeconds,\r\n binarySearchScratchLeapSecond,\r\n compareLeapSecondDates\r\n );\r\n\r\n if (index < 0) {\r\n index = ~index;\r\n }\r\n\r\n if (index >= leapSeconds.length) {\r\n index = leapSeconds.length - 1;\r\n }\r\n\r\n var offset = leapSeconds[index].offset;\r\n if (index > 0) {\r\n //Now we have the index of the closest leap second that comes on or after our UTC time.\r\n //However, if the difference between the UTC date being converted and the TAI\r\n //defined leap second is greater than the offset, we are off by one and need to use\r\n //the previous leap second.\r\n var difference = JulianDate.secondsDifference(\r\n leapSeconds[index].julianDate,\r\n julianDate\r\n );\r\n if (difference > offset) {\r\n index--;\r\n offset = leapSeconds[index].offset;\r\n }\r\n }\r\n\r\n JulianDate.addSeconds(julianDate, offset, julianDate);\r\n}\r\n\r\nfunction convertTaiToUtc(julianDate, result) {\r\n binarySearchScratchLeapSecond.julianDate = julianDate;\r\n var leapSeconds = JulianDate.leapSeconds;\r\n var index = binarySearch(\r\n leapSeconds,\r\n binarySearchScratchLeapSecond,\r\n compareLeapSecondDates\r\n );\r\n if (index < 0) {\r\n index = ~index;\r\n }\r\n\r\n //All times before our first leap second get the first offset.\r\n if (index === 0) {\r\n return JulianDate.addSeconds(julianDate, -leapSeconds[0].offset, result);\r\n }\r\n\r\n //All times after our leap second get the last offset.\r\n if (index >= leapSeconds.length) {\r\n return JulianDate.addSeconds(\r\n julianDate,\r\n -leapSeconds[index - 1].offset,\r\n result\r\n );\r\n }\r\n\r\n //Compute the difference between the found leap second and the time we are converting.\r\n var difference = JulianDate.secondsDifference(\r\n leapSeconds[index].julianDate,\r\n julianDate\r\n );\r\n\r\n if (difference === 0) {\r\n //The date is in our leap second table.\r\n return JulianDate.addSeconds(\r\n julianDate,\r\n -leapSeconds[index].offset,\r\n result\r\n );\r\n }\r\n\r\n if (difference <= 1.0) {\r\n //The requested date is during the moment of a leap second, then we cannot convert to UTC\r\n return undefined;\r\n }\r\n\r\n //The time is in between two leap seconds, index is the leap second after the date\r\n //we're converting, so we subtract one to get the correct LeapSecond instance.\r\n return JulianDate.addSeconds(\r\n julianDate,\r\n -leapSeconds[--index].offset,\r\n result\r\n );\r\n}\r\n\r\nfunction setComponents(wholeDays, secondsOfDay, julianDate) {\r\n var extraDays = (secondsOfDay / TimeConstants.SECONDS_PER_DAY) | 0;\r\n wholeDays += extraDays;\r\n secondsOfDay -= TimeConstants.SECONDS_PER_DAY * extraDays;\r\n\r\n if (secondsOfDay < 0) {\r\n wholeDays--;\r\n secondsOfDay += TimeConstants.SECONDS_PER_DAY;\r\n }\r\n\r\n julianDate.dayNumber = wholeDays;\r\n julianDate.secondsOfDay = secondsOfDay;\r\n return julianDate;\r\n}\r\n\r\nfunction computeJulianDateComponents(\r\n year,\r\n month,\r\n day,\r\n hour,\r\n minute,\r\n second,\r\n millisecond\r\n) {\r\n // Algorithm from page 604 of the Explanatory Supplement to the\r\n // Astronomical Almanac (Seidelmann 1992).\r\n\r\n var a = ((month - 14) / 12) | 0;\r\n var b = year + 4800 + a;\r\n var dayNumber =\r\n (((1461 * b) / 4) | 0) +\r\n (((367 * (month - 2 - 12 * a)) / 12) | 0) -\r\n (((3 * (((b + 100) / 100) | 0)) / 4) | 0) +\r\n day -\r\n 32075;\r\n\r\n // JulianDates are noon-based\r\n hour = hour - 12;\r\n if (hour < 0) {\r\n hour += 24;\r\n }\r\n\r\n var secondsOfDay =\r\n second +\r\n (hour * TimeConstants.SECONDS_PER_HOUR +\r\n minute * TimeConstants.SECONDS_PER_MINUTE +\r\n millisecond * TimeConstants.SECONDS_PER_MILLISECOND);\r\n\r\n if (secondsOfDay >= 43200.0) {\r\n dayNumber -= 1;\r\n }\r\n\r\n return [dayNumber, secondsOfDay];\r\n}\r\n\r\n//Regular expressions used for ISO8601 date parsing.\r\n//YYYY\r\nvar matchCalendarYear = /^(\\d{4})$/;\r\n//YYYY-MM (YYYYMM is invalid)\r\nvar matchCalendarMonth = /^(\\d{4})-(\\d{2})$/;\r\n//YYYY-DDD or YYYYDDD\r\nvar matchOrdinalDate = /^(\\d{4})-?(\\d{3})$/;\r\n//YYYY-Www or YYYYWww or YYYY-Www-D or YYYYWwwD\r\nvar matchWeekDate = /^(\\d{4})-?W(\\d{2})-?(\\d{1})?$/;\r\n//YYYY-MM-DD or YYYYMMDD\r\nvar matchCalendarDate = /^(\\d{4})-?(\\d{2})-?(\\d{2})$/;\r\n// Match utc offset\r\nvar utcOffset = /([Z+\\-])?(\\d{2})?:?(\\d{2})?$/;\r\n// Match hours HH or HH.xxxxx\r\nvar matchHours = /^(\\d{2})(\\.\\d+)?/.source + utcOffset.source;\r\n// Match hours/minutes HH:MM HHMM.xxxxx\r\nvar matchHoursMinutes = /^(\\d{2}):?(\\d{2})(\\.\\d+)?/.source + utcOffset.source;\r\n// Match hours/minutes HH:MM:SS HHMMSS.xxxxx\r\nvar matchHoursMinutesSeconds =\r\n /^(\\d{2}):?(\\d{2}):?(\\d{2})(\\.\\d+)?/.source + utcOffset.source;\r\n\r\nvar iso8601ErrorMessage = \"Invalid ISO 8601 date.\";\r\n\r\n/**\r\n * Represents an astronomical Julian date, which is the number of days since noon on January 1, -4712 (4713 BC).\r\n * For increased precision, this class stores the whole number part of the date and the seconds\r\n * part of the date in separate components. In order to be safe for arithmetic and represent\r\n * leap seconds, the date is always stored in the International Atomic Time standard\r\n * {@link TimeStandard.TAI}.\r\n * @alias JulianDate\r\n * @constructor\r\n *\r\n * @param {Number} [julianDayNumber=0.0] The Julian Day Number representing the number of whole days. Fractional days will also be handled correctly.\r\n * @param {Number} [secondsOfDay=0.0] The number of seconds into the current Julian Day Number. Fractional seconds, negative seconds and seconds greater than a day will be handled correctly.\r\n * @param {TimeStandard} [timeStandard=TimeStandard.UTC] The time standard in which the first two parameters are defined.\r\n */\r\nfunction JulianDate(julianDayNumber, secondsOfDay, timeStandard) {\r\n /**\r\n * Gets or sets the number of whole days.\r\n * @type {Number}\r\n */\r\n this.dayNumber = undefined;\r\n\r\n /**\r\n * Gets or sets the number of seconds into the current day.\r\n * @type {Number}\r\n */\r\n this.secondsOfDay = undefined;\r\n\r\n julianDayNumber = defaultValue(julianDayNumber, 0.0);\r\n secondsOfDay = defaultValue(secondsOfDay, 0.0);\r\n timeStandard = defaultValue(timeStandard, TimeStandard.UTC);\r\n\r\n //If julianDayNumber is fractional, make it an integer and add the number of seconds the fraction represented.\r\n var wholeDays = julianDayNumber | 0;\r\n secondsOfDay =\r\n secondsOfDay +\r\n (julianDayNumber - wholeDays) * TimeConstants.SECONDS_PER_DAY;\r\n\r\n setComponents(wholeDays, secondsOfDay, this);\r\n\r\n if (timeStandard === TimeStandard.UTC) {\r\n convertUtcToTai(this);\r\n }\r\n}\r\n\r\n/**\r\n * Creates a new instance from a GregorianDate.\r\n *\r\n * @param {GregorianDate} date A GregorianDate.\r\n * @param {JulianDate} [result] An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter or a new instance if none was provided.\r\n *\r\n * @exception {DeveloperError} date must be a valid GregorianDate.\r\n */\r\nJulianDate.fromGregorianDate = function (date, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!(date instanceof GregorianDate)) {\r\n throw new DeveloperError(\"date must be a valid GregorianDate.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var components = computeJulianDateComponents(\r\n date.year,\r\n date.month,\r\n date.day,\r\n date.hour,\r\n date.minute,\r\n date.second,\r\n date.millisecond\r\n );\r\n if (!defined(result)) {\r\n return new JulianDate(components[0], components[1], TimeStandard.UTC);\r\n }\r\n setComponents(components[0], components[1], result);\r\n convertUtcToTai(result);\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new instance from a JavaScript Date.\r\n *\r\n * @param {Date} date A JavaScript Date.\r\n * @param {JulianDate} [result] An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter or a new instance if none was provided.\r\n *\r\n * @exception {DeveloperError} date must be a valid JavaScript Date.\r\n */\r\nJulianDate.fromDate = function (date, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!(date instanceof Date) || isNaN(date.getTime())) {\r\n throw new DeveloperError(\"date must be a valid JavaScript Date.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var components = computeJulianDateComponents(\r\n date.getUTCFullYear(),\r\n date.getUTCMonth() + 1,\r\n date.getUTCDate(),\r\n date.getUTCHours(),\r\n date.getUTCMinutes(),\r\n date.getUTCSeconds(),\r\n date.getUTCMilliseconds()\r\n );\r\n if (!defined(result)) {\r\n return new JulianDate(components[0], components[1], TimeStandard.UTC);\r\n }\r\n setComponents(components[0], components[1], result);\r\n convertUtcToTai(result);\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new instance from a from an {@link http://en.wikipedia.org/wiki/ISO_8601|ISO 8601} date.\r\n * This method is superior to Date.parse because it will handle all valid formats defined by the ISO 8601\r\n * specification, including leap seconds and sub-millisecond times, which discarded by most JavaScript implementations.\r\n *\r\n * @param {String} iso8601String An ISO 8601 date.\r\n * @param {JulianDate} [result] An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter or a new instance if none was provided.\r\n *\r\n * @exception {DeveloperError} Invalid ISO 8601 date.\r\n */\r\nJulianDate.fromIso8601 = function (iso8601String, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof iso8601String !== \"string\") {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n //Comma and decimal point both indicate a fractional number according to ISO 8601,\r\n //start out by blanket replacing , with . which is the only valid such symbol in JS.\r\n iso8601String = iso8601String.replace(\",\", \".\");\r\n\r\n //Split the string into its date and time components, denoted by a mandatory T\r\n var tokens = iso8601String.split(\"T\");\r\n var year;\r\n var month = 1;\r\n var day = 1;\r\n var hour = 0;\r\n var minute = 0;\r\n var second = 0;\r\n var millisecond = 0;\r\n\r\n //Lacking a time is okay, but a missing date is illegal.\r\n var date = tokens[0];\r\n var time = tokens[1];\r\n var tmp;\r\n var inLeapYear;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(date)) {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n\r\n var dashCount;\r\n //>>includeEnd('debug');\r\n\r\n //First match the date against possible regular expressions.\r\n tokens = date.match(matchCalendarDate);\r\n if (tokens !== null) {\r\n //>>includeStart('debug', pragmas.debug);\r\n dashCount = date.split(\"-\").length - 1;\r\n if (dashCount > 0 && dashCount !== 2) {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n //>>includeEnd('debug');\r\n year = +tokens[1];\r\n month = +tokens[2];\r\n day = +tokens[3];\r\n } else {\r\n tokens = date.match(matchCalendarMonth);\r\n if (tokens !== null) {\r\n year = +tokens[1];\r\n month = +tokens[2];\r\n } else {\r\n tokens = date.match(matchCalendarYear);\r\n if (tokens !== null) {\r\n year = +tokens[1];\r\n } else {\r\n //Not a year/month/day so it must be an ordinal date.\r\n var dayOfYear;\r\n tokens = date.match(matchOrdinalDate);\r\n if (tokens !== null) {\r\n year = +tokens[1];\r\n dayOfYear = +tokens[2];\r\n inLeapYear = isLeapYear(year);\r\n\r\n //This validation is only applicable for this format.\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n dayOfYear < 1 ||\r\n (inLeapYear && dayOfYear > 366) ||\r\n (!inLeapYear && dayOfYear > 365)\r\n ) {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n //>>includeEnd('debug')\r\n } else {\r\n tokens = date.match(matchWeekDate);\r\n if (tokens !== null) {\r\n //ISO week date to ordinal date from\r\n //http://en.wikipedia.org/w/index.php?title=ISO_week_date&oldid=474176775\r\n year = +tokens[1];\r\n var weekNumber = +tokens[2];\r\n var dayOfWeek = +tokens[3] || 0;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n dashCount = date.split(\"-\").length - 1;\r\n if (\r\n dashCount > 0 &&\r\n ((!defined(tokens[3]) && dashCount !== 1) ||\r\n (defined(tokens[3]) && dashCount !== 2))\r\n ) {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n //>>includeEnd('debug')\r\n\r\n var january4 = new Date(Date.UTC(year, 0, 4));\r\n dayOfYear = weekNumber * 7 + dayOfWeek - january4.getUTCDay() - 3;\r\n } else {\r\n //None of our regular expressions succeeded in parsing the date properly.\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n //>>includeEnd('debug')\r\n }\r\n }\r\n //Split an ordinal date into month/day.\r\n tmp = new Date(Date.UTC(year, 0, 1));\r\n tmp.setUTCDate(dayOfYear);\r\n month = tmp.getUTCMonth() + 1;\r\n day = tmp.getUTCDate();\r\n }\r\n }\r\n }\r\n\r\n //Now that we have all of the date components, validate them to make sure nothing is out of range.\r\n inLeapYear = isLeapYear(year);\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n month < 1 ||\r\n month > 12 ||\r\n day < 1 ||\r\n ((month !== 2 || !inLeapYear) && day > daysInMonth[month - 1]) ||\r\n (inLeapYear && month === 2 && day > daysInLeapFeburary)\r\n ) {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n //>>includeEnd('debug')\r\n\r\n //Now move onto the time string, which is much simpler.\r\n //If no time is specified, it is considered the beginning of the day, UTC to match Javascript's implementation.\r\n var offsetIndex;\r\n if (defined(time)) {\r\n tokens = time.match(matchHoursMinutesSeconds);\r\n if (tokens !== null) {\r\n //>>includeStart('debug', pragmas.debug);\r\n dashCount = time.split(\":\").length - 1;\r\n if (dashCount > 0 && dashCount !== 2 && dashCount !== 3) {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n //>>includeEnd('debug')\r\n\r\n hour = +tokens[1];\r\n minute = +tokens[2];\r\n second = +tokens[3];\r\n millisecond = +(tokens[4] || 0) * 1000.0;\r\n offsetIndex = 5;\r\n } else {\r\n tokens = time.match(matchHoursMinutes);\r\n if (tokens !== null) {\r\n //>>includeStart('debug', pragmas.debug);\r\n dashCount = time.split(\":\").length - 1;\r\n if (dashCount > 2) {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n //>>includeEnd('debug')\r\n\r\n hour = +tokens[1];\r\n minute = +tokens[2];\r\n second = +(tokens[3] || 0) * 60.0;\r\n offsetIndex = 4;\r\n } else {\r\n tokens = time.match(matchHours);\r\n if (tokens !== null) {\r\n hour = +tokens[1];\r\n minute = +(tokens[2] || 0) * 60.0;\r\n offsetIndex = 3;\r\n } else {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n //>>includeEnd('debug')\r\n }\r\n }\r\n }\r\n\r\n //Validate that all values are in proper range. Minutes and hours have special cases at 60 and 24.\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n minute >= 60 ||\r\n second >= 61 ||\r\n hour > 24 ||\r\n (hour === 24 && (minute > 0 || second > 0 || millisecond > 0))\r\n ) {\r\n throw new DeveloperError(iso8601ErrorMessage);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n //Check the UTC offset value, if no value exists, use local time\r\n //a Z indicates UTC, + or - are offsets.\r\n var offset = tokens[offsetIndex];\r\n var offsetHours = +tokens[offsetIndex + 1];\r\n var offsetMinutes = +(tokens[offsetIndex + 2] || 0);\r\n switch (offset) {\r\n case \"+\":\r\n hour = hour - offsetHours;\r\n minute = minute - offsetMinutes;\r\n break;\r\n case \"-\":\r\n hour = hour + offsetHours;\r\n minute = minute + offsetMinutes;\r\n break;\r\n case \"Z\":\r\n break;\r\n default:\r\n minute =\r\n minute +\r\n new Date(\r\n Date.UTC(year, month - 1, day, hour, minute)\r\n ).getTimezoneOffset();\r\n break;\r\n }\r\n }\r\n\r\n //ISO8601 denotes a leap second by any time having a seconds component of 60 seconds.\r\n //If that's the case, we need to temporarily subtract a second in order to build a UTC date.\r\n //Then we add it back in after converting to TAI.\r\n var isLeapSecond = second === 60;\r\n if (isLeapSecond) {\r\n second--;\r\n }\r\n\r\n //Even if we successfully parsed the string into its components, after applying UTC offset or\r\n //special cases like 24:00:00 denoting midnight, we need to normalize the data appropriately.\r\n\r\n //milliseconds can never be greater than 1000, and seconds can't be above 60, so we start with minutes\r\n while (minute >= 60) {\r\n minute -= 60;\r\n hour++;\r\n }\r\n\r\n while (hour >= 24) {\r\n hour -= 24;\r\n day++;\r\n }\r\n\r\n tmp = inLeapYear && month === 2 ? daysInLeapFeburary : daysInMonth[month - 1];\r\n while (day > tmp) {\r\n day -= tmp;\r\n month++;\r\n\r\n if (month > 12) {\r\n month -= 12;\r\n year++;\r\n }\r\n\r\n tmp =\r\n inLeapYear && month === 2 ? daysInLeapFeburary : daysInMonth[month - 1];\r\n }\r\n\r\n //If UTC offset is at the beginning/end of the day, minutes can be negative.\r\n while (minute < 0) {\r\n minute += 60;\r\n hour--;\r\n }\r\n\r\n while (hour < 0) {\r\n hour += 24;\r\n day--;\r\n }\r\n\r\n while (day < 1) {\r\n month--;\r\n if (month < 1) {\r\n month += 12;\r\n year--;\r\n }\r\n\r\n tmp =\r\n inLeapYear && month === 2 ? daysInLeapFeburary : daysInMonth[month - 1];\r\n day += tmp;\r\n }\r\n\r\n //Now create the JulianDate components from the Gregorian date and actually create our instance.\r\n var components = computeJulianDateComponents(\r\n year,\r\n month,\r\n day,\r\n hour,\r\n minute,\r\n second,\r\n millisecond\r\n );\r\n\r\n if (!defined(result)) {\r\n result = new JulianDate(components[0], components[1], TimeStandard.UTC);\r\n } else {\r\n setComponents(components[0], components[1], result);\r\n convertUtcToTai(result);\r\n }\r\n\r\n //If we were on a leap second, add it back.\r\n if (isLeapSecond) {\r\n JulianDate.addSeconds(result, 1, result);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new instance that represents the current system time.\r\n * This is equivalent to calling JulianDate.fromDate(new Date());.\r\n *\r\n * @param {JulianDate} [result] An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter or a new instance if none was provided.\r\n */\r\nJulianDate.now = function (result) {\r\n return JulianDate.fromDate(new Date(), result);\r\n};\r\n\r\nvar toGregorianDateScratch = new JulianDate(0, 0, TimeStandard.TAI);\r\n\r\n/**\r\n * Creates a {@link GregorianDate} from the provided instance.\r\n *\r\n * @param {JulianDate} julianDate The date to be converted.\r\n * @param {GregorianDate} [result] An existing instance to use for the result.\r\n * @returns {GregorianDate} The modified result parameter or a new instance if none was provided.\r\n */\r\nJulianDate.toGregorianDate = function (julianDate, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(julianDate)) {\r\n throw new DeveloperError(\"julianDate is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var isLeapSecond = false;\r\n var thisUtc = convertTaiToUtc(julianDate, toGregorianDateScratch);\r\n if (!defined(thisUtc)) {\r\n //Conversion to UTC will fail if we are during a leap second.\r\n //If that's the case, subtract a second and convert again.\r\n //JavaScript doesn't support leap seconds, so this results in second 59 being repeated twice.\r\n JulianDate.addSeconds(julianDate, -1, toGregorianDateScratch);\r\n thisUtc = convertTaiToUtc(toGregorianDateScratch, toGregorianDateScratch);\r\n isLeapSecond = true;\r\n }\r\n\r\n var julianDayNumber = thisUtc.dayNumber;\r\n var secondsOfDay = thisUtc.secondsOfDay;\r\n\r\n if (secondsOfDay >= 43200.0) {\r\n julianDayNumber += 1;\r\n }\r\n\r\n // Algorithm from page 604 of the Explanatory Supplement to the\r\n // Astronomical Almanac (Seidelmann 1992).\r\n var L = (julianDayNumber + 68569) | 0;\r\n var N = ((4 * L) / 146097) | 0;\r\n L = (L - (((146097 * N + 3) / 4) | 0)) | 0;\r\n var I = ((4000 * (L + 1)) / 1461001) | 0;\r\n L = (L - (((1461 * I) / 4) | 0) + 31) | 0;\r\n var J = ((80 * L) / 2447) | 0;\r\n var day = (L - (((2447 * J) / 80) | 0)) | 0;\r\n L = (J / 11) | 0;\r\n var month = (J + 2 - 12 * L) | 0;\r\n var year = (100 * (N - 49) + I + L) | 0;\r\n\r\n var hour = (secondsOfDay / TimeConstants.SECONDS_PER_HOUR) | 0;\r\n var remainingSeconds = secondsOfDay - hour * TimeConstants.SECONDS_PER_HOUR;\r\n var minute = (remainingSeconds / TimeConstants.SECONDS_PER_MINUTE) | 0;\r\n remainingSeconds =\r\n remainingSeconds - minute * TimeConstants.SECONDS_PER_MINUTE;\r\n var second = remainingSeconds | 0;\r\n var millisecond =\r\n (remainingSeconds - second) / TimeConstants.SECONDS_PER_MILLISECOND;\r\n\r\n // JulianDates are noon-based\r\n hour += 12;\r\n if (hour > 23) {\r\n hour -= 24;\r\n }\r\n\r\n //If we were on a leap second, add it back.\r\n if (isLeapSecond) {\r\n second += 1;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new GregorianDate(\r\n year,\r\n month,\r\n day,\r\n hour,\r\n minute,\r\n second,\r\n millisecond,\r\n isLeapSecond\r\n );\r\n }\r\n\r\n result.year = year;\r\n result.month = month;\r\n result.day = day;\r\n result.hour = hour;\r\n result.minute = minute;\r\n result.second = second;\r\n result.millisecond = millisecond;\r\n result.isLeapSecond = isLeapSecond;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a JavaScript Date from the provided instance.\r\n * Since JavaScript dates are only accurate to the nearest millisecond and\r\n * cannot represent a leap second, consider using {@link JulianDate.toGregorianDate} instead.\r\n * If the provided JulianDate is during a leap second, the previous second is used.\r\n *\r\n * @param {JulianDate} julianDate The date to be converted.\r\n * @returns {Date} A new instance representing the provided date.\r\n */\r\nJulianDate.toDate = function (julianDate) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(julianDate)) {\r\n throw new DeveloperError(\"julianDate is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var gDate = JulianDate.toGregorianDate(julianDate, gregorianDateScratch);\r\n var second = gDate.second;\r\n if (gDate.isLeapSecond) {\r\n second -= 1;\r\n }\r\n return new Date(\r\n Date.UTC(\r\n gDate.year,\r\n gDate.month - 1,\r\n gDate.day,\r\n gDate.hour,\r\n gDate.minute,\r\n second,\r\n gDate.millisecond\r\n )\r\n );\r\n};\r\n\r\n/**\r\n * Creates an ISO8601 representation of the provided date.\r\n *\r\n * @param {JulianDate} julianDate The date to be converted.\r\n * @param {Number} [precision] The number of fractional digits used to represent the seconds component. By default, the most precise representation is used.\r\n * @returns {String} The ISO8601 representation of the provided date.\r\n */\r\nJulianDate.toIso8601 = function (julianDate, precision) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(julianDate)) {\r\n throw new DeveloperError(\"julianDate is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var gDate = JulianDate.toGregorianDate(julianDate, gregorianDateScratch);\r\n var year = gDate.year;\r\n var month = gDate.month;\r\n var day = gDate.day;\r\n var hour = gDate.hour;\r\n var minute = gDate.minute;\r\n var second = gDate.second;\r\n var millisecond = gDate.millisecond;\r\n\r\n // special case - Iso8601.MAXIMUM_VALUE produces a string which we can't parse unless we adjust.\r\n // 10000-01-01T00:00:00 is the same instant as 9999-12-31T24:00:00\r\n if (\r\n year === 10000 &&\r\n month === 1 &&\r\n day === 1 &&\r\n hour === 0 &&\r\n minute === 0 &&\r\n second === 0 &&\r\n millisecond === 0\r\n ) {\r\n year = 9999;\r\n month = 12;\r\n day = 31;\r\n hour = 24;\r\n }\r\n\r\n var millisecondStr;\r\n\r\n if (!defined(precision) && millisecond !== 0) {\r\n //Forces milliseconds into a number with at least 3 digits to whatever the default toString() precision is.\r\n millisecondStr = (millisecond * 0.01).toString().replace(\".\", \"\");\r\n return sprintf(\r\n \"%04d-%02d-%02dT%02d:%02d:%02d.%sZ\",\r\n year,\r\n month,\r\n day,\r\n hour,\r\n minute,\r\n second,\r\n millisecondStr\r\n );\r\n }\r\n\r\n //Precision is either 0 or milliseconds is 0 with undefined precision, in either case, leave off milliseconds entirely\r\n if (!defined(precision) || precision === 0) {\r\n return sprintf(\r\n \"%04d-%02d-%02dT%02d:%02d:%02dZ\",\r\n year,\r\n month,\r\n day,\r\n hour,\r\n minute,\r\n second\r\n );\r\n }\r\n\r\n //Forces milliseconds into a number with at least 3 digits to whatever the specified precision is.\r\n millisecondStr = (millisecond * 0.01)\r\n .toFixed(precision)\r\n .replace(\".\", \"\")\r\n .slice(0, precision);\r\n return sprintf(\r\n \"%04d-%02d-%02dT%02d:%02d:%02d.%sZ\",\r\n year,\r\n month,\r\n day,\r\n hour,\r\n minute,\r\n second,\r\n millisecondStr\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates a JulianDate instance.\r\n *\r\n * @param {JulianDate} julianDate The date to duplicate.\r\n * @param {JulianDate} [result] An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter or a new instance if none was provided. Returns undefined if julianDate is undefined.\r\n */\r\nJulianDate.clone = function (julianDate, result) {\r\n if (!defined(julianDate)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new JulianDate(\r\n julianDate.dayNumber,\r\n julianDate.secondsOfDay,\r\n TimeStandard.TAI\r\n );\r\n }\r\n result.dayNumber = julianDate.dayNumber;\r\n result.secondsOfDay = julianDate.secondsOfDay;\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares two instances.\r\n *\r\n * @param {JulianDate} left The first instance.\r\n * @param {JulianDate} right The second instance.\r\n * @returns {Number} A negative value if left is less than right, a positive value if left is greater than right, or zero if left and right are equal.\r\n */\r\nJulianDate.compare = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\"left is required.\");\r\n }\r\n if (!defined(right)) {\r\n throw new DeveloperError(\"right is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var julianDayNumberDifference = left.dayNumber - right.dayNumber;\r\n if (julianDayNumberDifference !== 0) {\r\n return julianDayNumberDifference;\r\n }\r\n return left.secondsOfDay - right.secondsOfDay;\r\n};\r\n\r\n/**\r\n * Compares two instances and returns true if they are equal, false otherwise.\r\n *\r\n * @param {JulianDate} [left] The first instance.\r\n * @param {JulianDate} [right] The second instance.\r\n * @returns {Boolean} true if the dates are equal; otherwise, false.\r\n */\r\nJulianDate.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.dayNumber === right.dayNumber &&\r\n left.secondsOfDay === right.secondsOfDay)\r\n );\r\n};\r\n\r\n/**\r\n * Compares two instances and returns true if they are within epsilon seconds of\r\n * each other. That is, in order for the dates to be considered equal (and for\r\n * this function to return true), the absolute value of the difference between them, in\r\n * seconds, must be less than epsilon.\r\n *\r\n * @param {JulianDate} [left] The first instance.\r\n * @param {JulianDate} [right] The second instance.\r\n * @param {Number} [epsilon=0] The maximum number of seconds that should separate the two instances.\r\n * @returns {Boolean} true if the two dates are within epsilon seconds of each other; otherwise false.\r\n */\r\nJulianDate.equalsEpsilon = function (left, right, epsilon) {\r\n epsilon = defaultValue(epsilon, 0);\r\n\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Math.abs(JulianDate.secondsDifference(left, right)) <= epsilon)\r\n );\r\n};\r\n\r\n/**\r\n * Computes the total number of whole and fractional days represented by the provided instance.\r\n *\r\n * @param {JulianDate} julianDate The date.\r\n * @returns {Number} The Julian date as single floating point number.\r\n */\r\nJulianDate.totalDays = function (julianDate) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(julianDate)) {\r\n throw new DeveloperError(\"julianDate is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n return (\r\n julianDate.dayNumber +\r\n julianDate.secondsOfDay / TimeConstants.SECONDS_PER_DAY\r\n );\r\n};\r\n\r\n/**\r\n * Computes the difference in seconds between the provided instance.\r\n *\r\n * @param {JulianDate} left The first instance.\r\n * @param {JulianDate} right The second instance.\r\n * @returns {Number} The difference, in seconds, when subtracting right from left.\r\n */\r\nJulianDate.secondsDifference = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\"left is required.\");\r\n }\r\n if (!defined(right)) {\r\n throw new DeveloperError(\"right is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var dayDifference =\r\n (left.dayNumber - right.dayNumber) * TimeConstants.SECONDS_PER_DAY;\r\n return dayDifference + (left.secondsOfDay - right.secondsOfDay);\r\n};\r\n\r\n/**\r\n * Computes the difference in days between the provided instance.\r\n *\r\n * @param {JulianDate} left The first instance.\r\n * @param {JulianDate} right The second instance.\r\n * @returns {Number} The difference, in days, when subtracting right from left.\r\n */\r\nJulianDate.daysDifference = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\"left is required.\");\r\n }\r\n if (!defined(right)) {\r\n throw new DeveloperError(\"right is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var dayDifference = left.dayNumber - right.dayNumber;\r\n var secondDifference =\r\n (left.secondsOfDay - right.secondsOfDay) / TimeConstants.SECONDS_PER_DAY;\r\n return dayDifference + secondDifference;\r\n};\r\n\r\n/**\r\n * Computes the number of seconds the provided instance is ahead of UTC.\r\n *\r\n * @param {JulianDate} julianDate The date.\r\n * @returns {Number} The number of seconds the provided instance is ahead of UTC\r\n */\r\nJulianDate.computeTaiMinusUtc = function (julianDate) {\r\n binarySearchScratchLeapSecond.julianDate = julianDate;\r\n var leapSeconds = JulianDate.leapSeconds;\r\n var index = binarySearch(\r\n leapSeconds,\r\n binarySearchScratchLeapSecond,\r\n compareLeapSecondDates\r\n );\r\n if (index < 0) {\r\n index = ~index;\r\n --index;\r\n if (index < 0) {\r\n index = 0;\r\n }\r\n }\r\n return leapSeconds[index].offset;\r\n};\r\n\r\n/**\r\n * Adds the provided number of seconds to the provided date instance.\r\n *\r\n * @param {JulianDate} julianDate The date.\r\n * @param {Number} seconds The number of seconds to add or subtract.\r\n * @param {JulianDate} result An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter.\r\n */\r\nJulianDate.addSeconds = function (julianDate, seconds, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(julianDate)) {\r\n throw new DeveloperError(\"julianDate is required.\");\r\n }\r\n if (!defined(seconds)) {\r\n throw new DeveloperError(\"seconds is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return setComponents(\r\n julianDate.dayNumber,\r\n julianDate.secondsOfDay + seconds,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Adds the provided number of minutes to the provided date instance.\r\n *\r\n * @param {JulianDate} julianDate The date.\r\n * @param {Number} minutes The number of minutes to add or subtract.\r\n * @param {JulianDate} result An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter.\r\n */\r\nJulianDate.addMinutes = function (julianDate, minutes, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(julianDate)) {\r\n throw new DeveloperError(\"julianDate is required.\");\r\n }\r\n if (!defined(minutes)) {\r\n throw new DeveloperError(\"minutes is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var newSecondsOfDay =\r\n julianDate.secondsOfDay + minutes * TimeConstants.SECONDS_PER_MINUTE;\r\n return setComponents(julianDate.dayNumber, newSecondsOfDay, result);\r\n};\r\n\r\n/**\r\n * Adds the provided number of hours to the provided date instance.\r\n *\r\n * @param {JulianDate} julianDate The date.\r\n * @param {Number} hours The number of hours to add or subtract.\r\n * @param {JulianDate} result An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter.\r\n */\r\nJulianDate.addHours = function (julianDate, hours, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(julianDate)) {\r\n throw new DeveloperError(\"julianDate is required.\");\r\n }\r\n if (!defined(hours)) {\r\n throw new DeveloperError(\"hours is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var newSecondsOfDay =\r\n julianDate.secondsOfDay + hours * TimeConstants.SECONDS_PER_HOUR;\r\n return setComponents(julianDate.dayNumber, newSecondsOfDay, result);\r\n};\r\n\r\n/**\r\n * Adds the provided number of days to the provided date instance.\r\n *\r\n * @param {JulianDate} julianDate The date.\r\n * @param {Number} days The number of days to add or subtract.\r\n * @param {JulianDate} result An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter.\r\n */\r\nJulianDate.addDays = function (julianDate, days, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(julianDate)) {\r\n throw new DeveloperError(\"julianDate is required.\");\r\n }\r\n if (!defined(days)) {\r\n throw new DeveloperError(\"days is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var newJulianDayNumber = julianDate.dayNumber + days;\r\n return setComponents(newJulianDayNumber, julianDate.secondsOfDay, result);\r\n};\r\n\r\n/**\r\n * Compares the provided instances and returns true if left is earlier than right, false otherwise.\r\n *\r\n * @param {JulianDate} left The first instance.\r\n * @param {JulianDate} right The second instance.\r\n * @returns {Boolean} true if left is earlier than right, false otherwise.\r\n */\r\nJulianDate.lessThan = function (left, right) {\r\n return JulianDate.compare(left, right) < 0;\r\n};\r\n\r\n/**\r\n * Compares the provided instances and returns true if left is earlier than or equal to right, false otherwise.\r\n *\r\n * @param {JulianDate} left The first instance.\r\n * @param {JulianDate} right The second instance.\r\n * @returns {Boolean} true if left is earlier than or equal to right, false otherwise.\r\n */\r\nJulianDate.lessThanOrEquals = function (left, right) {\r\n return JulianDate.compare(left, right) <= 0;\r\n};\r\n\r\n/**\r\n * Compares the provided instances and returns true if left is later than right, false otherwise.\r\n *\r\n * @param {JulianDate} left The first instance.\r\n * @param {JulianDate} right The second instance.\r\n * @returns {Boolean} true if left is later than right, false otherwise.\r\n */\r\nJulianDate.greaterThan = function (left, right) {\r\n return JulianDate.compare(left, right) > 0;\r\n};\r\n\r\n/**\r\n * Compares the provided instances and returns true if left is later than or equal to right, false otherwise.\r\n *\r\n * @param {JulianDate} left The first instance.\r\n * @param {JulianDate} right The second instance.\r\n * @returns {Boolean} true if left is later than or equal to right, false otherwise.\r\n */\r\nJulianDate.greaterThanOrEquals = function (left, right) {\r\n return JulianDate.compare(left, right) >= 0;\r\n};\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {JulianDate} [result] An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter or a new instance if none was provided.\r\n */\r\nJulianDate.prototype.clone = function (result) {\r\n return JulianDate.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this and the provided instance and returns true if they are equal, false otherwise.\r\n *\r\n * @param {JulianDate} [right] The second instance.\r\n * @returns {Boolean} true if the dates are equal; otherwise, false.\r\n */\r\nJulianDate.prototype.equals = function (right) {\r\n return JulianDate.equals(this, right);\r\n};\r\n\r\n/**\r\n * Compares this and the provided instance and returns true if they are within epsilon seconds of\r\n * each other. That is, in order for the dates to be considered equal (and for\r\n * this function to return true), the absolute value of the difference between them, in\r\n * seconds, must be less than epsilon.\r\n *\r\n * @param {JulianDate} [right] The second instance.\r\n * @param {Number} [epsilon=0] The maximum number of seconds that should separate the two instances.\r\n * @returns {Boolean} true if the two dates are within epsilon seconds of each other; otherwise false.\r\n */\r\nJulianDate.prototype.equalsEpsilon = function (right, epsilon) {\r\n return JulianDate.equalsEpsilon(this, right, epsilon);\r\n};\r\n\r\n/**\r\n * Creates a string representing this date in ISO8601 format.\r\n *\r\n * @returns {String} A string representing this date in ISO8601 format.\r\n */\r\nJulianDate.prototype.toString = function () {\r\n return JulianDate.toIso8601(this);\r\n};\r\n\r\n/**\r\n * Gets or sets the list of leap seconds used throughout Cesium.\r\n * @memberof JulianDate\r\n * @type {LeapSecond[]}\r\n */\r\nJulianDate.leapSeconds = [\r\n new LeapSecond(new JulianDate(2441317, 43210.0, TimeStandard.TAI), 10), // January 1, 1972 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2441499, 43211.0, TimeStandard.TAI), 11), // July 1, 1972 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2441683, 43212.0, TimeStandard.TAI), 12), // January 1, 1973 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2442048, 43213.0, TimeStandard.TAI), 13), // January 1, 1974 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2442413, 43214.0, TimeStandard.TAI), 14), // January 1, 1975 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2442778, 43215.0, TimeStandard.TAI), 15), // January 1, 1976 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2443144, 43216.0, TimeStandard.TAI), 16), // January 1, 1977 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2443509, 43217.0, TimeStandard.TAI), 17), // January 1, 1978 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2443874, 43218.0, TimeStandard.TAI), 18), // January 1, 1979 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2444239, 43219.0, TimeStandard.TAI), 19), // January 1, 1980 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2444786, 43220.0, TimeStandard.TAI), 20), // July 1, 1981 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2445151, 43221.0, TimeStandard.TAI), 21), // July 1, 1982 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2445516, 43222.0, TimeStandard.TAI), 22), // July 1, 1983 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2446247, 43223.0, TimeStandard.TAI), 23), // July 1, 1985 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2447161, 43224.0, TimeStandard.TAI), 24), // January 1, 1988 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2447892, 43225.0, TimeStandard.TAI), 25), // January 1, 1990 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2448257, 43226.0, TimeStandard.TAI), 26), // January 1, 1991 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2448804, 43227.0, TimeStandard.TAI), 27), // July 1, 1992 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2449169, 43228.0, TimeStandard.TAI), 28), // July 1, 1993 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2449534, 43229.0, TimeStandard.TAI), 29), // July 1, 1994 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2450083, 43230.0, TimeStandard.TAI), 30), // January 1, 1996 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2450630, 43231.0, TimeStandard.TAI), 31), // July 1, 1997 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2451179, 43232.0, TimeStandard.TAI), 32), // January 1, 1999 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2453736, 43233.0, TimeStandard.TAI), 33), // January 1, 2006 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2454832, 43234.0, TimeStandard.TAI), 34), // January 1, 2009 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2456109, 43235.0, TimeStandard.TAI), 35), // July 1, 2012 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2457204, 43236.0, TimeStandard.TAI), 36), // July 1, 2015 00:00:00 UTC\r\n new LeapSecond(new JulianDate(2457754, 43237.0, TimeStandard.TAI), 37), // January 1, 2017 00:00:00 UTC\r\n];\r\nexport default JulianDate;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport binarySearch from \"./binarySearch.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport EarthOrientationParametersSample from \"./EarthOrientationParametersSample.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\nimport LeapSecond from \"./LeapSecond.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\nimport TimeConstants from \"./TimeConstants.js\";\r\nimport TimeStandard from \"./TimeStandard.js\";\r\n\r\n/**\r\n * Specifies Earth polar motion coordinates and the difference between UT1 and UTC.\r\n * These Earth Orientation Parameters (EOP) are primarily used in the transformation from\r\n * the International Celestial Reference Frame (ICRF) to the International Terrestrial\r\n * Reference Frame (ITRF).\r\n *\r\n * @alias EarthOrientationParameters\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Resource|String} [options.url] The URL from which to obtain EOP data. If neither this\r\n * parameter nor options.data is specified, all EOP values are assumed\r\n * to be 0.0. If options.data is specified, this parameter is\r\n * ignored.\r\n * @param {Object} [options.data] The actual EOP data. If neither this\r\n * parameter nor options.data is specified, all EOP values are assumed\r\n * to be 0.0.\r\n * @param {Boolean} [options.addNewLeapSeconds=true] True if leap seconds that\r\n * are specified in the EOP data but not in {@link JulianDate.leapSeconds}\r\n * should be added to {@link JulianDate.leapSeconds}. False if\r\n * new leap seconds should be handled correctly in the context\r\n * of the EOP data but otherwise ignored.\r\n *\r\n * @example\r\n * // An example EOP data file, EOP.json:\r\n * {\r\n * \"columnNames\" : [\"dateIso8601\",\"modifiedJulianDateUtc\",\"xPoleWanderRadians\",\"yPoleWanderRadians\",\"ut1MinusUtcSeconds\",\"lengthOfDayCorrectionSeconds\",\"xCelestialPoleOffsetRadians\",\"yCelestialPoleOffsetRadians\",\"taiMinusUtcSeconds\"],\r\n * \"samples\" : [\r\n * \"2011-07-01T00:00:00Z\",55743.0,2.117957047295119e-7,2.111518721609984e-6,-0.2908948,-2.956e-4,3.393695767766752e-11,3.3452143996557983e-10,34.0,\r\n * \"2011-07-02T00:00:00Z\",55744.0,2.193297093339541e-7,2.115460256837405e-6,-0.29065,-1.824e-4,-8.241832578862112e-11,5.623838700870617e-10,34.0,\r\n * \"2011-07-03T00:00:00Z\",55745.0,2.262286080161428e-7,2.1191157519929706e-6,-0.2905572,1.9e-6,-3.490658503988659e-10,6.981317007977318e-10,34.0\r\n * ]\r\n * }\r\n *\r\n * @example\r\n * // Loading the EOP data\r\n * var eop = new Cesium.EarthOrientationParameters({ url : 'Data/EOP.json' });\r\n * Cesium.Transforms.earthOrientationParameters = eop;\r\n *\r\n * @private\r\n */\r\nfunction EarthOrientationParameters(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._dates = undefined;\r\n this._samples = undefined;\r\n\r\n this._dateColumn = -1;\r\n this._xPoleWanderRadiansColumn = -1;\r\n this._yPoleWanderRadiansColumn = -1;\r\n this._ut1MinusUtcSecondsColumn = -1;\r\n this._xCelestialPoleOffsetRadiansColumn = -1;\r\n this._yCelestialPoleOffsetRadiansColumn = -1;\r\n this._taiMinusUtcSecondsColumn = -1;\r\n\r\n this._columnCount = 0;\r\n this._lastIndex = -1;\r\n\r\n this._downloadPromise = undefined;\r\n this._dataError = undefined;\r\n\r\n this._addNewLeapSeconds = defaultValue(options.addNewLeapSeconds, true);\r\n\r\n if (defined(options.data)) {\r\n // Use supplied EOP data.\r\n onDataReady(this, options.data);\r\n } else if (defined(options.url)) {\r\n var resource = Resource.createIfNeeded(options.url);\r\n\r\n // Download EOP data.\r\n var that = this;\r\n this._downloadPromise = resource\r\n .fetchJson()\r\n .then(function (eopData) {\r\n onDataReady(that, eopData);\r\n })\r\n .otherwise(function () {\r\n that._dataError =\r\n \"An error occurred while retrieving the EOP data from the URL \" +\r\n resource.url +\r\n \".\";\r\n });\r\n } else {\r\n // Use all zeros for EOP data.\r\n onDataReady(this, {\r\n columnNames: [\r\n \"dateIso8601\",\r\n \"modifiedJulianDateUtc\",\r\n \"xPoleWanderRadians\",\r\n \"yPoleWanderRadians\",\r\n \"ut1MinusUtcSeconds\",\r\n \"lengthOfDayCorrectionSeconds\",\r\n \"xCelestialPoleOffsetRadians\",\r\n \"yCelestialPoleOffsetRadians\",\r\n \"taiMinusUtcSeconds\",\r\n ],\r\n samples: [],\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * A default {@link EarthOrientationParameters} instance that returns zero for all EOP values.\r\n */\r\nEarthOrientationParameters.NONE = Object.freeze({\r\n getPromiseToLoad: function () {\r\n return when.resolve();\r\n },\r\n compute: function (date, result) {\r\n if (!defined(result)) {\r\n result = new EarthOrientationParametersSample(0.0, 0.0, 0.0, 0.0, 0.0);\r\n } else {\r\n result.xPoleWander = 0.0;\r\n result.yPoleWander = 0.0;\r\n result.xPoleOffset = 0.0;\r\n result.yPoleOffset = 0.0;\r\n result.ut1MinusUtc = 0.0;\r\n }\r\n return result;\r\n },\r\n});\r\n\r\n/**\r\n * Gets a promise that, when resolved, indicates that the EOP data has been loaded and is\r\n * ready to use.\r\n *\r\n * @returns {Promise} The promise.\r\n */\r\nEarthOrientationParameters.prototype.getPromiseToLoad = function () {\r\n return when(this._downloadPromise);\r\n};\r\n\r\n/**\r\n * Computes the Earth Orientation Parameters (EOP) for a given date by interpolating.\r\n * If the EOP data has not yet been download, this method returns undefined.\r\n *\r\n * @param {JulianDate} date The date for each to evaluate the EOP.\r\n * @param {EarthOrientationParametersSample} [result] The instance to which to copy the result.\r\n * If this parameter is undefined, a new instance is created and returned.\r\n * @returns {EarthOrientationParametersSample} The EOP evaluated at the given date, or\r\n * undefined if the data necessary to evaluate EOP at the date has not yet been\r\n * downloaded.\r\n *\r\n * @exception {RuntimeError} The loaded EOP data has an error and cannot be used.\r\n *\r\n * @see EarthOrientationParameters#getPromiseToLoad\r\n */\r\nEarthOrientationParameters.prototype.compute = function (date, result) {\r\n // We cannot compute until the samples are available.\r\n if (!defined(this._samples)) {\r\n if (defined(this._dataError)) {\r\n throw new RuntimeError(this._dataError);\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new EarthOrientationParametersSample(0.0, 0.0, 0.0, 0.0, 0.0);\r\n }\r\n\r\n if (this._samples.length === 0) {\r\n result.xPoleWander = 0.0;\r\n result.yPoleWander = 0.0;\r\n result.xPoleOffset = 0.0;\r\n result.yPoleOffset = 0.0;\r\n result.ut1MinusUtc = 0.0;\r\n return result;\r\n }\r\n\r\n var dates = this._dates;\r\n var lastIndex = this._lastIndex;\r\n\r\n var before = 0;\r\n var after = 0;\r\n if (defined(lastIndex)) {\r\n var previousIndexDate = dates[lastIndex];\r\n var nextIndexDate = dates[lastIndex + 1];\r\n var isAfterPrevious = JulianDate.lessThanOrEquals(previousIndexDate, date);\r\n var isAfterLastSample = !defined(nextIndexDate);\r\n var isBeforeNext =\r\n isAfterLastSample || JulianDate.greaterThanOrEquals(nextIndexDate, date);\r\n\r\n if (isAfterPrevious && isBeforeNext) {\r\n before = lastIndex;\r\n\r\n if (!isAfterLastSample && nextIndexDate.equals(date)) {\r\n ++before;\r\n }\r\n after = before + 1;\r\n\r\n interpolate(this, dates, this._samples, date, before, after, result);\r\n return result;\r\n }\r\n }\r\n\r\n var index = binarySearch(dates, date, JulianDate.compare, this._dateColumn);\r\n if (index >= 0) {\r\n // If the next entry is the same date, use the later entry. This way, if two entries\r\n // describe the same moment, one before a leap second and the other after, then we will use\r\n // the post-leap second data.\r\n if (index < dates.length - 1 && dates[index + 1].equals(date)) {\r\n ++index;\r\n }\r\n before = index;\r\n after = index;\r\n } else {\r\n after = ~index;\r\n before = after - 1;\r\n\r\n // Use the first entry if the date requested is before the beginning of the data.\r\n if (before < 0) {\r\n before = 0;\r\n }\r\n }\r\n\r\n this._lastIndex = before;\r\n\r\n interpolate(this, dates, this._samples, date, before, after, result);\r\n return result;\r\n};\r\n\r\nfunction compareLeapSecondDates(leapSecond, dateToFind) {\r\n return JulianDate.compare(leapSecond.julianDate, dateToFind);\r\n}\r\n\r\nfunction onDataReady(eop, eopData) {\r\n if (!defined(eopData.columnNames)) {\r\n eop._dataError =\r\n \"Error in loaded EOP data: The columnNames property is required.\";\r\n return;\r\n }\r\n\r\n if (!defined(eopData.samples)) {\r\n eop._dataError =\r\n \"Error in loaded EOP data: The samples property is required.\";\r\n return;\r\n }\r\n\r\n var dateColumn = eopData.columnNames.indexOf(\"modifiedJulianDateUtc\");\r\n var xPoleWanderRadiansColumn = eopData.columnNames.indexOf(\r\n \"xPoleWanderRadians\"\r\n );\r\n var yPoleWanderRadiansColumn = eopData.columnNames.indexOf(\r\n \"yPoleWanderRadians\"\r\n );\r\n var ut1MinusUtcSecondsColumn = eopData.columnNames.indexOf(\r\n \"ut1MinusUtcSeconds\"\r\n );\r\n var xCelestialPoleOffsetRadiansColumn = eopData.columnNames.indexOf(\r\n \"xCelestialPoleOffsetRadians\"\r\n );\r\n var yCelestialPoleOffsetRadiansColumn = eopData.columnNames.indexOf(\r\n \"yCelestialPoleOffsetRadians\"\r\n );\r\n var taiMinusUtcSecondsColumn = eopData.columnNames.indexOf(\r\n \"taiMinusUtcSeconds\"\r\n );\r\n\r\n if (\r\n dateColumn < 0 ||\r\n xPoleWanderRadiansColumn < 0 ||\r\n yPoleWanderRadiansColumn < 0 ||\r\n ut1MinusUtcSecondsColumn < 0 ||\r\n xCelestialPoleOffsetRadiansColumn < 0 ||\r\n yCelestialPoleOffsetRadiansColumn < 0 ||\r\n taiMinusUtcSecondsColumn < 0\r\n ) {\r\n eop._dataError =\r\n \"Error in loaded EOP data: The columnNames property must include modifiedJulianDateUtc, xPoleWanderRadians, yPoleWanderRadians, ut1MinusUtcSeconds, xCelestialPoleOffsetRadians, yCelestialPoleOffsetRadians, and taiMinusUtcSeconds columns\";\r\n return;\r\n }\r\n\r\n var samples = (eop._samples = eopData.samples);\r\n var dates = (eop._dates = []);\r\n\r\n eop._dateColumn = dateColumn;\r\n eop._xPoleWanderRadiansColumn = xPoleWanderRadiansColumn;\r\n eop._yPoleWanderRadiansColumn = yPoleWanderRadiansColumn;\r\n eop._ut1MinusUtcSecondsColumn = ut1MinusUtcSecondsColumn;\r\n eop._xCelestialPoleOffsetRadiansColumn = xCelestialPoleOffsetRadiansColumn;\r\n eop._yCelestialPoleOffsetRadiansColumn = yCelestialPoleOffsetRadiansColumn;\r\n eop._taiMinusUtcSecondsColumn = taiMinusUtcSecondsColumn;\r\n\r\n eop._columnCount = eopData.columnNames.length;\r\n eop._lastIndex = undefined;\r\n\r\n var lastTaiMinusUtc;\r\n\r\n var addNewLeapSeconds = eop._addNewLeapSeconds;\r\n\r\n // Convert the ISO8601 dates to JulianDates.\r\n for (var i = 0, len = samples.length; i < len; i += eop._columnCount) {\r\n var mjd = samples[i + dateColumn];\r\n var taiMinusUtc = samples[i + taiMinusUtcSecondsColumn];\r\n var day = mjd + TimeConstants.MODIFIED_JULIAN_DATE_DIFFERENCE;\r\n var date = new JulianDate(day, taiMinusUtc, TimeStandard.TAI);\r\n dates.push(date);\r\n\r\n if (addNewLeapSeconds) {\r\n if (taiMinusUtc !== lastTaiMinusUtc && defined(lastTaiMinusUtc)) {\r\n // We crossed a leap second boundary, so add the leap second\r\n // if it does not already exist.\r\n var leapSeconds = JulianDate.leapSeconds;\r\n var leapSecondIndex = binarySearch(\r\n leapSeconds,\r\n date,\r\n compareLeapSecondDates\r\n );\r\n if (leapSecondIndex < 0) {\r\n var leapSecond = new LeapSecond(date, taiMinusUtc);\r\n leapSeconds.splice(~leapSecondIndex, 0, leapSecond);\r\n }\r\n }\r\n lastTaiMinusUtc = taiMinusUtc;\r\n }\r\n }\r\n}\r\n\r\nfunction fillResultFromIndex(eop, samples, index, columnCount, result) {\r\n var start = index * columnCount;\r\n result.xPoleWander = samples[start + eop._xPoleWanderRadiansColumn];\r\n result.yPoleWander = samples[start + eop._yPoleWanderRadiansColumn];\r\n result.xPoleOffset = samples[start + eop._xCelestialPoleOffsetRadiansColumn];\r\n result.yPoleOffset = samples[start + eop._yCelestialPoleOffsetRadiansColumn];\r\n result.ut1MinusUtc = samples[start + eop._ut1MinusUtcSecondsColumn];\r\n}\r\n\r\nfunction linearInterp(dx, y1, y2) {\r\n return y1 + dx * (y2 - y1);\r\n}\r\n\r\nfunction interpolate(eop, dates, samples, date, before, after, result) {\r\n var columnCount = eop._columnCount;\r\n\r\n // First check the bounds on the EOP data\r\n // If we are after the bounds of the data, return zeros.\r\n // The 'before' index should never be less than zero.\r\n if (after > dates.length - 1) {\r\n result.xPoleWander = 0;\r\n result.yPoleWander = 0;\r\n result.xPoleOffset = 0;\r\n result.yPoleOffset = 0;\r\n result.ut1MinusUtc = 0;\r\n return result;\r\n }\r\n\r\n var beforeDate = dates[before];\r\n var afterDate = dates[after];\r\n if (beforeDate.equals(afterDate) || date.equals(beforeDate)) {\r\n fillResultFromIndex(eop, samples, before, columnCount, result);\r\n return result;\r\n } else if (date.equals(afterDate)) {\r\n fillResultFromIndex(eop, samples, after, columnCount, result);\r\n return result;\r\n }\r\n\r\n var factor =\r\n JulianDate.secondsDifference(date, beforeDate) /\r\n JulianDate.secondsDifference(afterDate, beforeDate);\r\n\r\n var startBefore = before * columnCount;\r\n var startAfter = after * columnCount;\r\n\r\n // Handle UT1 leap second edge case\r\n var beforeUt1MinusUtc = samples[startBefore + eop._ut1MinusUtcSecondsColumn];\r\n var afterUt1MinusUtc = samples[startAfter + eop._ut1MinusUtcSecondsColumn];\r\n\r\n var offsetDifference = afterUt1MinusUtc - beforeUt1MinusUtc;\r\n if (offsetDifference > 0.5 || offsetDifference < -0.5) {\r\n // The absolute difference between the values is more than 0.5, so we may have\r\n // crossed a leap second. Check if this is the case and, if so, adjust the\r\n // afterValue to account for the leap second. This way, our interpolation will\r\n // produce reasonable results.\r\n var beforeTaiMinusUtc =\r\n samples[startBefore + eop._taiMinusUtcSecondsColumn];\r\n var afterTaiMinusUtc = samples[startAfter + eop._taiMinusUtcSecondsColumn];\r\n if (beforeTaiMinusUtc !== afterTaiMinusUtc) {\r\n if (afterDate.equals(date)) {\r\n // If we are at the end of the leap second interval, take the second value\r\n // Otherwise, the interpolation below will yield the wrong side of the\r\n // discontinuity\r\n // At the end of the leap second, we need to start accounting for the jump\r\n beforeUt1MinusUtc = afterUt1MinusUtc;\r\n } else {\r\n // Otherwise, remove the leap second so that the interpolation is correct\r\n afterUt1MinusUtc -= afterTaiMinusUtc - beforeTaiMinusUtc;\r\n }\r\n }\r\n }\r\n\r\n result.xPoleWander = linearInterp(\r\n factor,\r\n samples[startBefore + eop._xPoleWanderRadiansColumn],\r\n samples[startAfter + eop._xPoleWanderRadiansColumn]\r\n );\r\n result.yPoleWander = linearInterp(\r\n factor,\r\n samples[startBefore + eop._yPoleWanderRadiansColumn],\r\n samples[startAfter + eop._yPoleWanderRadiansColumn]\r\n );\r\n result.xPoleOffset = linearInterp(\r\n factor,\r\n samples[startBefore + eop._xCelestialPoleOffsetRadiansColumn],\r\n samples[startAfter + eop._xCelestialPoleOffsetRadiansColumn]\r\n );\r\n result.yPoleOffset = linearInterp(\r\n factor,\r\n samples[startBefore + eop._yCelestialPoleOffsetRadiansColumn],\r\n samples[startAfter + eop._yCelestialPoleOffsetRadiansColumn]\r\n );\r\n result.ut1MinusUtc = linearInterp(\r\n factor,\r\n beforeUt1MinusUtc,\r\n afterUt1MinusUtc\r\n );\r\n return result;\r\n}\r\nexport default EarthOrientationParameters;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * A rotation expressed as a heading, pitch, and roll. Heading is the rotation about the\r\n * negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about\r\n * the positive x axis.\r\n * @alias HeadingPitchRoll\r\n * @constructor\r\n *\r\n * @param {Number} [heading=0.0] The heading component in radians.\r\n * @param {Number} [pitch=0.0] The pitch component in radians.\r\n * @param {Number} [roll=0.0] The roll component in radians.\r\n */\r\nfunction HeadingPitchRoll(heading, pitch, roll) {\r\n /**\r\n * Gets or sets the heading.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.heading = defaultValue(heading, 0.0);\r\n /**\r\n * Gets or sets the pitch.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.pitch = defaultValue(pitch, 0.0);\r\n /**\r\n * Gets or sets the roll.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.roll = defaultValue(roll, 0.0);\r\n}\r\n\r\n/**\r\n * Computes the heading, pitch and roll from a quaternion (see http://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles )\r\n *\r\n * @param {Quaternion} quaternion The quaternion from which to retrieve heading, pitch, and roll, all expressed in radians.\r\n * @param {HeadingPitchRoll} [result] The object in which to store the result. If not provided, a new instance is created and returned.\r\n * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided.\r\n */\r\nHeadingPitchRoll.fromQuaternion = function (quaternion, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(quaternion)) {\r\n throw new DeveloperError(\"quaternion is required\");\r\n }\r\n //>>includeEnd('debug');\r\n if (!defined(result)) {\r\n result = new HeadingPitchRoll();\r\n }\r\n var test = 2 * (quaternion.w * quaternion.y - quaternion.z * quaternion.x);\r\n var denominatorRoll =\r\n 1 - 2 * (quaternion.x * quaternion.x + quaternion.y * quaternion.y);\r\n var numeratorRoll =\r\n 2 * (quaternion.w * quaternion.x + quaternion.y * quaternion.z);\r\n var denominatorHeading =\r\n 1 - 2 * (quaternion.y * quaternion.y + quaternion.z * quaternion.z);\r\n var numeratorHeading =\r\n 2 * (quaternion.w * quaternion.z + quaternion.x * quaternion.y);\r\n result.heading = -Math.atan2(numeratorHeading, denominatorHeading);\r\n result.roll = Math.atan2(numeratorRoll, denominatorRoll);\r\n result.pitch = -CesiumMath.asinClamped(test);\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns a new HeadingPitchRoll instance from angles given in degrees.\r\n *\r\n * @param {Number} heading the heading in degrees\r\n * @param {Number} pitch the pitch in degrees\r\n * @param {Number} roll the heading in degrees\r\n * @param {HeadingPitchRoll} [result] The object in which to store the result. If not provided, a new instance is created and returned.\r\n * @returns {HeadingPitchRoll} A new HeadingPitchRoll instance\r\n */\r\nHeadingPitchRoll.fromDegrees = function (heading, pitch, roll, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(heading)) {\r\n throw new DeveloperError(\"heading is required\");\r\n }\r\n if (!defined(pitch)) {\r\n throw new DeveloperError(\"pitch is required\");\r\n }\r\n if (!defined(roll)) {\r\n throw new DeveloperError(\"roll is required\");\r\n }\r\n //>>includeEnd('debug');\r\n if (!defined(result)) {\r\n result = new HeadingPitchRoll();\r\n }\r\n result.heading = heading * CesiumMath.RADIANS_PER_DEGREE;\r\n result.pitch = pitch * CesiumMath.RADIANS_PER_DEGREE;\r\n result.roll = roll * CesiumMath.RADIANS_PER_DEGREE;\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a HeadingPitchRoll instance.\r\n *\r\n * @param {HeadingPitchRoll} headingPitchRoll The HeadingPitchRoll to duplicate.\r\n * @param {HeadingPitchRoll} [result] The object onto which to store the result.\r\n * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided. (Returns undefined if headingPitchRoll is undefined)\r\n */\r\nHeadingPitchRoll.clone = function (headingPitchRoll, result) {\r\n if (!defined(headingPitchRoll)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new HeadingPitchRoll(\r\n headingPitchRoll.heading,\r\n headingPitchRoll.pitch,\r\n headingPitchRoll.roll\r\n );\r\n }\r\n result.heading = headingPitchRoll.heading;\r\n result.pitch = headingPitchRoll.pitch;\r\n result.roll = headingPitchRoll.roll;\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided HeadingPitchRolls componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {HeadingPitchRoll} [left] The first HeadingPitchRoll.\r\n * @param {HeadingPitchRoll} [right] The second HeadingPitchRoll.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nHeadingPitchRoll.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.heading === right.heading &&\r\n left.pitch === right.pitch &&\r\n left.roll === right.roll)\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided HeadingPitchRolls componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {HeadingPitchRoll} [left] The first HeadingPitchRoll.\r\n * @param {HeadingPitchRoll} [right] The second HeadingPitchRoll.\r\n * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nHeadingPitchRoll.equalsEpsilon = function (\r\n left,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n CesiumMath.equalsEpsilon(\r\n left.heading,\r\n right.heading,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n left.pitch,\r\n right.pitch,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n left.roll,\r\n right.roll,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ))\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates this HeadingPitchRoll instance.\r\n *\r\n * @param {HeadingPitchRoll} [result] The object onto which to store the result.\r\n * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if one was not provided.\r\n */\r\nHeadingPitchRoll.prototype.clone = function (result) {\r\n return HeadingPitchRoll.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this HeadingPitchRoll against the provided HeadingPitchRoll componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {HeadingPitchRoll} [right] The right hand side HeadingPitchRoll.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nHeadingPitchRoll.prototype.equals = function (right) {\r\n return HeadingPitchRoll.equals(this, right);\r\n};\r\n\r\n/**\r\n * Compares this HeadingPitchRoll against the provided HeadingPitchRoll componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {HeadingPitchRoll} [right] The right hand side HeadingPitchRoll.\r\n * @param {Number} [relativeEpsilon=0] The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if they are within the provided epsilon, false otherwise.\r\n */\r\nHeadingPitchRoll.prototype.equalsEpsilon = function (\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return HeadingPitchRoll.equalsEpsilon(\r\n this,\r\n right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n );\r\n};\r\n\r\n/**\r\n * Creates a string representing this HeadingPitchRoll in the format '(heading, pitch, roll)' in radians.\r\n *\r\n * @returns {String} A string representing the provided HeadingPitchRoll in the format '(heading, pitch, roll)'.\r\n */\r\nHeadingPitchRoll.prototype.toString = function () {\r\n return \"(\" + this.heading + \", \" + this.pitch + \", \" + this.roll + \")\";\r\n};\r\nexport default HeadingPitchRoll;\r\n","/**\r\n * An IAU 2006 XYS value sampled at a particular time.\r\n *\r\n * @alias Iau2006XysSample\r\n * @constructor\r\n *\r\n * @param {Number} x The X value.\r\n * @param {Number} y The Y value.\r\n * @param {Number} s The S value.\r\n *\r\n * @private\r\n */\r\nfunction Iau2006XysSample(x, y, s) {\r\n /**\r\n * The X value.\r\n * @type {Number}\r\n */\r\n this.x = x;\r\n\r\n /**\r\n * The Y value.\r\n * @type {Number}\r\n */\r\n this.y = y;\r\n\r\n /**\r\n * The S value.\r\n * @type {Number}\r\n */\r\n this.s = s;\r\n}\r\nexport default Iau2006XysSample;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport buildModuleUrl from \"./buildModuleUrl.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Iau2006XysSample from \"./Iau2006XysSample.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport TimeStandard from \"./TimeStandard.js\";\r\n\r\n/**\r\n * A set of IAU2006 XYS data that is used to evaluate the transformation between the International\r\n * Celestial Reference Frame (ICRF) and the International Terrestrial Reference Frame (ITRF).\r\n *\r\n * @alias Iau2006XysData\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Resource|String} [options.xysFileUrlTemplate='Assets/IAU2006_XYS/IAU2006_XYS_{0}.json'] A template URL for obtaining the XYS data. In the template,\r\n * `{0}` will be replaced with the file index.\r\n * @param {Number} [options.interpolationOrder=9] The order of interpolation to perform on the XYS data.\r\n * @param {Number} [options.sampleZeroJulianEphemerisDate=2442396.5] The Julian ephemeris date (JED) of the\r\n * first XYS sample.\r\n * @param {Number} [options.stepSizeDays=1.0] The step size, in days, between successive XYS samples.\r\n * @param {Number} [options.samplesPerXysFile=1000] The number of samples in each XYS file.\r\n * @param {Number} [options.totalSamples=27426] The total number of samples in all XYS files.\r\n *\r\n * @private\r\n */\r\nfunction Iau2006XysData(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._xysFileUrlTemplate = Resource.createIfNeeded(\r\n options.xysFileUrlTemplate\r\n );\r\n this._interpolationOrder = defaultValue(options.interpolationOrder, 9);\r\n this._sampleZeroJulianEphemerisDate = defaultValue(\r\n options.sampleZeroJulianEphemerisDate,\r\n 2442396.5\r\n );\r\n this._sampleZeroDateTT = new JulianDate(\r\n this._sampleZeroJulianEphemerisDate,\r\n 0.0,\r\n TimeStandard.TAI\r\n );\r\n this._stepSizeDays = defaultValue(options.stepSizeDays, 1.0);\r\n this._samplesPerXysFile = defaultValue(options.samplesPerXysFile, 1000);\r\n this._totalSamples = defaultValue(options.totalSamples, 27426);\r\n this._samples = new Array(this._totalSamples * 3);\r\n this._chunkDownloadsInProgress = [];\r\n\r\n var order = this._interpolationOrder;\r\n\r\n // Compute denominators and X values for interpolation.\r\n var denom = (this._denominators = new Array(order + 1));\r\n var xTable = (this._xTable = new Array(order + 1));\r\n\r\n var stepN = Math.pow(this._stepSizeDays, order);\r\n\r\n for (var i = 0; i <= order; ++i) {\r\n denom[i] = stepN;\r\n xTable[i] = i * this._stepSizeDays;\r\n\r\n for (var j = 0; j <= order; ++j) {\r\n if (j !== i) {\r\n denom[i] *= i - j;\r\n }\r\n }\r\n\r\n denom[i] = 1.0 / denom[i];\r\n }\r\n\r\n // Allocate scratch arrays for interpolation.\r\n this._work = new Array(order + 1);\r\n this._coef = new Array(order + 1);\r\n}\r\n\r\nvar julianDateScratch = new JulianDate(0, 0.0, TimeStandard.TAI);\r\n\r\nfunction getDaysSinceEpoch(xys, dayTT, secondTT) {\r\n var dateTT = julianDateScratch;\r\n dateTT.dayNumber = dayTT;\r\n dateTT.secondsOfDay = secondTT;\r\n return JulianDate.daysDifference(dateTT, xys._sampleZeroDateTT);\r\n}\r\n\r\n/**\r\n * Preloads XYS data for a specified date range.\r\n *\r\n * @param {Number} startDayTT The Julian day number of the beginning of the interval to preload, expressed in\r\n * the Terrestrial Time (TT) time standard.\r\n * @param {Number} startSecondTT The seconds past noon of the beginning of the interval to preload, expressed in\r\n * the Terrestrial Time (TT) time standard.\r\n * @param {Number} stopDayTT The Julian day number of the end of the interval to preload, expressed in\r\n * the Terrestrial Time (TT) time standard.\r\n * @param {Number} stopSecondTT The seconds past noon of the end of the interval to preload, expressed in\r\n * the Terrestrial Time (TT) time standard.\r\n * @returns {Promise} A promise that, when resolved, indicates that the requested interval has been\r\n * preloaded.\r\n */\r\nIau2006XysData.prototype.preload = function (\r\n startDayTT,\r\n startSecondTT,\r\n stopDayTT,\r\n stopSecondTT\r\n) {\r\n var startDaysSinceEpoch = getDaysSinceEpoch(this, startDayTT, startSecondTT);\r\n var stopDaysSinceEpoch = getDaysSinceEpoch(this, stopDayTT, stopSecondTT);\r\n\r\n var startIndex =\r\n (startDaysSinceEpoch / this._stepSizeDays - this._interpolationOrder / 2) |\r\n 0;\r\n if (startIndex < 0) {\r\n startIndex = 0;\r\n }\r\n\r\n var stopIndex =\r\n (stopDaysSinceEpoch / this._stepSizeDays - this._interpolationOrder / 2) |\r\n (0 + this._interpolationOrder);\r\n if (stopIndex >= this._totalSamples) {\r\n stopIndex = this._totalSamples - 1;\r\n }\r\n\r\n var startChunk = (startIndex / this._samplesPerXysFile) | 0;\r\n var stopChunk = (stopIndex / this._samplesPerXysFile) | 0;\r\n\r\n var promises = [];\r\n for (var i = startChunk; i <= stopChunk; ++i) {\r\n promises.push(requestXysChunk(this, i));\r\n }\r\n\r\n return when.all(promises);\r\n};\r\n\r\n/**\r\n * Computes the XYS values for a given date by interpolating. If the required data is not yet downloaded,\r\n * this method will return undefined.\r\n *\r\n * @param {Number} dayTT The Julian day number for which to compute the XYS value, expressed in\r\n * the Terrestrial Time (TT) time standard.\r\n * @param {Number} secondTT The seconds past noon of the date for which to compute the XYS value, expressed in\r\n * the Terrestrial Time (TT) time standard.\r\n * @param {Iau2006XysSample} [result] The instance to which to copy the interpolated result. If this parameter\r\n * is undefined, a new instance is allocated and returned.\r\n * @returns {Iau2006XysSample} The interpolated XYS values, or undefined if the required data for this\r\n * computation has not yet been downloaded.\r\n *\r\n * @see Iau2006XysData#preload\r\n */\r\nIau2006XysData.prototype.computeXysRadians = function (\r\n dayTT,\r\n secondTT,\r\n result\r\n) {\r\n var daysSinceEpoch = getDaysSinceEpoch(this, dayTT, secondTT);\r\n if (daysSinceEpoch < 0.0) {\r\n // Can't evaluate prior to the epoch of the data.\r\n return undefined;\r\n }\r\n\r\n var centerIndex = (daysSinceEpoch / this._stepSizeDays) | 0;\r\n if (centerIndex >= this._totalSamples) {\r\n // Can't evaluate after the last sample in the data.\r\n return undefined;\r\n }\r\n\r\n var degree = this._interpolationOrder;\r\n\r\n var firstIndex = centerIndex - ((degree / 2) | 0);\r\n if (firstIndex < 0) {\r\n firstIndex = 0;\r\n }\r\n var lastIndex = firstIndex + degree;\r\n if (lastIndex >= this._totalSamples) {\r\n lastIndex = this._totalSamples - 1;\r\n firstIndex = lastIndex - degree;\r\n if (firstIndex < 0) {\r\n firstIndex = 0;\r\n }\r\n }\r\n\r\n // Are all the samples we need present?\r\n // We can assume so if the first and last are present\r\n var isDataMissing = false;\r\n var samples = this._samples;\r\n if (!defined(samples[firstIndex * 3])) {\r\n requestXysChunk(this, (firstIndex / this._samplesPerXysFile) | 0);\r\n isDataMissing = true;\r\n }\r\n\r\n if (!defined(samples[lastIndex * 3])) {\r\n requestXysChunk(this, (lastIndex / this._samplesPerXysFile) | 0);\r\n isDataMissing = true;\r\n }\r\n\r\n if (isDataMissing) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new Iau2006XysSample(0.0, 0.0, 0.0);\r\n } else {\r\n result.x = 0.0;\r\n result.y = 0.0;\r\n result.s = 0.0;\r\n }\r\n\r\n var x = daysSinceEpoch - firstIndex * this._stepSizeDays;\r\n\r\n var work = this._work;\r\n var denom = this._denominators;\r\n var coef = this._coef;\r\n var xTable = this._xTable;\r\n\r\n var i, j;\r\n for (i = 0; i <= degree; ++i) {\r\n work[i] = x - xTable[i];\r\n }\r\n\r\n for (i = 0; i <= degree; ++i) {\r\n coef[i] = 1.0;\r\n\r\n for (j = 0; j <= degree; ++j) {\r\n if (j !== i) {\r\n coef[i] *= work[j];\r\n }\r\n }\r\n\r\n coef[i] *= denom[i];\r\n\r\n var sampleIndex = (firstIndex + i) * 3;\r\n result.x += coef[i] * samples[sampleIndex++];\r\n result.y += coef[i] * samples[sampleIndex++];\r\n result.s += coef[i] * samples[sampleIndex];\r\n }\r\n\r\n return result;\r\n};\r\n\r\nfunction requestXysChunk(xysData, chunkIndex) {\r\n if (xysData._chunkDownloadsInProgress[chunkIndex]) {\r\n // Chunk has already been requested.\r\n return xysData._chunkDownloadsInProgress[chunkIndex];\r\n }\r\n\r\n var deferred = when.defer();\r\n\r\n xysData._chunkDownloadsInProgress[chunkIndex] = deferred;\r\n\r\n var chunkUrl;\r\n var xysFileUrlTemplate = xysData._xysFileUrlTemplate;\r\n if (defined(xysFileUrlTemplate)) {\r\n chunkUrl = xysFileUrlTemplate.getDerivedResource({\r\n templateValues: {\r\n 0: chunkIndex,\r\n },\r\n });\r\n } else {\r\n chunkUrl = new Resource({\r\n url: buildModuleUrl(\r\n \"Assets/IAU2006_XYS/IAU2006_XYS_\" + chunkIndex + \".json\"\r\n ),\r\n });\r\n }\r\n\r\n when(chunkUrl.fetchJson(), function (chunk) {\r\n xysData._chunkDownloadsInProgress[chunkIndex] = false;\r\n\r\n var samples = xysData._samples;\r\n var newSamples = chunk.samples;\r\n var startIndex = chunkIndex * xysData._samplesPerXysFile * 3;\r\n\r\n for (var i = 0, len = newSamples.length; i < len; ++i) {\r\n samples[startIndex + i] = newSamples[i];\r\n }\r\n\r\n deferred.resolve();\r\n });\r\n\r\n return deferred.promise;\r\n}\r\nexport default Iau2006XysData;\r\n","import defined from \"./defined.js\";\r\n\r\nvar _supportsFullscreen;\r\nvar _names = {\r\n requestFullscreen: undefined,\r\n exitFullscreen: undefined,\r\n fullscreenEnabled: undefined,\r\n fullscreenElement: undefined,\r\n fullscreenchange: undefined,\r\n fullscreenerror: undefined,\r\n};\r\n\r\n/**\r\n * Browser-independent functions for working with the standard fullscreen API.\r\n *\r\n * @namespace Fullscreen\r\n *\r\n * @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}\r\n */\r\nvar Fullscreen = {};\r\n\r\nObject.defineProperties(Fullscreen, {\r\n /**\r\n * The element that is currently fullscreen, if any. To simply check if the\r\n * browser is in fullscreen mode or not, use {@link Fullscreen#fullscreen}.\r\n * @memberof Fullscreen\r\n * @type {Object}\r\n * @readonly\r\n */\r\n element: {\r\n get: function () {\r\n if (!Fullscreen.supportsFullscreen()) {\r\n return undefined;\r\n }\r\n\r\n return document[_names.fullscreenElement];\r\n },\r\n },\r\n\r\n /**\r\n * The name of the event on the document that is fired when fullscreen is\r\n * entered or exited. This event name is intended for use with addEventListener.\r\n * In your event handler, to determine if the browser is in fullscreen mode or not,\r\n * use {@link Fullscreen#fullscreen}.\r\n * @memberof Fullscreen\r\n * @type {String}\r\n * @readonly\r\n */\r\n changeEventName: {\r\n get: function () {\r\n if (!Fullscreen.supportsFullscreen()) {\r\n return undefined;\r\n }\r\n\r\n return _names.fullscreenchange;\r\n },\r\n },\r\n\r\n /**\r\n * The name of the event that is fired when a fullscreen error\r\n * occurs. This event name is intended for use with addEventListener.\r\n * @memberof Fullscreen\r\n * @type {String}\r\n * @readonly\r\n */\r\n errorEventName: {\r\n get: function () {\r\n if (!Fullscreen.supportsFullscreen()) {\r\n return undefined;\r\n }\r\n\r\n return _names.fullscreenerror;\r\n },\r\n },\r\n\r\n /**\r\n * Determine whether the browser will allow an element to be made fullscreen, or not.\r\n * For example, by default, iframes cannot go fullscreen unless the containing page\r\n * adds an \"allowfullscreen\" attribute (or prefixed equivalent).\r\n * @memberof Fullscreen\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n enabled: {\r\n get: function () {\r\n if (!Fullscreen.supportsFullscreen()) {\r\n return undefined;\r\n }\r\n\r\n return document[_names.fullscreenEnabled];\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the browser is currently in fullscreen mode.\r\n * @memberof Fullscreen\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n fullscreen: {\r\n get: function () {\r\n if (!Fullscreen.supportsFullscreen()) {\r\n return undefined;\r\n }\r\n\r\n return Fullscreen.element !== null;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Detects whether the browser supports the standard fullscreen API.\r\n *\r\n * @returns {Boolean} true if the browser supports the standard fullscreen API,\r\n * false otherwise.\r\n */\r\nFullscreen.supportsFullscreen = function () {\r\n if (defined(_supportsFullscreen)) {\r\n return _supportsFullscreen;\r\n }\r\n\r\n _supportsFullscreen = false;\r\n\r\n var body = document.body;\r\n if (typeof body.requestFullscreen === \"function\") {\r\n // go with the unprefixed, standard set of names\r\n _names.requestFullscreen = \"requestFullscreen\";\r\n _names.exitFullscreen = \"exitFullscreen\";\r\n _names.fullscreenEnabled = \"fullscreenEnabled\";\r\n _names.fullscreenElement = \"fullscreenElement\";\r\n _names.fullscreenchange = \"fullscreenchange\";\r\n _names.fullscreenerror = \"fullscreenerror\";\r\n _supportsFullscreen = true;\r\n return _supportsFullscreen;\r\n }\r\n\r\n //check for the correct combination of prefix plus the various names that browsers use\r\n var prefixes = [\"webkit\", \"moz\", \"o\", \"ms\", \"khtml\"];\r\n var name;\r\n for (var i = 0, len = prefixes.length; i < len; ++i) {\r\n var prefix = prefixes[i];\r\n\r\n // casing of Fullscreen differs across browsers\r\n name = prefix + \"RequestFullscreen\";\r\n if (typeof body[name] === \"function\") {\r\n _names.requestFullscreen = name;\r\n _supportsFullscreen = true;\r\n } else {\r\n name = prefix + \"RequestFullScreen\";\r\n if (typeof body[name] === \"function\") {\r\n _names.requestFullscreen = name;\r\n _supportsFullscreen = true;\r\n }\r\n }\r\n\r\n // disagreement about whether it's \"exit\" as per spec, or \"cancel\"\r\n name = prefix + \"ExitFullscreen\";\r\n if (typeof document[name] === \"function\") {\r\n _names.exitFullscreen = name;\r\n } else {\r\n name = prefix + \"CancelFullScreen\";\r\n if (typeof document[name] === \"function\") {\r\n _names.exitFullscreen = name;\r\n }\r\n }\r\n\r\n // casing of Fullscreen differs across browsers\r\n name = prefix + \"FullscreenEnabled\";\r\n if (document[name] !== undefined) {\r\n _names.fullscreenEnabled = name;\r\n } else {\r\n name = prefix + \"FullScreenEnabled\";\r\n if (document[name] !== undefined) {\r\n _names.fullscreenEnabled = name;\r\n }\r\n }\r\n\r\n // casing of Fullscreen differs across browsers\r\n name = prefix + \"FullscreenElement\";\r\n if (document[name] !== undefined) {\r\n _names.fullscreenElement = name;\r\n } else {\r\n name = prefix + \"FullScreenElement\";\r\n if (document[name] !== undefined) {\r\n _names.fullscreenElement = name;\r\n }\r\n }\r\n\r\n // thankfully, event names are all lowercase per spec\r\n name = prefix + \"fullscreenchange\";\r\n // event names do not have 'on' in the front, but the property on the document does\r\n if (document[\"on\" + name] !== undefined) {\r\n //except on IE\r\n if (prefix === \"ms\") {\r\n name = \"MSFullscreenChange\";\r\n }\r\n _names.fullscreenchange = name;\r\n }\r\n\r\n name = prefix + \"fullscreenerror\";\r\n if (document[\"on\" + name] !== undefined) {\r\n //except on IE\r\n if (prefix === \"ms\") {\r\n name = \"MSFullscreenError\";\r\n }\r\n _names.fullscreenerror = name;\r\n }\r\n }\r\n\r\n return _supportsFullscreen;\r\n};\r\n\r\n/**\r\n * Asynchronously requests the browser to enter fullscreen mode on the given element.\r\n * If fullscreen mode is not supported by the browser, does nothing.\r\n *\r\n * @param {Object} element The HTML element which will be placed into fullscreen mode.\r\n * @param {Object} [vrDevice] The HMDVRDevice device.\r\n *\r\n * @example\r\n * // Put the entire page into fullscreen.\r\n * Cesium.Fullscreen.requestFullscreen(document.body)\r\n *\r\n * // Place only the Cesium canvas into fullscreen.\r\n * Cesium.Fullscreen.requestFullscreen(scene.canvas)\r\n */\r\nFullscreen.requestFullscreen = function (element, vrDevice) {\r\n if (!Fullscreen.supportsFullscreen()) {\r\n return;\r\n }\r\n\r\n element[_names.requestFullscreen]({ vrDisplay: vrDevice });\r\n};\r\n\r\n/**\r\n * Asynchronously exits fullscreen mode. If the browser is not currently\r\n * in fullscreen, or if fullscreen mode is not supported by the browser, does nothing.\r\n */\r\nFullscreen.exitFullscreen = function () {\r\n if (!Fullscreen.supportsFullscreen()) {\r\n return;\r\n }\r\n\r\n document[_names.exitFullscreen]();\r\n};\r\n\r\n//For unit tests\r\nFullscreen._names = _names;\r\nexport default Fullscreen;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Fullscreen from \"./Fullscreen.js\";\r\n\r\nvar theNavigator;\r\nif (typeof navigator !== \"undefined\") {\r\n theNavigator = navigator;\r\n} else {\r\n theNavigator = {};\r\n}\r\n\r\nfunction extractVersion(versionString) {\r\n var parts = versionString.split(\".\");\r\n for (var i = 0, len = parts.length; i < len; ++i) {\r\n parts[i] = parseInt(parts[i], 10);\r\n }\r\n return parts;\r\n}\r\n\r\nvar isChromeResult;\r\nvar chromeVersionResult;\r\nfunction isChrome() {\r\n if (!defined(isChromeResult)) {\r\n isChromeResult = false;\r\n // Edge contains Chrome in the user agent too\r\n if (!isEdge()) {\r\n var fields = / Chrome\\/([\\.0-9]+)/.exec(theNavigator.userAgent);\r\n if (fields !== null) {\r\n isChromeResult = true;\r\n chromeVersionResult = extractVersion(fields[1]);\r\n }\r\n }\r\n }\r\n\r\n return isChromeResult;\r\n}\r\n\r\nfunction chromeVersion() {\r\n return isChrome() && chromeVersionResult;\r\n}\r\n\r\nvar isSafariResult;\r\nvar safariVersionResult;\r\nfunction isSafari() {\r\n if (!defined(isSafariResult)) {\r\n isSafariResult = false;\r\n\r\n // Chrome and Edge contain Safari in the user agent too\r\n if (\r\n !isChrome() &&\r\n !isEdge() &&\r\n / Safari\\/[\\.0-9]+/.test(theNavigator.userAgent)\r\n ) {\r\n var fields = / Version\\/([\\.0-9]+)/.exec(theNavigator.userAgent);\r\n if (fields !== null) {\r\n isSafariResult = true;\r\n safariVersionResult = extractVersion(fields[1]);\r\n }\r\n }\r\n }\r\n\r\n return isSafariResult;\r\n}\r\n\r\nfunction safariVersion() {\r\n return isSafari() && safariVersionResult;\r\n}\r\n\r\nvar isWebkitResult;\r\nvar webkitVersionResult;\r\nfunction isWebkit() {\r\n if (!defined(isWebkitResult)) {\r\n isWebkitResult = false;\r\n\r\n var fields = / AppleWebKit\\/([\\.0-9]+)(\\+?)/.exec(theNavigator.userAgent);\r\n if (fields !== null) {\r\n isWebkitResult = true;\r\n webkitVersionResult = extractVersion(fields[1]);\r\n webkitVersionResult.isNightly = !!fields[2];\r\n }\r\n }\r\n\r\n return isWebkitResult;\r\n}\r\n\r\nfunction webkitVersion() {\r\n return isWebkit() && webkitVersionResult;\r\n}\r\n\r\nvar isInternetExplorerResult;\r\nvar internetExplorerVersionResult;\r\nfunction isInternetExplorer() {\r\n if (!defined(isInternetExplorerResult)) {\r\n isInternetExplorerResult = false;\r\n\r\n var fields;\r\n if (theNavigator.appName === \"Microsoft Internet Explorer\") {\r\n fields = /MSIE ([0-9]{1,}[\\.0-9]{0,})/.exec(theNavigator.userAgent);\r\n if (fields !== null) {\r\n isInternetExplorerResult = true;\r\n internetExplorerVersionResult = extractVersion(fields[1]);\r\n }\r\n } else if (theNavigator.appName === \"Netscape\") {\r\n fields = /Trident\\/.*rv:([0-9]{1,}[\\.0-9]{0,})/.exec(\r\n theNavigator.userAgent\r\n );\r\n if (fields !== null) {\r\n isInternetExplorerResult = true;\r\n internetExplorerVersionResult = extractVersion(fields[1]);\r\n }\r\n }\r\n }\r\n return isInternetExplorerResult;\r\n}\r\n\r\nfunction internetExplorerVersion() {\r\n return isInternetExplorer() && internetExplorerVersionResult;\r\n}\r\n\r\nvar isEdgeResult;\r\nvar edgeVersionResult;\r\nfunction isEdge() {\r\n if (!defined(isEdgeResult)) {\r\n isEdgeResult = false;\r\n var fields = / Edge\\/([\\.0-9]+)/.exec(theNavigator.userAgent);\r\n if (fields !== null) {\r\n isEdgeResult = true;\r\n edgeVersionResult = extractVersion(fields[1]);\r\n }\r\n }\r\n return isEdgeResult;\r\n}\r\n\r\nfunction edgeVersion() {\r\n return isEdge() && edgeVersionResult;\r\n}\r\n\r\nvar isFirefoxResult;\r\nvar firefoxVersionResult;\r\nfunction isFirefox() {\r\n if (!defined(isFirefoxResult)) {\r\n isFirefoxResult = false;\r\n\r\n var fields = /Firefox\\/([\\.0-9]+)/.exec(theNavigator.userAgent);\r\n if (fields !== null) {\r\n isFirefoxResult = true;\r\n firefoxVersionResult = extractVersion(fields[1]);\r\n }\r\n }\r\n return isFirefoxResult;\r\n}\r\n\r\nvar isWindowsResult;\r\nfunction isWindows() {\r\n if (!defined(isWindowsResult)) {\r\n isWindowsResult = /Windows/i.test(theNavigator.appVersion);\r\n }\r\n return isWindowsResult;\r\n}\r\n\r\nfunction firefoxVersion() {\r\n return isFirefox() && firefoxVersionResult;\r\n}\r\n\r\nvar hasPointerEvents;\r\nfunction supportsPointerEvents() {\r\n if (!defined(hasPointerEvents)) {\r\n //While navigator.pointerEnabled is deprecated in the W3C specification\r\n //we still need to use it if it exists in order to support browsers\r\n //that rely on it, such as the Windows WebBrowser control which defines\r\n //PointerEvent but sets navigator.pointerEnabled to false.\r\n\r\n //Firefox disabled because of https://github.com/CesiumGS/cesium/issues/6372\r\n hasPointerEvents =\r\n !isFirefox() &&\r\n typeof PointerEvent !== \"undefined\" &&\r\n (!defined(theNavigator.pointerEnabled) || theNavigator.pointerEnabled);\r\n }\r\n return hasPointerEvents;\r\n}\r\n\r\nvar imageRenderingValueResult;\r\nvar supportsImageRenderingPixelatedResult;\r\nfunction supportsImageRenderingPixelated() {\r\n if (!defined(supportsImageRenderingPixelatedResult)) {\r\n var canvas = document.createElement(\"canvas\");\r\n canvas.setAttribute(\r\n \"style\",\r\n \"image-rendering: -moz-crisp-edges;\" + \"image-rendering: pixelated;\"\r\n );\r\n //canvas.style.imageRendering will be undefined, null or an empty string on unsupported browsers.\r\n var tmp = canvas.style.imageRendering;\r\n supportsImageRenderingPixelatedResult = defined(tmp) && tmp !== \"\";\r\n if (supportsImageRenderingPixelatedResult) {\r\n imageRenderingValueResult = tmp;\r\n }\r\n }\r\n return supportsImageRenderingPixelatedResult;\r\n}\r\n\r\nfunction imageRenderingValue() {\r\n return supportsImageRenderingPixelated()\r\n ? imageRenderingValueResult\r\n : undefined;\r\n}\r\n\r\nfunction supportsWebP() {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!supportsWebP.initialized) {\r\n throw new DeveloperError(\r\n \"You must call FeatureDetection.supportsWebP.initialize and wait for the promise to resolve before calling FeatureDetection.supportsWebP\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return supportsWebP._result;\r\n}\r\nsupportsWebP._promise = undefined;\r\nsupportsWebP._result = undefined;\r\nsupportsWebP.initialize = function () {\r\n // From https://developers.google.com/speed/webp/faq#how_can_i_detect_browser_support_for_webp\r\n if (defined(supportsWebP._promise)) {\r\n return supportsWebP._promise;\r\n }\r\n\r\n var supportsWebPDeferred = when.defer();\r\n supportsWebP._promise = supportsWebPDeferred.promise;\r\n if (isEdge()) {\r\n // Edge's WebP support with WebGL is incomplete.\r\n // See bug report: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/19221241/\r\n supportsWebP._result = false;\r\n supportsWebPDeferred.resolve(supportsWebP._result);\r\n return supportsWebPDeferred.promise;\r\n }\r\n\r\n var image = new Image();\r\n image.onload = function () {\r\n supportsWebP._result = image.width > 0 && image.height > 0;\r\n supportsWebPDeferred.resolve(supportsWebP._result);\r\n };\r\n\r\n image.onerror = function () {\r\n supportsWebP._result = false;\r\n supportsWebPDeferred.resolve(supportsWebP._result);\r\n };\r\n\r\n image.src =\r\n \"data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA\";\r\n\r\n return supportsWebPDeferred.promise;\r\n};\r\nObject.defineProperties(supportsWebP, {\r\n initialized: {\r\n get: function () {\r\n return defined(supportsWebP._result);\r\n },\r\n },\r\n});\r\n\r\nvar typedArrayTypes = [];\r\nif (typeof ArrayBuffer !== \"undefined\") {\r\n typedArrayTypes.push(\r\n Int8Array,\r\n Uint8Array,\r\n Int16Array,\r\n Uint16Array,\r\n Int32Array,\r\n Uint32Array,\r\n Float32Array,\r\n Float64Array\r\n );\r\n\r\n if (typeof Uint8ClampedArray !== \"undefined\") {\r\n typedArrayTypes.push(Uint8ClampedArray);\r\n }\r\n\r\n if (typeof Uint8ClampedArray !== \"undefined\") {\r\n typedArrayTypes.push(Uint8ClampedArray);\r\n }\r\n}\r\n\r\n/**\r\n * A set of functions to detect whether the current browser supports\r\n * various features.\r\n *\r\n * @namespace FeatureDetection\r\n */\r\nvar FeatureDetection = {\r\n isChrome: isChrome,\r\n chromeVersion: chromeVersion,\r\n isSafari: isSafari,\r\n safariVersion: safariVersion,\r\n isWebkit: isWebkit,\r\n webkitVersion: webkitVersion,\r\n isInternetExplorer: isInternetExplorer,\r\n internetExplorerVersion: internetExplorerVersion,\r\n isEdge: isEdge,\r\n edgeVersion: edgeVersion,\r\n isFirefox: isFirefox,\r\n firefoxVersion: firefoxVersion,\r\n isWindows: isWindows,\r\n hardwareConcurrency: defaultValue(theNavigator.hardwareConcurrency, 3),\r\n supportsPointerEvents: supportsPointerEvents,\r\n supportsImageRenderingPixelated: supportsImageRenderingPixelated,\r\n supportsWebP: supportsWebP,\r\n imageRenderingValue: imageRenderingValue,\r\n typedArrayTypes: typedArrayTypes,\r\n};\r\n\r\n/**\r\n * Detects whether the current browser supports the full screen standard.\r\n *\r\n * @returns {Boolean} true if the browser supports the full screen standard, false if not.\r\n *\r\n * @see Fullscreen\r\n * @see {@link http://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html|W3C Fullscreen Living Specification}\r\n */\r\nFeatureDetection.supportsFullscreen = function () {\r\n return Fullscreen.supportsFullscreen();\r\n};\r\n\r\n/**\r\n * Detects whether the current browser supports typed arrays.\r\n *\r\n * @returns {Boolean} true if the browser supports typed arrays, false if not.\r\n *\r\n * @see {@link http://www.khronos.org/registry/typedarray/specs/latest/|Typed Array Specification}\r\n */\r\nFeatureDetection.supportsTypedArrays = function () {\r\n return typeof ArrayBuffer !== \"undefined\";\r\n};\r\n\r\n/**\r\n * Detects whether the current browser supports Web Workers.\r\n *\r\n * @returns {Boolean} true if the browsers supports Web Workers, false if not.\r\n *\r\n * @see {@link http://www.w3.org/TR/workers/}\r\n */\r\nFeatureDetection.supportsWebWorkers = function () {\r\n return typeof Worker !== \"undefined\";\r\n};\r\n\r\n/**\r\n * Detects whether the current browser supports Web Assembly.\r\n *\r\n * @returns {Boolean} true if the browsers supports Web Assembly, false if not.\r\n *\r\n * @see {@link https://developer.mozilla.org/en-US/docs/WebAssembly}\r\n */\r\nFeatureDetection.supportsWebAssembly = function () {\r\n return typeof WebAssembly !== \"undefined\" && !FeatureDetection.isEdge();\r\n};\r\nexport default FeatureDetection;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport FeatureDetection from \"./FeatureDetection.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\n\r\n/**\r\n * A set of 4-dimensional coordinates used to represent rotation in 3-dimensional space.\r\n * @alias Quaternion\r\n * @constructor\r\n *\r\n * @param {Number} [x=0.0] The X component.\r\n * @param {Number} [y=0.0] The Y component.\r\n * @param {Number} [z=0.0] The Z component.\r\n * @param {Number} [w=0.0] The W component.\r\n *\r\n * @see PackableForInterpolation\r\n */\r\nfunction Quaternion(x, y, z, w) {\r\n /**\r\n * The X component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.x = defaultValue(x, 0.0);\r\n\r\n /**\r\n * The Y component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.y = defaultValue(y, 0.0);\r\n\r\n /**\r\n * The Z component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.z = defaultValue(z, 0.0);\r\n\r\n /**\r\n * The W component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.w = defaultValue(w, 0.0);\r\n}\r\n\r\nvar fromAxisAngleScratch = new Cartesian3();\r\n\r\n/**\r\n * Computes a quaternion representing a rotation around an axis.\r\n *\r\n * @param {Cartesian3} axis The axis of rotation.\r\n * @param {Number} angle The angle in radians to rotate around the axis.\r\n * @param {Quaternion} [result] The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.\r\n */\r\nQuaternion.fromAxisAngle = function (axis, angle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"axis\", axis);\r\n Check.typeOf.number(\"angle\", angle);\r\n //>>includeEnd('debug');\r\n\r\n var halfAngle = angle / 2.0;\r\n var s = Math.sin(halfAngle);\r\n fromAxisAngleScratch = Cartesian3.normalize(axis, fromAxisAngleScratch);\r\n\r\n var x = fromAxisAngleScratch.x * s;\r\n var y = fromAxisAngleScratch.y * s;\r\n var z = fromAxisAngleScratch.z * s;\r\n var w = Math.cos(halfAngle);\r\n if (!defined(result)) {\r\n return new Quaternion(x, y, z, w);\r\n }\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n result.w = w;\r\n return result;\r\n};\r\n\r\nvar fromRotationMatrixNext = [1, 2, 0];\r\nvar fromRotationMatrixQuat = new Array(3);\r\n/**\r\n * Computes a Quaternion from the provided Matrix3 instance.\r\n *\r\n * @param {Matrix3} matrix The rotation matrix.\r\n * @param {Quaternion} [result] The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.\r\n *\r\n * @see Matrix3.fromQuaternion\r\n */\r\nQuaternion.fromRotationMatrix = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n //>>includeEnd('debug');\r\n\r\n var root;\r\n var x;\r\n var y;\r\n var z;\r\n var w;\r\n\r\n var m00 = matrix[Matrix3.COLUMN0ROW0];\r\n var m11 = matrix[Matrix3.COLUMN1ROW1];\r\n var m22 = matrix[Matrix3.COLUMN2ROW2];\r\n var trace = m00 + m11 + m22;\r\n\r\n if (trace > 0.0) {\r\n // |w| > 1/2, may as well choose w > 1/2\r\n root = Math.sqrt(trace + 1.0); // 2w\r\n w = 0.5 * root;\r\n root = 0.5 / root; // 1/(4w)\r\n\r\n x = (matrix[Matrix3.COLUMN1ROW2] - matrix[Matrix3.COLUMN2ROW1]) * root;\r\n y = (matrix[Matrix3.COLUMN2ROW0] - matrix[Matrix3.COLUMN0ROW2]) * root;\r\n z = (matrix[Matrix3.COLUMN0ROW1] - matrix[Matrix3.COLUMN1ROW0]) * root;\r\n } else {\r\n // |w| <= 1/2\r\n var next = fromRotationMatrixNext;\r\n\r\n var i = 0;\r\n if (m11 > m00) {\r\n i = 1;\r\n }\r\n if (m22 > m00 && m22 > m11) {\r\n i = 2;\r\n }\r\n var j = next[i];\r\n var k = next[j];\r\n\r\n root = Math.sqrt(\r\n matrix[Matrix3.getElementIndex(i, i)] -\r\n matrix[Matrix3.getElementIndex(j, j)] -\r\n matrix[Matrix3.getElementIndex(k, k)] +\r\n 1.0\r\n );\r\n\r\n var quat = fromRotationMatrixQuat;\r\n quat[i] = 0.5 * root;\r\n root = 0.5 / root;\r\n w =\r\n (matrix[Matrix3.getElementIndex(k, j)] -\r\n matrix[Matrix3.getElementIndex(j, k)]) *\r\n root;\r\n quat[j] =\r\n (matrix[Matrix3.getElementIndex(j, i)] +\r\n matrix[Matrix3.getElementIndex(i, j)]) *\r\n root;\r\n quat[k] =\r\n (matrix[Matrix3.getElementIndex(k, i)] +\r\n matrix[Matrix3.getElementIndex(i, k)]) *\r\n root;\r\n\r\n x = -quat[0];\r\n y = -quat[1];\r\n z = -quat[2];\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Quaternion(x, y, z, w);\r\n }\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n result.w = w;\r\n return result;\r\n};\r\n\r\nvar scratchHPRQuaternion = new Quaternion();\r\nvar scratchHeadingQuaternion = new Quaternion();\r\nvar scratchPitchQuaternion = new Quaternion();\r\nvar scratchRollQuaternion = new Quaternion();\r\n\r\n/**\r\n * Computes a rotation from the given heading, pitch and roll angles. Heading is the rotation about the\r\n * negative z axis. Pitch is the rotation about the negative y axis. Roll is the rotation about\r\n * the positive x axis.\r\n *\r\n * @param {HeadingPitchRoll} headingPitchRoll The rotation expressed as a heading, pitch and roll.\r\n * @param {Quaternion} [result] The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new Quaternion instance if none was provided.\r\n */\r\nQuaternion.fromHeadingPitchRoll = function (headingPitchRoll, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"headingPitchRoll\", headingPitchRoll);\r\n //>>includeEnd('debug');\r\n\r\n scratchRollQuaternion = Quaternion.fromAxisAngle(\r\n Cartesian3.UNIT_X,\r\n headingPitchRoll.roll,\r\n scratchHPRQuaternion\r\n );\r\n scratchPitchQuaternion = Quaternion.fromAxisAngle(\r\n Cartesian3.UNIT_Y,\r\n -headingPitchRoll.pitch,\r\n result\r\n );\r\n result = Quaternion.multiply(\r\n scratchPitchQuaternion,\r\n scratchRollQuaternion,\r\n scratchPitchQuaternion\r\n );\r\n scratchHeadingQuaternion = Quaternion.fromAxisAngle(\r\n Cartesian3.UNIT_Z,\r\n -headingPitchRoll.heading,\r\n scratchHPRQuaternion\r\n );\r\n return Quaternion.multiply(scratchHeadingQuaternion, result, result);\r\n};\r\n\r\nvar sampledQuaternionAxis = new Cartesian3();\r\nvar sampledQuaternionRotation = new Cartesian3();\r\nvar sampledQuaternionTempQuaternion = new Quaternion();\r\nvar sampledQuaternionQuaternion0 = new Quaternion();\r\nvar sampledQuaternionQuaternion0Conjugate = new Quaternion();\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nQuaternion.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Quaternion} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nQuaternion.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.x;\r\n array[startingIndex++] = value.y;\r\n array[startingIndex++] = value.z;\r\n array[startingIndex] = value.w;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Quaternion} [result] The object into which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.\r\n */\r\nQuaternion.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Quaternion();\r\n }\r\n result.x = array[startingIndex];\r\n result.y = array[startingIndex + 1];\r\n result.z = array[startingIndex + 2];\r\n result.w = array[startingIndex + 3];\r\n return result;\r\n};\r\n\r\n/**\r\n * The number of elements used to store the object into an array in its interpolatable form.\r\n * @type {Number}\r\n */\r\nQuaternion.packedInterpolationLength = 3;\r\n\r\n/**\r\n * Converts a packed array into a form suitable for interpolation.\r\n *\r\n * @param {Number[]} packedArray The packed array.\r\n * @param {Number} [startingIndex=0] The index of the first element to be converted.\r\n * @param {Number} [lastIndex=packedArray.length] The index of the last element to be converted.\r\n * @param {Number[]} [result] The object into which to store the result.\r\n */\r\nQuaternion.convertPackedArrayForInterpolation = function (\r\n packedArray,\r\n startingIndex,\r\n lastIndex,\r\n result\r\n) {\r\n Quaternion.unpack(\r\n packedArray,\r\n lastIndex * 4,\r\n sampledQuaternionQuaternion0Conjugate\r\n );\r\n Quaternion.conjugate(\r\n sampledQuaternionQuaternion0Conjugate,\r\n sampledQuaternionQuaternion0Conjugate\r\n );\r\n\r\n for (var i = 0, len = lastIndex - startingIndex + 1; i < len; i++) {\r\n var offset = i * 3;\r\n Quaternion.unpack(\r\n packedArray,\r\n (startingIndex + i) * 4,\r\n sampledQuaternionTempQuaternion\r\n );\r\n\r\n Quaternion.multiply(\r\n sampledQuaternionTempQuaternion,\r\n sampledQuaternionQuaternion0Conjugate,\r\n sampledQuaternionTempQuaternion\r\n );\r\n\r\n if (sampledQuaternionTempQuaternion.w < 0) {\r\n Quaternion.negate(\r\n sampledQuaternionTempQuaternion,\r\n sampledQuaternionTempQuaternion\r\n );\r\n }\r\n\r\n Quaternion.computeAxis(\r\n sampledQuaternionTempQuaternion,\r\n sampledQuaternionAxis\r\n );\r\n var angle = Quaternion.computeAngle(sampledQuaternionTempQuaternion);\r\n if (!defined(result)) {\r\n result = [];\r\n }\r\n result[offset] = sampledQuaternionAxis.x * angle;\r\n result[offset + 1] = sampledQuaternionAxis.y * angle;\r\n result[offset + 2] = sampledQuaternionAxis.z * angle;\r\n }\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array converted with {@link convertPackedArrayForInterpolation}.\r\n *\r\n * @param {Number[]} array The array previously packed for interpolation.\r\n * @param {Number[]} sourceArray The original packed array.\r\n * @param {Number} [firstIndex=0] The firstIndex used to convert the array.\r\n * @param {Number} [lastIndex=packedArray.length] The lastIndex used to convert the array.\r\n * @param {Quaternion} [result] The object into which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.\r\n */\r\nQuaternion.unpackInterpolationResult = function (\r\n array,\r\n sourceArray,\r\n firstIndex,\r\n lastIndex,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new Quaternion();\r\n }\r\n Cartesian3.fromArray(array, 0, sampledQuaternionRotation);\r\n var magnitude = Cartesian3.magnitude(sampledQuaternionRotation);\r\n\r\n Quaternion.unpack(sourceArray, lastIndex * 4, sampledQuaternionQuaternion0);\r\n\r\n if (magnitude === 0) {\r\n Quaternion.clone(Quaternion.IDENTITY, sampledQuaternionTempQuaternion);\r\n } else {\r\n Quaternion.fromAxisAngle(\r\n sampledQuaternionRotation,\r\n magnitude,\r\n sampledQuaternionTempQuaternion\r\n );\r\n }\r\n\r\n return Quaternion.multiply(\r\n sampledQuaternionTempQuaternion,\r\n sampledQuaternionQuaternion0,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates a Quaternion instance.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to duplicate.\r\n * @param {Quaternion} [result] The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided. (Returns undefined if quaternion is undefined)\r\n */\r\nQuaternion.clone = function (quaternion, result) {\r\n if (!defined(quaternion)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Quaternion(\r\n quaternion.x,\r\n quaternion.y,\r\n quaternion.z,\r\n quaternion.w\r\n );\r\n }\r\n\r\n result.x = quaternion.x;\r\n result.y = quaternion.y;\r\n result.z = quaternion.z;\r\n result.w = quaternion.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the conjugate of the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to conjugate.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.conjugate = function (quaternion, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = -quaternion.x;\r\n result.y = -quaternion.y;\r\n result.z = -quaternion.z;\r\n result.w = quaternion.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes magnitude squared for the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to conjugate.\r\n * @returns {Number} The magnitude squared.\r\n */\r\nQuaternion.magnitudeSquared = function (quaternion) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n //>>includeEnd('debug');\r\n\r\n return (\r\n quaternion.x * quaternion.x +\r\n quaternion.y * quaternion.y +\r\n quaternion.z * quaternion.z +\r\n quaternion.w * quaternion.w\r\n );\r\n};\r\n\r\n/**\r\n * Computes magnitude for the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to conjugate.\r\n * @returns {Number} The magnitude.\r\n */\r\nQuaternion.magnitude = function (quaternion) {\r\n return Math.sqrt(Quaternion.magnitudeSquared(quaternion));\r\n};\r\n\r\n/**\r\n * Computes the normalized form of the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to normalize.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.normalize = function (quaternion, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var inverseMagnitude = 1.0 / Quaternion.magnitude(quaternion);\r\n var x = quaternion.x * inverseMagnitude;\r\n var y = quaternion.y * inverseMagnitude;\r\n var z = quaternion.z * inverseMagnitude;\r\n var w = quaternion.w * inverseMagnitude;\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n result.w = w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the inverse of the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to normalize.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.inverse = function (quaternion, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var magnitudeSquared = Quaternion.magnitudeSquared(quaternion);\r\n result = Quaternion.conjugate(quaternion, result);\r\n return Quaternion.multiplyByScalar(result, 1.0 / magnitudeSquared, result);\r\n};\r\n\r\n/**\r\n * Computes the componentwise sum of two quaternions.\r\n *\r\n * @param {Quaternion} left The first quaternion.\r\n * @param {Quaternion} right The second quaternion.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.add = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x + right.x;\r\n result.y = left.y + right.y;\r\n result.z = left.z + right.z;\r\n result.w = left.w + right.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise difference of two quaternions.\r\n *\r\n * @param {Quaternion} left The first quaternion.\r\n * @param {Quaternion} right The second quaternion.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.subtract = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = left.x - right.x;\r\n result.y = left.y - right.y;\r\n result.z = left.z - right.z;\r\n result.w = left.w - right.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Negates the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to be negated.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.negate = function (quaternion, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = -quaternion.x;\r\n result.y = -quaternion.y;\r\n result.z = -quaternion.z;\r\n result.w = -quaternion.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the dot (scalar) product of two quaternions.\r\n *\r\n * @param {Quaternion} left The first quaternion.\r\n * @param {Quaternion} right The second quaternion.\r\n * @returns {Number} The dot product.\r\n */\r\nQuaternion.dot = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n return (\r\n left.x * right.x + left.y * right.y + left.z * right.z + left.w * right.w\r\n );\r\n};\r\n\r\n/**\r\n * Computes the product of two quaternions.\r\n *\r\n * @param {Quaternion} left The first quaternion.\r\n * @param {Quaternion} right The second quaternion.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.multiply = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var leftX = left.x;\r\n var leftY = left.y;\r\n var leftZ = left.z;\r\n var leftW = left.w;\r\n\r\n var rightX = right.x;\r\n var rightY = right.y;\r\n var rightZ = right.z;\r\n var rightW = right.w;\r\n\r\n var x = leftW * rightX + leftX * rightW + leftY * rightZ - leftZ * rightY;\r\n var y = leftW * rightY - leftX * rightZ + leftY * rightW + leftZ * rightX;\r\n var z = leftW * rightZ + leftX * rightY - leftY * rightX + leftZ * rightW;\r\n var w = leftW * rightW - leftX * rightX - leftY * rightY - leftZ * rightZ;\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n result.w = w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Multiplies the provided quaternion componentwise by the provided scalar.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to be scaled.\r\n * @param {Number} scalar The scalar to multiply with.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.multiplyByScalar = function (quaternion, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = quaternion.x * scalar;\r\n result.y = quaternion.y * scalar;\r\n result.z = quaternion.z * scalar;\r\n result.w = quaternion.w * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Divides the provided quaternion componentwise by the provided scalar.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to be divided.\r\n * @param {Number} scalar The scalar to divide by.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.divideByScalar = function (quaternion, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = quaternion.x / scalar;\r\n result.y = quaternion.y / scalar;\r\n result.z = quaternion.z / scalar;\r\n result.w = quaternion.w / scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the axis of rotation of the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to use.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nQuaternion.computeAxis = function (quaternion, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var w = quaternion.w;\r\n if (Math.abs(w - 1.0) < CesiumMath.EPSILON6) {\r\n result.x = result.y = result.z = 0;\r\n return result;\r\n }\r\n\r\n var scalar = 1.0 / Math.sqrt(1.0 - w * w);\r\n\r\n result.x = quaternion.x * scalar;\r\n result.y = quaternion.y * scalar;\r\n result.z = quaternion.z * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the angle of rotation of the provided quaternion.\r\n *\r\n * @param {Quaternion} quaternion The quaternion to use.\r\n * @returns {Number} The angle of rotation.\r\n */\r\nQuaternion.computeAngle = function (quaternion) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n //>>includeEnd('debug');\r\n\r\n if (Math.abs(quaternion.w - 1.0) < CesiumMath.EPSILON6) {\r\n return 0.0;\r\n }\r\n return 2.0 * Math.acos(quaternion.w);\r\n};\r\n\r\nvar lerpScratch = new Quaternion();\r\n/**\r\n * Computes the linear interpolation or extrapolation at t using the provided quaternions.\r\n *\r\n * @param {Quaternion} start The value corresponding to t at 0.0.\r\n * @param {Quaternion} end The value corresponding to t at 1.0.\r\n * @param {Number} t The point along t at which to interpolate.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.lerp = function (start, end, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"start\", start);\r\n Check.typeOf.object(\"end\", end);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n lerpScratch = Quaternion.multiplyByScalar(end, t, lerpScratch);\r\n result = Quaternion.multiplyByScalar(start, 1.0 - t, result);\r\n return Quaternion.add(lerpScratch, result, result);\r\n};\r\n\r\nvar slerpEndNegated = new Quaternion();\r\nvar slerpScaledP = new Quaternion();\r\nvar slerpScaledR = new Quaternion();\r\n/**\r\n * Computes the spherical linear interpolation or extrapolation at t using the provided quaternions.\r\n *\r\n * @param {Quaternion} start The value corresponding to t at 0.0.\r\n * @param {Quaternion} end The value corresponding to t at 1.0.\r\n * @param {Number} t The point along t at which to interpolate.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n *\r\n * @see Quaternion#fastSlerp\r\n */\r\nQuaternion.slerp = function (start, end, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"start\", start);\r\n Check.typeOf.object(\"end\", end);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var dot = Quaternion.dot(start, end);\r\n\r\n // The angle between start must be acute. Since q and -q represent\r\n // the same rotation, negate q to get the acute angle.\r\n var r = end;\r\n if (dot < 0.0) {\r\n dot = -dot;\r\n r = slerpEndNegated = Quaternion.negate(end, slerpEndNegated);\r\n }\r\n\r\n // dot > 0, as the dot product approaches 1, the angle between the\r\n // quaternions vanishes. use linear interpolation.\r\n if (1.0 - dot < CesiumMath.EPSILON6) {\r\n return Quaternion.lerp(start, r, t, result);\r\n }\r\n\r\n var theta = Math.acos(dot);\r\n slerpScaledP = Quaternion.multiplyByScalar(\r\n start,\r\n Math.sin((1 - t) * theta),\r\n slerpScaledP\r\n );\r\n slerpScaledR = Quaternion.multiplyByScalar(\r\n r,\r\n Math.sin(t * theta),\r\n slerpScaledR\r\n );\r\n result = Quaternion.add(slerpScaledP, slerpScaledR, result);\r\n return Quaternion.multiplyByScalar(result, 1.0 / Math.sin(theta), result);\r\n};\r\n\r\n/**\r\n * The logarithmic quaternion function.\r\n *\r\n * @param {Quaternion} quaternion The unit quaternion.\r\n * @param {Cartesian3} result The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter.\r\n */\r\nQuaternion.log = function (quaternion, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"quaternion\", quaternion);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var theta = CesiumMath.acosClamped(quaternion.w);\r\n var thetaOverSinTheta = 0.0;\r\n\r\n if (theta !== 0.0) {\r\n thetaOverSinTheta = theta / Math.sin(theta);\r\n }\r\n\r\n return Cartesian3.multiplyByScalar(quaternion, thetaOverSinTheta, result);\r\n};\r\n\r\n/**\r\n * The exponential quaternion function.\r\n *\r\n * @param {Cartesian3} cartesian The cartesian.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n */\r\nQuaternion.exp = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var theta = Cartesian3.magnitude(cartesian);\r\n var sinThetaOverTheta = 0.0;\r\n\r\n if (theta !== 0.0) {\r\n sinThetaOverTheta = Math.sin(theta) / theta;\r\n }\r\n\r\n result.x = cartesian.x * sinThetaOverTheta;\r\n result.y = cartesian.y * sinThetaOverTheta;\r\n result.z = cartesian.z * sinThetaOverTheta;\r\n result.w = Math.cos(theta);\r\n\r\n return result;\r\n};\r\n\r\nvar squadScratchCartesian0 = new Cartesian3();\r\nvar squadScratchCartesian1 = new Cartesian3();\r\nvar squadScratchQuaternion0 = new Quaternion();\r\nvar squadScratchQuaternion1 = new Quaternion();\r\n\r\n/**\r\n * Computes an inner quadrangle point.\r\n *

This will compute quaternions that ensure a squad curve is C1.

\r\n *\r\n * @param {Quaternion} q0 The first quaternion.\r\n * @param {Quaternion} q1 The second quaternion.\r\n * @param {Quaternion} q2 The third quaternion.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n *\r\n * @see Quaternion#squad\r\n */\r\nQuaternion.computeInnerQuadrangle = function (q0, q1, q2, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"q0\", q0);\r\n Check.typeOf.object(\"q1\", q1);\r\n Check.typeOf.object(\"q2\", q2);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var qInv = Quaternion.conjugate(q1, squadScratchQuaternion0);\r\n Quaternion.multiply(qInv, q2, squadScratchQuaternion1);\r\n var cart0 = Quaternion.log(squadScratchQuaternion1, squadScratchCartesian0);\r\n\r\n Quaternion.multiply(qInv, q0, squadScratchQuaternion1);\r\n var cart1 = Quaternion.log(squadScratchQuaternion1, squadScratchCartesian1);\r\n\r\n Cartesian3.add(cart0, cart1, cart0);\r\n Cartesian3.multiplyByScalar(cart0, 0.25, cart0);\r\n Cartesian3.negate(cart0, cart0);\r\n Quaternion.exp(cart0, squadScratchQuaternion0);\r\n\r\n return Quaternion.multiply(q1, squadScratchQuaternion0, result);\r\n};\r\n\r\n/**\r\n * Computes the spherical quadrangle interpolation between quaternions.\r\n *\r\n * @param {Quaternion} q0 The first quaternion.\r\n * @param {Quaternion} q1 The second quaternion.\r\n * @param {Quaternion} s0 The first inner quadrangle.\r\n * @param {Quaternion} s1 The second inner quadrangle.\r\n * @param {Number} t The time in [0,1] used to interpolate.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n *\r\n *\r\n * @example\r\n * // 1. compute the squad interpolation between two quaternions on a curve\r\n * var s0 = Cesium.Quaternion.computeInnerQuadrangle(quaternions[i - 1], quaternions[i], quaternions[i + 1], new Cesium.Quaternion());\r\n * var s1 = Cesium.Quaternion.computeInnerQuadrangle(quaternions[i], quaternions[i + 1], quaternions[i + 2], new Cesium.Quaternion());\r\n * var q = Cesium.Quaternion.squad(quaternions[i], quaternions[i + 1], s0, s1, t, new Cesium.Quaternion());\r\n *\r\n * // 2. compute the squad interpolation as above but where the first quaternion is a end point.\r\n * var s1 = Cesium.Quaternion.computeInnerQuadrangle(quaternions[0], quaternions[1], quaternions[2], new Cesium.Quaternion());\r\n * var q = Cesium.Quaternion.squad(quaternions[0], quaternions[1], quaternions[0], s1, t, new Cesium.Quaternion());\r\n *\r\n * @see Quaternion#computeInnerQuadrangle\r\n */\r\nQuaternion.squad = function (q0, q1, s0, s1, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"q0\", q0);\r\n Check.typeOf.object(\"q1\", q1);\r\n Check.typeOf.object(\"s0\", s0);\r\n Check.typeOf.object(\"s1\", s1);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var slerp0 = Quaternion.slerp(q0, q1, t, squadScratchQuaternion0);\r\n var slerp1 = Quaternion.slerp(s0, s1, t, squadScratchQuaternion1);\r\n return Quaternion.slerp(slerp0, slerp1, 2.0 * t * (1.0 - t), result);\r\n};\r\n\r\nvar fastSlerpScratchQuaternion = new Quaternion();\r\nvar opmu = 1.90110745351730037;\r\nvar u = FeatureDetection.supportsTypedArrays() ? new Float32Array(8) : [];\r\nvar v = FeatureDetection.supportsTypedArrays() ? new Float32Array(8) : [];\r\nvar bT = FeatureDetection.supportsTypedArrays() ? new Float32Array(8) : [];\r\nvar bD = FeatureDetection.supportsTypedArrays() ? new Float32Array(8) : [];\r\n\r\nfor (var i = 0; i < 7; ++i) {\r\n var s = i + 1.0;\r\n var t = 2.0 * s + 1.0;\r\n u[i] = 1.0 / (s * t);\r\n v[i] = s / t;\r\n}\r\n\r\nu[7] = opmu / (8.0 * 17.0);\r\nv[7] = (opmu * 8.0) / 17.0;\r\n\r\n/**\r\n * Computes the spherical linear interpolation or extrapolation at t using the provided quaternions.\r\n * This implementation is faster than {@link Quaternion#slerp}, but is only accurate up to 10-6.\r\n *\r\n * @param {Quaternion} start The value corresponding to t at 0.0.\r\n * @param {Quaternion} end The value corresponding to t at 1.0.\r\n * @param {Number} t The point along t at which to interpolate.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter.\r\n *\r\n * @see Quaternion#slerp\r\n */\r\nQuaternion.fastSlerp = function (start, end, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"start\", start);\r\n Check.typeOf.object(\"end\", end);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var x = Quaternion.dot(start, end);\r\n\r\n var sign;\r\n if (x >= 0) {\r\n sign = 1.0;\r\n } else {\r\n sign = -1.0;\r\n x = -x;\r\n }\r\n\r\n var xm1 = x - 1.0;\r\n var d = 1.0 - t;\r\n var sqrT = t * t;\r\n var sqrD = d * d;\r\n\r\n for (var i = 7; i >= 0; --i) {\r\n bT[i] = (u[i] * sqrT - v[i]) * xm1;\r\n bD[i] = (u[i] * sqrD - v[i]) * xm1;\r\n }\r\n\r\n var cT =\r\n sign *\r\n t *\r\n (1.0 +\r\n bT[0] *\r\n (1.0 +\r\n bT[1] *\r\n (1.0 +\r\n bT[2] *\r\n (1.0 +\r\n bT[3] *\r\n (1.0 +\r\n bT[4] *\r\n (1.0 + bT[5] * (1.0 + bT[6] * (1.0 + bT[7]))))))));\r\n var cD =\r\n d *\r\n (1.0 +\r\n bD[0] *\r\n (1.0 +\r\n bD[1] *\r\n (1.0 +\r\n bD[2] *\r\n (1.0 +\r\n bD[3] *\r\n (1.0 +\r\n bD[4] *\r\n (1.0 + bD[5] * (1.0 + bD[6] * (1.0 + bD[7]))))))));\r\n\r\n var temp = Quaternion.multiplyByScalar(start, cD, fastSlerpScratchQuaternion);\r\n Quaternion.multiplyByScalar(end, cT, result);\r\n return Quaternion.add(temp, result, result);\r\n};\r\n\r\n/**\r\n * Computes the spherical quadrangle interpolation between quaternions.\r\n * An implementation that is faster than {@link Quaternion#squad}, but less accurate.\r\n *\r\n * @param {Quaternion} q0 The first quaternion.\r\n * @param {Quaternion} q1 The second quaternion.\r\n * @param {Quaternion} s0 The first inner quadrangle.\r\n * @param {Quaternion} s1 The second inner quadrangle.\r\n * @param {Number} t The time in [0,1] used to interpolate.\r\n * @param {Quaternion} result The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new instance if none was provided.\r\n *\r\n * @see Quaternion#squad\r\n */\r\nQuaternion.fastSquad = function (q0, q1, s0, s1, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"q0\", q0);\r\n Check.typeOf.object(\"q1\", q1);\r\n Check.typeOf.object(\"s0\", s0);\r\n Check.typeOf.object(\"s1\", s1);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var slerp0 = Quaternion.fastSlerp(q0, q1, t, squadScratchQuaternion0);\r\n var slerp1 = Quaternion.fastSlerp(s0, s1, t, squadScratchQuaternion1);\r\n return Quaternion.fastSlerp(slerp0, slerp1, 2.0 * t * (1.0 - t), result);\r\n};\r\n\r\n/**\r\n * Compares the provided quaternions componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Quaternion} [left] The first quaternion.\r\n * @param {Quaternion} [right] The second quaternion.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nQuaternion.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.x === right.x &&\r\n left.y === right.y &&\r\n left.z === right.z &&\r\n left.w === right.w)\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided quaternions componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Quaternion} [left] The first quaternion.\r\n * @param {Quaternion} [right] The second quaternion.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nQuaternion.equalsEpsilon = function (left, right, epsilon) {\r\n epsilon = defaultValue(epsilon, 0);\r\n\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Math.abs(left.x - right.x) <= epsilon &&\r\n Math.abs(left.y - right.y) <= epsilon &&\r\n Math.abs(left.z - right.z) <= epsilon &&\r\n Math.abs(left.w - right.w) <= epsilon)\r\n );\r\n};\r\n\r\n/**\r\n * An immutable Quaternion instance initialized to (0.0, 0.0, 0.0, 0.0).\r\n *\r\n * @type {Quaternion}\r\n * @constant\r\n */\r\nQuaternion.ZERO = Object.freeze(new Quaternion(0.0, 0.0, 0.0, 0.0));\r\n\r\n/**\r\n * An immutable Quaternion instance initialized to (0.0, 0.0, 0.0, 1.0).\r\n *\r\n * @type {Quaternion}\r\n * @constant\r\n */\r\nQuaternion.IDENTITY = Object.freeze(new Quaternion(0.0, 0.0, 0.0, 1.0));\r\n\r\n/**\r\n * Duplicates this Quaternion instance.\r\n *\r\n * @param {Quaternion} [result] The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new Quaternion instance if one was not provided.\r\n */\r\nQuaternion.prototype.clone = function (result) {\r\n return Quaternion.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this and the provided quaternion componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Quaternion} [right] The right hand side quaternion.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nQuaternion.prototype.equals = function (right) {\r\n return Quaternion.equals(this, right);\r\n};\r\n\r\n/**\r\n * Compares this and the provided quaternion componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Quaternion} [right] The right hand side quaternion.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nQuaternion.prototype.equalsEpsilon = function (right, epsilon) {\r\n return Quaternion.equalsEpsilon(this, right, epsilon);\r\n};\r\n\r\n/**\r\n * Returns a string representing this quaternion in the format (x, y, z, w).\r\n *\r\n * @returns {String} A string representing this Quaternion.\r\n */\r\nQuaternion.prototype.toString = function () {\r\n return \"(\" + this.x + \", \" + this.y + \", \" + this.z + \", \" + this.w + \")\";\r\n};\r\nexport default Quaternion;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport EarthOrientationParameters from \"./EarthOrientationParameters.js\";\r\nimport EarthOrientationParametersSample from \"./EarthOrientationParametersSample.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport HeadingPitchRoll from \"./HeadingPitchRoll.js\";\r\nimport Iau2006XysData from \"./Iau2006XysData.js\";\r\nimport Iau2006XysSample from \"./Iau2006XysSample.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport TimeConstants from \"./TimeConstants.js\";\r\n\r\n/**\r\n * Contains functions for transforming positions to various reference frames.\r\n *\r\n * @namespace Transforms\r\n */\r\nvar Transforms = {};\r\n\r\nvar vectorProductLocalFrame = {\r\n up: {\r\n south: \"east\",\r\n north: \"west\",\r\n west: \"south\",\r\n east: \"north\",\r\n },\r\n down: {\r\n south: \"west\",\r\n north: \"east\",\r\n west: \"north\",\r\n east: \"south\",\r\n },\r\n south: {\r\n up: \"west\",\r\n down: \"east\",\r\n west: \"down\",\r\n east: \"up\",\r\n },\r\n north: {\r\n up: \"east\",\r\n down: \"west\",\r\n west: \"up\",\r\n east: \"down\",\r\n },\r\n west: {\r\n up: \"north\",\r\n down: \"south\",\r\n north: \"down\",\r\n south: \"up\",\r\n },\r\n east: {\r\n up: \"south\",\r\n down: \"north\",\r\n north: \"up\",\r\n south: \"down\",\r\n },\r\n};\r\n\r\nvar degeneratePositionLocalFrame = {\r\n north: [-1, 0, 0],\r\n east: [0, 1, 0],\r\n up: [0, 0, 1],\r\n south: [1, 0, 0],\r\n west: [0, -1, 0],\r\n down: [0, 0, -1],\r\n};\r\n\r\nvar localFrameToFixedFrameCache = {};\r\n\r\nvar scratchCalculateCartesian = {\r\n east: new Cartesian3(),\r\n north: new Cartesian3(),\r\n up: new Cartesian3(),\r\n west: new Cartesian3(),\r\n south: new Cartesian3(),\r\n down: new Cartesian3(),\r\n};\r\nvar scratchFirstCartesian = new Cartesian3();\r\nvar scratchSecondCartesian = new Cartesian3();\r\nvar scratchThirdCartesian = new Cartesian3();\r\n/**\r\n * Generates a function that computes a 4x4 transformation matrix from a reference frame\r\n * centered at the provided origin to the provided ellipsoid's fixed reference frame.\r\n * @param {String} firstAxis name of the first axis of the local reference frame. Must be\r\n * 'east', 'north', 'up', 'west', 'south' or 'down'.\r\n * @param {String} secondAxis name of the second axis of the local reference frame. Must be\r\n * 'east', 'north', 'up', 'west', 'south' or 'down'.\r\n * @return {Transforms.LocalFrameToFixedFrame} The function that will computes a\r\n * 4x4 transformation matrix from a reference frame, with first axis and second axis compliant with the parameters,\r\n */\r\nTransforms.localFrameToFixedFrameGenerator = function (firstAxis, secondAxis) {\r\n if (\r\n !vectorProductLocalFrame.hasOwnProperty(firstAxis) ||\r\n !vectorProductLocalFrame[firstAxis].hasOwnProperty(secondAxis)\r\n ) {\r\n throw new DeveloperError(\r\n \"firstAxis and secondAxis must be east, north, up, west, south or down.\"\r\n );\r\n }\r\n var thirdAxis = vectorProductLocalFrame[firstAxis][secondAxis];\r\n\r\n /**\r\n * Computes a 4x4 transformation matrix from a reference frame\r\n * centered at the provided origin to the provided ellipsoid's fixed reference frame.\r\n * @callback Transforms.LocalFrameToFixedFrame\r\n * @param {Cartesian3} origin The center point of the local reference frame.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.\r\n */\r\n var resultat;\r\n var hashAxis = firstAxis + secondAxis;\r\n if (defined(localFrameToFixedFrameCache[hashAxis])) {\r\n resultat = localFrameToFixedFrameCache[hashAxis];\r\n } else {\r\n resultat = function (origin, ellipsoid, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(origin)) {\r\n throw new DeveloperError(\"origin is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n if (!defined(result)) {\r\n result = new Matrix4();\r\n }\r\n if (\r\n Cartesian3.equalsEpsilon(origin, Cartesian3.ZERO, CesiumMath.EPSILON14)\r\n ) {\r\n // If x, y, and z are zero, use the degenerate local frame, which is a special case\r\n Cartesian3.unpack(\r\n degeneratePositionLocalFrame[firstAxis],\r\n 0,\r\n scratchFirstCartesian\r\n );\r\n Cartesian3.unpack(\r\n degeneratePositionLocalFrame[secondAxis],\r\n 0,\r\n scratchSecondCartesian\r\n );\r\n Cartesian3.unpack(\r\n degeneratePositionLocalFrame[thirdAxis],\r\n 0,\r\n scratchThirdCartesian\r\n );\r\n } else if (\r\n CesiumMath.equalsEpsilon(origin.x, 0.0, CesiumMath.EPSILON14) &&\r\n CesiumMath.equalsEpsilon(origin.y, 0.0, CesiumMath.EPSILON14)\r\n ) {\r\n // If x and y are zero, assume origin is at a pole, which is a special case.\r\n var sign = CesiumMath.sign(origin.z);\r\n\r\n Cartesian3.unpack(\r\n degeneratePositionLocalFrame[firstAxis],\r\n 0,\r\n scratchFirstCartesian\r\n );\r\n if (firstAxis !== \"east\" && firstAxis !== \"west\") {\r\n Cartesian3.multiplyByScalar(\r\n scratchFirstCartesian,\r\n sign,\r\n scratchFirstCartesian\r\n );\r\n }\r\n\r\n Cartesian3.unpack(\r\n degeneratePositionLocalFrame[secondAxis],\r\n 0,\r\n scratchSecondCartesian\r\n );\r\n if (secondAxis !== \"east\" && secondAxis !== \"west\") {\r\n Cartesian3.multiplyByScalar(\r\n scratchSecondCartesian,\r\n sign,\r\n scratchSecondCartesian\r\n );\r\n }\r\n\r\n Cartesian3.unpack(\r\n degeneratePositionLocalFrame[thirdAxis],\r\n 0,\r\n scratchThirdCartesian\r\n );\r\n if (thirdAxis !== \"east\" && thirdAxis !== \"west\") {\r\n Cartesian3.multiplyByScalar(\r\n scratchThirdCartesian,\r\n sign,\r\n scratchThirdCartesian\r\n );\r\n }\r\n } else {\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n ellipsoid.geodeticSurfaceNormal(origin, scratchCalculateCartesian.up);\r\n\r\n var up = scratchCalculateCartesian.up;\r\n var east = scratchCalculateCartesian.east;\r\n east.x = -origin.y;\r\n east.y = origin.x;\r\n east.z = 0.0;\r\n Cartesian3.normalize(east, scratchCalculateCartesian.east);\r\n Cartesian3.cross(up, east, scratchCalculateCartesian.north);\r\n\r\n Cartesian3.multiplyByScalar(\r\n scratchCalculateCartesian.up,\r\n -1,\r\n scratchCalculateCartesian.down\r\n );\r\n Cartesian3.multiplyByScalar(\r\n scratchCalculateCartesian.east,\r\n -1,\r\n scratchCalculateCartesian.west\r\n );\r\n Cartesian3.multiplyByScalar(\r\n scratchCalculateCartesian.north,\r\n -1,\r\n scratchCalculateCartesian.south\r\n );\r\n\r\n scratchFirstCartesian = scratchCalculateCartesian[firstAxis];\r\n scratchSecondCartesian = scratchCalculateCartesian[secondAxis];\r\n scratchThirdCartesian = scratchCalculateCartesian[thirdAxis];\r\n }\r\n result[0] = scratchFirstCartesian.x;\r\n result[1] = scratchFirstCartesian.y;\r\n result[2] = scratchFirstCartesian.z;\r\n result[3] = 0.0;\r\n result[4] = scratchSecondCartesian.x;\r\n result[5] = scratchSecondCartesian.y;\r\n result[6] = scratchSecondCartesian.z;\r\n result[7] = 0.0;\r\n result[8] = scratchThirdCartesian.x;\r\n result[9] = scratchThirdCartesian.y;\r\n result[10] = scratchThirdCartesian.z;\r\n result[11] = 0.0;\r\n result[12] = origin.x;\r\n result[13] = origin.y;\r\n result[14] = origin.z;\r\n result[15] = 1.0;\r\n return result;\r\n };\r\n localFrameToFixedFrameCache[hashAxis] = resultat;\r\n }\r\n return resultat;\r\n};\r\n\r\n/**\r\n * Computes a 4x4 transformation matrix from a reference frame with an east-north-up axes\r\n * centered at the provided origin to the provided ellipsoid's fixed reference frame.\r\n * The local axes are defined as:\r\n *
    \r\n *
  • The x axis points in the local east direction.
  • \r\n *
  • The y axis points in the local north direction.
  • \r\n *
  • The z axis points in the direction of the ellipsoid surface normal which passes through the position.
  • \r\n *
\r\n *\r\n * @function\r\n * @param {Cartesian3} origin The center point of the local reference frame.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.\r\n *\r\n * @example\r\n * // Get the transform from local east-north-up at cartographic (0.0, 0.0) to Earth's fixed frame.\r\n * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center);\r\n */\r\nTransforms.eastNorthUpToFixedFrame = Transforms.localFrameToFixedFrameGenerator(\r\n \"east\",\r\n \"north\"\r\n);\r\n\r\n/**\r\n * Computes a 4x4 transformation matrix from a reference frame with an north-east-down axes\r\n * centered at the provided origin to the provided ellipsoid's fixed reference frame.\r\n * The local axes are defined as:\r\n *
    \r\n *
  • The x axis points in the local north direction.
  • \r\n *
  • The y axis points in the local east direction.
  • \r\n *
  • The z axis points in the opposite direction of the ellipsoid surface normal which passes through the position.
  • \r\n *
\r\n *\r\n * @function\r\n * @param {Cartesian3} origin The center point of the local reference frame.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.\r\n *\r\n * @example\r\n * // Get the transform from local north-east-down at cartographic (0.0, 0.0) to Earth's fixed frame.\r\n * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var transform = Cesium.Transforms.northEastDownToFixedFrame(center);\r\n */\r\nTransforms.northEastDownToFixedFrame = Transforms.localFrameToFixedFrameGenerator(\r\n \"north\",\r\n \"east\"\r\n);\r\n\r\n/**\r\n * Computes a 4x4 transformation matrix from a reference frame with an north-up-east axes\r\n * centered at the provided origin to the provided ellipsoid's fixed reference frame.\r\n * The local axes are defined as:\r\n *
    \r\n *
  • The x axis points in the local north direction.
  • \r\n *
  • The y axis points in the direction of the ellipsoid surface normal which passes through the position.
  • \r\n *
  • The z axis points in the local east direction.
  • \r\n *
\r\n *\r\n * @function\r\n * @param {Cartesian3} origin The center point of the local reference frame.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.\r\n *\r\n * @example\r\n * // Get the transform from local north-up-east at cartographic (0.0, 0.0) to Earth's fixed frame.\r\n * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var transform = Cesium.Transforms.northUpEastToFixedFrame(center);\r\n */\r\nTransforms.northUpEastToFixedFrame = Transforms.localFrameToFixedFrameGenerator(\r\n \"north\",\r\n \"up\"\r\n);\r\n\r\n/**\r\n * Computes a 4x4 transformation matrix from a reference frame with an north-west-up axes\r\n * centered at the provided origin to the provided ellipsoid's fixed reference frame.\r\n * The local axes are defined as:\r\n *
    \r\n *
  • The x axis points in the local north direction.
  • \r\n *
  • The y axis points in the local west direction.
  • \r\n *
  • The z axis points in the direction of the ellipsoid surface normal which passes through the position.
  • \r\n *
\r\n *\r\n * @function\r\n * @param {Cartesian3} origin The center point of the local reference frame.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.\r\n *\r\n * @example\r\n * // Get the transform from local north-West-Up at cartographic (0.0, 0.0) to Earth's fixed frame.\r\n * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var transform = Cesium.Transforms.northWestUpToFixedFrame(center);\r\n */\r\nTransforms.northWestUpToFixedFrame = Transforms.localFrameToFixedFrameGenerator(\r\n \"north\",\r\n \"west\"\r\n);\r\n\r\nvar scratchHPRQuaternion = new Quaternion();\r\nvar scratchScale = new Cartesian3(1.0, 1.0, 1.0);\r\nvar scratchHPRMatrix4 = new Matrix4();\r\n\r\n/**\r\n * Computes a 4x4 transformation matrix from a reference frame with axes computed from the heading-pitch-roll angles\r\n * centered at the provided origin to the provided ellipsoid's fixed reference frame. Heading is the rotation from the local north\r\n * direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles\r\n * are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.\r\n *\r\n * @param {Cartesian3} origin The center point of the local reference frame.\r\n * @param {HeadingPitchRoll} headingPitchRoll The heading, pitch, and roll.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation\r\n * matrix from a reference frame to the provided ellipsoid's fixed reference frame\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if none was provided.\r\n *\r\n * @example\r\n * // Get the transform from local heading-pitch-roll at cartographic (0.0, 0.0) to Earth's fixed frame.\r\n * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var heading = -Cesium.Math.PI_OVER_TWO;\r\n * var pitch = Cesium.Math.PI_OVER_FOUR;\r\n * var roll = 0.0;\r\n * var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);\r\n * var transform = Cesium.Transforms.headingPitchRollToFixedFrame(center, hpr);\r\n */\r\nTransforms.headingPitchRollToFixedFrame = function (\r\n origin,\r\n headingPitchRoll,\r\n ellipsoid,\r\n fixedFrameTransform,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"HeadingPitchRoll\", headingPitchRoll);\r\n //>>includeEnd('debug');\r\n\r\n fixedFrameTransform = defaultValue(\r\n fixedFrameTransform,\r\n Transforms.eastNorthUpToFixedFrame\r\n );\r\n var hprQuaternion = Quaternion.fromHeadingPitchRoll(\r\n headingPitchRoll,\r\n scratchHPRQuaternion\r\n );\r\n var hprMatrix = Matrix4.fromTranslationQuaternionRotationScale(\r\n Cartesian3.ZERO,\r\n hprQuaternion,\r\n scratchScale,\r\n scratchHPRMatrix4\r\n );\r\n result = fixedFrameTransform(origin, ellipsoid, result);\r\n return Matrix4.multiply(result, hprMatrix, result);\r\n};\r\n\r\nvar scratchENUMatrix4 = new Matrix4();\r\nvar scratchHPRMatrix3 = new Matrix3();\r\n\r\n/**\r\n * Computes a quaternion from a reference frame with axes computed from the heading-pitch-roll angles\r\n * centered at the provided origin. Heading is the rotation from the local north\r\n * direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles\r\n * are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.\r\n *\r\n * @param {Cartesian3} origin The center point of the local reference frame.\r\n * @param {HeadingPitchRoll} headingPitchRoll The heading, pitch, and roll.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation\r\n * matrix from a reference frame to the provided ellipsoid's fixed reference frame\r\n * @param {Quaternion} [result] The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new Quaternion instance if none was provided.\r\n *\r\n * @example\r\n * // Get the quaternion from local heading-pitch-roll at cartographic (0.0, 0.0) to Earth's fixed frame.\r\n * var center = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var heading = -Cesium.Math.PI_OVER_TWO;\r\n * var pitch = Cesium.Math.PI_OVER_FOUR;\r\n * var roll = 0.0;\r\n * var hpr = new HeadingPitchRoll(heading, pitch, roll);\r\n * var quaternion = Cesium.Transforms.headingPitchRollQuaternion(center, hpr);\r\n */\r\nTransforms.headingPitchRollQuaternion = function (\r\n origin,\r\n headingPitchRoll,\r\n ellipsoid,\r\n fixedFrameTransform,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"HeadingPitchRoll\", headingPitchRoll);\r\n //>>includeEnd('debug');\r\n\r\n var transform = Transforms.headingPitchRollToFixedFrame(\r\n origin,\r\n headingPitchRoll,\r\n ellipsoid,\r\n fixedFrameTransform,\r\n scratchENUMatrix4\r\n );\r\n var rotation = Matrix4.getMatrix3(transform, scratchHPRMatrix3);\r\n return Quaternion.fromRotationMatrix(rotation, result);\r\n};\r\n\r\nvar noScale = new Cartesian3(1.0, 1.0, 1.0);\r\nvar hprCenterScratch = new Cartesian3();\r\nvar ffScratch = new Matrix4();\r\nvar hprTransformScratch = new Matrix4();\r\nvar hprRotationScratch = new Matrix3();\r\nvar hprQuaternionScratch = new Quaternion();\r\n/**\r\n * Computes heading-pitch-roll angles from a transform in a particular reference frame. Heading is the rotation from the local north\r\n * direction where a positive angle is increasing eastward. Pitch is the rotation from the local east-north plane. Positive pitch angles\r\n * are above the plane. Negative pitch angles are below the plane. Roll is the first rotation applied about the local east axis.\r\n *\r\n * @param {Matrix4} transform The transform\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Transforms.LocalFrameToFixedFrame} [fixedFrameTransform=Transforms.eastNorthUpToFixedFrame] A 4x4 transformation\r\n * matrix from a reference frame to the provided ellipsoid's fixed reference frame\r\n * @param {HeadingPitchRoll} [result] The object onto which to store the result.\r\n * @returns {HeadingPitchRoll} The modified result parameter or a new HeadingPitchRoll instance if none was provided.\r\n */\r\nTransforms.fixedFrameToHeadingPitchRoll = function (\r\n transform,\r\n ellipsoid,\r\n fixedFrameTransform,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"transform\", transform);\r\n //>>includeEnd('debug');\r\n\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n fixedFrameTransform = defaultValue(\r\n fixedFrameTransform,\r\n Transforms.eastNorthUpToFixedFrame\r\n );\r\n if (!defined(result)) {\r\n result = new HeadingPitchRoll();\r\n }\r\n\r\n var center = Matrix4.getTranslation(transform, hprCenterScratch);\r\n if (Cartesian3.equals(center, Cartesian3.ZERO)) {\r\n result.heading = 0;\r\n result.pitch = 0;\r\n result.roll = 0;\r\n return result;\r\n }\r\n var toFixedFrame = Matrix4.inverseTransformation(\r\n fixedFrameTransform(center, ellipsoid, ffScratch),\r\n ffScratch\r\n );\r\n var transformCopy = Matrix4.setScale(transform, noScale, hprTransformScratch);\r\n transformCopy = Matrix4.setTranslation(\r\n transformCopy,\r\n Cartesian3.ZERO,\r\n transformCopy\r\n );\r\n\r\n toFixedFrame = Matrix4.multiply(toFixedFrame, transformCopy, toFixedFrame);\r\n var quaternionRotation = Quaternion.fromRotationMatrix(\r\n Matrix4.getMatrix3(toFixedFrame, hprRotationScratch),\r\n hprQuaternionScratch\r\n );\r\n quaternionRotation = Quaternion.normalize(\r\n quaternionRotation,\r\n quaternionRotation\r\n );\r\n\r\n return HeadingPitchRoll.fromQuaternion(quaternionRotation, result);\r\n};\r\n\r\nvar gmstConstant0 = 6 * 3600 + 41 * 60 + 50.54841;\r\nvar gmstConstant1 = 8640184.812866;\r\nvar gmstConstant2 = 0.093104;\r\nvar gmstConstant3 = -6.2e-6;\r\nvar rateCoef = 1.1772758384668e-19;\r\nvar wgs84WRPrecessing = 7.2921158553e-5;\r\nvar twoPiOverSecondsInDay = CesiumMath.TWO_PI / 86400.0;\r\nvar dateInUtc = new JulianDate();\r\n\r\n/**\r\n * Computes a rotation matrix to transform a point or vector from True Equator Mean Equinox (TEME) axes to the\r\n * pseudo-fixed axes at a given time. This method treats the UT1 time standard as equivalent to UTC.\r\n *\r\n * @param {JulianDate} date The time at which to compute the rotation matrix.\r\n * @param {Matrix3} [result] The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if none was provided.\r\n *\r\n * @example\r\n * //Set the view to the inertial frame.\r\n * scene.postUpdate.addEventListener(function(scene, time) {\r\n * var now = Cesium.JulianDate.now();\r\n * var offset = Cesium.Matrix4.multiplyByPoint(camera.transform, camera.position, new Cesium.Cartesian3());\r\n * var transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Transforms.computeTemeToPseudoFixedMatrix(now));\r\n * var inverseTransform = Cesium.Matrix4.inverseTransformation(transform, new Cesium.Matrix4());\r\n * Cesium.Matrix4.multiplyByPoint(inverseTransform, offset, offset);\r\n * camera.lookAtTransform(transform, offset);\r\n * });\r\n */\r\nTransforms.computeTemeToPseudoFixedMatrix = function (date, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(date)) {\r\n throw new DeveloperError(\"date is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // GMST is actually computed using UT1. We're using UTC as an approximation of UT1.\r\n // We do not want to use the function like convertTaiToUtc in JulianDate because\r\n // we explicitly do not want to fail when inside the leap second.\r\n\r\n dateInUtc = JulianDate.addSeconds(\r\n date,\r\n -JulianDate.computeTaiMinusUtc(date),\r\n dateInUtc\r\n );\r\n var utcDayNumber = dateInUtc.dayNumber;\r\n var utcSecondsIntoDay = dateInUtc.secondsOfDay;\r\n\r\n var t;\r\n var diffDays = utcDayNumber - 2451545;\r\n if (utcSecondsIntoDay >= 43200.0) {\r\n t = (diffDays + 0.5) / TimeConstants.DAYS_PER_JULIAN_CENTURY;\r\n } else {\r\n t = (diffDays - 0.5) / TimeConstants.DAYS_PER_JULIAN_CENTURY;\r\n }\r\n\r\n var gmst0 =\r\n gmstConstant0 +\r\n t * (gmstConstant1 + t * (gmstConstant2 + t * gmstConstant3));\r\n var angle = (gmst0 * twoPiOverSecondsInDay) % CesiumMath.TWO_PI;\r\n var ratio = wgs84WRPrecessing + rateCoef * (utcDayNumber - 2451545.5);\r\n var secondsSinceMidnight =\r\n (utcSecondsIntoDay + TimeConstants.SECONDS_PER_DAY * 0.5) %\r\n TimeConstants.SECONDS_PER_DAY;\r\n var gha = angle + ratio * secondsSinceMidnight;\r\n var cosGha = Math.cos(gha);\r\n var sinGha = Math.sin(gha);\r\n\r\n if (!defined(result)) {\r\n return new Matrix3(\r\n cosGha,\r\n sinGha,\r\n 0.0,\r\n -sinGha,\r\n cosGha,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n );\r\n }\r\n result[0] = cosGha;\r\n result[1] = -sinGha;\r\n result[2] = 0.0;\r\n result[3] = sinGha;\r\n result[4] = cosGha;\r\n result[5] = 0.0;\r\n result[6] = 0.0;\r\n result[7] = 0.0;\r\n result[8] = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * The source of IAU 2006 XYS data, used for computing the transformation between the\r\n * Fixed and ICRF axes.\r\n * @type {Iau2006XysData}\r\n *\r\n * @see Transforms.computeIcrfToFixedMatrix\r\n * @see Transforms.computeFixedToIcrfMatrix\r\n *\r\n * @private\r\n */\r\nTransforms.iau2006XysData = new Iau2006XysData();\r\n\r\n/**\r\n * The source of Earth Orientation Parameters (EOP) data, used for computing the transformation\r\n * between the Fixed and ICRF axes. By default, zero values are used for all EOP values,\r\n * yielding a reasonable but not completely accurate representation of the ICRF axes.\r\n * @type {EarthOrientationParameters}\r\n *\r\n * @see Transforms.computeIcrfToFixedMatrix\r\n * @see Transforms.computeFixedToIcrfMatrix\r\n *\r\n * @private\r\n */\r\nTransforms.earthOrientationParameters = EarthOrientationParameters.NONE;\r\n\r\nvar ttMinusTai = 32.184;\r\nvar j2000ttDays = 2451545.0;\r\n\r\n/**\r\n * Preloads the data necessary to transform between the ICRF and Fixed axes, in either\r\n * direction, over a given interval. This function returns a promise that, when resolved,\r\n * indicates that the preload has completed.\r\n *\r\n * @param {TimeInterval} timeInterval The interval to preload.\r\n * @returns {Promise} A promise that, when resolved, indicates that the preload has completed\r\n * and evaluation of the transformation between the fixed and ICRF axes will\r\n * no longer return undefined for a time inside the interval.\r\n *\r\n *\r\n * @example\r\n * var interval = new Cesium.TimeInterval(...);\r\n * when(Cesium.Transforms.preloadIcrfFixed(interval), function() {\r\n * // the data is now loaded\r\n * });\r\n *\r\n * @see Transforms.computeIcrfToFixedMatrix\r\n * @see Transforms.computeFixedToIcrfMatrix\r\n * @see when\r\n */\r\nTransforms.preloadIcrfFixed = function (timeInterval) {\r\n var startDayTT = timeInterval.start.dayNumber;\r\n var startSecondTT = timeInterval.start.secondsOfDay + ttMinusTai;\r\n var stopDayTT = timeInterval.stop.dayNumber;\r\n var stopSecondTT = timeInterval.stop.secondsOfDay + ttMinusTai;\r\n\r\n var xysPromise = Transforms.iau2006XysData.preload(\r\n startDayTT,\r\n startSecondTT,\r\n stopDayTT,\r\n stopSecondTT\r\n );\r\n var eopPromise = Transforms.earthOrientationParameters.getPromiseToLoad();\r\n\r\n return when.all([xysPromise, eopPromise]);\r\n};\r\n\r\n/**\r\n * Computes a rotation matrix to transform a point or vector from the International Celestial\r\n * Reference Frame (GCRF/ICRF) inertial frame axes to the Earth-Fixed frame axes (ITRF)\r\n * at a given time. This function may return undefined if the data necessary to\r\n * do the transformation is not yet loaded.\r\n *\r\n * @param {JulianDate} date The time at which to compute the rotation matrix.\r\n * @param {Matrix3} [result] The object onto which to store the result. If this parameter is\r\n * not specified, a new instance is created and returned.\r\n * @returns {Matrix3} The rotation matrix, or undefined if the data necessary to do the\r\n * transformation is not yet loaded.\r\n *\r\n *\r\n * @example\r\n * scene.postUpdate.addEventListener(function(scene, time) {\r\n * // View in ICRF.\r\n * var icrfToFixed = Cesium.Transforms.computeIcrfToFixedMatrix(time);\r\n * if (Cesium.defined(icrfToFixed)) {\r\n * var offset = Cesium.Cartesian3.clone(camera.position);\r\n * var transform = Cesium.Matrix4.fromRotationTranslation(icrfToFixed);\r\n * camera.lookAtTransform(transform, offset);\r\n * }\r\n * });\r\n *\r\n * @see Transforms.preloadIcrfFixed\r\n */\r\nTransforms.computeIcrfToFixedMatrix = function (date, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(date)) {\r\n throw new DeveloperError(\"date is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n if (!defined(result)) {\r\n result = new Matrix3();\r\n }\r\n\r\n var fixedToIcrfMtx = Transforms.computeFixedToIcrfMatrix(date, result);\r\n if (!defined(fixedToIcrfMtx)) {\r\n return undefined;\r\n }\r\n\r\n return Matrix3.transpose(fixedToIcrfMtx, result);\r\n};\r\n\r\nvar xysScratch = new Iau2006XysSample(0.0, 0.0, 0.0);\r\nvar eopScratch = new EarthOrientationParametersSample(\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0\r\n);\r\nvar rotation1Scratch = new Matrix3();\r\nvar rotation2Scratch = new Matrix3();\r\n\r\n/**\r\n * Computes a rotation matrix to transform a point or vector from the Earth-Fixed frame axes (ITRF)\r\n * to the International Celestial Reference Frame (GCRF/ICRF) inertial frame axes\r\n * at a given time. This function may return undefined if the data necessary to\r\n * do the transformation is not yet loaded.\r\n *\r\n * @param {JulianDate} date The time at which to compute the rotation matrix.\r\n * @param {Matrix3} [result] The object onto which to store the result. If this parameter is\r\n * not specified, a new instance is created and returned.\r\n * @returns {Matrix3} The rotation matrix, or undefined if the data necessary to do the\r\n * transformation is not yet loaded.\r\n *\r\n *\r\n * @example\r\n * // Transform a point from the ICRF axes to the Fixed axes.\r\n * var now = Cesium.JulianDate.now();\r\n * var pointInFixed = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var fixedToIcrf = Cesium.Transforms.computeIcrfToFixedMatrix(now);\r\n * var pointInInertial = new Cesium.Cartesian3();\r\n * if (Cesium.defined(fixedToIcrf)) {\r\n * pointInInertial = Cesium.Matrix3.multiplyByVector(fixedToIcrf, pointInFixed, pointInInertial);\r\n * }\r\n *\r\n * @see Transforms.preloadIcrfFixed\r\n */\r\nTransforms.computeFixedToIcrfMatrix = function (date, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(date)) {\r\n throw new DeveloperError(\"date is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Matrix3();\r\n }\r\n\r\n // Compute pole wander\r\n var eop = Transforms.earthOrientationParameters.compute(date, eopScratch);\r\n if (!defined(eop)) {\r\n return undefined;\r\n }\r\n\r\n // There is no external conversion to Terrestrial Time (TT).\r\n // So use International Atomic Time (TAI) and convert using offsets.\r\n // Here we are assuming that dayTT and secondTT are positive\r\n var dayTT = date.dayNumber;\r\n // It's possible here that secondTT could roll over 86400\r\n // This does not seem to affect the precision (unit tests check for this)\r\n var secondTT = date.secondsOfDay + ttMinusTai;\r\n\r\n var xys = Transforms.iau2006XysData.computeXysRadians(\r\n dayTT,\r\n secondTT,\r\n xysScratch\r\n );\r\n if (!defined(xys)) {\r\n return undefined;\r\n }\r\n\r\n var x = xys.x + eop.xPoleOffset;\r\n var y = xys.y + eop.yPoleOffset;\r\n\r\n // Compute XYS rotation\r\n var a = 1.0 / (1.0 + Math.sqrt(1.0 - x * x - y * y));\r\n\r\n var rotation1 = rotation1Scratch;\r\n rotation1[0] = 1.0 - a * x * x;\r\n rotation1[3] = -a * x * y;\r\n rotation1[6] = x;\r\n rotation1[1] = -a * x * y;\r\n rotation1[4] = 1 - a * y * y;\r\n rotation1[7] = y;\r\n rotation1[2] = -x;\r\n rotation1[5] = -y;\r\n rotation1[8] = 1 - a * (x * x + y * y);\r\n\r\n var rotation2 = Matrix3.fromRotationZ(-xys.s, rotation2Scratch);\r\n var matrixQ = Matrix3.multiply(rotation1, rotation2, rotation1Scratch);\r\n\r\n // Similar to TT conversions above\r\n // It's possible here that secondTT could roll over 86400\r\n // This does not seem to affect the precision (unit tests check for this)\r\n var dateUt1day = date.dayNumber;\r\n var dateUt1sec =\r\n date.secondsOfDay - JulianDate.computeTaiMinusUtc(date) + eop.ut1MinusUtc;\r\n\r\n // Compute Earth rotation angle\r\n // The IERS standard for era is\r\n // era = 0.7790572732640 + 1.00273781191135448 * Tu\r\n // where\r\n // Tu = JulianDateInUt1 - 2451545.0\r\n // However, you get much more precision if you make the following simplification\r\n // era = a + (1 + b) * (JulianDayNumber + FractionOfDay - 2451545)\r\n // era = a + (JulianDayNumber - 2451545) + FractionOfDay + b (JulianDayNumber - 2451545 + FractionOfDay)\r\n // era = a + FractionOfDay + b (JulianDayNumber - 2451545 + FractionOfDay)\r\n // since (JulianDayNumber - 2451545) represents an integer number of revolutions which will be discarded anyway.\r\n var daysSinceJ2000 = dateUt1day - 2451545;\r\n var fractionOfDay = dateUt1sec / TimeConstants.SECONDS_PER_DAY;\r\n var era =\r\n 0.779057273264 +\r\n fractionOfDay +\r\n 0.00273781191135448 * (daysSinceJ2000 + fractionOfDay);\r\n era = (era % 1.0) * CesiumMath.TWO_PI;\r\n\r\n var earthRotation = Matrix3.fromRotationZ(era, rotation2Scratch);\r\n\r\n // pseudoFixed to ICRF\r\n var pfToIcrf = Matrix3.multiply(matrixQ, earthRotation, rotation1Scratch);\r\n\r\n // Compute pole wander matrix\r\n var cosxp = Math.cos(eop.xPoleWander);\r\n var cosyp = Math.cos(eop.yPoleWander);\r\n var sinxp = Math.sin(eop.xPoleWander);\r\n var sinyp = Math.sin(eop.yPoleWander);\r\n\r\n var ttt = dayTT - j2000ttDays + secondTT / TimeConstants.SECONDS_PER_DAY;\r\n ttt /= 36525.0;\r\n\r\n // approximate sp value in rad\r\n var sp = (-47.0e-6 * ttt * CesiumMath.RADIANS_PER_DEGREE) / 3600.0;\r\n var cossp = Math.cos(sp);\r\n var sinsp = Math.sin(sp);\r\n\r\n var fToPfMtx = rotation2Scratch;\r\n fToPfMtx[0] = cosxp * cossp;\r\n fToPfMtx[1] = cosxp * sinsp;\r\n fToPfMtx[2] = sinxp;\r\n fToPfMtx[3] = -cosyp * sinsp + sinyp * sinxp * cossp;\r\n fToPfMtx[4] = cosyp * cossp + sinyp * sinxp * sinsp;\r\n fToPfMtx[5] = -sinyp * cosxp;\r\n fToPfMtx[6] = -sinyp * sinsp - cosyp * sinxp * cossp;\r\n fToPfMtx[7] = sinyp * cossp - cosyp * sinxp * sinsp;\r\n fToPfMtx[8] = cosyp * cosxp;\r\n\r\n return Matrix3.multiply(pfToIcrf, fToPfMtx, result);\r\n};\r\n\r\nvar pointToWindowCoordinatesTemp = new Cartesian4();\r\n\r\n/**\r\n * Transform a point from model coordinates to window coordinates.\r\n *\r\n * @param {Matrix4} modelViewProjectionMatrix The 4x4 model-view-projection matrix.\r\n * @param {Matrix4} viewportTransformation The 4x4 viewport transformation.\r\n * @param {Cartesian3} point The point to transform.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if none was provided.\r\n */\r\nTransforms.pointToWindowCoordinates = function (\r\n modelViewProjectionMatrix,\r\n viewportTransformation,\r\n point,\r\n result\r\n) {\r\n result = Transforms.pointToGLWindowCoordinates(\r\n modelViewProjectionMatrix,\r\n viewportTransformation,\r\n point,\r\n result\r\n );\r\n result.y = 2.0 * viewportTransformation[5] - result.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nTransforms.pointToGLWindowCoordinates = function (\r\n modelViewProjectionMatrix,\r\n viewportTransformation,\r\n point,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(modelViewProjectionMatrix)) {\r\n throw new DeveloperError(\"modelViewProjectionMatrix is required.\");\r\n }\r\n\r\n if (!defined(viewportTransformation)) {\r\n throw new DeveloperError(\"viewportTransformation is required.\");\r\n }\r\n\r\n if (!defined(point)) {\r\n throw new DeveloperError(\"point is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian2();\r\n }\r\n\r\n var tmp = pointToWindowCoordinatesTemp;\r\n\r\n Matrix4.multiplyByVector(\r\n modelViewProjectionMatrix,\r\n Cartesian4.fromElements(point.x, point.y, point.z, 1, tmp),\r\n tmp\r\n );\r\n Cartesian4.multiplyByScalar(tmp, 1.0 / tmp.w, tmp);\r\n Matrix4.multiplyByVector(viewportTransformation, tmp, tmp);\r\n return Cartesian2.fromCartesian4(tmp, result);\r\n};\r\n\r\nvar normalScratch = new Cartesian3();\r\nvar rightScratch = new Cartesian3();\r\nvar upScratch = new Cartesian3();\r\n\r\n/**\r\n * Transform a position and velocity to a rotation matrix.\r\n *\r\n * @param {Cartesian3} position The position to transform.\r\n * @param {Cartesian3} velocity The velocity vector to transform.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid whose fixed frame is used in the transformation.\r\n * @param {Matrix3} [result] The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter or a new Matrix3 instance if none was provided.\r\n */\r\nTransforms.rotationMatrixFromPositionVelocity = function (\r\n position,\r\n velocity,\r\n ellipsoid,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(position)) {\r\n throw new DeveloperError(\"position is required.\");\r\n }\r\n\r\n if (!defined(velocity)) {\r\n throw new DeveloperError(\"velocity is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var normal = defaultValue(ellipsoid, Ellipsoid.WGS84).geodeticSurfaceNormal(\r\n position,\r\n normalScratch\r\n );\r\n var right = Cartesian3.cross(velocity, normal, rightScratch);\r\n\r\n if (Cartesian3.equalsEpsilon(right, Cartesian3.ZERO, CesiumMath.EPSILON6)) {\r\n right = Cartesian3.clone(Cartesian3.UNIT_X, right);\r\n }\r\n\r\n var up = Cartesian3.cross(right, velocity, upScratch);\r\n Cartesian3.normalize(up, up);\r\n Cartesian3.cross(velocity, up, right);\r\n Cartesian3.negate(right, right);\r\n Cartesian3.normalize(right, right);\r\n\r\n if (!defined(result)) {\r\n result = new Matrix3();\r\n }\r\n\r\n result[0] = velocity.x;\r\n result[1] = velocity.y;\r\n result[2] = velocity.z;\r\n result[3] = right.x;\r\n result[4] = right.y;\r\n result[5] = right.z;\r\n result[6] = up.x;\r\n result[7] = up.y;\r\n result[8] = up.z;\r\n\r\n return result;\r\n};\r\n\r\nvar swizzleMatrix = new Matrix4(\r\n 0.0,\r\n 0.0,\r\n 1.0,\r\n 0.0,\r\n 1.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 0.0,\r\n 1.0\r\n);\r\n\r\nvar scratchCartographic = new Cartographic();\r\nvar scratchCartesian3Projection = new Cartesian3();\r\nvar scratchCenter = new Cartesian3();\r\nvar scratchRotation = new Matrix3();\r\nvar scratchFromENU = new Matrix4();\r\nvar scratchToENU = new Matrix4();\r\n\r\n/**\r\n * @private\r\n */\r\nTransforms.basisTo2D = function (projection, matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(projection)) {\r\n throw new DeveloperError(\"projection is required.\");\r\n }\r\n if (!defined(matrix)) {\r\n throw new DeveloperError(\"matrix is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var rtcCenter = Matrix4.getTranslation(matrix, scratchCenter);\r\n var ellipsoid = projection.ellipsoid;\r\n\r\n // Get the 2D Center\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n rtcCenter,\r\n scratchCartographic\r\n );\r\n var projectedPosition = projection.project(\r\n cartographic,\r\n scratchCartesian3Projection\r\n );\r\n Cartesian3.fromElements(\r\n projectedPosition.z,\r\n projectedPosition.x,\r\n projectedPosition.y,\r\n projectedPosition\r\n );\r\n\r\n // Assuming the instance are positioned in WGS84, invert the WGS84 transform to get the local transform and then convert to 2D\r\n var fromENU = Transforms.eastNorthUpToFixedFrame(\r\n rtcCenter,\r\n ellipsoid,\r\n scratchFromENU\r\n );\r\n var toENU = Matrix4.inverseTransformation(fromENU, scratchToENU);\r\n var rotation = Matrix4.getMatrix3(matrix, scratchRotation);\r\n var local = Matrix4.multiplyByMatrix3(toENU, rotation, result);\r\n Matrix4.multiply(swizzleMatrix, local, result); // Swap x, y, z for 2D\r\n Matrix4.setTranslation(result, projectedPosition, result); // Use the projected center\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nTransforms.wgs84To2DModelMatrix = function (projection, center, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(projection)) {\r\n throw new DeveloperError(\"projection is required.\");\r\n }\r\n if (!defined(center)) {\r\n throw new DeveloperError(\"center is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var ellipsoid = projection.ellipsoid;\r\n\r\n var fromENU = Transforms.eastNorthUpToFixedFrame(\r\n center,\r\n ellipsoid,\r\n scratchFromENU\r\n );\r\n var toENU = Matrix4.inverseTransformation(fromENU, scratchToENU);\r\n\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n center,\r\n scratchCartographic\r\n );\r\n var projectedPosition = projection.project(\r\n cartographic,\r\n scratchCartesian3Projection\r\n );\r\n Cartesian3.fromElements(\r\n projectedPosition.z,\r\n projectedPosition.x,\r\n projectedPosition.y,\r\n projectedPosition\r\n );\r\n\r\n var translation = Matrix4.fromTranslation(projectedPosition, scratchFromENU);\r\n Matrix4.multiply(swizzleMatrix, toENU, result);\r\n Matrix4.multiply(translation, result, result);\r\n\r\n return result;\r\n};\r\nexport default Transforms;\r\n","import AxisAlignedBoundingBox from \"./AxisAlignedBoundingBox.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport IntersectionTests from \"./IntersectionTests.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport Plane from \"./Plane.js\";\r\nimport Ray from \"./Ray.js\";\r\nimport Transforms from \"./Transforms.js\";\r\n\r\nvar scratchCart4 = new Cartesian4();\r\n/**\r\n * A plane tangent to the provided ellipsoid at the provided origin.\r\n * If origin is not on the surface of the ellipsoid, it's surface projection will be used.\r\n * If origin is at the center of the ellipsoid, an exception will be thrown.\r\n * @alias EllipsoidTangentPlane\r\n * @constructor\r\n *\r\n * @param {Cartesian3} origin The point on the surface of the ellipsoid where the tangent plane touches.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use.\r\n *\r\n * @exception {DeveloperError} origin must not be at the center of the ellipsoid.\r\n */\r\nfunction EllipsoidTangentPlane(origin, ellipsoid) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"origin\", origin);\r\n //>>includeEnd('debug');\r\n\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n origin = ellipsoid.scaleToGeodeticSurface(origin);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(origin)) {\r\n throw new DeveloperError(\r\n \"origin must not be at the center of the ellipsoid.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var eastNorthUp = Transforms.eastNorthUpToFixedFrame(origin, ellipsoid);\r\n this._ellipsoid = ellipsoid;\r\n this._origin = origin;\r\n this._xAxis = Cartesian3.fromCartesian4(\r\n Matrix4.getColumn(eastNorthUp, 0, scratchCart4)\r\n );\r\n this._yAxis = Cartesian3.fromCartesian4(\r\n Matrix4.getColumn(eastNorthUp, 1, scratchCart4)\r\n );\r\n\r\n var normal = Cartesian3.fromCartesian4(\r\n Matrix4.getColumn(eastNorthUp, 2, scratchCart4)\r\n );\r\n this._plane = Plane.fromPointNormal(origin, normal);\r\n}\r\n\r\nObject.defineProperties(EllipsoidTangentPlane.prototype, {\r\n /**\r\n * Gets the ellipsoid.\r\n * @memberof EllipsoidTangentPlane.prototype\r\n * @type {Ellipsoid}\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the origin.\r\n * @memberof EllipsoidTangentPlane.prototype\r\n * @type {Cartesian3}\r\n */\r\n origin: {\r\n get: function () {\r\n return this._origin;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the plane which is tangent to the ellipsoid.\r\n * @memberof EllipsoidTangentPlane.prototype\r\n * @readonly\r\n * @type {Plane}\r\n */\r\n plane: {\r\n get: function () {\r\n return this._plane;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the local X-axis (east) of the tangent plane.\r\n * @memberof EllipsoidTangentPlane.prototype\r\n * @readonly\r\n * @type {Cartesian3}\r\n */\r\n xAxis: {\r\n get: function () {\r\n return this._xAxis;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the local Y-axis (north) of the tangent plane.\r\n * @memberof EllipsoidTangentPlane.prototype\r\n * @readonly\r\n * @type {Cartesian3}\r\n */\r\n yAxis: {\r\n get: function () {\r\n return this._yAxis;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the local Z-axis (up) of the tangent plane.\r\n * @memberof EllipsoidTangentPlane.prototype\r\n * @readonly\r\n * @type {Cartesian3}\r\n */\r\n zAxis: {\r\n get: function () {\r\n return this._plane.normal;\r\n },\r\n },\r\n});\r\n\r\nvar tmp = new AxisAlignedBoundingBox();\r\n/**\r\n * Creates a new instance from the provided ellipsoid and the center\r\n * point of the provided Cartesians.\r\n *\r\n * @param {Cartesian3[]} cartesians The list of positions surrounding the center point.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use.\r\n * @returns {EllipsoidTangentPlane} The new instance of EllipsoidTangentPlane.\r\n */\r\nEllipsoidTangentPlane.fromPoints = function (cartesians, ellipsoid) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesians\", cartesians);\r\n //>>includeEnd('debug');\r\n\r\n var box = AxisAlignedBoundingBox.fromPoints(cartesians, tmp);\r\n return new EllipsoidTangentPlane(box.center, ellipsoid);\r\n};\r\n\r\nvar scratchProjectPointOntoPlaneRay = new Ray();\r\nvar scratchProjectPointOntoPlaneCartesian3 = new Cartesian3();\r\n\r\n/**\r\n * Computes the projection of the provided 3D position onto the 2D plane, radially outward from the {@link EllipsoidTangentPlane.ellipsoid} coordinate system origin.\r\n *\r\n * @param {Cartesian3} cartesian The point to project.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if none was provided. Undefined if there is no intersection point\r\n */\r\nEllipsoidTangentPlane.prototype.projectPointOntoPlane = function (\r\n cartesian,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n var ray = scratchProjectPointOntoPlaneRay;\r\n ray.origin = cartesian;\r\n Cartesian3.normalize(cartesian, ray.direction);\r\n\r\n var intersectionPoint = IntersectionTests.rayPlane(\r\n ray,\r\n this._plane,\r\n scratchProjectPointOntoPlaneCartesian3\r\n );\r\n if (!defined(intersectionPoint)) {\r\n Cartesian3.negate(ray.direction, ray.direction);\r\n intersectionPoint = IntersectionTests.rayPlane(\r\n ray,\r\n this._plane,\r\n scratchProjectPointOntoPlaneCartesian3\r\n );\r\n }\r\n\r\n if (defined(intersectionPoint)) {\r\n var v = Cartesian3.subtract(\r\n intersectionPoint,\r\n this._origin,\r\n intersectionPoint\r\n );\r\n var x = Cartesian3.dot(this._xAxis, v);\r\n var y = Cartesian3.dot(this._yAxis, v);\r\n\r\n if (!defined(result)) {\r\n return new Cartesian2(x, y);\r\n }\r\n result.x = x;\r\n result.y = y;\r\n return result;\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Computes the projection of the provided 3D positions onto the 2D plane (where possible), radially outward from the global origin.\r\n * The resulting array may be shorter than the input array - if a single projection is impossible it will not be included.\r\n *\r\n * @see EllipsoidTangentPlane.projectPointOntoPlane\r\n *\r\n * @param {Cartesian3[]} cartesians The array of points to project.\r\n * @param {Cartesian2[]} [result] The array of Cartesian2 instances onto which to store results.\r\n * @returns {Cartesian2[]} The modified result parameter or a new array of Cartesian2 instances if none was provided.\r\n */\r\nEllipsoidTangentPlane.prototype.projectPointsOntoPlane = function (\r\n cartesians,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesians\", cartesians);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = [];\r\n }\r\n\r\n var count = 0;\r\n var length = cartesians.length;\r\n for (var i = 0; i < length; i++) {\r\n var p = this.projectPointOntoPlane(cartesians[i], result[count]);\r\n if (defined(p)) {\r\n result[count] = p;\r\n count++;\r\n }\r\n }\r\n result.length = count;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the projection of the provided 3D position onto the 2D plane, along the plane normal.\r\n *\r\n * @param {Cartesian3} cartesian The point to project.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if none was provided.\r\n */\r\nEllipsoidTangentPlane.prototype.projectPointToNearestOnPlane = function (\r\n cartesian,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian2();\r\n }\r\n\r\n var ray = scratchProjectPointOntoPlaneRay;\r\n ray.origin = cartesian;\r\n Cartesian3.clone(this._plane.normal, ray.direction);\r\n\r\n var intersectionPoint = IntersectionTests.rayPlane(\r\n ray,\r\n this._plane,\r\n scratchProjectPointOntoPlaneCartesian3\r\n );\r\n if (!defined(intersectionPoint)) {\r\n Cartesian3.negate(ray.direction, ray.direction);\r\n intersectionPoint = IntersectionTests.rayPlane(\r\n ray,\r\n this._plane,\r\n scratchProjectPointOntoPlaneCartesian3\r\n );\r\n }\r\n\r\n var v = Cartesian3.subtract(\r\n intersectionPoint,\r\n this._origin,\r\n intersectionPoint\r\n );\r\n var x = Cartesian3.dot(this._xAxis, v);\r\n var y = Cartesian3.dot(this._yAxis, v);\r\n\r\n result.x = x;\r\n result.y = y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the projection of the provided 3D positions onto the 2D plane, along the plane normal.\r\n *\r\n * @see EllipsoidTangentPlane.projectPointToNearestOnPlane\r\n *\r\n * @param {Cartesian3[]} cartesians The array of points to project.\r\n * @param {Cartesian2[]} [result] The array of Cartesian2 instances onto which to store results.\r\n * @returns {Cartesian2[]} The modified result parameter or a new array of Cartesian2 instances if none was provided. This will have the same length as cartesians.\r\n */\r\nEllipsoidTangentPlane.prototype.projectPointsToNearestOnPlane = function (\r\n cartesians,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesians\", cartesians);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = [];\r\n }\r\n\r\n var length = cartesians.length;\r\n result.length = length;\r\n for (var i = 0; i < length; i++) {\r\n result[i] = this.projectPointToNearestOnPlane(cartesians[i], result[i]);\r\n }\r\n return result;\r\n};\r\n\r\nvar projectPointsOntoEllipsoidScratch = new Cartesian3();\r\n/**\r\n * Computes the projection of the provided 2D position onto the 3D ellipsoid.\r\n *\r\n * @param {Cartesian2} cartesian The points to project.\r\n * @param {Cartesian3} [result] The Cartesian3 instance to store result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if none was provided.\r\n */\r\nEllipsoidTangentPlane.prototype.projectPointOntoEllipsoid = function (\r\n cartesian,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n var ellipsoid = this._ellipsoid;\r\n var origin = this._origin;\r\n var xAxis = this._xAxis;\r\n var yAxis = this._yAxis;\r\n var tmp = projectPointsOntoEllipsoidScratch;\r\n\r\n Cartesian3.multiplyByScalar(xAxis, cartesian.x, tmp);\r\n result = Cartesian3.add(origin, tmp, result);\r\n Cartesian3.multiplyByScalar(yAxis, cartesian.y, tmp);\r\n Cartesian3.add(result, tmp, result);\r\n ellipsoid.scaleToGeocentricSurface(result, result);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the projection of the provided 2D positions onto the 3D ellipsoid.\r\n *\r\n * @param {Cartesian2[]} cartesians The array of points to project.\r\n * @param {Cartesian3[]} [result] The array of Cartesian3 instances onto which to store results.\r\n * @returns {Cartesian3[]} The modified result parameter or a new array of Cartesian3 instances if none was provided.\r\n */\r\nEllipsoidTangentPlane.prototype.projectPointsOntoEllipsoid = function (\r\n cartesians,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesians\", cartesians);\r\n //>>includeEnd('debug');\r\n\r\n var length = cartesians.length;\r\n if (!defined(result)) {\r\n result = new Array(length);\r\n } else {\r\n result.length = length;\r\n }\r\n\r\n for (var i = 0; i < length; ++i) {\r\n result[i] = this.projectPointOntoEllipsoid(cartesians[i], result[i]);\r\n }\r\n\r\n return result;\r\n};\r\nexport default EllipsoidTangentPlane;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport EllipsoidTangentPlane from \"./EllipsoidTangentPlane.js\";\r\nimport Intersect from \"./Intersect.js\";\r\nimport Interval from \"./Interval.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Plane from \"./Plane.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\n\r\n/**\r\n * Creates an instance of an OrientedBoundingBox.\r\n * An OrientedBoundingBox of some object is a closed and convex cuboid. It can provide a tighter bounding volume than {@link BoundingSphere} or {@link AxisAlignedBoundingBox} in many cases.\r\n * @alias OrientedBoundingBox\r\n * @constructor\r\n *\r\n * @param {Cartesian3} [center=Cartesian3.ZERO] The center of the box.\r\n * @param {Matrix3} [halfAxes=Matrix3.ZERO] The three orthogonal half-axes of the bounding box.\r\n * Equivalently, the transformation matrix, to rotate and scale a 0x0x0\r\n * cube centered at the origin.\r\n *\r\n *\r\n * @example\r\n * // Create an OrientedBoundingBox using a transformation matrix, a position where the box will be translated, and a scale.\r\n * var center = new Cesium.Cartesian3(1.0, 0.0, 0.0);\r\n * var halfAxes = Cesium.Matrix3.fromScale(new Cesium.Cartesian3(1.0, 3.0, 2.0), new Cesium.Matrix3());\r\n *\r\n * var obb = new Cesium.OrientedBoundingBox(center, halfAxes);\r\n *\r\n * @see BoundingSphere\r\n * @see BoundingRectangle\r\n */\r\nfunction OrientedBoundingBox(center, halfAxes) {\r\n /**\r\n * The center of the box.\r\n * @type {Cartesian3}\r\n * @default {@link Cartesian3.ZERO}\r\n */\r\n this.center = Cartesian3.clone(defaultValue(center, Cartesian3.ZERO));\r\n /**\r\n * The transformation matrix, to rotate the box to the right position.\r\n * @type {Matrix3}\r\n * @default {@link Matrix3.ZERO}\r\n */\r\n this.halfAxes = Matrix3.clone(defaultValue(halfAxes, Matrix3.ZERO));\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nOrientedBoundingBox.packedLength =\r\n Cartesian3.packedLength + Matrix3.packedLength;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {OrientedBoundingBox} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nOrientedBoundingBox.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Cartesian3.pack(value.center, array, startingIndex);\r\n Matrix3.pack(value.halfAxes, array, startingIndex + Cartesian3.packedLength);\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {OrientedBoundingBox} [result] The object into which to store the result.\r\n * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if one was not provided.\r\n */\r\nOrientedBoundingBox.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new OrientedBoundingBox();\r\n }\r\n\r\n Cartesian3.unpack(array, startingIndex, result.center);\r\n Matrix3.unpack(\r\n array,\r\n startingIndex + Cartesian3.packedLength,\r\n result.halfAxes\r\n );\r\n return result;\r\n};\r\n\r\nvar scratchCartesian1 = new Cartesian3();\r\nvar scratchCartesian2 = new Cartesian3();\r\nvar scratchCartesian3 = new Cartesian3();\r\nvar scratchCartesian4 = new Cartesian3();\r\nvar scratchCartesian5 = new Cartesian3();\r\nvar scratchCartesian6 = new Cartesian3();\r\nvar scratchCovarianceResult = new Matrix3();\r\nvar scratchEigenResult = {\r\n unitary: new Matrix3(),\r\n diagonal: new Matrix3(),\r\n};\r\n\r\n/**\r\n * Computes an instance of an OrientedBoundingBox of the given positions.\r\n * This is an implementation of Stefan Gottschalk's Collision Queries using Oriented Bounding Boxes solution (PHD thesis).\r\n * Reference: http://gamma.cs.unc.edu/users/gottschalk/main.pdf\r\n *\r\n * @param {Cartesian3[]} [positions] List of {@link Cartesian3} points that the bounding box will enclose.\r\n * @param {OrientedBoundingBox} [result] The object onto which to store the result.\r\n * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if one was not provided.\r\n *\r\n * @example\r\n * // Compute an object oriented bounding box enclosing two points.\r\n * var box = Cesium.OrientedBoundingBox.fromPoints([new Cesium.Cartesian3(2, 0, 0), new Cesium.Cartesian3(-2, 0, 0)]);\r\n */\r\nOrientedBoundingBox.fromPoints = function (positions, result) {\r\n if (!defined(result)) {\r\n result = new OrientedBoundingBox();\r\n }\r\n\r\n if (!defined(positions) || positions.length === 0) {\r\n result.halfAxes = Matrix3.ZERO;\r\n result.center = Cartesian3.ZERO;\r\n return result;\r\n }\r\n\r\n var i;\r\n var length = positions.length;\r\n\r\n var meanPoint = Cartesian3.clone(positions[0], scratchCartesian1);\r\n for (i = 1; i < length; i++) {\r\n Cartesian3.add(meanPoint, positions[i], meanPoint);\r\n }\r\n var invLength = 1.0 / length;\r\n Cartesian3.multiplyByScalar(meanPoint, invLength, meanPoint);\r\n\r\n var exx = 0.0;\r\n var exy = 0.0;\r\n var exz = 0.0;\r\n var eyy = 0.0;\r\n var eyz = 0.0;\r\n var ezz = 0.0;\r\n var p;\r\n\r\n for (i = 0; i < length; i++) {\r\n p = Cartesian3.subtract(positions[i], meanPoint, scratchCartesian2);\r\n exx += p.x * p.x;\r\n exy += p.x * p.y;\r\n exz += p.x * p.z;\r\n eyy += p.y * p.y;\r\n eyz += p.y * p.z;\r\n ezz += p.z * p.z;\r\n }\r\n\r\n exx *= invLength;\r\n exy *= invLength;\r\n exz *= invLength;\r\n eyy *= invLength;\r\n eyz *= invLength;\r\n ezz *= invLength;\r\n\r\n var covarianceMatrix = scratchCovarianceResult;\r\n covarianceMatrix[0] = exx;\r\n covarianceMatrix[1] = exy;\r\n covarianceMatrix[2] = exz;\r\n covarianceMatrix[3] = exy;\r\n covarianceMatrix[4] = eyy;\r\n covarianceMatrix[5] = eyz;\r\n covarianceMatrix[6] = exz;\r\n covarianceMatrix[7] = eyz;\r\n covarianceMatrix[8] = ezz;\r\n\r\n var eigenDecomposition = Matrix3.computeEigenDecomposition(\r\n covarianceMatrix,\r\n scratchEigenResult\r\n );\r\n var rotation = Matrix3.clone(eigenDecomposition.unitary, result.halfAxes);\r\n\r\n var v1 = Matrix3.getColumn(rotation, 0, scratchCartesian4);\r\n var v2 = Matrix3.getColumn(rotation, 1, scratchCartesian5);\r\n var v3 = Matrix3.getColumn(rotation, 2, scratchCartesian6);\r\n\r\n var u1 = -Number.MAX_VALUE;\r\n var u2 = -Number.MAX_VALUE;\r\n var u3 = -Number.MAX_VALUE;\r\n var l1 = Number.MAX_VALUE;\r\n var l2 = Number.MAX_VALUE;\r\n var l3 = Number.MAX_VALUE;\r\n\r\n for (i = 0; i < length; i++) {\r\n p = positions[i];\r\n u1 = Math.max(Cartesian3.dot(v1, p), u1);\r\n u2 = Math.max(Cartesian3.dot(v2, p), u2);\r\n u3 = Math.max(Cartesian3.dot(v3, p), u3);\r\n\r\n l1 = Math.min(Cartesian3.dot(v1, p), l1);\r\n l2 = Math.min(Cartesian3.dot(v2, p), l2);\r\n l3 = Math.min(Cartesian3.dot(v3, p), l3);\r\n }\r\n\r\n v1 = Cartesian3.multiplyByScalar(v1, 0.5 * (l1 + u1), v1);\r\n v2 = Cartesian3.multiplyByScalar(v2, 0.5 * (l2 + u2), v2);\r\n v3 = Cartesian3.multiplyByScalar(v3, 0.5 * (l3 + u3), v3);\r\n\r\n var center = Cartesian3.add(v1, v2, result.center);\r\n Cartesian3.add(center, v3, center);\r\n\r\n var scale = scratchCartesian3;\r\n scale.x = u1 - l1;\r\n scale.y = u2 - l2;\r\n scale.z = u3 - l3;\r\n Cartesian3.multiplyByScalar(scale, 0.5, scale);\r\n Matrix3.multiplyByScale(result.halfAxes, scale, result.halfAxes);\r\n\r\n return result;\r\n};\r\n\r\nvar scratchOffset = new Cartesian3();\r\nvar scratchScale = new Cartesian3();\r\nfunction fromPlaneExtents(\r\n planeOrigin,\r\n planeXAxis,\r\n planeYAxis,\r\n planeZAxis,\r\n minimumX,\r\n maximumX,\r\n minimumY,\r\n maximumY,\r\n minimumZ,\r\n maximumZ,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(minimumX) ||\r\n !defined(maximumX) ||\r\n !defined(minimumY) ||\r\n !defined(maximumY) ||\r\n !defined(minimumZ) ||\r\n !defined(maximumZ)\r\n ) {\r\n throw new DeveloperError(\r\n \"all extents (minimum/maximum X/Y/Z) are required.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new OrientedBoundingBox();\r\n }\r\n\r\n var halfAxes = result.halfAxes;\r\n Matrix3.setColumn(halfAxes, 0, planeXAxis, halfAxes);\r\n Matrix3.setColumn(halfAxes, 1, planeYAxis, halfAxes);\r\n Matrix3.setColumn(halfAxes, 2, planeZAxis, halfAxes);\r\n\r\n var centerOffset = scratchOffset;\r\n centerOffset.x = (minimumX + maximumX) / 2.0;\r\n centerOffset.y = (minimumY + maximumY) / 2.0;\r\n centerOffset.z = (minimumZ + maximumZ) / 2.0;\r\n\r\n var scale = scratchScale;\r\n scale.x = (maximumX - minimumX) / 2.0;\r\n scale.y = (maximumY - minimumY) / 2.0;\r\n scale.z = (maximumZ - minimumZ) / 2.0;\r\n\r\n var center = result.center;\r\n centerOffset = Matrix3.multiplyByVector(halfAxes, centerOffset, centerOffset);\r\n Cartesian3.add(planeOrigin, centerOffset, center);\r\n Matrix3.multiplyByScale(halfAxes, scale, halfAxes);\r\n\r\n return result;\r\n}\r\n\r\nvar scratchRectangleCenterCartographic = new Cartographic();\r\nvar scratchRectangleCenter = new Cartesian3();\r\nvar scratchPerimeterCartographicNC = new Cartographic();\r\nvar scratchPerimeterCartographicNW = new Cartographic();\r\nvar scratchPerimeterCartographicCW = new Cartographic();\r\nvar scratchPerimeterCartographicSW = new Cartographic();\r\nvar scratchPerimeterCartographicSC = new Cartographic();\r\nvar scratchPerimeterCartesianNC = new Cartesian3();\r\nvar scratchPerimeterCartesianNW = new Cartesian3();\r\nvar scratchPerimeterCartesianCW = new Cartesian3();\r\nvar scratchPerimeterCartesianSW = new Cartesian3();\r\nvar scratchPerimeterCartesianSC = new Cartesian3();\r\nvar scratchPerimeterProjectedNC = new Cartesian2();\r\nvar scratchPerimeterProjectedNW = new Cartesian2();\r\nvar scratchPerimeterProjectedCW = new Cartesian2();\r\nvar scratchPerimeterProjectedSW = new Cartesian2();\r\nvar scratchPerimeterProjectedSC = new Cartesian2();\r\n\r\nvar scratchPlaneOrigin = new Cartesian3();\r\nvar scratchPlaneNormal = new Cartesian3();\r\nvar scratchPlaneXAxis = new Cartesian3();\r\nvar scratchHorizonCartesian = new Cartesian3();\r\nvar scratchHorizonProjected = new Cartesian2();\r\nvar scratchMaxY = new Cartesian3();\r\nvar scratchMinY = new Cartesian3();\r\nvar scratchZ = new Cartesian3();\r\nvar scratchPlane = new Plane(Cartesian3.UNIT_X, 0.0);\r\n\r\n/**\r\n * Computes an OrientedBoundingBox that bounds a {@link Rectangle} on the surface of an {@link Ellipsoid}.\r\n * There are no guarantees about the orientation of the bounding box.\r\n *\r\n * @param {Rectangle} rectangle The cartographic rectangle on the surface of the ellipsoid.\r\n * @param {Number} [minimumHeight=0.0] The minimum height (elevation) within the tile.\r\n * @param {Number} [maximumHeight=0.0] The maximum height (elevation) within the tile.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the rectangle is defined.\r\n * @param {OrientedBoundingBox} [result] The object onto which to store the result.\r\n * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if none was provided.\r\n *\r\n * @exception {DeveloperError} rectangle.width must be between 0 and pi.\r\n * @exception {DeveloperError} rectangle.height must be between 0 and pi.\r\n * @exception {DeveloperError} ellipsoid must be an ellipsoid of revolution (radii.x == radii.y)\r\n */\r\nOrientedBoundingBox.fromRectangle = function (\r\n rectangle,\r\n minimumHeight,\r\n maximumHeight,\r\n ellipsoid,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(rectangle)) {\r\n throw new DeveloperError(\"rectangle is required\");\r\n }\r\n if (rectangle.width < 0.0 || rectangle.width > CesiumMath.TWO_PI) {\r\n throw new DeveloperError(\"Rectangle width must be between 0 and 2*pi\");\r\n }\r\n if (rectangle.height < 0.0 || rectangle.height > CesiumMath.PI) {\r\n throw new DeveloperError(\"Rectangle height must be between 0 and pi\");\r\n }\r\n if (\r\n defined(ellipsoid) &&\r\n !CesiumMath.equalsEpsilon(\r\n ellipsoid.radii.x,\r\n ellipsoid.radii.y,\r\n CesiumMath.EPSILON15\r\n )\r\n ) {\r\n throw new DeveloperError(\r\n \"Ellipsoid must be an ellipsoid of revolution (radii.x == radii.y)\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n minimumHeight = defaultValue(minimumHeight, 0.0);\r\n maximumHeight = defaultValue(maximumHeight, 0.0);\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n\r\n var minX, maxX, minY, maxY, minZ, maxZ, plane;\r\n\r\n if (rectangle.width <= CesiumMath.PI) {\r\n // The bounding box will be aligned with the tangent plane at the center of the rectangle.\r\n var tangentPointCartographic = Rectangle.center(\r\n rectangle,\r\n scratchRectangleCenterCartographic\r\n );\r\n var tangentPoint = ellipsoid.cartographicToCartesian(\r\n tangentPointCartographic,\r\n scratchRectangleCenter\r\n );\r\n var tangentPlane = new EllipsoidTangentPlane(tangentPoint, ellipsoid);\r\n plane = tangentPlane.plane;\r\n\r\n // If the rectangle spans the equator, CW is instead aligned with the equator (because it sticks out the farthest at the equator).\r\n var lonCenter = tangentPointCartographic.longitude;\r\n var latCenter =\r\n rectangle.south < 0.0 && rectangle.north > 0.0\r\n ? 0.0\r\n : tangentPointCartographic.latitude;\r\n\r\n // Compute XY extents using the rectangle at maximum height\r\n var perimeterCartographicNC = Cartographic.fromRadians(\r\n lonCenter,\r\n rectangle.north,\r\n maximumHeight,\r\n scratchPerimeterCartographicNC\r\n );\r\n var perimeterCartographicNW = Cartographic.fromRadians(\r\n rectangle.west,\r\n rectangle.north,\r\n maximumHeight,\r\n scratchPerimeterCartographicNW\r\n );\r\n var perimeterCartographicCW = Cartographic.fromRadians(\r\n rectangle.west,\r\n latCenter,\r\n maximumHeight,\r\n scratchPerimeterCartographicCW\r\n );\r\n var perimeterCartographicSW = Cartographic.fromRadians(\r\n rectangle.west,\r\n rectangle.south,\r\n maximumHeight,\r\n scratchPerimeterCartographicSW\r\n );\r\n var perimeterCartographicSC = Cartographic.fromRadians(\r\n lonCenter,\r\n rectangle.south,\r\n maximumHeight,\r\n scratchPerimeterCartographicSC\r\n );\r\n\r\n var perimeterCartesianNC = ellipsoid.cartographicToCartesian(\r\n perimeterCartographicNC,\r\n scratchPerimeterCartesianNC\r\n );\r\n var perimeterCartesianNW = ellipsoid.cartographicToCartesian(\r\n perimeterCartographicNW,\r\n scratchPerimeterCartesianNW\r\n );\r\n var perimeterCartesianCW = ellipsoid.cartographicToCartesian(\r\n perimeterCartographicCW,\r\n scratchPerimeterCartesianCW\r\n );\r\n var perimeterCartesianSW = ellipsoid.cartographicToCartesian(\r\n perimeterCartographicSW,\r\n scratchPerimeterCartesianSW\r\n );\r\n var perimeterCartesianSC = ellipsoid.cartographicToCartesian(\r\n perimeterCartographicSC,\r\n scratchPerimeterCartesianSC\r\n );\r\n\r\n var perimeterProjectedNC = tangentPlane.projectPointToNearestOnPlane(\r\n perimeterCartesianNC,\r\n scratchPerimeterProjectedNC\r\n );\r\n var perimeterProjectedNW = tangentPlane.projectPointToNearestOnPlane(\r\n perimeterCartesianNW,\r\n scratchPerimeterProjectedNW\r\n );\r\n var perimeterProjectedCW = tangentPlane.projectPointToNearestOnPlane(\r\n perimeterCartesianCW,\r\n scratchPerimeterProjectedCW\r\n );\r\n var perimeterProjectedSW = tangentPlane.projectPointToNearestOnPlane(\r\n perimeterCartesianSW,\r\n scratchPerimeterProjectedSW\r\n );\r\n var perimeterProjectedSC = tangentPlane.projectPointToNearestOnPlane(\r\n perimeterCartesianSC,\r\n scratchPerimeterProjectedSC\r\n );\r\n\r\n minX = Math.min(\r\n perimeterProjectedNW.x,\r\n perimeterProjectedCW.x,\r\n perimeterProjectedSW.x\r\n );\r\n maxX = -minX; // symmetrical\r\n\r\n maxY = Math.max(perimeterProjectedNW.y, perimeterProjectedNC.y);\r\n minY = Math.min(perimeterProjectedSW.y, perimeterProjectedSC.y);\r\n\r\n // Compute minimum Z using the rectangle at minimum height, since it will be deeper than the maximum height\r\n perimeterCartographicNW.height = perimeterCartographicSW.height = minimumHeight;\r\n perimeterCartesianNW = ellipsoid.cartographicToCartesian(\r\n perimeterCartographicNW,\r\n scratchPerimeterCartesianNW\r\n );\r\n perimeterCartesianSW = ellipsoid.cartographicToCartesian(\r\n perimeterCartographicSW,\r\n scratchPerimeterCartesianSW\r\n );\r\n\r\n minZ = Math.min(\r\n Plane.getPointDistance(plane, perimeterCartesianNW),\r\n Plane.getPointDistance(plane, perimeterCartesianSW)\r\n );\r\n maxZ = maximumHeight; // Since the tangent plane touches the surface at height = 0, this is okay\r\n\r\n return fromPlaneExtents(\r\n tangentPlane.origin,\r\n tangentPlane.xAxis,\r\n tangentPlane.yAxis,\r\n tangentPlane.zAxis,\r\n minX,\r\n maxX,\r\n minY,\r\n maxY,\r\n minZ,\r\n maxZ,\r\n result\r\n );\r\n }\r\n\r\n // Handle the case where rectangle width is greater than PI (wraps around more than half the ellipsoid).\r\n var fullyAboveEquator = rectangle.south > 0.0;\r\n var fullyBelowEquator = rectangle.north < 0.0;\r\n var latitudeNearestToEquator = fullyAboveEquator\r\n ? rectangle.south\r\n : fullyBelowEquator\r\n ? rectangle.north\r\n : 0.0;\r\n var centerLongitude = Rectangle.center(\r\n rectangle,\r\n scratchRectangleCenterCartographic\r\n ).longitude;\r\n\r\n // Plane is located at the rectangle's center longitude and the rectangle's latitude that is closest to the equator. It rotates around the Z axis.\r\n // This results in a better fit than the obb approach for smaller rectangles, which orients with the rectangle's center normal.\r\n var planeOrigin = Cartesian3.fromRadians(\r\n centerLongitude,\r\n latitudeNearestToEquator,\r\n maximumHeight,\r\n ellipsoid,\r\n scratchPlaneOrigin\r\n );\r\n planeOrigin.z = 0.0; // center the plane on the equator to simpify plane normal calculation\r\n var isPole =\r\n Math.abs(planeOrigin.x) < CesiumMath.EPSILON10 &&\r\n Math.abs(planeOrigin.y) < CesiumMath.EPSILON10;\r\n var planeNormal = !isPole\r\n ? Cartesian3.normalize(planeOrigin, scratchPlaneNormal)\r\n : Cartesian3.UNIT_X;\r\n var planeYAxis = Cartesian3.UNIT_Z;\r\n var planeXAxis = Cartesian3.cross(planeNormal, planeYAxis, scratchPlaneXAxis);\r\n plane = Plane.fromPointNormal(planeOrigin, planeNormal, scratchPlane);\r\n\r\n // Get the horizon point relative to the center. This will be the farthest extent in the plane's X dimension.\r\n var horizonCartesian = Cartesian3.fromRadians(\r\n centerLongitude + CesiumMath.PI_OVER_TWO,\r\n latitudeNearestToEquator,\r\n maximumHeight,\r\n ellipsoid,\r\n scratchHorizonCartesian\r\n );\r\n maxX = Cartesian3.dot(\r\n Plane.projectPointOntoPlane(\r\n plane,\r\n horizonCartesian,\r\n scratchHorizonProjected\r\n ),\r\n planeXAxis\r\n );\r\n minX = -maxX; // symmetrical\r\n\r\n // Get the min and max Y, using the height that will give the largest extent\r\n maxY = Cartesian3.fromRadians(\r\n 0.0,\r\n rectangle.north,\r\n fullyBelowEquator ? minimumHeight : maximumHeight,\r\n ellipsoid,\r\n scratchMaxY\r\n ).z;\r\n minY = Cartesian3.fromRadians(\r\n 0.0,\r\n rectangle.south,\r\n fullyAboveEquator ? minimumHeight : maximumHeight,\r\n ellipsoid,\r\n scratchMinY\r\n ).z;\r\n\r\n var farZ = Cartesian3.fromRadians(\r\n rectangle.east,\r\n latitudeNearestToEquator,\r\n maximumHeight,\r\n ellipsoid,\r\n scratchZ\r\n );\r\n minZ = Plane.getPointDistance(plane, farZ);\r\n maxZ = 0.0; // plane origin starts at maxZ already\r\n\r\n // min and max are local to the plane axes\r\n return fromPlaneExtents(\r\n planeOrigin,\r\n planeXAxis,\r\n planeYAxis,\r\n planeNormal,\r\n minX,\r\n maxX,\r\n minY,\r\n maxY,\r\n minZ,\r\n maxZ,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates a OrientedBoundingBox instance.\r\n *\r\n * @param {OrientedBoundingBox} box The bounding box to duplicate.\r\n * @param {OrientedBoundingBox} [result] The object onto which to store the result.\r\n * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if none was provided. (Returns undefined if box is undefined)\r\n */\r\nOrientedBoundingBox.clone = function (box, result) {\r\n if (!defined(box)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new OrientedBoundingBox(box.center, box.halfAxes);\r\n }\r\n\r\n Cartesian3.clone(box.center, result.center);\r\n Matrix3.clone(box.halfAxes, result.halfAxes);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines which side of a plane the oriented bounding box is located.\r\n *\r\n * @param {OrientedBoundingBox} box The oriented bounding box to test.\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the box\r\n * intersects the plane.\r\n */\r\nOrientedBoundingBox.intersectPlane = function (box, plane) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(box)) {\r\n throw new DeveloperError(\"box is required.\");\r\n }\r\n\r\n if (!defined(plane)) {\r\n throw new DeveloperError(\"plane is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var center = box.center;\r\n var normal = plane.normal;\r\n var halfAxes = box.halfAxes;\r\n var normalX = normal.x,\r\n normalY = normal.y,\r\n normalZ = normal.z;\r\n // plane is used as if it is its normal; the first three components are assumed to be normalized\r\n var radEffective =\r\n Math.abs(\r\n normalX * halfAxes[Matrix3.COLUMN0ROW0] +\r\n normalY * halfAxes[Matrix3.COLUMN0ROW1] +\r\n normalZ * halfAxes[Matrix3.COLUMN0ROW2]\r\n ) +\r\n Math.abs(\r\n normalX * halfAxes[Matrix3.COLUMN1ROW0] +\r\n normalY * halfAxes[Matrix3.COLUMN1ROW1] +\r\n normalZ * halfAxes[Matrix3.COLUMN1ROW2]\r\n ) +\r\n Math.abs(\r\n normalX * halfAxes[Matrix3.COLUMN2ROW0] +\r\n normalY * halfAxes[Matrix3.COLUMN2ROW1] +\r\n normalZ * halfAxes[Matrix3.COLUMN2ROW2]\r\n );\r\n var distanceToPlane = Cartesian3.dot(normal, center) + plane.distance;\r\n\r\n if (distanceToPlane <= -radEffective) {\r\n // The entire box is on the negative side of the plane normal\r\n return Intersect.OUTSIDE;\r\n } else if (distanceToPlane >= radEffective) {\r\n // The entire box is on the positive side of the plane normal\r\n return Intersect.INSIDE;\r\n }\r\n return Intersect.INTERSECTING;\r\n};\r\n\r\nvar scratchCartesianU = new Cartesian3();\r\nvar scratchCartesianV = new Cartesian3();\r\nvar scratchCartesianW = new Cartesian3();\r\nvar scratchPPrime = new Cartesian3();\r\n\r\n/**\r\n * Computes the estimated distance squared from the closest point on a bounding box to a point.\r\n *\r\n * @param {OrientedBoundingBox} box The box.\r\n * @param {Cartesian3} cartesian The point\r\n * @returns {Number} The estimated distance squared from the bounding sphere to the point.\r\n *\r\n * @example\r\n * // Sort bounding boxes from back to front\r\n * boxes.sort(function(a, b) {\r\n * return Cesium.OrientedBoundingBox.distanceSquaredTo(b, camera.positionWC) - Cesium.OrientedBoundingBox.distanceSquaredTo(a, camera.positionWC);\r\n * });\r\n */\r\nOrientedBoundingBox.distanceSquaredTo = function (box, cartesian) {\r\n // See Geometric Tools for Computer Graphics 10.4.2\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(box)) {\r\n throw new DeveloperError(\"box is required.\");\r\n }\r\n if (!defined(cartesian)) {\r\n throw new DeveloperError(\"cartesian is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var offset = Cartesian3.subtract(cartesian, box.center, scratchOffset);\r\n\r\n var halfAxes = box.halfAxes;\r\n var u = Matrix3.getColumn(halfAxes, 0, scratchCartesianU);\r\n var v = Matrix3.getColumn(halfAxes, 1, scratchCartesianV);\r\n var w = Matrix3.getColumn(halfAxes, 2, scratchCartesianW);\r\n\r\n var uHalf = Cartesian3.magnitude(u);\r\n var vHalf = Cartesian3.magnitude(v);\r\n var wHalf = Cartesian3.magnitude(w);\r\n\r\n Cartesian3.normalize(u, u);\r\n Cartesian3.normalize(v, v);\r\n Cartesian3.normalize(w, w);\r\n\r\n var pPrime = scratchPPrime;\r\n pPrime.x = Cartesian3.dot(offset, u);\r\n pPrime.y = Cartesian3.dot(offset, v);\r\n pPrime.z = Cartesian3.dot(offset, w);\r\n\r\n var distanceSquared = 0.0;\r\n var d;\r\n\r\n if (pPrime.x < -uHalf) {\r\n d = pPrime.x + uHalf;\r\n distanceSquared += d * d;\r\n } else if (pPrime.x > uHalf) {\r\n d = pPrime.x - uHalf;\r\n distanceSquared += d * d;\r\n }\r\n\r\n if (pPrime.y < -vHalf) {\r\n d = pPrime.y + vHalf;\r\n distanceSquared += d * d;\r\n } else if (pPrime.y > vHalf) {\r\n d = pPrime.y - vHalf;\r\n distanceSquared += d * d;\r\n }\r\n\r\n if (pPrime.z < -wHalf) {\r\n d = pPrime.z + wHalf;\r\n distanceSquared += d * d;\r\n } else if (pPrime.z > wHalf) {\r\n d = pPrime.z - wHalf;\r\n distanceSquared += d * d;\r\n }\r\n\r\n return distanceSquared;\r\n};\r\n\r\nvar scratchCorner = new Cartesian3();\r\nvar scratchToCenter = new Cartesian3();\r\n\r\n/**\r\n * The distances calculated by the vector from the center of the bounding box to position projected onto direction.\r\n *
\r\n * If you imagine the infinite number of planes with normal direction, this computes the smallest distance to the\r\n * closest and farthest planes from position that intersect the bounding box.\r\n *\r\n * @param {OrientedBoundingBox} box The bounding box to calculate the distance to.\r\n * @param {Cartesian3} position The position to calculate the distance from.\r\n * @param {Cartesian3} direction The direction from position.\r\n * @param {Interval} [result] A Interval to store the nearest and farthest distances.\r\n * @returns {Interval} The nearest and farthest distances on the bounding box from position in direction.\r\n */\r\nOrientedBoundingBox.computePlaneDistances = function (\r\n box,\r\n position,\r\n direction,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(box)) {\r\n throw new DeveloperError(\"box is required.\");\r\n }\r\n\r\n if (!defined(position)) {\r\n throw new DeveloperError(\"position is required.\");\r\n }\r\n\r\n if (!defined(direction)) {\r\n throw new DeveloperError(\"direction is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Interval();\r\n }\r\n\r\n var minDist = Number.POSITIVE_INFINITY;\r\n var maxDist = Number.NEGATIVE_INFINITY;\r\n\r\n var center = box.center;\r\n var halfAxes = box.halfAxes;\r\n\r\n var u = Matrix3.getColumn(halfAxes, 0, scratchCartesianU);\r\n var v = Matrix3.getColumn(halfAxes, 1, scratchCartesianV);\r\n var w = Matrix3.getColumn(halfAxes, 2, scratchCartesianW);\r\n\r\n // project first corner\r\n var corner = Cartesian3.add(u, v, scratchCorner);\r\n Cartesian3.add(corner, w, corner);\r\n Cartesian3.add(corner, center, corner);\r\n\r\n var toCenter = Cartesian3.subtract(corner, position, scratchToCenter);\r\n var mag = Cartesian3.dot(direction, toCenter);\r\n\r\n minDist = Math.min(mag, minDist);\r\n maxDist = Math.max(mag, maxDist);\r\n\r\n // project second corner\r\n Cartesian3.add(center, u, corner);\r\n Cartesian3.add(corner, v, corner);\r\n Cartesian3.subtract(corner, w, corner);\r\n\r\n Cartesian3.subtract(corner, position, toCenter);\r\n mag = Cartesian3.dot(direction, toCenter);\r\n\r\n minDist = Math.min(mag, minDist);\r\n maxDist = Math.max(mag, maxDist);\r\n\r\n // project third corner\r\n Cartesian3.add(center, u, corner);\r\n Cartesian3.subtract(corner, v, corner);\r\n Cartesian3.add(corner, w, corner);\r\n\r\n Cartesian3.subtract(corner, position, toCenter);\r\n mag = Cartesian3.dot(direction, toCenter);\r\n\r\n minDist = Math.min(mag, minDist);\r\n maxDist = Math.max(mag, maxDist);\r\n\r\n // project fourth corner\r\n Cartesian3.add(center, u, corner);\r\n Cartesian3.subtract(corner, v, corner);\r\n Cartesian3.subtract(corner, w, corner);\r\n\r\n Cartesian3.subtract(corner, position, toCenter);\r\n mag = Cartesian3.dot(direction, toCenter);\r\n\r\n minDist = Math.min(mag, minDist);\r\n maxDist = Math.max(mag, maxDist);\r\n\r\n // project fifth corner\r\n Cartesian3.subtract(center, u, corner);\r\n Cartesian3.add(corner, v, corner);\r\n Cartesian3.add(corner, w, corner);\r\n\r\n Cartesian3.subtract(corner, position, toCenter);\r\n mag = Cartesian3.dot(direction, toCenter);\r\n\r\n minDist = Math.min(mag, minDist);\r\n maxDist = Math.max(mag, maxDist);\r\n\r\n // project sixth corner\r\n Cartesian3.subtract(center, u, corner);\r\n Cartesian3.add(corner, v, corner);\r\n Cartesian3.subtract(corner, w, corner);\r\n\r\n Cartesian3.subtract(corner, position, toCenter);\r\n mag = Cartesian3.dot(direction, toCenter);\r\n\r\n minDist = Math.min(mag, minDist);\r\n maxDist = Math.max(mag, maxDist);\r\n\r\n // project seventh corner\r\n Cartesian3.subtract(center, u, corner);\r\n Cartesian3.subtract(corner, v, corner);\r\n Cartesian3.add(corner, w, corner);\r\n\r\n Cartesian3.subtract(corner, position, toCenter);\r\n mag = Cartesian3.dot(direction, toCenter);\r\n\r\n minDist = Math.min(mag, minDist);\r\n maxDist = Math.max(mag, maxDist);\r\n\r\n // project eighth corner\r\n Cartesian3.subtract(center, u, corner);\r\n Cartesian3.subtract(corner, v, corner);\r\n Cartesian3.subtract(corner, w, corner);\r\n\r\n Cartesian3.subtract(corner, position, toCenter);\r\n mag = Cartesian3.dot(direction, toCenter);\r\n\r\n minDist = Math.min(mag, minDist);\r\n maxDist = Math.max(mag, maxDist);\r\n\r\n result.start = minDist;\r\n result.stop = maxDist;\r\n return result;\r\n};\r\n\r\nvar scratchBoundingSphere = new BoundingSphere();\r\n\r\n/**\r\n * Determines whether or not a bounding box is hidden from view by the occluder.\r\n *\r\n * @param {OrientedBoundingBox} box The bounding box surrounding the occludee object.\r\n * @param {Occluder} occluder The occluder.\r\n * @returns {Boolean} true if the box is not visible; otherwise false.\r\n */\r\nOrientedBoundingBox.isOccluded = function (box, occluder) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(box)) {\r\n throw new DeveloperError(\"box is required.\");\r\n }\r\n if (!defined(occluder)) {\r\n throw new DeveloperError(\"occluder is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var sphere = BoundingSphere.fromOrientedBoundingBox(\r\n box,\r\n scratchBoundingSphere\r\n );\r\n\r\n return !occluder.isBoundingSphereVisible(sphere);\r\n};\r\n\r\n/**\r\n * Determines which side of a plane the oriented bounding box is located.\r\n *\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the box\r\n * intersects the plane.\r\n */\r\nOrientedBoundingBox.prototype.intersectPlane = function (plane) {\r\n return OrientedBoundingBox.intersectPlane(this, plane);\r\n};\r\n\r\n/**\r\n * Computes the estimated distance squared from the closest point on a bounding box to a point.\r\n *\r\n * @param {Cartesian3} cartesian The point\r\n * @returns {Number} The estimated distance squared from the bounding sphere to the point.\r\n *\r\n * @example\r\n * // Sort bounding boxes from back to front\r\n * boxes.sort(function(a, b) {\r\n * return b.distanceSquaredTo(camera.positionWC) - a.distanceSquaredTo(camera.positionWC);\r\n * });\r\n */\r\nOrientedBoundingBox.prototype.distanceSquaredTo = function (cartesian) {\r\n return OrientedBoundingBox.distanceSquaredTo(this, cartesian);\r\n};\r\n\r\n/**\r\n * The distances calculated by the vector from the center of the bounding box to position projected onto direction.\r\n *
\r\n * If you imagine the infinite number of planes with normal direction, this computes the smallest distance to the\r\n * closest and farthest planes from position that intersect the bounding box.\r\n *\r\n * @param {Cartesian3} position The position to calculate the distance from.\r\n * @param {Cartesian3} direction The direction from position.\r\n * @param {Interval} [result] A Interval to store the nearest and farthest distances.\r\n * @returns {Interval} The nearest and farthest distances on the bounding box from position in direction.\r\n */\r\nOrientedBoundingBox.prototype.computePlaneDistances = function (\r\n position,\r\n direction,\r\n result\r\n) {\r\n return OrientedBoundingBox.computePlaneDistances(\r\n this,\r\n position,\r\n direction,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Determines whether or not a bounding box is hidden from view by the occluder.\r\n *\r\n * @param {Occluder} occluder The occluder.\r\n * @returns {Boolean} true if the sphere is not visible; otherwise false.\r\n */\r\nOrientedBoundingBox.prototype.isOccluded = function (occluder) {\r\n return OrientedBoundingBox.isOccluded(this, occluder);\r\n};\r\n\r\n/**\r\n * Compares the provided OrientedBoundingBox componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {OrientedBoundingBox} left The first OrientedBoundingBox.\r\n * @param {OrientedBoundingBox} right The second OrientedBoundingBox.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nOrientedBoundingBox.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Cartesian3.equals(left.center, right.center) &&\r\n Matrix3.equals(left.halfAxes, right.halfAxes))\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates this OrientedBoundingBox instance.\r\n *\r\n * @param {OrientedBoundingBox} [result] The object onto which to store the result.\r\n * @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if one was not provided.\r\n */\r\nOrientedBoundingBox.prototype.clone = function (result) {\r\n return OrientedBoundingBox.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this OrientedBoundingBox against the provided OrientedBoundingBox componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {OrientedBoundingBox} [right] The right hand side OrientedBoundingBox.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nOrientedBoundingBox.prototype.equals = function (right) {\r\n return OrientedBoundingBox.equals(this, right);\r\n};\r\nexport default OrientedBoundingBox;\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nvar RIGHT_SHIFT = 1.0 / 256.0;\r\nvar LEFT_SHIFT = 256.0;\r\n\r\n/**\r\n * Attribute compression and decompression functions.\r\n *\r\n * @namespace AttributeCompression\r\n *\r\n * @private\r\n */\r\nvar AttributeCompression = {};\r\n\r\n/**\r\n * Encodes a normalized vector into 2 SNORM values in the range of [0-rangeMax] following the 'oct' encoding.\r\n *\r\n * Oct encoding is a compact representation of unit length vectors.\r\n * The 'oct' encoding is described in \"A Survey of Efficient Representations of Independent Unit Vectors\",\r\n * Cigolle et al 2014: {@link http://jcgt.org/published/0003/02/01/}\r\n *\r\n * @param {Cartesian3} vector The normalized vector to be compressed into 2 component 'oct' encoding.\r\n * @param {Cartesian2} result The 2 component oct-encoded unit length vector.\r\n * @param {Number} rangeMax The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits.\r\n * @returns {Cartesian2} The 2 component oct-encoded unit length vector.\r\n *\r\n * @exception {DeveloperError} vector must be normalized.\r\n *\r\n * @see AttributeCompression.octDecodeInRange\r\n */\r\nAttributeCompression.octEncodeInRange = function (vector, rangeMax, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"vector\", vector);\r\n Check.defined(\"result\", result);\r\n var magSquared = Cartesian3.magnitudeSquared(vector);\r\n if (Math.abs(magSquared - 1.0) > CesiumMath.EPSILON6) {\r\n throw new DeveloperError(\"vector must be normalized.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n result.x =\r\n vector.x / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z));\r\n result.y =\r\n vector.y / (Math.abs(vector.x) + Math.abs(vector.y) + Math.abs(vector.z));\r\n if (vector.z < 0) {\r\n var x = result.x;\r\n var y = result.y;\r\n result.x = (1.0 - Math.abs(y)) * CesiumMath.signNotZero(x);\r\n result.y = (1.0 - Math.abs(x)) * CesiumMath.signNotZero(y);\r\n }\r\n\r\n result.x = CesiumMath.toSNorm(result.x, rangeMax);\r\n result.y = CesiumMath.toSNorm(result.y, rangeMax);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Encodes a normalized vector into 2 SNORM values in the range of [0-255] following the 'oct' encoding.\r\n *\r\n * @param {Cartesian3} vector The normalized vector to be compressed into 2 byte 'oct' encoding.\r\n * @param {Cartesian2} result The 2 byte oct-encoded unit length vector.\r\n * @returns {Cartesian2} The 2 byte oct-encoded unit length vector.\r\n *\r\n * @exception {DeveloperError} vector must be normalized.\r\n *\r\n * @see AttributeCompression.octEncodeInRange\r\n * @see AttributeCompression.octDecode\r\n */\r\nAttributeCompression.octEncode = function (vector, result) {\r\n return AttributeCompression.octEncodeInRange(vector, 255, result);\r\n};\r\n\r\nvar octEncodeScratch = new Cartesian2();\r\nvar uint8ForceArray = new Uint8Array(1);\r\nfunction forceUint8(value) {\r\n uint8ForceArray[0] = value;\r\n return uint8ForceArray[0];\r\n}\r\n/**\r\n * @param {Cartesian3} vector The normalized vector to be compressed into 4 byte 'oct' encoding.\r\n * @param {Cartesian4} result The 4 byte oct-encoded unit length vector.\r\n * @returns {Cartesian4} The 4 byte oct-encoded unit length vector.\r\n *\r\n * @exception {DeveloperError} vector must be normalized.\r\n *\r\n * @see AttributeCompression.octEncodeInRange\r\n * @see AttributeCompression.octDecodeFromCartesian4\r\n */\r\nAttributeCompression.octEncodeToCartesian4 = function (vector, result) {\r\n AttributeCompression.octEncodeInRange(vector, 65535, octEncodeScratch);\r\n result.x = forceUint8(octEncodeScratch.x * RIGHT_SHIFT);\r\n result.y = forceUint8(octEncodeScratch.x);\r\n result.z = forceUint8(octEncodeScratch.y * RIGHT_SHIFT);\r\n result.w = forceUint8(octEncodeScratch.y);\r\n return result;\r\n};\r\n\r\n/**\r\n * Decodes a unit-length vector in 'oct' encoding to a normalized 3-component vector.\r\n *\r\n * @param {Number} x The x component of the oct-encoded unit length vector.\r\n * @param {Number} y The y component of the oct-encoded unit length vector.\r\n * @param {Number} rangeMax The maximum value of the SNORM range. The encoded vector is stored in log2(rangeMax+1) bits.\r\n * @param {Cartesian3} result The decoded and normalized vector\r\n * @returns {Cartesian3} The decoded and normalized vector.\r\n *\r\n * @exception {DeveloperError} x and y must be unsigned normalized integers between 0 and rangeMax.\r\n *\r\n * @see AttributeCompression.octEncodeInRange\r\n */\r\nAttributeCompression.octDecodeInRange = function (x, y, rangeMax, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"result\", result);\r\n if (x < 0 || x > rangeMax || y < 0 || y > rangeMax) {\r\n throw new DeveloperError(\r\n \"x and y must be unsigned normalized integers between 0 and \" + rangeMax\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n result.x = CesiumMath.fromSNorm(x, rangeMax);\r\n result.y = CesiumMath.fromSNorm(y, rangeMax);\r\n result.z = 1.0 - (Math.abs(result.x) + Math.abs(result.y));\r\n\r\n if (result.z < 0.0) {\r\n var oldVX = result.x;\r\n result.x = (1.0 - Math.abs(result.y)) * CesiumMath.signNotZero(oldVX);\r\n result.y = (1.0 - Math.abs(oldVX)) * CesiumMath.signNotZero(result.y);\r\n }\r\n\r\n return Cartesian3.normalize(result, result);\r\n};\r\n\r\n/**\r\n * Decodes a unit-length vector in 2 byte 'oct' encoding to a normalized 3-component vector.\r\n *\r\n * @param {Number} x The x component of the oct-encoded unit length vector.\r\n * @param {Number} y The y component of the oct-encoded unit length vector.\r\n * @param {Cartesian3} result The decoded and normalized vector.\r\n * @returns {Cartesian3} The decoded and normalized vector.\r\n *\r\n * @exception {DeveloperError} x and y must be an unsigned normalized integer between 0 and 255.\r\n *\r\n * @see AttributeCompression.octDecodeInRange\r\n */\r\nAttributeCompression.octDecode = function (x, y, result) {\r\n return AttributeCompression.octDecodeInRange(x, y, 255, result);\r\n};\r\n\r\n/**\r\n * Decodes a unit-length vector in 4 byte 'oct' encoding to a normalized 3-component vector.\r\n *\r\n * @param {Cartesian4} encoded The oct-encoded unit length vector.\r\n * @param {Cartesian3} result The decoded and normalized vector.\r\n * @returns {Cartesian3} The decoded and normalized vector.\r\n *\r\n * @exception {DeveloperError} x, y, z, and w must be unsigned normalized integers between 0 and 255.\r\n *\r\n * @see AttributeCompression.octDecodeInRange\r\n * @see AttributeCompression.octEncodeToCartesian4\r\n */\r\nAttributeCompression.octDecodeFromCartesian4 = function (encoded, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"encoded\", encoded);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n var x = encoded.x;\r\n var y = encoded.y;\r\n var z = encoded.z;\r\n var w = encoded.w;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n x < 0 ||\r\n x > 255 ||\r\n y < 0 ||\r\n y > 255 ||\r\n z < 0 ||\r\n z > 255 ||\r\n w < 0 ||\r\n w > 255\r\n ) {\r\n throw new DeveloperError(\r\n \"x, y, z, and w must be unsigned normalized integers between 0 and 255\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var xOct16 = x * LEFT_SHIFT + y;\r\n var yOct16 = z * LEFT_SHIFT + w;\r\n return AttributeCompression.octDecodeInRange(xOct16, yOct16, 65535, result);\r\n};\r\n\r\n/**\r\n * Packs an oct encoded vector into a single floating-point number.\r\n *\r\n * @param {Cartesian2} encoded The oct encoded vector.\r\n * @returns {Number} The oct encoded vector packed into a single float.\r\n *\r\n */\r\nAttributeCompression.octPackFloat = function (encoded) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"encoded\", encoded);\r\n //>>includeEnd('debug');\r\n return 256.0 * encoded.x + encoded.y;\r\n};\r\n\r\nvar scratchEncodeCart2 = new Cartesian2();\r\n\r\n/**\r\n * Encodes a normalized vector into 2 SNORM values in the range of [0-255] following the 'oct' encoding and\r\n * stores those values in a single float-point number.\r\n *\r\n * @param {Cartesian3} vector The normalized vector to be compressed into 2 byte 'oct' encoding.\r\n * @returns {Number} The 2 byte oct-encoded unit length vector.\r\n *\r\n * @exception {DeveloperError} vector must be normalized.\r\n */\r\nAttributeCompression.octEncodeFloat = function (vector) {\r\n AttributeCompression.octEncode(vector, scratchEncodeCart2);\r\n return AttributeCompression.octPackFloat(scratchEncodeCart2);\r\n};\r\n\r\n/**\r\n * Decodes a unit-length vector in 'oct' encoding packed in a floating-point number to a normalized 3-component vector.\r\n *\r\n * @param {Number} value The oct-encoded unit length vector stored as a single floating-point number.\r\n * @param {Cartesian3} result The decoded and normalized vector\r\n * @returns {Cartesian3} The decoded and normalized vector.\r\n *\r\n */\r\nAttributeCompression.octDecodeFloat = function (value, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"value\", value);\r\n //>>includeEnd('debug');\r\n\r\n var temp = value / 256.0;\r\n var x = Math.floor(temp);\r\n var y = (temp - x) * 256.0;\r\n\r\n return AttributeCompression.octDecode(x, y, result);\r\n};\r\n\r\n/**\r\n * Encodes three normalized vectors into 6 SNORM values in the range of [0-255] following the 'oct' encoding and\r\n * packs those into two floating-point numbers.\r\n *\r\n * @param {Cartesian3} v1 A normalized vector to be compressed.\r\n * @param {Cartesian3} v2 A normalized vector to be compressed.\r\n * @param {Cartesian3} v3 A normalized vector to be compressed.\r\n * @param {Cartesian2} result The 'oct' encoded vectors packed into two floating-point numbers.\r\n * @returns {Cartesian2} The 'oct' encoded vectors packed into two floating-point numbers.\r\n *\r\n */\r\nAttributeCompression.octPack = function (v1, v2, v3, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"v1\", v1);\r\n Check.defined(\"v2\", v2);\r\n Check.defined(\"v3\", v3);\r\n Check.defined(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var encoded1 = AttributeCompression.octEncodeFloat(v1);\r\n var encoded2 = AttributeCompression.octEncodeFloat(v2);\r\n\r\n var encoded3 = AttributeCompression.octEncode(v3, scratchEncodeCart2);\r\n result.x = 65536.0 * encoded3.x + encoded1;\r\n result.y = 65536.0 * encoded3.y + encoded2;\r\n return result;\r\n};\r\n\r\n/**\r\n * Decodes three unit-length vectors in 'oct' encoding packed into a floating-point number to a normalized 3-component vector.\r\n *\r\n * @param {Cartesian2} packed The three oct-encoded unit length vectors stored as two floating-point number.\r\n * @param {Cartesian3} v1 One decoded and normalized vector.\r\n * @param {Cartesian3} v2 One decoded and normalized vector.\r\n * @param {Cartesian3} v3 One decoded and normalized vector.\r\n */\r\nAttributeCompression.octUnpack = function (packed, v1, v2, v3) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"packed\", packed);\r\n Check.defined(\"v1\", v1);\r\n Check.defined(\"v2\", v2);\r\n Check.defined(\"v3\", v3);\r\n //>>includeEnd('debug');\r\n\r\n var temp = packed.x / 65536.0;\r\n var x = Math.floor(temp);\r\n var encodedFloat1 = (temp - x) * 65536.0;\r\n\r\n temp = packed.y / 65536.0;\r\n var y = Math.floor(temp);\r\n var encodedFloat2 = (temp - y) * 65536.0;\r\n\r\n AttributeCompression.octDecodeFloat(encodedFloat1, v1);\r\n AttributeCompression.octDecodeFloat(encodedFloat2, v2);\r\n AttributeCompression.octDecode(x, y, v3);\r\n};\r\n\r\n/**\r\n * Pack texture coordinates into a single float. The texture coordinates will only preserve 12 bits of precision.\r\n *\r\n * @param {Cartesian2} textureCoordinates The texture coordinates to compress. Both coordinates must be in the range 0.0-1.0.\r\n * @returns {Number} The packed texture coordinates.\r\n *\r\n */\r\nAttributeCompression.compressTextureCoordinates = function (\r\n textureCoordinates\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"textureCoordinates\", textureCoordinates);\r\n //>>includeEnd('debug');\r\n\r\n // Move x and y to the range 0-4095;\r\n var x = (textureCoordinates.x * 4095.0) | 0;\r\n var y = (textureCoordinates.y * 4095.0) | 0;\r\n return 4096.0 * x + y;\r\n};\r\n\r\n/**\r\n * Decompresses texture coordinates that were packed into a single float.\r\n *\r\n * @param {Number} compressed The compressed texture coordinates.\r\n * @param {Cartesian2} result The decompressed texture coordinates.\r\n * @returns {Cartesian2} The modified result parameter.\r\n *\r\n */\r\nAttributeCompression.decompressTextureCoordinates = function (\r\n compressed,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"compressed\", compressed);\r\n Check.defined(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var temp = compressed / 4096.0;\r\n var xZeroTo4095 = Math.floor(temp);\r\n result.x = xZeroTo4095 / 4095.0;\r\n result.y = (compressed - xZeroTo4095 * 4096) / 4095;\r\n return result;\r\n};\r\n\r\nfunction zigZagDecode(value) {\r\n return (value >> 1) ^ -(value & 1);\r\n}\r\n\r\n/**\r\n * Decodes delta and ZigZag encoded vertices. This modifies the buffers in place.\r\n *\r\n * @param {Uint16Array} uBuffer The buffer view of u values.\r\n * @param {Uint16Array} vBuffer The buffer view of v values.\r\n * @param {Uint16Array} [heightBuffer] The buffer view of height values.\r\n *\r\n * @see {@link https://github.com/CesiumGS/quantized-mesh|quantized-mesh-1.0 terrain format}\r\n */\r\nAttributeCompression.zigZagDeltaDecode = function (\r\n uBuffer,\r\n vBuffer,\r\n heightBuffer\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"uBuffer\", uBuffer);\r\n Check.defined(\"vBuffer\", vBuffer);\r\n Check.typeOf.number.equals(\r\n \"uBuffer.length\",\r\n \"vBuffer.length\",\r\n uBuffer.length,\r\n vBuffer.length\r\n );\r\n if (defined(heightBuffer)) {\r\n Check.typeOf.number.equals(\r\n \"uBuffer.length\",\r\n \"heightBuffer.length\",\r\n uBuffer.length,\r\n heightBuffer.length\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var count = uBuffer.length;\r\n\r\n var u = 0;\r\n var v = 0;\r\n var height = 0;\r\n\r\n for (var i = 0; i < count; ++i) {\r\n u += zigZagDecode(uBuffer[i]);\r\n v += zigZagDecode(vBuffer[i]);\r\n\r\n uBuffer[i] = u;\r\n vBuffer[i] = v;\r\n\r\n if (defined(heightBuffer)) {\r\n height += zigZagDecode(heightBuffer[i]);\r\n heightBuffer[i] = height;\r\n }\r\n }\r\n};\r\nexport default AttributeCompression;\r\n","/**\r\n * Enum containing WebGL Constant values by name.\r\n * for use without an active WebGL context, or in cases where certain constants are unavailable using the WebGL context\r\n * (For example, in [Safari 9]{@link https://github.com/CesiumGS/cesium/issues/2989}).\r\n *\r\n * These match the constants from the [WebGL 1.0]{@link https://www.khronos.org/registry/webgl/specs/latest/1.0/}\r\n * and [WebGL 2.0]{@link https://www.khronos.org/registry/webgl/specs/latest/2.0/}\r\n * specifications.\r\n *\r\n * @enum {Number}\r\n */\r\nvar WebGLConstants = {\r\n DEPTH_BUFFER_BIT: 0x00000100,\r\n STENCIL_BUFFER_BIT: 0x00000400,\r\n COLOR_BUFFER_BIT: 0x00004000,\r\n POINTS: 0x0000,\r\n LINES: 0x0001,\r\n LINE_LOOP: 0x0002,\r\n LINE_STRIP: 0x0003,\r\n TRIANGLES: 0x0004,\r\n TRIANGLE_STRIP: 0x0005,\r\n TRIANGLE_FAN: 0x0006,\r\n ZERO: 0,\r\n ONE: 1,\r\n SRC_COLOR: 0x0300,\r\n ONE_MINUS_SRC_COLOR: 0x0301,\r\n SRC_ALPHA: 0x0302,\r\n ONE_MINUS_SRC_ALPHA: 0x0303,\r\n DST_ALPHA: 0x0304,\r\n ONE_MINUS_DST_ALPHA: 0x0305,\r\n DST_COLOR: 0x0306,\r\n ONE_MINUS_DST_COLOR: 0x0307,\r\n SRC_ALPHA_SATURATE: 0x0308,\r\n FUNC_ADD: 0x8006,\r\n BLEND_EQUATION: 0x8009,\r\n BLEND_EQUATION_RGB: 0x8009, // same as BLEND_EQUATION\r\n BLEND_EQUATION_ALPHA: 0x883d,\r\n FUNC_SUBTRACT: 0x800a,\r\n FUNC_REVERSE_SUBTRACT: 0x800b,\r\n BLEND_DST_RGB: 0x80c8,\r\n BLEND_SRC_RGB: 0x80c9,\r\n BLEND_DST_ALPHA: 0x80ca,\r\n BLEND_SRC_ALPHA: 0x80cb,\r\n CONSTANT_COLOR: 0x8001,\r\n ONE_MINUS_CONSTANT_COLOR: 0x8002,\r\n CONSTANT_ALPHA: 0x8003,\r\n ONE_MINUS_CONSTANT_ALPHA: 0x8004,\r\n BLEND_COLOR: 0x8005,\r\n ARRAY_BUFFER: 0x8892,\r\n ELEMENT_ARRAY_BUFFER: 0x8893,\r\n ARRAY_BUFFER_BINDING: 0x8894,\r\n ELEMENT_ARRAY_BUFFER_BINDING: 0x8895,\r\n STREAM_DRAW: 0x88e0,\r\n STATIC_DRAW: 0x88e4,\r\n DYNAMIC_DRAW: 0x88e8,\r\n BUFFER_SIZE: 0x8764,\r\n BUFFER_USAGE: 0x8765,\r\n CURRENT_VERTEX_ATTRIB: 0x8626,\r\n FRONT: 0x0404,\r\n BACK: 0x0405,\r\n FRONT_AND_BACK: 0x0408,\r\n CULL_FACE: 0x0b44,\r\n BLEND: 0x0be2,\r\n DITHER: 0x0bd0,\r\n STENCIL_TEST: 0x0b90,\r\n DEPTH_TEST: 0x0b71,\r\n SCISSOR_TEST: 0x0c11,\r\n POLYGON_OFFSET_FILL: 0x8037,\r\n SAMPLE_ALPHA_TO_COVERAGE: 0x809e,\r\n SAMPLE_COVERAGE: 0x80a0,\r\n NO_ERROR: 0,\r\n INVALID_ENUM: 0x0500,\r\n INVALID_VALUE: 0x0501,\r\n INVALID_OPERATION: 0x0502,\r\n OUT_OF_MEMORY: 0x0505,\r\n CW: 0x0900,\r\n CCW: 0x0901,\r\n LINE_WIDTH: 0x0b21,\r\n ALIASED_POINT_SIZE_RANGE: 0x846d,\r\n ALIASED_LINE_WIDTH_RANGE: 0x846e,\r\n CULL_FACE_MODE: 0x0b45,\r\n FRONT_FACE: 0x0b46,\r\n DEPTH_RANGE: 0x0b70,\r\n DEPTH_WRITEMASK: 0x0b72,\r\n DEPTH_CLEAR_VALUE: 0x0b73,\r\n DEPTH_FUNC: 0x0b74,\r\n STENCIL_CLEAR_VALUE: 0x0b91,\r\n STENCIL_FUNC: 0x0b92,\r\n STENCIL_FAIL: 0x0b94,\r\n STENCIL_PASS_DEPTH_FAIL: 0x0b95,\r\n STENCIL_PASS_DEPTH_PASS: 0x0b96,\r\n STENCIL_REF: 0x0b97,\r\n STENCIL_VALUE_MASK: 0x0b93,\r\n STENCIL_WRITEMASK: 0x0b98,\r\n STENCIL_BACK_FUNC: 0x8800,\r\n STENCIL_BACK_FAIL: 0x8801,\r\n STENCIL_BACK_PASS_DEPTH_FAIL: 0x8802,\r\n STENCIL_BACK_PASS_DEPTH_PASS: 0x8803,\r\n STENCIL_BACK_REF: 0x8ca3,\r\n STENCIL_BACK_VALUE_MASK: 0x8ca4,\r\n STENCIL_BACK_WRITEMASK: 0x8ca5,\r\n VIEWPORT: 0x0ba2,\r\n SCISSOR_BOX: 0x0c10,\r\n COLOR_CLEAR_VALUE: 0x0c22,\r\n COLOR_WRITEMASK: 0x0c23,\r\n UNPACK_ALIGNMENT: 0x0cf5,\r\n PACK_ALIGNMENT: 0x0d05,\r\n MAX_TEXTURE_SIZE: 0x0d33,\r\n MAX_VIEWPORT_DIMS: 0x0d3a,\r\n SUBPIXEL_BITS: 0x0d50,\r\n RED_BITS: 0x0d52,\r\n GREEN_BITS: 0x0d53,\r\n BLUE_BITS: 0x0d54,\r\n ALPHA_BITS: 0x0d55,\r\n DEPTH_BITS: 0x0d56,\r\n STENCIL_BITS: 0x0d57,\r\n POLYGON_OFFSET_UNITS: 0x2a00,\r\n POLYGON_OFFSET_FACTOR: 0x8038,\r\n TEXTURE_BINDING_2D: 0x8069,\r\n SAMPLE_BUFFERS: 0x80a8,\r\n SAMPLES: 0x80a9,\r\n SAMPLE_COVERAGE_VALUE: 0x80aa,\r\n SAMPLE_COVERAGE_INVERT: 0x80ab,\r\n COMPRESSED_TEXTURE_FORMATS: 0x86a3,\r\n DONT_CARE: 0x1100,\r\n FASTEST: 0x1101,\r\n NICEST: 0x1102,\r\n GENERATE_MIPMAP_HINT: 0x8192,\r\n BYTE: 0x1400,\r\n UNSIGNED_BYTE: 0x1401,\r\n SHORT: 0x1402,\r\n UNSIGNED_SHORT: 0x1403,\r\n INT: 0x1404,\r\n UNSIGNED_INT: 0x1405,\r\n FLOAT: 0x1406,\r\n DEPTH_COMPONENT: 0x1902,\r\n ALPHA: 0x1906,\r\n RGB: 0x1907,\r\n RGBA: 0x1908,\r\n LUMINANCE: 0x1909,\r\n LUMINANCE_ALPHA: 0x190a,\r\n UNSIGNED_SHORT_4_4_4_4: 0x8033,\r\n UNSIGNED_SHORT_5_5_5_1: 0x8034,\r\n UNSIGNED_SHORT_5_6_5: 0x8363,\r\n FRAGMENT_SHADER: 0x8b30,\r\n VERTEX_SHADER: 0x8b31,\r\n MAX_VERTEX_ATTRIBS: 0x8869,\r\n MAX_VERTEX_UNIFORM_VECTORS: 0x8dfb,\r\n MAX_VARYING_VECTORS: 0x8dfc,\r\n MAX_COMBINED_TEXTURE_IMAGE_UNITS: 0x8b4d,\r\n MAX_VERTEX_TEXTURE_IMAGE_UNITS: 0x8b4c,\r\n MAX_TEXTURE_IMAGE_UNITS: 0x8872,\r\n MAX_FRAGMENT_UNIFORM_VECTORS: 0x8dfd,\r\n SHADER_TYPE: 0x8b4f,\r\n DELETE_STATUS: 0x8b80,\r\n LINK_STATUS: 0x8b82,\r\n VALIDATE_STATUS: 0x8b83,\r\n ATTACHED_SHADERS: 0x8b85,\r\n ACTIVE_UNIFORMS: 0x8b86,\r\n ACTIVE_ATTRIBUTES: 0x8b89,\r\n SHADING_LANGUAGE_VERSION: 0x8b8c,\r\n CURRENT_PROGRAM: 0x8b8d,\r\n NEVER: 0x0200,\r\n LESS: 0x0201,\r\n EQUAL: 0x0202,\r\n LEQUAL: 0x0203,\r\n GREATER: 0x0204,\r\n NOTEQUAL: 0x0205,\r\n GEQUAL: 0x0206,\r\n ALWAYS: 0x0207,\r\n KEEP: 0x1e00,\r\n REPLACE: 0x1e01,\r\n INCR: 0x1e02,\r\n DECR: 0x1e03,\r\n INVERT: 0x150a,\r\n INCR_WRAP: 0x8507,\r\n DECR_WRAP: 0x8508,\r\n VENDOR: 0x1f00,\r\n RENDERER: 0x1f01,\r\n VERSION: 0x1f02,\r\n NEAREST: 0x2600,\r\n LINEAR: 0x2601,\r\n NEAREST_MIPMAP_NEAREST: 0x2700,\r\n LINEAR_MIPMAP_NEAREST: 0x2701,\r\n NEAREST_MIPMAP_LINEAR: 0x2702,\r\n LINEAR_MIPMAP_LINEAR: 0x2703,\r\n TEXTURE_MAG_FILTER: 0x2800,\r\n TEXTURE_MIN_FILTER: 0x2801,\r\n TEXTURE_WRAP_S: 0x2802,\r\n TEXTURE_WRAP_T: 0x2803,\r\n TEXTURE_2D: 0x0de1,\r\n TEXTURE: 0x1702,\r\n TEXTURE_CUBE_MAP: 0x8513,\r\n TEXTURE_BINDING_CUBE_MAP: 0x8514,\r\n TEXTURE_CUBE_MAP_POSITIVE_X: 0x8515,\r\n TEXTURE_CUBE_MAP_NEGATIVE_X: 0x8516,\r\n TEXTURE_CUBE_MAP_POSITIVE_Y: 0x8517,\r\n TEXTURE_CUBE_MAP_NEGATIVE_Y: 0x8518,\r\n TEXTURE_CUBE_MAP_POSITIVE_Z: 0x8519,\r\n TEXTURE_CUBE_MAP_NEGATIVE_Z: 0x851a,\r\n MAX_CUBE_MAP_TEXTURE_SIZE: 0x851c,\r\n TEXTURE0: 0x84c0,\r\n TEXTURE1: 0x84c1,\r\n TEXTURE2: 0x84c2,\r\n TEXTURE3: 0x84c3,\r\n TEXTURE4: 0x84c4,\r\n TEXTURE5: 0x84c5,\r\n TEXTURE6: 0x84c6,\r\n TEXTURE7: 0x84c7,\r\n TEXTURE8: 0x84c8,\r\n TEXTURE9: 0x84c9,\r\n TEXTURE10: 0x84ca,\r\n TEXTURE11: 0x84cb,\r\n TEXTURE12: 0x84cc,\r\n TEXTURE13: 0x84cd,\r\n TEXTURE14: 0x84ce,\r\n TEXTURE15: 0x84cf,\r\n TEXTURE16: 0x84d0,\r\n TEXTURE17: 0x84d1,\r\n TEXTURE18: 0x84d2,\r\n TEXTURE19: 0x84d3,\r\n TEXTURE20: 0x84d4,\r\n TEXTURE21: 0x84d5,\r\n TEXTURE22: 0x84d6,\r\n TEXTURE23: 0x84d7,\r\n TEXTURE24: 0x84d8,\r\n TEXTURE25: 0x84d9,\r\n TEXTURE26: 0x84da,\r\n TEXTURE27: 0x84db,\r\n TEXTURE28: 0x84dc,\r\n TEXTURE29: 0x84dd,\r\n TEXTURE30: 0x84de,\r\n TEXTURE31: 0x84df,\r\n ACTIVE_TEXTURE: 0x84e0,\r\n REPEAT: 0x2901,\r\n CLAMP_TO_EDGE: 0x812f,\r\n MIRRORED_REPEAT: 0x8370,\r\n FLOAT_VEC2: 0x8b50,\r\n FLOAT_VEC3: 0x8b51,\r\n FLOAT_VEC4: 0x8b52,\r\n INT_VEC2: 0x8b53,\r\n INT_VEC3: 0x8b54,\r\n INT_VEC4: 0x8b55,\r\n BOOL: 0x8b56,\r\n BOOL_VEC2: 0x8b57,\r\n BOOL_VEC3: 0x8b58,\r\n BOOL_VEC4: 0x8b59,\r\n FLOAT_MAT2: 0x8b5a,\r\n FLOAT_MAT3: 0x8b5b,\r\n FLOAT_MAT4: 0x8b5c,\r\n SAMPLER_2D: 0x8b5e,\r\n SAMPLER_CUBE: 0x8b60,\r\n VERTEX_ATTRIB_ARRAY_ENABLED: 0x8622,\r\n VERTEX_ATTRIB_ARRAY_SIZE: 0x8623,\r\n VERTEX_ATTRIB_ARRAY_STRIDE: 0x8624,\r\n VERTEX_ATTRIB_ARRAY_TYPE: 0x8625,\r\n VERTEX_ATTRIB_ARRAY_NORMALIZED: 0x886a,\r\n VERTEX_ATTRIB_ARRAY_POINTER: 0x8645,\r\n VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 0x889f,\r\n IMPLEMENTATION_COLOR_READ_TYPE: 0x8b9a,\r\n IMPLEMENTATION_COLOR_READ_FORMAT: 0x8b9b,\r\n COMPILE_STATUS: 0x8b81,\r\n LOW_FLOAT: 0x8df0,\r\n MEDIUM_FLOAT: 0x8df1,\r\n HIGH_FLOAT: 0x8df2,\r\n LOW_INT: 0x8df3,\r\n MEDIUM_INT: 0x8df4,\r\n HIGH_INT: 0x8df5,\r\n FRAMEBUFFER: 0x8d40,\r\n RENDERBUFFER: 0x8d41,\r\n RGBA4: 0x8056,\r\n RGB5_A1: 0x8057,\r\n RGB565: 0x8d62,\r\n DEPTH_COMPONENT16: 0x81a5,\r\n STENCIL_INDEX: 0x1901,\r\n STENCIL_INDEX8: 0x8d48,\r\n DEPTH_STENCIL: 0x84f9,\r\n RENDERBUFFER_WIDTH: 0x8d42,\r\n RENDERBUFFER_HEIGHT: 0x8d43,\r\n RENDERBUFFER_INTERNAL_FORMAT: 0x8d44,\r\n RENDERBUFFER_RED_SIZE: 0x8d50,\r\n RENDERBUFFER_GREEN_SIZE: 0x8d51,\r\n RENDERBUFFER_BLUE_SIZE: 0x8d52,\r\n RENDERBUFFER_ALPHA_SIZE: 0x8d53,\r\n RENDERBUFFER_DEPTH_SIZE: 0x8d54,\r\n RENDERBUFFER_STENCIL_SIZE: 0x8d55,\r\n FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 0x8cd0,\r\n FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 0x8cd1,\r\n FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 0x8cd2,\r\n FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 0x8cd3,\r\n COLOR_ATTACHMENT0: 0x8ce0,\r\n DEPTH_ATTACHMENT: 0x8d00,\r\n STENCIL_ATTACHMENT: 0x8d20,\r\n DEPTH_STENCIL_ATTACHMENT: 0x821a,\r\n NONE: 0,\r\n FRAMEBUFFER_COMPLETE: 0x8cd5,\r\n FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 0x8cd6,\r\n FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 0x8cd7,\r\n FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 0x8cd9,\r\n FRAMEBUFFER_UNSUPPORTED: 0x8cdd,\r\n FRAMEBUFFER_BINDING: 0x8ca6,\r\n RENDERBUFFER_BINDING: 0x8ca7,\r\n MAX_RENDERBUFFER_SIZE: 0x84e8,\r\n INVALID_FRAMEBUFFER_OPERATION: 0x0506,\r\n UNPACK_FLIP_Y_WEBGL: 0x9240,\r\n UNPACK_PREMULTIPLY_ALPHA_WEBGL: 0x9241,\r\n CONTEXT_LOST_WEBGL: 0x9242,\r\n UNPACK_COLORSPACE_CONVERSION_WEBGL: 0x9243,\r\n BROWSER_DEFAULT_WEBGL: 0x9244,\r\n\r\n // WEBGL_compressed_texture_s3tc\r\n COMPRESSED_RGB_S3TC_DXT1_EXT: 0x83f0,\r\n COMPRESSED_RGBA_S3TC_DXT1_EXT: 0x83f1,\r\n COMPRESSED_RGBA_S3TC_DXT3_EXT: 0x83f2,\r\n COMPRESSED_RGBA_S3TC_DXT5_EXT: 0x83f3,\r\n\r\n // WEBGL_compressed_texture_pvrtc\r\n COMPRESSED_RGB_PVRTC_4BPPV1_IMG: 0x8c00,\r\n COMPRESSED_RGB_PVRTC_2BPPV1_IMG: 0x8c01,\r\n COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: 0x8c02,\r\n COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: 0x8c03,\r\n\r\n // WEBGL_compressed_texture_etc1\r\n COMPRESSED_RGB_ETC1_WEBGL: 0x8d64,\r\n\r\n // EXT_color_buffer_half_float\r\n HALF_FLOAT_OES: 0x8d61,\r\n\r\n // Desktop OpenGL\r\n DOUBLE: 0x140a,\r\n\r\n // WebGL 2\r\n READ_BUFFER: 0x0c02,\r\n UNPACK_ROW_LENGTH: 0x0cf2,\r\n UNPACK_SKIP_ROWS: 0x0cf3,\r\n UNPACK_SKIP_PIXELS: 0x0cf4,\r\n PACK_ROW_LENGTH: 0x0d02,\r\n PACK_SKIP_ROWS: 0x0d03,\r\n PACK_SKIP_PIXELS: 0x0d04,\r\n COLOR: 0x1800,\r\n DEPTH: 0x1801,\r\n STENCIL: 0x1802,\r\n RED: 0x1903,\r\n RGB8: 0x8051,\r\n RGBA8: 0x8058,\r\n RGB10_A2: 0x8059,\r\n TEXTURE_BINDING_3D: 0x806a,\r\n UNPACK_SKIP_IMAGES: 0x806d,\r\n UNPACK_IMAGE_HEIGHT: 0x806e,\r\n TEXTURE_3D: 0x806f,\r\n TEXTURE_WRAP_R: 0x8072,\r\n MAX_3D_TEXTURE_SIZE: 0x8073,\r\n UNSIGNED_INT_2_10_10_10_REV: 0x8368,\r\n MAX_ELEMENTS_VERTICES: 0x80e8,\r\n MAX_ELEMENTS_INDICES: 0x80e9,\r\n TEXTURE_MIN_LOD: 0x813a,\r\n TEXTURE_MAX_LOD: 0x813b,\r\n TEXTURE_BASE_LEVEL: 0x813c,\r\n TEXTURE_MAX_LEVEL: 0x813d,\r\n MIN: 0x8007,\r\n MAX: 0x8008,\r\n DEPTH_COMPONENT24: 0x81a6,\r\n MAX_TEXTURE_LOD_BIAS: 0x84fd,\r\n TEXTURE_COMPARE_MODE: 0x884c,\r\n TEXTURE_COMPARE_FUNC: 0x884d,\r\n CURRENT_QUERY: 0x8865,\r\n QUERY_RESULT: 0x8866,\r\n QUERY_RESULT_AVAILABLE: 0x8867,\r\n STREAM_READ: 0x88e1,\r\n STREAM_COPY: 0x88e2,\r\n STATIC_READ: 0x88e5,\r\n STATIC_COPY: 0x88e6,\r\n DYNAMIC_READ: 0x88e9,\r\n DYNAMIC_COPY: 0x88ea,\r\n MAX_DRAW_BUFFERS: 0x8824,\r\n DRAW_BUFFER0: 0x8825,\r\n DRAW_BUFFER1: 0x8826,\r\n DRAW_BUFFER2: 0x8827,\r\n DRAW_BUFFER3: 0x8828,\r\n DRAW_BUFFER4: 0x8829,\r\n DRAW_BUFFER5: 0x882a,\r\n DRAW_BUFFER6: 0x882b,\r\n DRAW_BUFFER7: 0x882c,\r\n DRAW_BUFFER8: 0x882d,\r\n DRAW_BUFFER9: 0x882e,\r\n DRAW_BUFFER10: 0x882f,\r\n DRAW_BUFFER11: 0x8830,\r\n DRAW_BUFFER12: 0x8831,\r\n DRAW_BUFFER13: 0x8832,\r\n DRAW_BUFFER14: 0x8833,\r\n DRAW_BUFFER15: 0x8834,\r\n MAX_FRAGMENT_UNIFORM_COMPONENTS: 0x8b49,\r\n MAX_VERTEX_UNIFORM_COMPONENTS: 0x8b4a,\r\n SAMPLER_3D: 0x8b5f,\r\n SAMPLER_2D_SHADOW: 0x8b62,\r\n FRAGMENT_SHADER_DERIVATIVE_HINT: 0x8b8b,\r\n PIXEL_PACK_BUFFER: 0x88eb,\r\n PIXEL_UNPACK_BUFFER: 0x88ec,\r\n PIXEL_PACK_BUFFER_BINDING: 0x88ed,\r\n PIXEL_UNPACK_BUFFER_BINDING: 0x88ef,\r\n FLOAT_MAT2x3: 0x8b65,\r\n FLOAT_MAT2x4: 0x8b66,\r\n FLOAT_MAT3x2: 0x8b67,\r\n FLOAT_MAT3x4: 0x8b68,\r\n FLOAT_MAT4x2: 0x8b69,\r\n FLOAT_MAT4x3: 0x8b6a,\r\n SRGB: 0x8c40,\r\n SRGB8: 0x8c41,\r\n SRGB8_ALPHA8: 0x8c43,\r\n COMPARE_REF_TO_TEXTURE: 0x884e,\r\n RGBA32F: 0x8814,\r\n RGB32F: 0x8815,\r\n RGBA16F: 0x881a,\r\n RGB16F: 0x881b,\r\n VERTEX_ATTRIB_ARRAY_INTEGER: 0x88fd,\r\n MAX_ARRAY_TEXTURE_LAYERS: 0x88ff,\r\n MIN_PROGRAM_TEXEL_OFFSET: 0x8904,\r\n MAX_PROGRAM_TEXEL_OFFSET: 0x8905,\r\n MAX_VARYING_COMPONENTS: 0x8b4b,\r\n TEXTURE_2D_ARRAY: 0x8c1a,\r\n TEXTURE_BINDING_2D_ARRAY: 0x8c1d,\r\n R11F_G11F_B10F: 0x8c3a,\r\n UNSIGNED_INT_10F_11F_11F_REV: 0x8c3b,\r\n RGB9_E5: 0x8c3d,\r\n UNSIGNED_INT_5_9_9_9_REV: 0x8c3e,\r\n TRANSFORM_FEEDBACK_BUFFER_MODE: 0x8c7f,\r\n MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: 0x8c80,\r\n TRANSFORM_FEEDBACK_VARYINGS: 0x8c83,\r\n TRANSFORM_FEEDBACK_BUFFER_START: 0x8c84,\r\n TRANSFORM_FEEDBACK_BUFFER_SIZE: 0x8c85,\r\n TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: 0x8c88,\r\n RASTERIZER_DISCARD: 0x8c89,\r\n MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: 0x8c8a,\r\n MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: 0x8c8b,\r\n INTERLEAVED_ATTRIBS: 0x8c8c,\r\n SEPARATE_ATTRIBS: 0x8c8d,\r\n TRANSFORM_FEEDBACK_BUFFER: 0x8c8e,\r\n TRANSFORM_FEEDBACK_BUFFER_BINDING: 0x8c8f,\r\n RGBA32UI: 0x8d70,\r\n RGB32UI: 0x8d71,\r\n RGBA16UI: 0x8d76,\r\n RGB16UI: 0x8d77,\r\n RGBA8UI: 0x8d7c,\r\n RGB8UI: 0x8d7d,\r\n RGBA32I: 0x8d82,\r\n RGB32I: 0x8d83,\r\n RGBA16I: 0x8d88,\r\n RGB16I: 0x8d89,\r\n RGBA8I: 0x8d8e,\r\n RGB8I: 0x8d8f,\r\n RED_INTEGER: 0x8d94,\r\n RGB_INTEGER: 0x8d98,\r\n RGBA_INTEGER: 0x8d99,\r\n SAMPLER_2D_ARRAY: 0x8dc1,\r\n SAMPLER_2D_ARRAY_SHADOW: 0x8dc4,\r\n SAMPLER_CUBE_SHADOW: 0x8dc5,\r\n UNSIGNED_INT_VEC2: 0x8dc6,\r\n UNSIGNED_INT_VEC3: 0x8dc7,\r\n UNSIGNED_INT_VEC4: 0x8dc8,\r\n INT_SAMPLER_2D: 0x8dca,\r\n INT_SAMPLER_3D: 0x8dcb,\r\n INT_SAMPLER_CUBE: 0x8dcc,\r\n INT_SAMPLER_2D_ARRAY: 0x8dcf,\r\n UNSIGNED_INT_SAMPLER_2D: 0x8dd2,\r\n UNSIGNED_INT_SAMPLER_3D: 0x8dd3,\r\n UNSIGNED_INT_SAMPLER_CUBE: 0x8dd4,\r\n UNSIGNED_INT_SAMPLER_2D_ARRAY: 0x8dd7,\r\n DEPTH_COMPONENT32F: 0x8cac,\r\n DEPTH32F_STENCIL8: 0x8cad,\r\n FLOAT_32_UNSIGNED_INT_24_8_REV: 0x8dad,\r\n FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: 0x8210,\r\n FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: 0x8211,\r\n FRAMEBUFFER_ATTACHMENT_RED_SIZE: 0x8212,\r\n FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: 0x8213,\r\n FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: 0x8214,\r\n FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: 0x8215,\r\n FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: 0x8216,\r\n FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: 0x8217,\r\n FRAMEBUFFER_DEFAULT: 0x8218,\r\n UNSIGNED_INT_24_8: 0x84fa,\r\n DEPTH24_STENCIL8: 0x88f0,\r\n UNSIGNED_NORMALIZED: 0x8c17,\r\n DRAW_FRAMEBUFFER_BINDING: 0x8ca6, // Same as FRAMEBUFFER_BINDING\r\n READ_FRAMEBUFFER: 0x8ca8,\r\n DRAW_FRAMEBUFFER: 0x8ca9,\r\n READ_FRAMEBUFFER_BINDING: 0x8caa,\r\n RENDERBUFFER_SAMPLES: 0x8cab,\r\n FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: 0x8cd4,\r\n MAX_COLOR_ATTACHMENTS: 0x8cdf,\r\n COLOR_ATTACHMENT1: 0x8ce1,\r\n COLOR_ATTACHMENT2: 0x8ce2,\r\n COLOR_ATTACHMENT3: 0x8ce3,\r\n COLOR_ATTACHMENT4: 0x8ce4,\r\n COLOR_ATTACHMENT5: 0x8ce5,\r\n COLOR_ATTACHMENT6: 0x8ce6,\r\n COLOR_ATTACHMENT7: 0x8ce7,\r\n COLOR_ATTACHMENT8: 0x8ce8,\r\n COLOR_ATTACHMENT9: 0x8ce9,\r\n COLOR_ATTACHMENT10: 0x8cea,\r\n COLOR_ATTACHMENT11: 0x8ceb,\r\n COLOR_ATTACHMENT12: 0x8cec,\r\n COLOR_ATTACHMENT13: 0x8ced,\r\n COLOR_ATTACHMENT14: 0x8cee,\r\n COLOR_ATTACHMENT15: 0x8cef,\r\n FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: 0x8d56,\r\n MAX_SAMPLES: 0x8d57,\r\n HALF_FLOAT: 0x140b,\r\n RG: 0x8227,\r\n RG_INTEGER: 0x8228,\r\n R8: 0x8229,\r\n RG8: 0x822b,\r\n R16F: 0x822d,\r\n R32F: 0x822e,\r\n RG16F: 0x822f,\r\n RG32F: 0x8230,\r\n R8I: 0x8231,\r\n R8UI: 0x8232,\r\n R16I: 0x8233,\r\n R16UI: 0x8234,\r\n R32I: 0x8235,\r\n R32UI: 0x8236,\r\n RG8I: 0x8237,\r\n RG8UI: 0x8238,\r\n RG16I: 0x8239,\r\n RG16UI: 0x823a,\r\n RG32I: 0x823b,\r\n RG32UI: 0x823c,\r\n VERTEX_ARRAY_BINDING: 0x85b5,\r\n R8_SNORM: 0x8f94,\r\n RG8_SNORM: 0x8f95,\r\n RGB8_SNORM: 0x8f96,\r\n RGBA8_SNORM: 0x8f97,\r\n SIGNED_NORMALIZED: 0x8f9c,\r\n COPY_READ_BUFFER: 0x8f36,\r\n COPY_WRITE_BUFFER: 0x8f37,\r\n COPY_READ_BUFFER_BINDING: 0x8f36, // Same as COPY_READ_BUFFER\r\n COPY_WRITE_BUFFER_BINDING: 0x8f37, // Same as COPY_WRITE_BUFFER\r\n UNIFORM_BUFFER: 0x8a11,\r\n UNIFORM_BUFFER_BINDING: 0x8a28,\r\n UNIFORM_BUFFER_START: 0x8a29,\r\n UNIFORM_BUFFER_SIZE: 0x8a2a,\r\n MAX_VERTEX_UNIFORM_BLOCKS: 0x8a2b,\r\n MAX_FRAGMENT_UNIFORM_BLOCKS: 0x8a2d,\r\n MAX_COMBINED_UNIFORM_BLOCKS: 0x8a2e,\r\n MAX_UNIFORM_BUFFER_BINDINGS: 0x8a2f,\r\n MAX_UNIFORM_BLOCK_SIZE: 0x8a30,\r\n MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: 0x8a31,\r\n MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: 0x8a33,\r\n UNIFORM_BUFFER_OFFSET_ALIGNMENT: 0x8a34,\r\n ACTIVE_UNIFORM_BLOCKS: 0x8a36,\r\n UNIFORM_TYPE: 0x8a37,\r\n UNIFORM_SIZE: 0x8a38,\r\n UNIFORM_BLOCK_INDEX: 0x8a3a,\r\n UNIFORM_OFFSET: 0x8a3b,\r\n UNIFORM_ARRAY_STRIDE: 0x8a3c,\r\n UNIFORM_MATRIX_STRIDE: 0x8a3d,\r\n UNIFORM_IS_ROW_MAJOR: 0x8a3e,\r\n UNIFORM_BLOCK_BINDING: 0x8a3f,\r\n UNIFORM_BLOCK_DATA_SIZE: 0x8a40,\r\n UNIFORM_BLOCK_ACTIVE_UNIFORMS: 0x8a42,\r\n UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: 0x8a43,\r\n UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: 0x8a44,\r\n UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: 0x8a46,\r\n INVALID_INDEX: 0xffffffff,\r\n MAX_VERTEX_OUTPUT_COMPONENTS: 0x9122,\r\n MAX_FRAGMENT_INPUT_COMPONENTS: 0x9125,\r\n MAX_SERVER_WAIT_TIMEOUT: 0x9111,\r\n OBJECT_TYPE: 0x9112,\r\n SYNC_CONDITION: 0x9113,\r\n SYNC_STATUS: 0x9114,\r\n SYNC_FLAGS: 0x9115,\r\n SYNC_FENCE: 0x9116,\r\n SYNC_GPU_COMMANDS_COMPLETE: 0x9117,\r\n UNSIGNALED: 0x9118,\r\n SIGNALED: 0x9119,\r\n ALREADY_SIGNALED: 0x911a,\r\n TIMEOUT_EXPIRED: 0x911b,\r\n CONDITION_SATISFIED: 0x911c,\r\n WAIT_FAILED: 0x911d,\r\n SYNC_FLUSH_COMMANDS_BIT: 0x00000001,\r\n VERTEX_ATTRIB_ARRAY_DIVISOR: 0x88fe,\r\n ANY_SAMPLES_PASSED: 0x8c2f,\r\n ANY_SAMPLES_PASSED_CONSERVATIVE: 0x8d6a,\r\n SAMPLER_BINDING: 0x8919,\r\n RGB10_A2UI: 0x906f,\r\n INT_2_10_10_10_REV: 0x8d9f,\r\n TRANSFORM_FEEDBACK: 0x8e22,\r\n TRANSFORM_FEEDBACK_PAUSED: 0x8e23,\r\n TRANSFORM_FEEDBACK_ACTIVE: 0x8e24,\r\n TRANSFORM_FEEDBACK_BINDING: 0x8e25,\r\n COMPRESSED_R11_EAC: 0x9270,\r\n COMPRESSED_SIGNED_R11_EAC: 0x9271,\r\n COMPRESSED_RG11_EAC: 0x9272,\r\n COMPRESSED_SIGNED_RG11_EAC: 0x9273,\r\n COMPRESSED_RGB8_ETC2: 0x9274,\r\n COMPRESSED_SRGB8_ETC2: 0x9275,\r\n COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 0x9276,\r\n COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 0x9277,\r\n COMPRESSED_RGBA8_ETC2_EAC: 0x9278,\r\n COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 0x9279,\r\n TEXTURE_IMMUTABLE_FORMAT: 0x912f,\r\n MAX_ELEMENT_INDEX: 0x8d6b,\r\n TEXTURE_IMMUTABLE_LEVELS: 0x82df,\r\n\r\n // Extensions\r\n MAX_TEXTURE_MAX_ANISOTROPY_EXT: 0x84ff,\r\n};\r\nexport default Object.freeze(WebGLConstants);\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport WebGLConstants from \"./WebGLConstants.js\";\r\n\r\n/**\r\n * WebGL component datatypes. Components are intrinsics,\r\n * which form attributes, which form vertices.\r\n *\r\n * @enum {Number}\r\n */\r\nvar ComponentDatatype = {\r\n /**\r\n * 8-bit signed byte corresponding to gl.BYTE and the type\r\n * of an element in Int8Array.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n BYTE: WebGLConstants.BYTE,\r\n\r\n /**\r\n * 8-bit unsigned byte corresponding to UNSIGNED_BYTE and the type\r\n * of an element in Uint8Array.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n UNSIGNED_BYTE: WebGLConstants.UNSIGNED_BYTE,\r\n\r\n /**\r\n * 16-bit signed short corresponding to SHORT and the type\r\n * of an element in Int16Array.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SHORT: WebGLConstants.SHORT,\r\n\r\n /**\r\n * 16-bit unsigned short corresponding to UNSIGNED_SHORT and the type\r\n * of an element in Uint16Array.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n UNSIGNED_SHORT: WebGLConstants.UNSIGNED_SHORT,\r\n\r\n /**\r\n * 32-bit signed int corresponding to INT and the type\r\n * of an element in Int32Array.\r\n *\r\n * @memberOf ComponentDatatype\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n INT: WebGLConstants.INT,\r\n\r\n /**\r\n * 32-bit unsigned int corresponding to UNSIGNED_INT and the type\r\n * of an element in Uint32Array.\r\n *\r\n * @memberOf ComponentDatatype\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n UNSIGNED_INT: WebGLConstants.UNSIGNED_INT,\r\n\r\n /**\r\n * 32-bit floating-point corresponding to FLOAT and the type\r\n * of an element in Float32Array.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n FLOAT: WebGLConstants.FLOAT,\r\n\r\n /**\r\n * 64-bit floating-point corresponding to gl.DOUBLE (in Desktop OpenGL;\r\n * this is not supported in WebGL, and is emulated in Cesium via {@link GeometryPipeline.encodeAttribute})\r\n * and the type of an element in Float64Array.\r\n *\r\n * @memberOf ComponentDatatype\r\n *\r\n * @type {Number}\r\n * @constant\r\n * @default 0x140A\r\n */\r\n DOUBLE: WebGLConstants.DOUBLE,\r\n};\r\n\r\n/**\r\n * Returns the size, in bytes, of the corresponding datatype.\r\n *\r\n * @param {ComponentDatatype} componentDatatype The component datatype to get the size of.\r\n * @returns {Number} The size in bytes.\r\n *\r\n * @exception {DeveloperError} componentDatatype is not a valid value.\r\n *\r\n * @example\r\n * // Returns Int8Array.BYTES_PER_ELEMENT\r\n * var size = Cesium.ComponentDatatype.getSizeInBytes(Cesium.ComponentDatatype.BYTE);\r\n */\r\nComponentDatatype.getSizeInBytes = function (componentDatatype) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(componentDatatype)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n switch (componentDatatype) {\r\n case ComponentDatatype.BYTE:\r\n return Int8Array.BYTES_PER_ELEMENT;\r\n case ComponentDatatype.UNSIGNED_BYTE:\r\n return Uint8Array.BYTES_PER_ELEMENT;\r\n case ComponentDatatype.SHORT:\r\n return Int16Array.BYTES_PER_ELEMENT;\r\n case ComponentDatatype.UNSIGNED_SHORT:\r\n return Uint16Array.BYTES_PER_ELEMENT;\r\n case ComponentDatatype.INT:\r\n return Int32Array.BYTES_PER_ELEMENT;\r\n case ComponentDatatype.UNSIGNED_INT:\r\n return Uint32Array.BYTES_PER_ELEMENT;\r\n case ComponentDatatype.FLOAT:\r\n return Float32Array.BYTES_PER_ELEMENT;\r\n case ComponentDatatype.DOUBLE:\r\n return Float64Array.BYTES_PER_ELEMENT;\r\n //>>includeStart('debug', pragmas.debug);\r\n default:\r\n throw new DeveloperError(\"componentDatatype is not a valid value.\");\r\n //>>includeEnd('debug');\r\n }\r\n};\r\n\r\n/**\r\n * Gets the {@link ComponentDatatype} for the provided TypedArray instance.\r\n *\r\n * @param {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} array The typed array.\r\n * @returns {ComponentDatatype} The ComponentDatatype for the provided array, or undefined if the array is not a TypedArray.\r\n */\r\nComponentDatatype.fromTypedArray = function (array) {\r\n if (array instanceof Int8Array) {\r\n return ComponentDatatype.BYTE;\r\n }\r\n if (array instanceof Uint8Array) {\r\n return ComponentDatatype.UNSIGNED_BYTE;\r\n }\r\n if (array instanceof Int16Array) {\r\n return ComponentDatatype.SHORT;\r\n }\r\n if (array instanceof Uint16Array) {\r\n return ComponentDatatype.UNSIGNED_SHORT;\r\n }\r\n if (array instanceof Int32Array) {\r\n return ComponentDatatype.INT;\r\n }\r\n if (array instanceof Uint32Array) {\r\n return ComponentDatatype.UNSIGNED_INT;\r\n }\r\n if (array instanceof Float32Array) {\r\n return ComponentDatatype.FLOAT;\r\n }\r\n if (array instanceof Float64Array) {\r\n return ComponentDatatype.DOUBLE;\r\n }\r\n};\r\n\r\n/**\r\n * Validates that the provided component datatype is a valid {@link ComponentDatatype}\r\n *\r\n * @param {ComponentDatatype} componentDatatype The component datatype to validate.\r\n * @returns {Boolean} true if the provided component datatype is a valid value; otherwise, false.\r\n *\r\n * @example\r\n * if (!Cesium.ComponentDatatype.validate(componentDatatype)) {\r\n * throw new Cesium.DeveloperError('componentDatatype must be a valid value.');\r\n * }\r\n */\r\nComponentDatatype.validate = function (componentDatatype) {\r\n return (\r\n defined(componentDatatype) &&\r\n (componentDatatype === ComponentDatatype.BYTE ||\r\n componentDatatype === ComponentDatatype.UNSIGNED_BYTE ||\r\n componentDatatype === ComponentDatatype.SHORT ||\r\n componentDatatype === ComponentDatatype.UNSIGNED_SHORT ||\r\n componentDatatype === ComponentDatatype.INT ||\r\n componentDatatype === ComponentDatatype.UNSIGNED_INT ||\r\n componentDatatype === ComponentDatatype.FLOAT ||\r\n componentDatatype === ComponentDatatype.DOUBLE)\r\n );\r\n};\r\n\r\n/**\r\n * Creates a typed array corresponding to component data type.\r\n *\r\n * @param {ComponentDatatype} componentDatatype The component data type.\r\n * @param {Number|Array} valuesOrLength The length of the array to create or an array.\r\n * @returns {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} A typed array.\r\n *\r\n * @exception {DeveloperError} componentDatatype is not a valid value.\r\n *\r\n * @example\r\n * // creates a Float32Array with length of 100\r\n * var typedArray = Cesium.ComponentDatatype.createTypedArray(Cesium.ComponentDatatype.FLOAT, 100);\r\n */\r\nComponentDatatype.createTypedArray = function (\r\n componentDatatype,\r\n valuesOrLength\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(componentDatatype)) {\r\n throw new DeveloperError(\"componentDatatype is required.\");\r\n }\r\n if (!defined(valuesOrLength)) {\r\n throw new DeveloperError(\"valuesOrLength is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n switch (componentDatatype) {\r\n case ComponentDatatype.BYTE:\r\n return new Int8Array(valuesOrLength);\r\n case ComponentDatatype.UNSIGNED_BYTE:\r\n return new Uint8Array(valuesOrLength);\r\n case ComponentDatatype.SHORT:\r\n return new Int16Array(valuesOrLength);\r\n case ComponentDatatype.UNSIGNED_SHORT:\r\n return new Uint16Array(valuesOrLength);\r\n case ComponentDatatype.INT:\r\n return new Int32Array(valuesOrLength);\r\n case ComponentDatatype.UNSIGNED_INT:\r\n return new Uint32Array(valuesOrLength);\r\n case ComponentDatatype.FLOAT:\r\n return new Float32Array(valuesOrLength);\r\n case ComponentDatatype.DOUBLE:\r\n return new Float64Array(valuesOrLength);\r\n //>>includeStart('debug', pragmas.debug);\r\n default:\r\n throw new DeveloperError(\"componentDatatype is not a valid value.\");\r\n //>>includeEnd('debug');\r\n }\r\n};\r\n\r\n/**\r\n * Creates a typed view of an array of bytes.\r\n *\r\n * @param {ComponentDatatype} componentDatatype The type of the view to create.\r\n * @param {ArrayBuffer} buffer The buffer storage to use for the view.\r\n * @param {Number} [byteOffset] The offset, in bytes, to the first element in the view.\r\n * @param {Number} [length] The number of elements in the view.\r\n * @returns {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} A typed array view of the buffer.\r\n *\r\n * @exception {DeveloperError} componentDatatype is not a valid value.\r\n */\r\nComponentDatatype.createArrayBufferView = function (\r\n componentDatatype,\r\n buffer,\r\n byteOffset,\r\n length\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(componentDatatype)) {\r\n throw new DeveloperError(\"componentDatatype is required.\");\r\n }\r\n if (!defined(buffer)) {\r\n throw new DeveloperError(\"buffer is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n byteOffset = defaultValue(byteOffset, 0);\r\n length = defaultValue(\r\n length,\r\n (buffer.byteLength - byteOffset) /\r\n ComponentDatatype.getSizeInBytes(componentDatatype)\r\n );\r\n\r\n switch (componentDatatype) {\r\n case ComponentDatatype.BYTE:\r\n return new Int8Array(buffer, byteOffset, length);\r\n case ComponentDatatype.UNSIGNED_BYTE:\r\n return new Uint8Array(buffer, byteOffset, length);\r\n case ComponentDatatype.SHORT:\r\n return new Int16Array(buffer, byteOffset, length);\r\n case ComponentDatatype.UNSIGNED_SHORT:\r\n return new Uint16Array(buffer, byteOffset, length);\r\n case ComponentDatatype.INT:\r\n return new Int32Array(buffer, byteOffset, length);\r\n case ComponentDatatype.UNSIGNED_INT:\r\n return new Uint32Array(buffer, byteOffset, length);\r\n case ComponentDatatype.FLOAT:\r\n return new Float32Array(buffer, byteOffset, length);\r\n case ComponentDatatype.DOUBLE:\r\n return new Float64Array(buffer, byteOffset, length);\r\n //>>includeStart('debug', pragmas.debug);\r\n default:\r\n throw new DeveloperError(\"componentDatatype is not a valid value.\");\r\n //>>includeEnd('debug');\r\n }\r\n};\r\n\r\n/**\r\n * Get the ComponentDatatype from its name.\r\n *\r\n * @param {String} name The name of the ComponentDatatype.\r\n * @returns {ComponentDatatype} The ComponentDatatype.\r\n *\r\n * @exception {DeveloperError} name is not a valid value.\r\n */\r\nComponentDatatype.fromName = function (name) {\r\n switch (name) {\r\n case \"BYTE\":\r\n return ComponentDatatype.BYTE;\r\n case \"UNSIGNED_BYTE\":\r\n return ComponentDatatype.UNSIGNED_BYTE;\r\n case \"SHORT\":\r\n return ComponentDatatype.SHORT;\r\n case \"UNSIGNED_SHORT\":\r\n return ComponentDatatype.UNSIGNED_SHORT;\r\n case \"INT\":\r\n return ComponentDatatype.INT;\r\n case \"UNSIGNED_INT\":\r\n return ComponentDatatype.UNSIGNED_INT;\r\n case \"FLOAT\":\r\n return ComponentDatatype.FLOAT;\r\n case \"DOUBLE\":\r\n return ComponentDatatype.DOUBLE;\r\n //>>includeStart('debug', pragmas.debug);\r\n default:\r\n throw new DeveloperError(\"name is not a valid value.\");\r\n //>>includeEnd('debug');\r\n }\r\n};\r\nexport default Object.freeze(ComponentDatatype);\r\n","/**\r\n * This enumerated type is used to determine how the vertices of the terrain mesh are compressed.\r\n *\r\n * @enum {Number}\r\n *\r\n * @private\r\n */\r\nvar TerrainQuantization = {\r\n /**\r\n * The vertices are not compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NONE: 0,\r\n\r\n /**\r\n * The vertices are compressed to 12 bits.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n BITS12: 1,\r\n};\r\nexport default Object.freeze(TerrainQuantization);\r\n","import AttributeCompression from \"./AttributeCompression.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport TerrainQuantization from \"./TerrainQuantization.js\";\r\n\r\nvar cartesian3Scratch = new Cartesian3();\r\nvar cartesian3DimScratch = new Cartesian3();\r\nvar cartesian2Scratch = new Cartesian2();\r\nvar matrix4Scratch = new Matrix4();\r\nvar matrix4Scratch2 = new Matrix4();\r\n\r\nvar SHIFT_LEFT_12 = Math.pow(2.0, 12.0);\r\n\r\n/**\r\n * Data used to quantize and pack the terrain mesh. The position can be unpacked for picking and all attributes\r\n * are unpacked in the vertex shader.\r\n *\r\n * @alias TerrainEncoding\r\n * @constructor\r\n *\r\n * @param {AxisAlignedBoundingBox} axisAlignedBoundingBox The bounds of the tile in the east-north-up coordinates at the tiles center.\r\n * @param {Number} minimumHeight The minimum height.\r\n * @param {Number} maximumHeight The maximum height.\r\n * @param {Matrix4} fromENU The east-north-up to fixed frame matrix at the center of the terrain mesh.\r\n * @param {Boolean} hasVertexNormals If the mesh has vertex normals.\r\n * @param {Boolean} [hasWebMercatorT=false] true if the terrain data includes a Web Mercator texture coordinate; otherwise, false.\r\n *\r\n * @private\r\n */\r\nfunction TerrainEncoding(\r\n axisAlignedBoundingBox,\r\n minimumHeight,\r\n maximumHeight,\r\n fromENU,\r\n hasVertexNormals,\r\n hasWebMercatorT\r\n) {\r\n var quantization = TerrainQuantization.NONE;\r\n var center;\r\n var toENU;\r\n var matrix;\r\n\r\n if (\r\n defined(axisAlignedBoundingBox) &&\r\n defined(minimumHeight) &&\r\n defined(maximumHeight) &&\r\n defined(fromENU)\r\n ) {\r\n var minimum = axisAlignedBoundingBox.minimum;\r\n var maximum = axisAlignedBoundingBox.maximum;\r\n\r\n var dimensions = Cartesian3.subtract(\r\n maximum,\r\n minimum,\r\n cartesian3DimScratch\r\n );\r\n var hDim = maximumHeight - minimumHeight;\r\n var maxDim = Math.max(Cartesian3.maximumComponent(dimensions), hDim);\r\n\r\n if (maxDim < SHIFT_LEFT_12 - 1.0) {\r\n quantization = TerrainQuantization.BITS12;\r\n } else {\r\n quantization = TerrainQuantization.NONE;\r\n }\r\n\r\n center = axisAlignedBoundingBox.center;\r\n toENU = Matrix4.inverseTransformation(fromENU, new Matrix4());\r\n\r\n var translation = Cartesian3.negate(minimum, cartesian3Scratch);\r\n Matrix4.multiply(\r\n Matrix4.fromTranslation(translation, matrix4Scratch),\r\n toENU,\r\n toENU\r\n );\r\n\r\n var scale = cartesian3Scratch;\r\n scale.x = 1.0 / dimensions.x;\r\n scale.y = 1.0 / dimensions.y;\r\n scale.z = 1.0 / dimensions.z;\r\n Matrix4.multiply(Matrix4.fromScale(scale, matrix4Scratch), toENU, toENU);\r\n\r\n matrix = Matrix4.clone(fromENU);\r\n Matrix4.setTranslation(matrix, Cartesian3.ZERO, matrix);\r\n\r\n fromENU = Matrix4.clone(fromENU, new Matrix4());\r\n\r\n var translationMatrix = Matrix4.fromTranslation(minimum, matrix4Scratch);\r\n var scaleMatrix = Matrix4.fromScale(dimensions, matrix4Scratch2);\r\n var st = Matrix4.multiply(translationMatrix, scaleMatrix, matrix4Scratch);\r\n\r\n Matrix4.multiply(fromENU, st, fromENU);\r\n Matrix4.multiply(matrix, st, matrix);\r\n }\r\n\r\n /**\r\n * How the vertices of the mesh were compressed.\r\n * @type {TerrainQuantization}\r\n */\r\n this.quantization = quantization;\r\n\r\n /**\r\n * The minimum height of the tile including the skirts.\r\n * @type {Number}\r\n */\r\n this.minimumHeight = minimumHeight;\r\n\r\n /**\r\n * The maximum height of the tile.\r\n * @type {Number}\r\n */\r\n this.maximumHeight = maximumHeight;\r\n\r\n /**\r\n * The center of the tile.\r\n * @type {Cartesian3}\r\n */\r\n this.center = center;\r\n\r\n /**\r\n * A matrix that takes a vertex from the tile, transforms it to east-north-up at the center and scales\r\n * it so each component is in the [0, 1] range.\r\n * @type {Matrix4}\r\n */\r\n this.toScaledENU = toENU;\r\n\r\n /**\r\n * A matrix that restores a vertex transformed with toScaledENU back to the earth fixed reference frame\r\n * @type {Matrix4}\r\n */\r\n this.fromScaledENU = fromENU;\r\n\r\n /**\r\n * The matrix used to decompress the terrain vertices in the shader for RTE rendering.\r\n * @type {Matrix4}\r\n */\r\n this.matrix = matrix;\r\n\r\n /**\r\n * The terrain mesh contains normals.\r\n * @type {Boolean}\r\n */\r\n this.hasVertexNormals = hasVertexNormals;\r\n\r\n /**\r\n * The terrain mesh contains a vertical texture coordinate following the Web Mercator projection.\r\n * @type {Boolean}\r\n */\r\n this.hasWebMercatorT = defaultValue(hasWebMercatorT, false);\r\n}\r\n\r\nTerrainEncoding.prototype.encode = function (\r\n vertexBuffer,\r\n bufferIndex,\r\n position,\r\n uv,\r\n height,\r\n normalToPack,\r\n webMercatorT\r\n) {\r\n var u = uv.x;\r\n var v = uv.y;\r\n\r\n if (this.quantization === TerrainQuantization.BITS12) {\r\n position = Matrix4.multiplyByPoint(\r\n this.toScaledENU,\r\n position,\r\n cartesian3Scratch\r\n );\r\n\r\n position.x = CesiumMath.clamp(position.x, 0.0, 1.0);\r\n position.y = CesiumMath.clamp(position.y, 0.0, 1.0);\r\n position.z = CesiumMath.clamp(position.z, 0.0, 1.0);\r\n\r\n var hDim = this.maximumHeight - this.minimumHeight;\r\n var h = CesiumMath.clamp((height - this.minimumHeight) / hDim, 0.0, 1.0);\r\n\r\n Cartesian2.fromElements(position.x, position.y, cartesian2Scratch);\r\n var compressed0 = AttributeCompression.compressTextureCoordinates(\r\n cartesian2Scratch\r\n );\r\n\r\n Cartesian2.fromElements(position.z, h, cartesian2Scratch);\r\n var compressed1 = AttributeCompression.compressTextureCoordinates(\r\n cartesian2Scratch\r\n );\r\n\r\n Cartesian2.fromElements(u, v, cartesian2Scratch);\r\n var compressed2 = AttributeCompression.compressTextureCoordinates(\r\n cartesian2Scratch\r\n );\r\n\r\n vertexBuffer[bufferIndex++] = compressed0;\r\n vertexBuffer[bufferIndex++] = compressed1;\r\n vertexBuffer[bufferIndex++] = compressed2;\r\n\r\n if (this.hasWebMercatorT) {\r\n Cartesian2.fromElements(webMercatorT, 0.0, cartesian2Scratch);\r\n var compressed3 = AttributeCompression.compressTextureCoordinates(\r\n cartesian2Scratch\r\n );\r\n vertexBuffer[bufferIndex++] = compressed3;\r\n }\r\n } else {\r\n Cartesian3.subtract(position, this.center, cartesian3Scratch);\r\n\r\n vertexBuffer[bufferIndex++] = cartesian3Scratch.x;\r\n vertexBuffer[bufferIndex++] = cartesian3Scratch.y;\r\n vertexBuffer[bufferIndex++] = cartesian3Scratch.z;\r\n vertexBuffer[bufferIndex++] = height;\r\n vertexBuffer[bufferIndex++] = u;\r\n vertexBuffer[bufferIndex++] = v;\r\n\r\n if (this.hasWebMercatorT) {\r\n vertexBuffer[bufferIndex++] = webMercatorT;\r\n }\r\n }\r\n\r\n if (this.hasVertexNormals) {\r\n vertexBuffer[bufferIndex++] = AttributeCompression.octPackFloat(\r\n normalToPack\r\n );\r\n }\r\n\r\n return bufferIndex;\r\n};\r\n\r\nTerrainEncoding.prototype.decodePosition = function (buffer, index, result) {\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n index *= this.getStride();\r\n\r\n if (this.quantization === TerrainQuantization.BITS12) {\r\n var xy = AttributeCompression.decompressTextureCoordinates(\r\n buffer[index],\r\n cartesian2Scratch\r\n );\r\n result.x = xy.x;\r\n result.y = xy.y;\r\n\r\n var zh = AttributeCompression.decompressTextureCoordinates(\r\n buffer[index + 1],\r\n cartesian2Scratch\r\n );\r\n result.z = zh.x;\r\n\r\n return Matrix4.multiplyByPoint(this.fromScaledENU, result, result);\r\n }\r\n\r\n result.x = buffer[index];\r\n result.y = buffer[index + 1];\r\n result.z = buffer[index + 2];\r\n return Cartesian3.add(result, this.center, result);\r\n};\r\n\r\nTerrainEncoding.prototype.decodeTextureCoordinates = function (\r\n buffer,\r\n index,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new Cartesian2();\r\n }\r\n\r\n index *= this.getStride();\r\n\r\n if (this.quantization === TerrainQuantization.BITS12) {\r\n return AttributeCompression.decompressTextureCoordinates(\r\n buffer[index + 2],\r\n result\r\n );\r\n }\r\n\r\n return Cartesian2.fromElements(buffer[index + 4], buffer[index + 5], result);\r\n};\r\n\r\nTerrainEncoding.prototype.decodeHeight = function (buffer, index) {\r\n index *= this.getStride();\r\n\r\n if (this.quantization === TerrainQuantization.BITS12) {\r\n var zh = AttributeCompression.decompressTextureCoordinates(\r\n buffer[index + 1],\r\n cartesian2Scratch\r\n );\r\n return (\r\n zh.y * (this.maximumHeight - this.minimumHeight) + this.minimumHeight\r\n );\r\n }\r\n\r\n return buffer[index + 3];\r\n};\r\n\r\nTerrainEncoding.prototype.decodeWebMercatorT = function (buffer, index) {\r\n index *= this.getStride();\r\n\r\n if (this.quantization === TerrainQuantization.BITS12) {\r\n return AttributeCompression.decompressTextureCoordinates(\r\n buffer[index + 3],\r\n cartesian2Scratch\r\n ).x;\r\n }\r\n\r\n return buffer[index + 6];\r\n};\r\n\r\nTerrainEncoding.prototype.getOctEncodedNormal = function (\r\n buffer,\r\n index,\r\n result\r\n) {\r\n var stride = this.getStride();\r\n index = (index + 1) * stride - 1;\r\n\r\n var temp = buffer[index] / 256.0;\r\n var x = Math.floor(temp);\r\n var y = (temp - x) * 256.0;\r\n\r\n return Cartesian2.fromElements(x, y, result);\r\n};\r\n\r\nTerrainEncoding.prototype.getStride = function () {\r\n var vertexStride;\r\n\r\n switch (this.quantization) {\r\n case TerrainQuantization.BITS12:\r\n vertexStride = 3;\r\n break;\r\n default:\r\n vertexStride = 6;\r\n }\r\n\r\n if (this.hasWebMercatorT) {\r\n ++vertexStride;\r\n }\r\n\r\n if (this.hasVertexNormals) {\r\n ++vertexStride;\r\n }\r\n\r\n return vertexStride;\r\n};\r\n\r\nvar attributesNone = {\r\n position3DAndHeight: 0,\r\n textureCoordAndEncodedNormals: 1,\r\n};\r\nvar attributes = {\r\n compressed0: 0,\r\n compressed1: 1,\r\n};\r\n\r\nTerrainEncoding.prototype.getAttributes = function (buffer) {\r\n var datatype = ComponentDatatype.FLOAT;\r\n var sizeInBytes = ComponentDatatype.getSizeInBytes(datatype);\r\n var stride;\r\n\r\n if (this.quantization === TerrainQuantization.NONE) {\r\n var position3DAndHeightLength = 4;\r\n var numTexCoordComponents = 2;\r\n\r\n if (this.hasWebMercatorT) {\r\n ++numTexCoordComponents;\r\n }\r\n\r\n if (this.hasVertexNormals) {\r\n ++numTexCoordComponents;\r\n }\r\n\r\n stride = (position3DAndHeightLength + numTexCoordComponents) * sizeInBytes;\r\n\r\n return [\r\n {\r\n index: attributesNone.position3DAndHeight,\r\n vertexBuffer: buffer,\r\n componentDatatype: datatype,\r\n componentsPerAttribute: position3DAndHeightLength,\r\n offsetInBytes: 0,\r\n strideInBytes: stride,\r\n },\r\n {\r\n index: attributesNone.textureCoordAndEncodedNormals,\r\n vertexBuffer: buffer,\r\n componentDatatype: datatype,\r\n componentsPerAttribute: numTexCoordComponents,\r\n offsetInBytes: position3DAndHeightLength * sizeInBytes,\r\n strideInBytes: stride,\r\n },\r\n ];\r\n }\r\n\r\n var numCompressed0 = 3;\r\n var numCompressed1 = 0;\r\n\r\n if (this.hasWebMercatorT || this.hasVertexNormals) {\r\n ++numCompressed0;\r\n }\r\n\r\n if (this.hasWebMercatorT && this.hasVertexNormals) {\r\n ++numCompressed1;\r\n\r\n stride = (numCompressed0 + numCompressed1) * sizeInBytes;\r\n\r\n return [\r\n {\r\n index: attributes.compressed0,\r\n vertexBuffer: buffer,\r\n componentDatatype: datatype,\r\n componentsPerAttribute: numCompressed0,\r\n offsetInBytes: 0,\r\n strideInBytes: stride,\r\n },\r\n {\r\n index: attributes.compressed1,\r\n vertexBuffer: buffer,\r\n componentDatatype: datatype,\r\n componentsPerAttribute: numCompressed1,\r\n offsetInBytes: numCompressed0 * sizeInBytes,\r\n strideInBytes: stride,\r\n },\r\n ];\r\n }\r\n return [\r\n {\r\n index: attributes.compressed0,\r\n vertexBuffer: buffer,\r\n componentDatatype: datatype,\r\n componentsPerAttribute: numCompressed0,\r\n },\r\n ];\r\n};\r\n\r\nTerrainEncoding.prototype.getAttributeLocations = function () {\r\n if (this.quantization === TerrainQuantization.NONE) {\r\n return attributesNone;\r\n }\r\n return attributes;\r\n};\r\n\r\nTerrainEncoding.clone = function (encoding, result) {\r\n if (!defined(result)) {\r\n result = new TerrainEncoding();\r\n }\r\n\r\n result.quantization = encoding.quantization;\r\n result.minimumHeight = encoding.minimumHeight;\r\n result.maximumHeight = encoding.maximumHeight;\r\n result.center = Cartesian3.clone(encoding.center);\r\n result.toScaledENU = Matrix4.clone(encoding.toScaledENU);\r\n result.fromScaledENU = Matrix4.clone(encoding.fromScaledENU);\r\n result.matrix = Matrix4.clone(encoding.matrix);\r\n result.hasVertexNormals = encoding.hasVertexNormals;\r\n result.hasWebMercatorT = encoding.hasWebMercatorT;\r\n return result;\r\n};\r\nexport default TerrainEncoding;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * The map projection used by Google Maps, Bing Maps, and most of ArcGIS Online, EPSG:3857. This\r\n * projection use longitude and latitude expressed with the WGS84 and transforms them to Mercator using\r\n * the spherical (rather than ellipsoidal) equations.\r\n *\r\n * @alias WebMercatorProjection\r\n * @constructor\r\n *\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid.\r\n *\r\n * @see GeographicProjection\r\n */\r\nfunction WebMercatorProjection(ellipsoid) {\r\n this._ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n this._semimajorAxis = this._ellipsoid.maximumRadius;\r\n this._oneOverSemimajorAxis = 1.0 / this._semimajorAxis;\r\n}\r\n\r\nObject.defineProperties(WebMercatorProjection.prototype, {\r\n /**\r\n * Gets the {@link Ellipsoid}.\r\n *\r\n * @memberof WebMercatorProjection.prototype\r\n *\r\n * @type {Ellipsoid}\r\n * @readonly\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Converts a Mercator angle, in the range -PI to PI, to a geodetic latitude\r\n * in the range -PI/2 to PI/2.\r\n *\r\n * @param {Number} mercatorAngle The angle to convert.\r\n * @returns {Number} The geodetic latitude in radians.\r\n */\r\nWebMercatorProjection.mercatorAngleToGeodeticLatitude = function (\r\n mercatorAngle\r\n) {\r\n return CesiumMath.PI_OVER_TWO - 2.0 * Math.atan(Math.exp(-mercatorAngle));\r\n};\r\n\r\n/**\r\n * Converts a geodetic latitude in radians, in the range -PI/2 to PI/2, to a Mercator\r\n * angle in the range -PI to PI.\r\n *\r\n * @param {Number} latitude The geodetic latitude in radians.\r\n * @returns {Number} The Mercator angle.\r\n */\r\nWebMercatorProjection.geodeticLatitudeToMercatorAngle = function (latitude) {\r\n // Clamp the latitude coordinate to the valid Mercator bounds.\r\n if (latitude > WebMercatorProjection.MaximumLatitude) {\r\n latitude = WebMercatorProjection.MaximumLatitude;\r\n } else if (latitude < -WebMercatorProjection.MaximumLatitude) {\r\n latitude = -WebMercatorProjection.MaximumLatitude;\r\n }\r\n var sinLatitude = Math.sin(latitude);\r\n return 0.5 * Math.log((1.0 + sinLatitude) / (1.0 - sinLatitude));\r\n};\r\n\r\n/**\r\n * The maximum latitude (both North and South) supported by a Web Mercator\r\n * (EPSG:3857) projection. Technically, the Mercator projection is defined\r\n * for any latitude up to (but not including) 90 degrees, but it makes sense\r\n * to cut it off sooner because it grows exponentially with increasing latitude.\r\n * The logic behind this particular cutoff value, which is the one used by\r\n * Google Maps, Bing Maps, and Esri, is that it makes the projection\r\n * square. That is, the rectangle is equal in the X and Y directions.\r\n *\r\n * The constant value is computed by calling:\r\n * WebMercatorProjection.mercatorAngleToGeodeticLatitude(Math.PI)\r\n *\r\n * @type {Number}\r\n */\r\nWebMercatorProjection.MaximumLatitude = WebMercatorProjection.mercatorAngleToGeodeticLatitude(\r\n Math.PI\r\n);\r\n\r\n/**\r\n * Converts geodetic ellipsoid coordinates, in radians, to the equivalent Web Mercator\r\n * X, Y, Z coordinates expressed in meters and returned in a {@link Cartesian3}. The height\r\n * is copied unmodified to the Z coordinate.\r\n *\r\n * @param {Cartographic} cartographic The cartographic coordinates in radians.\r\n * @param {Cartesian3} [result] The instance to which to copy the result, or undefined if a\r\n * new instance should be created.\r\n * @returns {Cartesian3} The equivalent web mercator X, Y, Z coordinates, in meters.\r\n */\r\nWebMercatorProjection.prototype.project = function (cartographic, result) {\r\n var semimajorAxis = this._semimajorAxis;\r\n var x = cartographic.longitude * semimajorAxis;\r\n var y =\r\n WebMercatorProjection.geodeticLatitudeToMercatorAngle(\r\n cartographic.latitude\r\n ) * semimajorAxis;\r\n var z = cartographic.height;\r\n\r\n if (!defined(result)) {\r\n return new Cartesian3(x, y, z);\r\n }\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.z = z;\r\n return result;\r\n};\r\n\r\n/**\r\n * Converts Web Mercator X, Y coordinates, expressed in meters, to a {@link Cartographic}\r\n * containing geodetic ellipsoid coordinates. The Z coordinate is copied unmodified to the\r\n * height.\r\n *\r\n * @param {Cartesian3} cartesian The web mercator Cartesian position to unrproject with height (z) in meters.\r\n * @param {Cartographic} [result] The instance to which to copy the result, or undefined if a\r\n * new instance should be created.\r\n * @returns {Cartographic} The equivalent cartographic coordinates.\r\n */\r\nWebMercatorProjection.prototype.unproject = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(cartesian)) {\r\n throw new DeveloperError(\"cartesian is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var oneOverEarthSemimajorAxis = this._oneOverSemimajorAxis;\r\n var longitude = cartesian.x * oneOverEarthSemimajorAxis;\r\n var latitude = WebMercatorProjection.mercatorAngleToGeodeticLatitude(\r\n cartesian.y * oneOverEarthSemimajorAxis\r\n );\r\n var height = cartesian.z;\r\n\r\n if (!defined(result)) {\r\n return new Cartographic(longitude, latitude, height);\r\n }\r\n\r\n result.longitude = longitude;\r\n result.latitude = latitude;\r\n result.height = height;\r\n return result;\r\n};\r\nexport default WebMercatorProjection;\r\n","import AxisAlignedBoundingBox from \"./AxisAlignedBoundingBox.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport EllipsoidalOccluder from \"./EllipsoidalOccluder.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport OrientedBoundingBox from \"./OrientedBoundingBox.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport TerrainEncoding from \"./TerrainEncoding.js\";\r\nimport Transforms from \"./Transforms.js\";\r\nimport WebMercatorProjection from \"./WebMercatorProjection.js\";\r\n\r\n/**\r\n * Contains functions to create a mesh from a heightmap image.\r\n *\r\n * @namespace HeightmapTessellator\r\n *\r\n * @private\r\n */\r\nvar HeightmapTessellator = {};\r\n\r\n/**\r\n * The default structure of a heightmap, as given to {@link HeightmapTessellator.computeVertices}.\r\n *\r\n * @constant\r\n */\r\nHeightmapTessellator.DEFAULT_STRUCTURE = Object.freeze({\r\n heightScale: 1.0,\r\n heightOffset: 0.0,\r\n elementsPerHeight: 1,\r\n stride: 1,\r\n elementMultiplier: 256.0,\r\n isBigEndian: false,\r\n});\r\n\r\nvar cartesian3Scratch = new Cartesian3();\r\nvar matrix4Scratch = new Matrix4();\r\nvar minimumScratch = new Cartesian3();\r\nvar maximumScratch = new Cartesian3();\r\n\r\n/**\r\n * Fills an array of vertices from a heightmap image.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} options.heightmap The heightmap to tessellate.\r\n * @param {Number} options.width The width of the heightmap, in height samples.\r\n * @param {Number} options.height The height of the heightmap, in height samples.\r\n * @param {Number} options.skirtHeight The height of skirts to drape at the edges of the heightmap.\r\n * @param {Rectangle} options.nativeRectangle A rectangle in the native coordinates of the heightmap's projection. For\r\n * a heightmap with a geographic projection, this is degrees. For the web mercator\r\n * projection, this is meters.\r\n * @param {Number} [options.exaggeration=1.0] The scale used to exaggerate the terrain.\r\n * @param {Rectangle} [options.rectangle] The rectangle covered by the heightmap, in geodetic coordinates with north, south, east and\r\n * west properties in radians. Either rectangle or nativeRectangle must be provided. If both\r\n * are provided, they're assumed to be consistent.\r\n * @param {Boolean} [options.isGeographic=true] True if the heightmap uses a {@link GeographicProjection}, or false if it uses\r\n * a {@link WebMercatorProjection}.\r\n * @param {Cartesian3} [options.relativeToCenter=Cartesian3.ZERO] The positions will be computed as Cartesian3.subtract(worldPosition, relativeToCenter).\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to which the heightmap applies.\r\n * @param {Object} [options.structure] An object describing the structure of the height data.\r\n * @param {Number} [options.structure.heightScale=1.0] The factor by which to multiply height samples in order to obtain\r\n * the height above the heightOffset, in meters. The heightOffset is added to the resulting\r\n * height after multiplying by the scale.\r\n * @param {Number} [options.structure.heightOffset=0.0] The offset to add to the scaled height to obtain the final\r\n * height in meters. The offset is added after the height sample is multiplied by the\r\n * heightScale.\r\n * @param {Number} [options.structure.elementsPerHeight=1] The number of elements in the buffer that make up a single height\r\n * sample. This is usually 1, indicating that each element is a separate height sample. If\r\n * it is greater than 1, that number of elements together form the height sample, which is\r\n * computed according to the structure.elementMultiplier and structure.isBigEndian properties.\r\n * @param {Number} [options.structure.stride=1] The number of elements to skip to get from the first element of\r\n * one height to the first element of the next height.\r\n * @param {Number} [options.structure.elementMultiplier=256.0] The multiplier used to compute the height value when the\r\n * stride property is greater than 1. For example, if the stride is 4 and the strideMultiplier\r\n * is 256, the height is computed as follows:\r\n * `height = buffer[index] + buffer[index + 1] * 256 + buffer[index + 2] * 256 * 256 + buffer[index + 3] * 256 * 256 * 256`\r\n * This is assuming that the isBigEndian property is false. If it is true, the order of the\r\n * elements is reversed.\r\n * @param {Number} [options.structure.lowestEncodedHeight] The lowest value that can be stored in the height buffer. Any heights that are lower\r\n * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height\r\n * buffer is a `Uint16Array`, this value should be 0 because a `Uint16Array` cannot store negative numbers. If this parameter is\r\n * not specified, no minimum value is enforced.\r\n * @param {Number} [options.structure.highestEncodedHeight] The highest value that can be stored in the height buffer. Any heights that are higher\r\n * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height\r\n * buffer is a `Uint16Array`, this value should be `256 * 256 - 1` or 65535 because a `Uint16Array` cannot store numbers larger\r\n * than 65535. If this parameter is not specified, no maximum value is enforced.\r\n * @param {Boolean} [options.structure.isBigEndian=false] Indicates endianness of the elements in the buffer when the\r\n * stride property is greater than 1. If this property is false, the first element is the\r\n * low-order element. If it is true, the first element is the high-order element.\r\n *\r\n * @example\r\n * var width = 5;\r\n * var height = 5;\r\n * var statistics = Cesium.HeightmapTessellator.computeVertices({\r\n * heightmap : [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],\r\n * width : width,\r\n * height : height,\r\n * skirtHeight : 0.0,\r\n * nativeRectangle : {\r\n * west : 10.0,\r\n * east : 20.0,\r\n * south : 30.0,\r\n * north : 40.0\r\n * }\r\n * });\r\n *\r\n * var encoding = statistics.encoding;\r\n * var position = encoding.decodePosition(statistics.vertices, index * encoding.getStride());\r\n */\r\nHeightmapTessellator.computeVertices = function (options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options) || !defined(options.heightmap)) {\r\n throw new DeveloperError(\"options.heightmap is required.\");\r\n }\r\n if (!defined(options.width) || !defined(options.height)) {\r\n throw new DeveloperError(\"options.width and options.height are required.\");\r\n }\r\n if (!defined(options.nativeRectangle)) {\r\n throw new DeveloperError(\"options.nativeRectangle is required.\");\r\n }\r\n if (!defined(options.skirtHeight)) {\r\n throw new DeveloperError(\"options.skirtHeight is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // This function tends to be a performance hotspot for terrain rendering,\r\n // so it employs a lot of inlining and unrolling as an optimization.\r\n // In particular, the functionality of Ellipsoid.cartographicToCartesian\r\n // is inlined.\r\n\r\n var cos = Math.cos;\r\n var sin = Math.sin;\r\n var sqrt = Math.sqrt;\r\n var atan = Math.atan;\r\n var exp = Math.exp;\r\n var piOverTwo = CesiumMath.PI_OVER_TWO;\r\n var toRadians = CesiumMath.toRadians;\r\n\r\n var heightmap = options.heightmap;\r\n var width = options.width;\r\n var height = options.height;\r\n var skirtHeight = options.skirtHeight;\r\n\r\n var isGeographic = defaultValue(options.isGeographic, true);\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n\r\n var oneOverGlobeSemimajorAxis = 1.0 / ellipsoid.maximumRadius;\r\n\r\n var nativeRectangle = options.nativeRectangle;\r\n\r\n var geographicWest;\r\n var geographicSouth;\r\n var geographicEast;\r\n var geographicNorth;\r\n\r\n var rectangle = options.rectangle;\r\n if (!defined(rectangle)) {\r\n if (isGeographic) {\r\n geographicWest = toRadians(nativeRectangle.west);\r\n geographicSouth = toRadians(nativeRectangle.south);\r\n geographicEast = toRadians(nativeRectangle.east);\r\n geographicNorth = toRadians(nativeRectangle.north);\r\n } else {\r\n geographicWest = nativeRectangle.west * oneOverGlobeSemimajorAxis;\r\n geographicSouth =\r\n piOverTwo -\r\n 2.0 * atan(exp(-nativeRectangle.south * oneOverGlobeSemimajorAxis));\r\n geographicEast = nativeRectangle.east * oneOverGlobeSemimajorAxis;\r\n geographicNorth =\r\n piOverTwo -\r\n 2.0 * atan(exp(-nativeRectangle.north * oneOverGlobeSemimajorAxis));\r\n }\r\n } else {\r\n geographicWest = rectangle.west;\r\n geographicSouth = rectangle.south;\r\n geographicEast = rectangle.east;\r\n geographicNorth = rectangle.north;\r\n }\r\n\r\n var relativeToCenter = options.relativeToCenter;\r\n var hasRelativeToCenter = defined(relativeToCenter);\r\n relativeToCenter = hasRelativeToCenter ? relativeToCenter : Cartesian3.ZERO;\r\n var exaggeration = defaultValue(options.exaggeration, 1.0);\r\n var includeWebMercatorT = defaultValue(options.includeWebMercatorT, false);\r\n\r\n var structure = defaultValue(\r\n options.structure,\r\n HeightmapTessellator.DEFAULT_STRUCTURE\r\n );\r\n var heightScale = defaultValue(\r\n structure.heightScale,\r\n HeightmapTessellator.DEFAULT_STRUCTURE.heightScale\r\n );\r\n var heightOffset = defaultValue(\r\n structure.heightOffset,\r\n HeightmapTessellator.DEFAULT_STRUCTURE.heightOffset\r\n );\r\n var elementsPerHeight = defaultValue(\r\n structure.elementsPerHeight,\r\n HeightmapTessellator.DEFAULT_STRUCTURE.elementsPerHeight\r\n );\r\n var stride = defaultValue(\r\n structure.stride,\r\n HeightmapTessellator.DEFAULT_STRUCTURE.stride\r\n );\r\n var elementMultiplier = defaultValue(\r\n structure.elementMultiplier,\r\n HeightmapTessellator.DEFAULT_STRUCTURE.elementMultiplier\r\n );\r\n var isBigEndian = defaultValue(\r\n structure.isBigEndian,\r\n HeightmapTessellator.DEFAULT_STRUCTURE.isBigEndian\r\n );\r\n\r\n var rectangleWidth = Rectangle.computeWidth(nativeRectangle);\r\n var rectangleHeight = Rectangle.computeHeight(nativeRectangle);\r\n\r\n var granularityX = rectangleWidth / (width - 1);\r\n var granularityY = rectangleHeight / (height - 1);\r\n\r\n if (!isGeographic) {\r\n rectangleWidth *= oneOverGlobeSemimajorAxis;\r\n rectangleHeight *= oneOverGlobeSemimajorAxis;\r\n }\r\n\r\n var radiiSquared = ellipsoid.radiiSquared;\r\n var radiiSquaredX = radiiSquared.x;\r\n var radiiSquaredY = radiiSquared.y;\r\n var radiiSquaredZ = radiiSquared.z;\r\n\r\n var minimumHeight = 65536.0;\r\n var maximumHeight = -65536.0;\r\n\r\n var fromENU = Transforms.eastNorthUpToFixedFrame(relativeToCenter, ellipsoid);\r\n var toENU = Matrix4.inverseTransformation(fromENU, matrix4Scratch);\r\n\r\n var southMercatorY;\r\n var oneOverMercatorHeight;\r\n if (includeWebMercatorT) {\r\n southMercatorY = WebMercatorProjection.geodeticLatitudeToMercatorAngle(\r\n geographicSouth\r\n );\r\n oneOverMercatorHeight =\r\n 1.0 /\r\n (WebMercatorProjection.geodeticLatitudeToMercatorAngle(geographicNorth) -\r\n southMercatorY);\r\n }\r\n\r\n var minimum = minimumScratch;\r\n minimum.x = Number.POSITIVE_INFINITY;\r\n minimum.y = Number.POSITIVE_INFINITY;\r\n minimum.z = Number.POSITIVE_INFINITY;\r\n\r\n var maximum = maximumScratch;\r\n maximum.x = Number.NEGATIVE_INFINITY;\r\n maximum.y = Number.NEGATIVE_INFINITY;\r\n maximum.z = Number.NEGATIVE_INFINITY;\r\n\r\n var hMin = Number.POSITIVE_INFINITY;\r\n\r\n var gridVertexCount = width * height;\r\n var edgeVertexCount = skirtHeight > 0.0 ? width * 2 + height * 2 : 0;\r\n var vertexCount = gridVertexCount + edgeVertexCount;\r\n\r\n var positions = new Array(vertexCount);\r\n var heights = new Array(vertexCount);\r\n var uvs = new Array(vertexCount);\r\n var webMercatorTs = includeWebMercatorT ? new Array(vertexCount) : [];\r\n\r\n var startRow = 0;\r\n var endRow = height;\r\n var startCol = 0;\r\n var endCol = width;\r\n\r\n if (skirtHeight > 0.0) {\r\n --startRow;\r\n ++endRow;\r\n --startCol;\r\n ++endCol;\r\n }\r\n\r\n var skirtOffsetPercentage = 0.00001;\r\n\r\n for (var rowIndex = startRow; rowIndex < endRow; ++rowIndex) {\r\n var row = rowIndex;\r\n if (row < 0) {\r\n row = 0;\r\n }\r\n if (row >= height) {\r\n row = height - 1;\r\n }\r\n\r\n var latitude = nativeRectangle.north - granularityY * row;\r\n\r\n if (!isGeographic) {\r\n latitude =\r\n piOverTwo - 2.0 * atan(exp(-latitude * oneOverGlobeSemimajorAxis));\r\n } else {\r\n latitude = toRadians(latitude);\r\n }\r\n\r\n var v = (latitude - geographicSouth) / (geographicNorth - geographicSouth);\r\n v = CesiumMath.clamp(v, 0.0, 1.0);\r\n\r\n var isNorthEdge = rowIndex === startRow;\r\n var isSouthEdge = rowIndex === endRow - 1;\r\n if (skirtHeight > 0.0) {\r\n if (isNorthEdge) {\r\n latitude += skirtOffsetPercentage * rectangleHeight;\r\n } else if (isSouthEdge) {\r\n latitude -= skirtOffsetPercentage * rectangleHeight;\r\n }\r\n }\r\n\r\n var cosLatitude = cos(latitude);\r\n var nZ = sin(latitude);\r\n var kZ = radiiSquaredZ * nZ;\r\n\r\n var webMercatorT;\r\n if (includeWebMercatorT) {\r\n webMercatorT =\r\n (WebMercatorProjection.geodeticLatitudeToMercatorAngle(latitude) -\r\n southMercatorY) *\r\n oneOverMercatorHeight;\r\n }\r\n\r\n for (var colIndex = startCol; colIndex < endCol; ++colIndex) {\r\n var col = colIndex;\r\n if (col < 0) {\r\n col = 0;\r\n }\r\n if (col >= width) {\r\n col = width - 1;\r\n }\r\n\r\n var terrainOffset = row * (width * stride) + col * stride;\r\n\r\n var heightSample;\r\n if (elementsPerHeight === 1) {\r\n heightSample = heightmap[terrainOffset];\r\n } else {\r\n heightSample = 0;\r\n\r\n var elementOffset;\r\n if (isBigEndian) {\r\n for (\r\n elementOffset = 0;\r\n elementOffset < elementsPerHeight;\r\n ++elementOffset\r\n ) {\r\n heightSample =\r\n heightSample * elementMultiplier +\r\n heightmap[terrainOffset + elementOffset];\r\n }\r\n } else {\r\n for (\r\n elementOffset = elementsPerHeight - 1;\r\n elementOffset >= 0;\r\n --elementOffset\r\n ) {\r\n heightSample =\r\n heightSample * elementMultiplier +\r\n heightmap[terrainOffset + elementOffset];\r\n }\r\n }\r\n }\r\n\r\n heightSample = (heightSample * heightScale + heightOffset) * exaggeration;\r\n\r\n maximumHeight = Math.max(maximumHeight, heightSample);\r\n minimumHeight = Math.min(minimumHeight, heightSample);\r\n\r\n var longitude = nativeRectangle.west + granularityX * col;\r\n\r\n if (!isGeographic) {\r\n longitude = longitude * oneOverGlobeSemimajorAxis;\r\n } else {\r\n longitude = toRadians(longitude);\r\n }\r\n\r\n var u = (longitude - geographicWest) / (geographicEast - geographicWest);\r\n u = CesiumMath.clamp(u, 0.0, 1.0);\r\n\r\n var index = row * width + col;\r\n\r\n if (skirtHeight > 0.0) {\r\n var isWestEdge = colIndex === startCol;\r\n var isEastEdge = colIndex === endCol - 1;\r\n var isEdge = isNorthEdge || isSouthEdge || isWestEdge || isEastEdge;\r\n var isCorner =\r\n (isNorthEdge || isSouthEdge) && (isWestEdge || isEastEdge);\r\n if (isCorner) {\r\n // Don't generate skirts on the corners.\r\n continue;\r\n } else if (isEdge) {\r\n heightSample -= skirtHeight;\r\n\r\n if (isWestEdge) {\r\n // The outer loop iterates north to south but the indices are ordered south to north, hence the index flip below\r\n index = gridVertexCount + (height - row - 1);\r\n longitude -= skirtOffsetPercentage * rectangleWidth;\r\n } else if (isSouthEdge) {\r\n // Add after west indices. South indices are ordered east to west.\r\n index = gridVertexCount + height + (width - col - 1);\r\n } else if (isEastEdge) {\r\n // Add after west and south indices. East indices are ordered north to south. The index is flipped like above.\r\n index = gridVertexCount + height + width + row;\r\n longitude += skirtOffsetPercentage * rectangleWidth;\r\n } else if (isNorthEdge) {\r\n // Add after west, south, and east indices. North indices are ordered west to east.\r\n index = gridVertexCount + height + width + height + col;\r\n }\r\n }\r\n }\r\n\r\n var nX = cosLatitude * cos(longitude);\r\n var nY = cosLatitude * sin(longitude);\r\n\r\n var kX = radiiSquaredX * nX;\r\n var kY = radiiSquaredY * nY;\r\n\r\n var gamma = sqrt(kX * nX + kY * nY + kZ * nZ);\r\n var oneOverGamma = 1.0 / gamma;\r\n\r\n var rSurfaceX = kX * oneOverGamma;\r\n var rSurfaceY = kY * oneOverGamma;\r\n var rSurfaceZ = kZ * oneOverGamma;\r\n\r\n var position = new Cartesian3();\r\n position.x = rSurfaceX + nX * heightSample;\r\n position.y = rSurfaceY + nY * heightSample;\r\n position.z = rSurfaceZ + nZ * heightSample;\r\n\r\n positions[index] = position;\r\n heights[index] = heightSample;\r\n uvs[index] = new Cartesian2(u, v);\r\n\r\n if (includeWebMercatorT) {\r\n webMercatorTs[index] = webMercatorT;\r\n }\r\n\r\n Matrix4.multiplyByPoint(toENU, position, cartesian3Scratch);\r\n\r\n Cartesian3.minimumByComponent(cartesian3Scratch, minimum, minimum);\r\n Cartesian3.maximumByComponent(cartesian3Scratch, maximum, maximum);\r\n hMin = Math.min(hMin, heightSample);\r\n }\r\n }\r\n\r\n var boundingSphere3D = BoundingSphere.fromPoints(positions);\r\n var orientedBoundingBox;\r\n if (defined(rectangle)) {\r\n orientedBoundingBox = OrientedBoundingBox.fromRectangle(\r\n rectangle,\r\n minimumHeight,\r\n maximumHeight,\r\n ellipsoid\r\n );\r\n }\r\n\r\n var occludeePointInScaledSpace;\r\n if (hasRelativeToCenter) {\r\n var occluder = new EllipsoidalOccluder(ellipsoid);\r\n occludeePointInScaledSpace = occluder.computeHorizonCullingPointPossiblyUnderEllipsoid(\r\n relativeToCenter,\r\n positions,\r\n minimumHeight\r\n );\r\n }\r\n\r\n var aaBox = new AxisAlignedBoundingBox(minimum, maximum, relativeToCenter);\r\n var encoding = new TerrainEncoding(\r\n aaBox,\r\n hMin,\r\n maximumHeight,\r\n fromENU,\r\n false,\r\n includeWebMercatorT\r\n );\r\n var vertices = new Float32Array(vertexCount * encoding.getStride());\r\n\r\n var bufferIndex = 0;\r\n for (var j = 0; j < vertexCount; ++j) {\r\n bufferIndex = encoding.encode(\r\n vertices,\r\n bufferIndex,\r\n positions[j],\r\n uvs[j],\r\n heights[j],\r\n undefined,\r\n webMercatorTs[j]\r\n );\r\n }\r\n\r\n return {\r\n vertices: vertices,\r\n maximumHeight: maximumHeight,\r\n minimumHeight: minimumHeight,\r\n encoding: encoding,\r\n boundingSphere3D: boundingSphere3D,\r\n orientedBoundingBox: orientedBoundingBox,\r\n occludeePointInScaledSpace: occludeePointInScaledSpace,\r\n };\r\n};\r\nexport default HeightmapTessellator;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\nfunction returnTrue() {\r\n return true;\r\n}\r\n\r\n/**\r\n * Destroys an object. Each of the object's functions, including functions in its prototype,\r\n * is replaced with a function that throws a {@link DeveloperError}, except for the object's\r\n * isDestroyed function, which is set to a function that returns true.\r\n * The object's properties are removed with delete.\r\n *

\r\n * This function is used by objects that hold native resources, e.g., WebGL resources, which\r\n * need to be explicitly released. Client code calls an object's destroy function,\r\n * which then releases the native resource and calls destroyObject to put itself\r\n * in a destroyed state.\r\n *\r\n * @function\r\n *\r\n * @param {Object} object The object to destroy.\r\n * @param {String} [message] The message to include in the exception that is thrown if\r\n * a destroyed object's function is called.\r\n *\r\n *\r\n * @example\r\n * // How a texture would destroy itself.\r\n * this.destroy = function () {\r\n * _gl.deleteTexture(_texture);\r\n * return Cesium.destroyObject(this);\r\n * };\r\n *\r\n * @see DeveloperError\r\n */\r\nfunction destroyObject(object, message) {\r\n message = defaultValue(\r\n message,\r\n \"This object was destroyed, i.e., destroy() was called.\"\r\n );\r\n\r\n function throwOnDestroyed() {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(message);\r\n //>>includeEnd('debug');\r\n }\r\n\r\n for (var key in object) {\r\n if (typeof object[key] === \"function\") {\r\n object[key] = throwOnDestroyed;\r\n }\r\n }\r\n\r\n object.isDestroyed = returnTrue;\r\n\r\n return undefined;\r\n}\r\nexport default destroyObject;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport buildModuleUrl from \"./buildModuleUrl.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport destroyObject from \"./destroyObject.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Event from \"./Event.js\";\r\nimport FeatureDetection from \"./FeatureDetection.js\";\r\nimport isCrossOriginUrl from \"./isCrossOriginUrl.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\n\r\nfunction canTransferArrayBuffer() {\r\n if (!defined(TaskProcessor._canTransferArrayBuffer)) {\r\n var worker = new Worker(getWorkerUrl(\"Workers/transferTypedArrayTest.js\"));\r\n worker.postMessage = defaultValue(\r\n worker.webkitPostMessage,\r\n worker.postMessage\r\n );\r\n\r\n var value = 99;\r\n var array = new Int8Array([value]);\r\n\r\n try {\r\n // postMessage might fail with a DataCloneError\r\n // if transferring array buffers is not supported.\r\n worker.postMessage(\r\n {\r\n array: array,\r\n },\r\n [array.buffer]\r\n );\r\n } catch (e) {\r\n TaskProcessor._canTransferArrayBuffer = false;\r\n return TaskProcessor._canTransferArrayBuffer;\r\n }\r\n\r\n var deferred = when.defer();\r\n\r\n worker.onmessage = function (event) {\r\n var array = event.data.array;\r\n\r\n // some versions of Firefox silently fail to transfer typed arrays.\r\n // https://bugzilla.mozilla.org/show_bug.cgi?id=841904\r\n // Check to make sure the value round-trips successfully.\r\n var result = defined(array) && array[0] === value;\r\n deferred.resolve(result);\r\n\r\n worker.terminate();\r\n\r\n TaskProcessor._canTransferArrayBuffer = result;\r\n };\r\n\r\n TaskProcessor._canTransferArrayBuffer = deferred.promise;\r\n }\r\n\r\n return TaskProcessor._canTransferArrayBuffer;\r\n}\r\n\r\nvar taskCompletedEvent = new Event();\r\n\r\nfunction completeTask(processor, data) {\r\n --processor._activeTasks;\r\n\r\n var id = data.id;\r\n if (!defined(id)) {\r\n // This is not one of ours.\r\n return;\r\n }\r\n\r\n var deferreds = processor._deferreds;\r\n var deferred = deferreds[id];\r\n\r\n if (defined(data.error)) {\r\n var error = data.error;\r\n if (error.name === \"RuntimeError\") {\r\n error = new RuntimeError(data.error.message);\r\n error.stack = data.error.stack;\r\n } else if (error.name === \"DeveloperError\") {\r\n error = new DeveloperError(data.error.message);\r\n error.stack = data.error.stack;\r\n }\r\n taskCompletedEvent.raiseEvent(error);\r\n deferred.reject(error);\r\n } else {\r\n taskCompletedEvent.raiseEvent();\r\n deferred.resolve(data.result);\r\n }\r\n\r\n delete deferreds[id];\r\n}\r\n\r\nfunction getWorkerUrl(moduleID) {\r\n var url = buildModuleUrl(moduleID);\r\n\r\n if (isCrossOriginUrl(url)) {\r\n //to load cross-origin, create a shim worker from a blob URL\r\n var script = 'importScripts(\"' + url + '\");';\r\n\r\n var blob;\r\n try {\r\n blob = new Blob([script], {\r\n type: \"application/javascript\",\r\n });\r\n } catch (e) {\r\n var BlobBuilder =\r\n window.BlobBuilder ||\r\n window.WebKitBlobBuilder ||\r\n window.MozBlobBuilder ||\r\n window.MSBlobBuilder;\r\n var blobBuilder = new BlobBuilder();\r\n blobBuilder.append(script);\r\n blob = blobBuilder.getBlob(\"application/javascript\");\r\n }\r\n\r\n var URL = window.URL || window.webkitURL;\r\n url = URL.createObjectURL(blob);\r\n }\r\n\r\n return url;\r\n}\r\n\r\nvar bootstrapperUrlResult;\r\nfunction getBootstrapperUrl() {\r\n if (!defined(bootstrapperUrlResult)) {\r\n bootstrapperUrlResult = getWorkerUrl(\"Workers/cesiumWorkerBootstrapper.js\");\r\n }\r\n return bootstrapperUrlResult;\r\n}\r\n\r\nfunction createWorker(processor) {\r\n var worker = new Worker(getBootstrapperUrl());\r\n worker.postMessage = defaultValue(\r\n worker.webkitPostMessage,\r\n worker.postMessage\r\n );\r\n\r\n var bootstrapMessage = {\r\n loaderConfig: {\r\n paths: {\r\n Workers: buildModuleUrl(\"Workers\"),\r\n },\r\n baseUrl: buildModuleUrl.getCesiumBaseUrl().url,\r\n },\r\n workerModule: processor._workerPath,\r\n };\r\n\r\n worker.postMessage(bootstrapMessage);\r\n worker.onmessage = function (event) {\r\n completeTask(processor, event.data);\r\n };\r\n\r\n return worker;\r\n}\r\n\r\nfunction getWebAssemblyLoaderConfig(processor, wasmOptions) {\r\n var config = {\r\n modulePath: undefined,\r\n wasmBinaryFile: undefined,\r\n wasmBinary: undefined,\r\n };\r\n\r\n // Web assembly not supported, use fallback js module if provided\r\n if (!FeatureDetection.supportsWebAssembly()) {\r\n if (!defined(wasmOptions.fallbackModulePath)) {\r\n throw new RuntimeError(\r\n \"This browser does not support Web Assembly, and no backup module was provided for \" +\r\n processor._workerPath\r\n );\r\n }\r\n\r\n config.modulePath = buildModuleUrl(wasmOptions.fallbackModulePath);\r\n return when.resolve(config);\r\n }\r\n\r\n config.modulePath = buildModuleUrl(wasmOptions.modulePath);\r\n config.wasmBinaryFile = buildModuleUrl(wasmOptions.wasmBinaryFile);\r\n\r\n return Resource.fetchArrayBuffer({\r\n url: config.wasmBinaryFile,\r\n }).then(function (arrayBuffer) {\r\n config.wasmBinary = arrayBuffer;\r\n return config;\r\n });\r\n}\r\n\r\n/**\r\n * A wrapper around a web worker that allows scheduling tasks for a given worker,\r\n * returning results asynchronously via a promise.\r\n *\r\n * The Worker is not constructed until a task is scheduled.\r\n *\r\n * @alias TaskProcessor\r\n * @constructor\r\n *\r\n * @param {String} workerPath The Url to the worker. This can either be an absolute path or relative to the Cesium Workers folder.\r\n * @param {Number} [maximumActiveTasks=Number.POSITIVE_INFINITY] The maximum number of active tasks. Once exceeded,\r\n * scheduleTask will not queue any more tasks, allowing\r\n * work to be rescheduled in future frames.\r\n */\r\nfunction TaskProcessor(workerPath, maximumActiveTasks) {\r\n this._workerPath = new Uri(workerPath).isAbsolute()\r\n ? workerPath\r\n : TaskProcessor._workerModulePrefix + workerPath;\r\n this._maximumActiveTasks = defaultValue(\r\n maximumActiveTasks,\r\n Number.POSITIVE_INFINITY\r\n );\r\n this._activeTasks = 0;\r\n this._deferreds = {};\r\n this._nextID = 0;\r\n}\r\n\r\nvar emptyTransferableObjectArray = [];\r\n\r\n/**\r\n * Schedule a task to be processed by the web worker asynchronously. If there are currently more\r\n * tasks active than the maximum set by the constructor, will immediately return undefined.\r\n * Otherwise, returns a promise that will resolve to the result posted back by the worker when\r\n * finished.\r\n *\r\n * @param {Object} parameters Any input data that will be posted to the worker.\r\n * @param {Object[]} [transferableObjects] An array of objects contained in parameters that should be\r\n * transferred to the worker instead of copied.\r\n * @returns {Promise.|undefined} Either a promise that will resolve to the result when available, or undefined\r\n * if there are too many active tasks,\r\n *\r\n * @example\r\n * var taskProcessor = new Cesium.TaskProcessor('myWorkerPath');\r\n * var promise = taskProcessor.scheduleTask({\r\n * someParameter : true,\r\n * another : 'hello'\r\n * });\r\n * if (!Cesium.defined(promise)) {\r\n * // too many active tasks - try again later\r\n * } else {\r\n * Cesium.when(promise, function(result) {\r\n * // use the result of the task\r\n * });\r\n * }\r\n */\r\nTaskProcessor.prototype.scheduleTask = function (\r\n parameters,\r\n transferableObjects\r\n) {\r\n if (!defined(this._worker)) {\r\n this._worker = createWorker(this);\r\n }\r\n\r\n if (this._activeTasks >= this._maximumActiveTasks) {\r\n return undefined;\r\n }\r\n\r\n ++this._activeTasks;\r\n\r\n var processor = this;\r\n return when(canTransferArrayBuffer(), function (canTransferArrayBuffer) {\r\n if (!defined(transferableObjects)) {\r\n transferableObjects = emptyTransferableObjectArray;\r\n } else if (!canTransferArrayBuffer) {\r\n transferableObjects.length = 0;\r\n }\r\n\r\n var id = processor._nextID++;\r\n var deferred = when.defer();\r\n processor._deferreds[id] = deferred;\r\n\r\n processor._worker.postMessage(\r\n {\r\n id: id,\r\n parameters: parameters,\r\n canTransferArrayBuffer: canTransferArrayBuffer,\r\n },\r\n transferableObjects\r\n );\r\n\r\n return deferred.promise;\r\n });\r\n};\r\n\r\n/**\r\n * Posts a message to a web worker with configuration to initialize loading\r\n * and compiling a web assembly module asychronously, as well as an optional\r\n * fallback JavaScript module to use if Web Assembly is not supported.\r\n *\r\n * @param {Object} [webAssemblyOptions] An object with the following properties:\r\n * @param {String} [webAssemblyOptions.modulePath] The path of the web assembly JavaScript wrapper module.\r\n * @param {String} [webAssemblyOptions.wasmBinaryFile] The path of the web assembly binary file.\r\n * @param {String} [webAssemblyOptions.fallbackModulePath] The path of the fallback JavaScript module to use if web assembly is not supported.\r\n * @returns {Promise.} A promise that resolves to the result when the web worker has loaded and compiled the web assembly module and is ready to process tasks.\r\n */\r\nTaskProcessor.prototype.initWebAssemblyModule = function (webAssemblyOptions) {\r\n if (!defined(this._worker)) {\r\n this._worker = createWorker(this);\r\n }\r\n\r\n var deferred = when.defer();\r\n var processor = this;\r\n var worker = this._worker;\r\n getWebAssemblyLoaderConfig(this, webAssemblyOptions).then(function (\r\n wasmConfig\r\n ) {\r\n return when(canTransferArrayBuffer(), function (canTransferArrayBuffer) {\r\n var transferableObjects;\r\n var binary = wasmConfig.wasmBinary;\r\n if (defined(binary) && canTransferArrayBuffer) {\r\n transferableObjects = [binary];\r\n }\r\n\r\n worker.onmessage = function (event) {\r\n worker.onmessage = function (event) {\r\n completeTask(processor, event.data);\r\n };\r\n\r\n deferred.resolve(event.data);\r\n };\r\n\r\n worker.postMessage(\r\n { webAssemblyConfig: wasmConfig },\r\n transferableObjects\r\n );\r\n });\r\n });\r\n\r\n return deferred;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n *\r\n * @see TaskProcessor#destroy\r\n */\r\nTaskProcessor.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys this object. This will immediately terminate the Worker.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n */\r\nTaskProcessor.prototype.destroy = function () {\r\n if (defined(this._worker)) {\r\n this._worker.terminate();\r\n }\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * An event that's raised when a task is completed successfully. Event handlers are passed\r\n * the error object is a task fails.\r\n *\r\n * @type {Event}\r\n *\r\n * @private\r\n */\r\nTaskProcessor.taskCompletedEvent = taskCompletedEvent;\r\n\r\n// exposed for testing purposes\r\nTaskProcessor._defaultWorkerModulePrefix = \"Workers/\";\r\nTaskProcessor._workerModulePrefix = TaskProcessor._defaultWorkerModulePrefix;\r\nTaskProcessor._canTransferArrayBuffer = undefined;\r\nexport default TaskProcessor;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Terrain data for a single tile. This type describes an\r\n * interface and is not intended to be instantiated directly.\r\n *\r\n * @alias TerrainData\r\n * @constructor\r\n *\r\n * @see HeightmapTerrainData\r\n * @see QuantizedMeshTerrainData\r\n * @see GoogleEarthEnterpriseTerrainData\r\n */\r\nfunction TerrainData() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\nObject.defineProperties(TerrainData.prototype, {\r\n /**\r\n * An array of credits for this tile.\r\n * @memberof TerrainData.prototype\r\n * @type {Credit[]}\r\n */\r\n credits: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * The water mask included in this terrain data, if any. A water mask is a rectangular\r\n * Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.\r\n * Values in between 0 and 255 are allowed as well to smoothly blend between land and water.\r\n * @memberof TerrainData.prototype\r\n * @type {Uint8Array|HTMLImageElement|HTMLCanvasElement}\r\n */\r\n waterMask: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n});\r\n\r\n/**\r\n * Computes the terrain height at a specified longitude and latitude.\r\n * @function\r\n *\r\n * @param {Rectangle} rectangle The rectangle covered by this terrain data.\r\n * @param {Number} longitude The longitude in radians.\r\n * @param {Number} latitude The latitude in radians.\r\n * @returns {Number} The terrain height at the specified position. If the position\r\n * is outside the rectangle, this method will extrapolate the height, which is likely to be wildly\r\n * incorrect for positions far outside the rectangle.\r\n */\r\nTerrainData.prototype.interpolateHeight =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Determines if a given child tile is available, based on the\r\n * {@link TerrainData#childTileMask}. The given child tile coordinates are assumed\r\n * to be one of the four children of this tile. If non-child tile coordinates are\r\n * given, the availability of the southeast child tile is returned.\r\n * @function\r\n *\r\n * @param {Number} thisX The tile X coordinate of this (the parent) tile.\r\n * @param {Number} thisY The tile Y coordinate of this (the parent) tile.\r\n * @param {Number} childX The tile X coordinate of the child tile to check for availability.\r\n * @param {Number} childY The tile Y coordinate of the child tile to check for availability.\r\n * @returns {Boolean} True if the child tile is available; otherwise, false.\r\n */\r\nTerrainData.prototype.isChildAvailable = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Creates a {@link TerrainMesh} from this terrain data.\r\n * @function\r\n *\r\n * @private\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {TilingScheme} options.tilingScheme The tiling scheme to which this tile belongs.\r\n * @param {Number} options.x The X coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.y The Y coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.level The level of the tile for which to create the terrain data.\r\n * @param {Number} [options.exaggeration=1.0] The scale used to exaggerate the terrain.\r\n * @param {Boolean} [options.throttle=true] If true, indicates that this operation will need to be retried if too many asynchronous mesh creations are already in progress.\r\n * @returns {Promise.|undefined} A promise for the terrain mesh, or undefined if too many\r\n * asynchronous mesh creations are already in progress and the operation should\r\n * be retried later.\r\n */\r\nTerrainData.prototype.createMesh = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Upsamples this terrain data for use by a descendant tile.\r\n * @function\r\n *\r\n * @param {TilingScheme} tilingScheme The tiling scheme of this terrain data.\r\n * @param {Number} thisX The X coordinate of this tile in the tiling scheme.\r\n * @param {Number} thisY The Y coordinate of this tile in the tiling scheme.\r\n * @param {Number} thisLevel The level of this tile in the tiling scheme.\r\n * @param {Number} descendantX The X coordinate within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @param {Number} descendantY The Y coordinate within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @param {Number} descendantLevel The level within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @returns {Promise.|undefined} A promise for upsampled terrain data for the descendant tile,\r\n * or undefined if too many asynchronous upsample operations are in progress and the request has been\r\n * deferred.\r\n */\r\nTerrainData.prototype.upsample = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Gets a value indicating whether or not this terrain data was created by upsampling lower resolution\r\n * terrain data. If this value is false, the data was obtained from some other source, such\r\n * as by downloading it from a remote server. This method should return true for instances\r\n * returned from a call to {@link TerrainData#upsample}.\r\n * @function\r\n *\r\n * @returns {Boolean} True if this instance was created by upsampling; otherwise, false.\r\n */\r\nTerrainData.prototype.wasCreatedByUpsampling =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * The maximum number of asynchronous tasks used for terrain processing.\r\n *\r\n * @type {Number}\r\n * @private\r\n */\r\nTerrainData.maximumAsynchronousTasks = 5;\r\n\r\nexport default TerrainData;\r\n","import defaultValue from \"./defaultValue.js\";\r\n\r\n/**\r\n * A mesh plus related metadata for a single tile of terrain. Instances of this type are\r\n * usually created from raw {@link TerrainData}.\r\n *\r\n * @alias TerrainMesh\r\n * @constructor\r\n *\r\n * @param {Cartesian3} center The center of the tile. Vertex positions are specified relative to this center.\r\n * @param {Float32Array} vertices The vertex data, including positions, texture coordinates, and heights.\r\n * The vertex data is in the order [X, Y, Z, H, U, V], where X, Y, and Z represent\r\n * the Cartesian position of the vertex, H is the height above the ellipsoid, and\r\n * U and V are the texture coordinates.\r\n * @param {Uint8Array|Uint16Array|Uint32Array} indices The indices describing how the vertices are connected to form triangles.\r\n * @param {Number} indexCountWithoutSkirts The index count of the mesh not including skirts.\r\n * @param {Number} vertexCountWithoutSkirts The vertex count of the mesh not including skirts.\r\n * @param {Number} minimumHeight The lowest height in the tile, in meters above the ellipsoid.\r\n * @param {Number} maximumHeight The highest height in the tile, in meters above the ellipsoid.\r\n * @param {BoundingSphere} boundingSphere3D A bounding sphere that completely contains the tile.\r\n * @param {Cartesian3} occludeePointInScaledSpace The occludee point of the tile, represented in ellipsoid-\r\n * scaled space, and used for horizon culling. If this point is below the horizon,\r\n * the tile is considered to be entirely below the horizon.\r\n * @param {Number} [vertexStride=6] The number of components in each vertex.\r\n * @param {OrientedBoundingBox} [orientedBoundingBox] A bounding box that completely contains the tile.\r\n * @param {TerrainEncoding} encoding Information used to decode the mesh.\r\n * @param {Number} exaggeration The amount that this mesh was exaggerated.\r\n * @param {Number[]} westIndicesSouthToNorth The indices of the vertices on the Western edge of the tile, ordered from South to North (clockwise).\r\n * @param {Number[]} southIndicesEastToWest The indices of the vertices on the Southern edge of the tile, ordered from East to West (clockwise).\r\n * @param {Number[]} eastIndicesNorthToSouth The indices of the vertices on the Eastern edge of the tile, ordered from North to South (clockwise).\r\n * @param {Number[]} northIndicesWestToEast The indices of the vertices on the Northern edge of the tile, ordered from West to East (clockwise).\r\n *\r\n * @private\r\n */\r\nfunction TerrainMesh(\r\n center,\r\n vertices,\r\n indices,\r\n indexCountWithoutSkirts,\r\n vertexCountWithoutSkirts,\r\n minimumHeight,\r\n maximumHeight,\r\n boundingSphere3D,\r\n occludeePointInScaledSpace,\r\n vertexStride,\r\n orientedBoundingBox,\r\n encoding,\r\n exaggeration,\r\n westIndicesSouthToNorth,\r\n southIndicesEastToWest,\r\n eastIndicesNorthToSouth,\r\n northIndicesWestToEast\r\n) {\r\n /**\r\n * The center of the tile. Vertex positions are specified relative to this center.\r\n * @type {Cartesian3}\r\n */\r\n this.center = center;\r\n\r\n /**\r\n * The vertex data, including positions, texture coordinates, and heights.\r\n * The vertex data is in the order [X, Y, Z, H, U, V], where X, Y, and Z represent\r\n * the Cartesian position of the vertex, H is the height above the ellipsoid, and\r\n * U and V are the texture coordinates. The vertex data may have additional attributes after those\r\n * mentioned above when the {@link TerrainMesh#stride} is greater than 6.\r\n * @type {Float32Array}\r\n */\r\n this.vertices = vertices;\r\n\r\n /**\r\n * The number of components in each vertex. Typically this is 6 for the 6 components\r\n * [X, Y, Z, H, U, V], but if each vertex has additional data (such as a vertex normal), this value\r\n * may be higher.\r\n * @type {Number}\r\n */\r\n this.stride = defaultValue(vertexStride, 6);\r\n\r\n /**\r\n * The indices describing how the vertices are connected to form triangles.\r\n * @type {Uint8Array|Uint16Array|Uint32Array}\r\n */\r\n this.indices = indices;\r\n\r\n /**\r\n * The index count of the mesh not including skirts.\r\n * @type {Number}\r\n */\r\n this.indexCountWithoutSkirts = indexCountWithoutSkirts;\r\n\r\n /**\r\n * The vertex count of the mesh not including skirts.\r\n * @type {Number}\r\n */\r\n this.vertexCountWithoutSkirts = vertexCountWithoutSkirts;\r\n\r\n /**\r\n * The lowest height in the tile, in meters above the ellipsoid.\r\n * @type {Number}\r\n */\r\n this.minimumHeight = minimumHeight;\r\n\r\n /**\r\n * The highest height in the tile, in meters above the ellipsoid.\r\n * @type {Number}\r\n */\r\n this.maximumHeight = maximumHeight;\r\n\r\n /**\r\n * A bounding sphere that completely contains the tile.\r\n * @type {BoundingSphere}\r\n */\r\n this.boundingSphere3D = boundingSphere3D;\r\n\r\n /**\r\n * The occludee point of the tile, represented in ellipsoid-\r\n * scaled space, and used for horizon culling. If this point is below the horizon,\r\n * the tile is considered to be entirely below the horizon.\r\n * @type {Cartesian3}\r\n */\r\n this.occludeePointInScaledSpace = occludeePointInScaledSpace;\r\n\r\n /**\r\n * A bounding box that completely contains the tile.\r\n * @type {OrientedBoundingBox}\r\n */\r\n this.orientedBoundingBox = orientedBoundingBox;\r\n\r\n /**\r\n * Information for decoding the mesh vertices.\r\n * @type {TerrainEncoding}\r\n */\r\n this.encoding = encoding;\r\n\r\n /**\r\n * The amount that this mesh was exaggerated.\r\n * @type {Number}\r\n */\r\n this.exaggeration = exaggeration;\r\n\r\n /**\r\n * The indices of the vertices on the Western edge of the tile, ordered from South to North (clockwise).\r\n * @type {Number[]}\r\n */\r\n this.westIndicesSouthToNorth = westIndicesSouthToNorth;\r\n\r\n /**\r\n * The indices of the vertices on the Southern edge of the tile, ordered from East to West (clockwise).\r\n * @type {Number[]}\r\n */\r\n this.southIndicesEastToWest = southIndicesEastToWest;\r\n\r\n /**\r\n * The indices of the vertices on the Eastern edge of the tile, ordered from North to South (clockwise).\r\n * @type {Number[]}\r\n */\r\n this.eastIndicesNorthToSouth = eastIndicesNorthToSouth;\r\n\r\n /**\r\n * The indices of the vertices on the Northern edge of the tile, ordered from West to East (clockwise).\r\n * @type {Number[]}\r\n */\r\n this.northIndicesWestToEast = northIndicesWestToEast;\r\n}\r\nexport default TerrainMesh;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport WebGLConstants from \"./WebGLConstants.js\";\r\n\r\n/**\r\n * Constants for WebGL index datatypes. These corresponds to the\r\n * type parameter of {@link http://www.khronos.org/opengles/sdk/docs/man/xhtml/glDrawElements.xml|drawElements}.\r\n *\r\n * @enum {Number}\r\n */\r\nvar IndexDatatype = {\r\n /**\r\n * 8-bit unsigned byte corresponding to UNSIGNED_BYTE and the type\r\n * of an element in Uint8Array.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n UNSIGNED_BYTE: WebGLConstants.UNSIGNED_BYTE,\r\n\r\n /**\r\n * 16-bit unsigned short corresponding to UNSIGNED_SHORT and the type\r\n * of an element in Uint16Array.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n UNSIGNED_SHORT: WebGLConstants.UNSIGNED_SHORT,\r\n\r\n /**\r\n * 32-bit unsigned int corresponding to UNSIGNED_INT and the type\r\n * of an element in Uint32Array.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n UNSIGNED_INT: WebGLConstants.UNSIGNED_INT,\r\n};\r\n\r\n/**\r\n * Returns the size, in bytes, of the corresponding datatype.\r\n *\r\n * @param {IndexDatatype} indexDatatype The index datatype to get the size of.\r\n * @returns {Number} The size in bytes.\r\n *\r\n * @example\r\n * // Returns 2\r\n * var size = Cesium.IndexDatatype.getSizeInBytes(Cesium.IndexDatatype.UNSIGNED_SHORT);\r\n */\r\nIndexDatatype.getSizeInBytes = function (indexDatatype) {\r\n switch (indexDatatype) {\r\n case IndexDatatype.UNSIGNED_BYTE:\r\n return Uint8Array.BYTES_PER_ELEMENT;\r\n case IndexDatatype.UNSIGNED_SHORT:\r\n return Uint16Array.BYTES_PER_ELEMENT;\r\n case IndexDatatype.UNSIGNED_INT:\r\n return Uint32Array.BYTES_PER_ELEMENT;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\r\n \"indexDatatype is required and must be a valid IndexDatatype constant.\"\r\n );\r\n //>>includeEnd('debug');\r\n};\r\n\r\n/**\r\n * Gets the datatype with a given size in bytes.\r\n *\r\n * @param {Number} sizeInBytes The size of a single index in bytes.\r\n * @returns {IndexDatatype} The index datatype with the given size.\r\n */\r\nIndexDatatype.fromSizeInBytes = function (sizeInBytes) {\r\n switch (sizeInBytes) {\r\n case 2:\r\n return IndexDatatype.UNSIGNED_SHORT;\r\n case 4:\r\n return IndexDatatype.UNSIGNED_INT;\r\n case 1:\r\n return IndexDatatype.UNSIGNED_BYTE;\r\n //>>includeStart('debug', pragmas.debug);\r\n default:\r\n throw new DeveloperError(\r\n \"Size in bytes cannot be mapped to an IndexDatatype\"\r\n );\r\n //>>includeEnd('debug');\r\n }\r\n};\r\n\r\n/**\r\n * Validates that the provided index datatype is a valid {@link IndexDatatype}.\r\n *\r\n * @param {IndexDatatype} indexDatatype The index datatype to validate.\r\n * @returns {Boolean} true if the provided index datatype is a valid value; otherwise, false.\r\n *\r\n * @example\r\n * if (!Cesium.IndexDatatype.validate(indexDatatype)) {\r\n * throw new Cesium.DeveloperError('indexDatatype must be a valid value.');\r\n * }\r\n */\r\nIndexDatatype.validate = function (indexDatatype) {\r\n return (\r\n defined(indexDatatype) &&\r\n (indexDatatype === IndexDatatype.UNSIGNED_BYTE ||\r\n indexDatatype === IndexDatatype.UNSIGNED_SHORT ||\r\n indexDatatype === IndexDatatype.UNSIGNED_INT)\r\n );\r\n};\r\n\r\n/**\r\n * Creates a typed array that will store indices, using either \r\n * or Uint32Array depending on the number of vertices.\r\n *\r\n * @param {Number} numberOfVertices Number of vertices that the indices will reference.\r\n * @param {Number|Array} indicesLengthOrArray Passed through to the typed array constructor.\r\n * @returns {Uint16Array|Uint32Array} A Uint16Array or Uint32Array constructed with indicesLengthOrArray.\r\n *\r\n * @example\r\n * this.indices = Cesium.IndexDatatype.createTypedArray(positions.length / 3, numberOfIndices);\r\n */\r\nIndexDatatype.createTypedArray = function (\r\n numberOfVertices,\r\n indicesLengthOrArray\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(numberOfVertices)) {\r\n throw new DeveloperError(\"numberOfVertices is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (numberOfVertices >= CesiumMath.SIXTY_FOUR_KILOBYTES) {\r\n return new Uint32Array(indicesLengthOrArray);\r\n }\r\n\r\n return new Uint16Array(indicesLengthOrArray);\r\n};\r\n\r\n/**\r\n * Creates a typed array from a source array buffer. The resulting typed array will store indices, using either \r\n * or Uint32Array depending on the number of vertices.\r\n *\r\n * @param {Number} numberOfVertices Number of vertices that the indices will reference.\r\n * @param {ArrayBuffer} sourceArray Passed through to the typed array constructor.\r\n * @param {Number} byteOffset Passed through to the typed array constructor.\r\n * @param {Number} length Passed through to the typed array constructor.\r\n * @returns {Uint16Array|Uint32Array} A Uint16Array or Uint32Array constructed with sourceArray, byteOffset, and length.\r\n *\r\n */\r\nIndexDatatype.createTypedArrayFromArrayBuffer = function (\r\n numberOfVertices,\r\n sourceArray,\r\n byteOffset,\r\n length\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(numberOfVertices)) {\r\n throw new DeveloperError(\"numberOfVertices is required.\");\r\n }\r\n if (!defined(sourceArray)) {\r\n throw new DeveloperError(\"sourceArray is required.\");\r\n }\r\n if (!defined(byteOffset)) {\r\n throw new DeveloperError(\"byteOffset is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (numberOfVertices >= CesiumMath.SIXTY_FOUR_KILOBYTES) {\r\n return new Uint32Array(sourceArray, byteOffset, length);\r\n }\r\n\r\n return new Uint16Array(sourceArray, byteOffset, length);\r\n};\r\nexport default Object.freeze(IndexDatatype);\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * Provides terrain or other geometry for the surface of an ellipsoid. The surface geometry is\r\n * organized into a pyramid of tiles according to a {@link TilingScheme}. This type describes an\r\n * interface and is not intended to be instantiated directly.\r\n *\r\n * @alias TerrainProvider\r\n * @constructor\r\n *\r\n * @see EllipsoidTerrainProvider\r\n * @see CesiumTerrainProvider\r\n * @see VRTheWorldTerrainProvider\r\n * @see GoogleEarthEnterpriseTerrainProvider\r\n */\r\nfunction TerrainProvider() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\nObject.defineProperties(TerrainProvider.prototype, {\r\n /**\r\n * Gets an event that is raised when the terrain provider encounters an asynchronous error.. By subscribing\r\n * to the event, you will be notified of the error and can potentially recover from it. Event listeners\r\n * are passed an instance of {@link TileProviderError}.\r\n * @memberof TerrainProvider.prototype\r\n * @type {Event}\r\n */\r\n errorEvent: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets the credit to display when this terrain provider is active. Typically this is used to credit\r\n * the source of the terrain. This function should\r\n * not be called before {@link TerrainProvider#ready} returns true.\r\n * @memberof TerrainProvider.prototype\r\n * @type {Credit}\r\n */\r\n credit: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets the tiling scheme used by the provider. This function should\r\n * not be called before {@link TerrainProvider#ready} returns true.\r\n * @memberof TerrainProvider.prototype\r\n * @type {TilingScheme}\r\n */\r\n tilingScheme: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider is ready for use.\r\n * @memberof TerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n ready: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves to true when the provider is ready for use.\r\n * @memberof TerrainProvider.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider includes a water mask. The water mask\r\n * indicates which areas of the globe are water rather than land, so they can be rendered\r\n * as a reflective surface with animated waves. This function should not be\r\n * called before {@link TerrainProvider#ready} returns true.\r\n * @memberof TerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasWaterMask: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the requested tiles include vertex normals.\r\n * This function should not be called before {@link TerrainProvider#ready} returns true.\r\n * @memberof TerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasVertexNormals: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets an object that can be used to determine availability of terrain from this provider, such as\r\n * at points and in rectangles. This function should not be called before\r\n * {@link TerrainProvider#ready} returns true. This property may be undefined if availability\r\n * information is not available.\r\n * @memberof TerrainProvider.prototype\r\n * @type {TileAvailability}\r\n */\r\n availability: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n});\r\n\r\nvar regularGridIndicesCache = [];\r\n\r\n/**\r\n * Gets a list of indices for a triangle mesh representing a regular grid. Calling\r\n * this function multiple times with the same grid width and height returns the\r\n * same list of indices. The total number of vertices must be less than or equal\r\n * to 65536.\r\n *\r\n * @param {Number} width The number of vertices in the regular grid in the horizontal direction.\r\n * @param {Number} height The number of vertices in the regular grid in the vertical direction.\r\n * @returns {Uint16Array|Uint32Array} The list of indices. Uint16Array gets returned for 64KB or less and Uint32Array for 4GB or less.\r\n */\r\nTerrainProvider.getRegularGridIndices = function (width, height) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (width * height >= CesiumMath.FOUR_GIGABYTES) {\r\n throw new DeveloperError(\r\n \"The total number of vertices (width * height) must be less than 4,294,967,296.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var byWidth = regularGridIndicesCache[width];\r\n if (!defined(byWidth)) {\r\n regularGridIndicesCache[width] = byWidth = [];\r\n }\r\n\r\n var indices = byWidth[height];\r\n if (!defined(indices)) {\r\n if (width * height < CesiumMath.SIXTY_FOUR_KILOBYTES) {\r\n indices = byWidth[height] = new Uint16Array(\r\n (width - 1) * (height - 1) * 6\r\n );\r\n } else {\r\n indices = byWidth[height] = new Uint32Array(\r\n (width - 1) * (height - 1) * 6\r\n );\r\n }\r\n addRegularGridIndices(width, height, indices, 0);\r\n }\r\n\r\n return indices;\r\n};\r\n\r\nvar regularGridAndEdgeIndicesCache = [];\r\n\r\n/**\r\n * @private\r\n */\r\nTerrainProvider.getRegularGridIndicesAndEdgeIndices = function (width, height) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (width * height >= CesiumMath.FOUR_GIGABYTES) {\r\n throw new DeveloperError(\r\n \"The total number of vertices (width * height) must be less than 4,294,967,296.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var byWidth = regularGridAndEdgeIndicesCache[width];\r\n if (!defined(byWidth)) {\r\n regularGridAndEdgeIndicesCache[width] = byWidth = [];\r\n }\r\n\r\n var indicesAndEdges = byWidth[height];\r\n if (!defined(indicesAndEdges)) {\r\n var indices = TerrainProvider.getRegularGridIndices(width, height);\r\n\r\n var edgeIndices = getEdgeIndices(width, height);\r\n var westIndicesSouthToNorth = edgeIndices.westIndicesSouthToNorth;\r\n var southIndicesEastToWest = edgeIndices.southIndicesEastToWest;\r\n var eastIndicesNorthToSouth = edgeIndices.eastIndicesNorthToSouth;\r\n var northIndicesWestToEast = edgeIndices.northIndicesWestToEast;\r\n\r\n indicesAndEdges = byWidth[height] = {\r\n indices: indices,\r\n westIndicesSouthToNorth: westIndicesSouthToNorth,\r\n southIndicesEastToWest: southIndicesEastToWest,\r\n eastIndicesNorthToSouth: eastIndicesNorthToSouth,\r\n northIndicesWestToEast: northIndicesWestToEast,\r\n };\r\n }\r\n\r\n return indicesAndEdges;\r\n};\r\n\r\nvar regularGridAndSkirtAndEdgeIndicesCache = [];\r\n\r\n/**\r\n * @private\r\n */\r\nTerrainProvider.getRegularGridAndSkirtIndicesAndEdgeIndices = function (\r\n width,\r\n height\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (width * height >= CesiumMath.FOUR_GIGABYTES) {\r\n throw new DeveloperError(\r\n \"The total number of vertices (width * height) must be less than 4,294,967,296.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var byWidth = regularGridAndSkirtAndEdgeIndicesCache[width];\r\n if (!defined(byWidth)) {\r\n regularGridAndSkirtAndEdgeIndicesCache[width] = byWidth = [];\r\n }\r\n\r\n var indicesAndEdges = byWidth[height];\r\n if (!defined(indicesAndEdges)) {\r\n var gridVertexCount = width * height;\r\n var gridIndexCount = (width - 1) * (height - 1) * 6;\r\n var edgeVertexCount = width * 2 + height * 2;\r\n var edgeIndexCount = Math.max(0, edgeVertexCount - 4) * 6;\r\n var vertexCount = gridVertexCount + edgeVertexCount;\r\n var indexCount = gridIndexCount + edgeIndexCount;\r\n\r\n var edgeIndices = getEdgeIndices(width, height);\r\n var westIndicesSouthToNorth = edgeIndices.westIndicesSouthToNorth;\r\n var southIndicesEastToWest = edgeIndices.southIndicesEastToWest;\r\n var eastIndicesNorthToSouth = edgeIndices.eastIndicesNorthToSouth;\r\n var northIndicesWestToEast = edgeIndices.northIndicesWestToEast;\r\n\r\n var indices = IndexDatatype.createTypedArray(vertexCount, indexCount);\r\n addRegularGridIndices(width, height, indices, 0);\r\n TerrainProvider.addSkirtIndices(\r\n westIndicesSouthToNorth,\r\n southIndicesEastToWest,\r\n eastIndicesNorthToSouth,\r\n northIndicesWestToEast,\r\n gridVertexCount,\r\n indices,\r\n gridIndexCount\r\n );\r\n\r\n indicesAndEdges = byWidth[height] = {\r\n indices: indices,\r\n westIndicesSouthToNorth: westIndicesSouthToNorth,\r\n southIndicesEastToWest: southIndicesEastToWest,\r\n eastIndicesNorthToSouth: eastIndicesNorthToSouth,\r\n northIndicesWestToEast: northIndicesWestToEast,\r\n indexCountWithoutSkirts: gridIndexCount,\r\n };\r\n }\r\n\r\n return indicesAndEdges;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nTerrainProvider.addSkirtIndices = function (\r\n westIndicesSouthToNorth,\r\n southIndicesEastToWest,\r\n eastIndicesNorthToSouth,\r\n northIndicesWestToEast,\r\n vertexCount,\r\n indices,\r\n offset\r\n) {\r\n var vertexIndex = vertexCount;\r\n offset = addSkirtIndices(\r\n westIndicesSouthToNorth,\r\n vertexIndex,\r\n indices,\r\n offset\r\n );\r\n vertexIndex += westIndicesSouthToNorth.length;\r\n offset = addSkirtIndices(\r\n southIndicesEastToWest,\r\n vertexIndex,\r\n indices,\r\n offset\r\n );\r\n vertexIndex += southIndicesEastToWest.length;\r\n offset = addSkirtIndices(\r\n eastIndicesNorthToSouth,\r\n vertexIndex,\r\n indices,\r\n offset\r\n );\r\n vertexIndex += eastIndicesNorthToSouth.length;\r\n addSkirtIndices(northIndicesWestToEast, vertexIndex, indices, offset);\r\n};\r\n\r\nfunction getEdgeIndices(width, height) {\r\n var westIndicesSouthToNorth = new Array(height);\r\n var southIndicesEastToWest = new Array(width);\r\n var eastIndicesNorthToSouth = new Array(height);\r\n var northIndicesWestToEast = new Array(width);\r\n\r\n var i;\r\n for (i = 0; i < width; ++i) {\r\n northIndicesWestToEast[i] = i;\r\n southIndicesEastToWest[i] = width * height - 1 - i;\r\n }\r\n\r\n for (i = 0; i < height; ++i) {\r\n eastIndicesNorthToSouth[i] = (i + 1) * width - 1;\r\n westIndicesSouthToNorth[i] = (height - i - 1) * width;\r\n }\r\n\r\n return {\r\n westIndicesSouthToNorth: westIndicesSouthToNorth,\r\n southIndicesEastToWest: southIndicesEastToWest,\r\n eastIndicesNorthToSouth: eastIndicesNorthToSouth,\r\n northIndicesWestToEast: northIndicesWestToEast,\r\n };\r\n}\r\n\r\nfunction addRegularGridIndices(width, height, indices, offset) {\r\n var index = 0;\r\n for (var j = 0; j < height - 1; ++j) {\r\n for (var i = 0; i < width - 1; ++i) {\r\n var upperLeft = index;\r\n var lowerLeft = upperLeft + width;\r\n var lowerRight = lowerLeft + 1;\r\n var upperRight = upperLeft + 1;\r\n\r\n indices[offset++] = upperLeft;\r\n indices[offset++] = lowerLeft;\r\n indices[offset++] = upperRight;\r\n indices[offset++] = upperRight;\r\n indices[offset++] = lowerLeft;\r\n indices[offset++] = lowerRight;\r\n\r\n ++index;\r\n }\r\n ++index;\r\n }\r\n}\r\n\r\nfunction addSkirtIndices(edgeIndices, vertexIndex, indices, offset) {\r\n var previousIndex = edgeIndices[0];\r\n\r\n var length = edgeIndices.length;\r\n for (var i = 1; i < length; ++i) {\r\n var index = edgeIndices[i];\r\n\r\n indices[offset++] = previousIndex;\r\n indices[offset++] = index;\r\n indices[offset++] = vertexIndex;\r\n\r\n indices[offset++] = vertexIndex;\r\n indices[offset++] = index;\r\n indices[offset++] = vertexIndex + 1;\r\n\r\n previousIndex = index;\r\n ++vertexIndex;\r\n }\r\n\r\n return offset;\r\n}\r\n\r\n/**\r\n * Specifies the quality of terrain created from heightmaps. A value of 1.0 will\r\n * ensure that adjacent heightmap vertices are separated by no more than\r\n * {@link Globe.maximumScreenSpaceError} screen pixels and will probably go very slowly.\r\n * A value of 0.5 will cut the estimated level zero geometric error in half, allowing twice the\r\n * screen pixels between adjacent heightmap vertices and thus rendering more quickly.\r\n * @type {Number}\r\n */\r\nTerrainProvider.heightmapTerrainQuality = 0.25;\r\n\r\n/**\r\n * Determines an appropriate geometric error estimate when the geometry comes from a heightmap.\r\n *\r\n * @param {Ellipsoid} ellipsoid The ellipsoid to which the terrain is attached.\r\n * @param {Number} tileImageWidth The width, in pixels, of the heightmap associated with a single tile.\r\n * @param {Number} numberOfTilesAtLevelZero The number of tiles in the horizontal direction at tile level zero.\r\n * @returns {Number} An estimated geometric error.\r\n */\r\nTerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap = function (\r\n ellipsoid,\r\n tileImageWidth,\r\n numberOfTilesAtLevelZero\r\n) {\r\n return (\r\n (ellipsoid.maximumRadius *\r\n 2 *\r\n Math.PI *\r\n TerrainProvider.heightmapTerrainQuality) /\r\n (tileImageWidth * numberOfTilesAtLevelZero)\r\n );\r\n};\r\n\r\n/**\r\n * Requests the geometry for a given tile. This function should not be called before\r\n * {@link TerrainProvider#ready} returns true. The result must include terrain data and\r\n * may optionally include a water mask and an indication of which child tiles are available.\r\n * @function\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @param {Request} [request] The request object. Intended for internal use only.\r\n *\r\n * @returns {Promise.|undefined} A promise for the requested geometry. If this method\r\n * returns undefined instead of a promise, it is an indication that too many requests are already\r\n * pending and the request will be retried later.\r\n */\r\nTerrainProvider.prototype.requestTileGeometry =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Gets the maximum geometric error allowed in a tile at a given level. This function should not be\r\n * called before {@link TerrainProvider#ready} returns true.\r\n * @function\r\n *\r\n * @param {Number} level The tile level for which to get the maximum geometric error.\r\n * @returns {Number} The maximum geometric error.\r\n */\r\nTerrainProvider.prototype.getLevelMaximumGeometricError =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Determines whether data for a tile is available to be loaded.\r\n * @function\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {Boolean} Undefined if not supported by the terrain provider, otherwise true or false.\r\n */\r\nTerrainProvider.prototype.getTileDataAvailable =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Makes sure we load availability data for a tile\r\n * @function\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {undefined|Promise} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded\r\n */\r\nTerrainProvider.prototype.loadTileDataAvailability =\r\n DeveloperError.throwInstantiationError;\r\nexport default TerrainProvider;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport GeographicProjection from \"./GeographicProjection.js\";\r\nimport HeightmapEncoding from \"./HeightmapEncoding.js\";\r\nimport HeightmapTessellator from \"./HeightmapTessellator.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport OrientedBoundingBox from \"./OrientedBoundingBox.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport TaskProcessor from \"./TaskProcessor.js\";\r\nimport TerrainData from \"./TerrainData.js\";\r\nimport TerrainEncoding from \"./TerrainEncoding.js\";\r\nimport TerrainMesh from \"./TerrainMesh.js\";\r\nimport TerrainProvider from \"./TerrainProvider.js\";\r\n\r\n/**\r\n * Terrain data for a single tile where the terrain data is represented as a heightmap. A heightmap\r\n * is a rectangular array of heights in row-major order from north to south and west to east.\r\n *\r\n * @alias HeightmapTerrainData\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} options.buffer The buffer containing height data.\r\n * @param {Number} options.width The width (longitude direction) of the heightmap, in samples.\r\n * @param {Number} options.height The height (latitude direction) of the heightmap, in samples.\r\n * @param {Number} [options.childTileMask=15] A bit mask indicating which of this tile's four children exist.\r\n * If a child's bit is set, geometry will be requested for that tile as well when it\r\n * is needed. If the bit is cleared, the child tile is not requested and geometry is\r\n * instead upsampled from the parent. The bit values are as follows:\r\n * \r\n * \r\n * \r\n * \r\n * \r\n * \r\n *
Bit PositionBit ValueChild Tile
01Southwest
12Southeast
24Northwest
38Northeast
\r\n * @param {Uint8Array} [options.waterMask] The water mask included in this terrain data, if any. A water mask is a square\r\n * Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.\r\n * Values in between 0 and 255 are allowed as well to smoothly blend between land and water.\r\n * @param {Object} [options.structure] An object describing the structure of the height data.\r\n * @param {Number} [options.structure.heightScale=1.0] The factor by which to multiply height samples in order to obtain\r\n * the height above the heightOffset, in meters. The heightOffset is added to the resulting\r\n * height after multiplying by the scale.\r\n * @param {Number} [options.structure.heightOffset=0.0] The offset to add to the scaled height to obtain the final\r\n * height in meters. The offset is added after the height sample is multiplied by the\r\n * heightScale.\r\n * @param {Number} [options.structure.elementsPerHeight=1] The number of elements in the buffer that make up a single height\r\n * sample. This is usually 1, indicating that each element is a separate height sample. If\r\n * it is greater than 1, that number of elements together form the height sample, which is\r\n * computed according to the structure.elementMultiplier and structure.isBigEndian properties.\r\n * @param {Number} [options.structure.stride=1] The number of elements to skip to get from the first element of\r\n * one height to the first element of the next height.\r\n * @param {Number} [options.structure.elementMultiplier=256.0] The multiplier used to compute the height value when the\r\n * stride property is greater than 1. For example, if the stride is 4 and the strideMultiplier\r\n * is 256, the height is computed as follows:\r\n * `height = buffer[index] + buffer[index + 1] * 256 + buffer[index + 2] * 256 * 256 + buffer[index + 3] * 256 * 256 * 256`\r\n * This is assuming that the isBigEndian property is false. If it is true, the order of the\r\n * elements is reversed.\r\n * @param {Boolean} [options.structure.isBigEndian=false] Indicates endianness of the elements in the buffer when the\r\n * stride property is greater than 1. If this property is false, the first element is the\r\n * low-order element. If it is true, the first element is the high-order element.\r\n * @param {Number} [options.structure.lowestEncodedHeight] The lowest value that can be stored in the height buffer. Any heights that are lower\r\n * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height\r\n * buffer is a `Uint16Array`, this value should be 0 because a `Uint16Array` cannot store negative numbers. If this parameter is\r\n * not specified, no minimum value is enforced.\r\n * @param {Number} [options.structure.highestEncodedHeight] The highest value that can be stored in the height buffer. Any heights that are higher\r\n * than this value after encoding with the `heightScale` and `heightOffset` are clamped to this value. For example, if the height\r\n * buffer is a `Uint16Array`, this value should be `256 * 256 - 1` or 65535 because a `Uint16Array` cannot store numbers larger\r\n * than 65535. If this parameter is not specified, no maximum value is enforced.\r\n * @param {HeightmapEncoding} [options.encoding=HeightmapEncoding.NONE] The encoding that is used on the buffer.\r\n * @param {Boolean} [options.createdByUpsampling=false] True if this instance was created by upsampling another instance;\r\n * otherwise, false.\r\n *\r\n *\r\n * @example\r\n * var buffer = ...\r\n * var heightBuffer = new Uint16Array(buffer, 0, that._heightmapWidth * that._heightmapWidth);\r\n * var childTileMask = new Uint8Array(buffer, heightBuffer.byteLength, 1)[0];\r\n * var waterMask = new Uint8Array(buffer, heightBuffer.byteLength + 1, buffer.byteLength - heightBuffer.byteLength - 1);\r\n * var terrainData = new Cesium.HeightmapTerrainData({\r\n * buffer : heightBuffer,\r\n * width : 65,\r\n * height : 65,\r\n * childTileMask : childTileMask,\r\n * waterMask : waterMask\r\n * });\r\n *\r\n * @see TerrainData\r\n * @see QuantizedMeshTerrainData\r\n * @see GoogleEarthEnterpriseTerrainData\r\n */\r\nfunction HeightmapTerrainData(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options) || !defined(options.buffer)) {\r\n throw new DeveloperError(\"options.buffer is required.\");\r\n }\r\n if (!defined(options.width)) {\r\n throw new DeveloperError(\"options.width is required.\");\r\n }\r\n if (!defined(options.height)) {\r\n throw new DeveloperError(\"options.height is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._buffer = options.buffer;\r\n this._width = options.width;\r\n this._height = options.height;\r\n this._childTileMask = defaultValue(options.childTileMask, 15);\r\n this._encoding = defaultValue(options.encoding, HeightmapEncoding.NONE);\r\n\r\n var defaultStructure = HeightmapTessellator.DEFAULT_STRUCTURE;\r\n var structure = options.structure;\r\n if (!defined(structure)) {\r\n structure = defaultStructure;\r\n } else if (structure !== defaultStructure) {\r\n structure.heightScale = defaultValue(\r\n structure.heightScale,\r\n defaultStructure.heightScale\r\n );\r\n structure.heightOffset = defaultValue(\r\n structure.heightOffset,\r\n defaultStructure.heightOffset\r\n );\r\n structure.elementsPerHeight = defaultValue(\r\n structure.elementsPerHeight,\r\n defaultStructure.elementsPerHeight\r\n );\r\n structure.stride = defaultValue(structure.stride, defaultStructure.stride);\r\n structure.elementMultiplier = defaultValue(\r\n structure.elementMultiplier,\r\n defaultStructure.elementMultiplier\r\n );\r\n structure.isBigEndian = defaultValue(\r\n structure.isBigEndian,\r\n defaultStructure.isBigEndian\r\n );\r\n }\r\n\r\n this._structure = structure;\r\n this._createdByUpsampling = defaultValue(options.createdByUpsampling, false);\r\n this._waterMask = options.waterMask;\r\n\r\n this._skirtHeight = undefined;\r\n this._bufferType =\r\n this._encoding === HeightmapEncoding.LERC\r\n ? Float32Array\r\n : this._buffer.constructor;\r\n this._mesh = undefined;\r\n}\r\n\r\nObject.defineProperties(HeightmapTerrainData.prototype, {\r\n /**\r\n * An array of credits for this tile.\r\n * @memberof HeightmapTerrainData.prototype\r\n * @type {Credit[]}\r\n */\r\n credits: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n /**\r\n * The water mask included in this terrain data, if any. A water mask is a square\r\n * Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.\r\n * Values in between 0 and 255 are allowed as well to smoothly blend between land and water.\r\n * @memberof HeightmapTerrainData.prototype\r\n * @type {Uint8Array|HTMLImageElement|HTMLCanvasElement}\r\n */\r\n waterMask: {\r\n get: function () {\r\n return this._waterMask;\r\n },\r\n },\r\n\r\n childTileMask: {\r\n get: function () {\r\n return this._childTileMask;\r\n },\r\n },\r\n});\r\n\r\nvar createMeshTaskName = \"createVerticesFromHeightmap\";\r\nvar createMeshTaskProcessorNoThrottle = new TaskProcessor(createMeshTaskName);\r\nvar createMeshTaskProcessorThrottle = new TaskProcessor(\r\n createMeshTaskName,\r\n TerrainData.maximumAsynchronousTasks\r\n);\r\n\r\n/**\r\n * Creates a {@link TerrainMesh} from this terrain data.\r\n *\r\n * @private\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {TilingScheme} options.tilingScheme The tiling scheme to which this tile belongs.\r\n * @param {Number} options.x The X coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.y The Y coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.level The level of the tile for which to create the terrain data.\r\n * @param {Number} [options.exaggeration=1.0] The scale used to exaggerate the terrain.\r\n * @param {Boolean} [options.throttle=true] If true, indicates that this operation will need to be retried if too many asynchronous mesh creations are already in progress.\r\n * @returns {Promise.|undefined} A promise for the terrain mesh, or undefined if too many\r\n * asynchronous mesh creations are already in progress and the operation should\r\n * be retried later.\r\n */\r\nHeightmapTerrainData.prototype.createMesh = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options.tilingScheme\", options.tilingScheme);\r\n Check.typeOf.number(\"options.x\", options.x);\r\n Check.typeOf.number(\"options.y\", options.y);\r\n Check.typeOf.number(\"options.level\", options.level);\r\n //>>includeEnd('debug');\r\n\r\n var tilingScheme = options.tilingScheme;\r\n var x = options.x;\r\n var y = options.y;\r\n var level = options.level;\r\n var exaggeration = defaultValue(options.exaggeration, 1.0);\r\n var throttle = defaultValue(options.throttle, true);\r\n\r\n var ellipsoid = tilingScheme.ellipsoid;\r\n var nativeRectangle = tilingScheme.tileXYToNativeRectangle(x, y, level);\r\n var rectangle = tilingScheme.tileXYToRectangle(x, y, level);\r\n\r\n // Compute the center of the tile for RTC rendering.\r\n var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle));\r\n\r\n var structure = this._structure;\r\n\r\n var levelZeroMaxError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(\r\n ellipsoid,\r\n this._width,\r\n tilingScheme.getNumberOfXTilesAtLevel(0)\r\n );\r\n var thisLevelMaxError = levelZeroMaxError / (1 << level);\r\n this._skirtHeight = Math.min(thisLevelMaxError * 4.0, 1000.0);\r\n\r\n var createMeshTaskProcessor = throttle\r\n ? createMeshTaskProcessorThrottle\r\n : createMeshTaskProcessorNoThrottle;\r\n\r\n var verticesPromise = createMeshTaskProcessor.scheduleTask({\r\n heightmap: this._buffer,\r\n structure: structure,\r\n includeWebMercatorT: true,\r\n width: this._width,\r\n height: this._height,\r\n nativeRectangle: nativeRectangle,\r\n rectangle: rectangle,\r\n relativeToCenter: center,\r\n ellipsoid: ellipsoid,\r\n skirtHeight: this._skirtHeight,\r\n isGeographic: tilingScheme.projection instanceof GeographicProjection,\r\n exaggeration: exaggeration,\r\n encoding: this._encoding,\r\n });\r\n\r\n if (!defined(verticesPromise)) {\r\n // Postponed\r\n return undefined;\r\n }\r\n\r\n var that = this;\r\n return when(verticesPromise, function (result) {\r\n var indicesAndEdges;\r\n if (that._skirtHeight > 0.0) {\r\n indicesAndEdges = TerrainProvider.getRegularGridAndSkirtIndicesAndEdgeIndices(\r\n result.gridWidth,\r\n result.gridHeight\r\n );\r\n } else {\r\n indicesAndEdges = TerrainProvider.getRegularGridIndicesAndEdgeIndices(\r\n result.gridWidth,\r\n result.gridHeight\r\n );\r\n }\r\n\r\n var vertexCountWithoutSkirts = result.gridWidth * result.gridHeight;\r\n\r\n // Clone complex result objects because the transfer from the web worker\r\n // has stripped them down to JSON-style objects.\r\n that._mesh = new TerrainMesh(\r\n center,\r\n new Float32Array(result.vertices),\r\n indicesAndEdges.indices,\r\n indicesAndEdges.indexCountWithoutSkirts,\r\n vertexCountWithoutSkirts,\r\n result.minimumHeight,\r\n result.maximumHeight,\r\n BoundingSphere.clone(result.boundingSphere3D),\r\n Cartesian3.clone(result.occludeePointInScaledSpace),\r\n result.numberOfAttributes,\r\n OrientedBoundingBox.clone(result.orientedBoundingBox),\r\n TerrainEncoding.clone(result.encoding),\r\n exaggeration,\r\n indicesAndEdges.westIndicesSouthToNorth,\r\n indicesAndEdges.southIndicesEastToWest,\r\n indicesAndEdges.eastIndicesNorthToSouth,\r\n indicesAndEdges.northIndicesWestToEast\r\n );\r\n\r\n // Free memory received from server after mesh is created.\r\n that._buffer = undefined;\r\n return that._mesh;\r\n });\r\n};\r\n\r\n/**\r\n * @param {Object} options Object with the following properties:\r\n * @param {TilingScheme} options.tilingScheme The tiling scheme to which this tile belongs.\r\n * @param {Number} options.x The X coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.y The Y coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.level The level of the tile for which to create the terrain data.\r\n * @param {Number} [options.exaggeration=1.0] The scale used to exaggerate the terrain.\r\n *\r\n * @private\r\n */\r\nHeightmapTerrainData.prototype._createMeshSync = function (options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options.tilingScheme\", options.tilingScheme);\r\n Check.typeOf.number(\"options.x\", options.x);\r\n Check.typeOf.number(\"options.y\", options.y);\r\n Check.typeOf.number(\"options.level\", options.level);\r\n //>>includeEnd('debug');\r\n\r\n var tilingScheme = options.tilingScheme;\r\n var x = options.x;\r\n var y = options.y;\r\n var level = options.level;\r\n var exaggeration = defaultValue(options.exaggeration, 1.0);\r\n\r\n var ellipsoid = tilingScheme.ellipsoid;\r\n var nativeRectangle = tilingScheme.tileXYToNativeRectangle(x, y, level);\r\n var rectangle = tilingScheme.tileXYToRectangle(x, y, level);\r\n\r\n // Compute the center of the tile for RTC rendering.\r\n var center = ellipsoid.cartographicToCartesian(Rectangle.center(rectangle));\r\n\r\n var structure = this._structure;\r\n\r\n var levelZeroMaxError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(\r\n ellipsoid,\r\n this._width,\r\n tilingScheme.getNumberOfXTilesAtLevel(0)\r\n );\r\n var thisLevelMaxError = levelZeroMaxError / (1 << level);\r\n this._skirtHeight = Math.min(thisLevelMaxError * 4.0, 1000.0);\r\n\r\n var result = HeightmapTessellator.computeVertices({\r\n heightmap: this._buffer,\r\n structure: structure,\r\n includeWebMercatorT: true,\r\n width: this._width,\r\n height: this._height,\r\n nativeRectangle: nativeRectangle,\r\n rectangle: rectangle,\r\n relativeToCenter: center,\r\n ellipsoid: ellipsoid,\r\n skirtHeight: this._skirtHeight,\r\n isGeographic: tilingScheme.projection instanceof GeographicProjection,\r\n exaggeration: exaggeration,\r\n });\r\n\r\n // Free memory received from server after mesh is created.\r\n this._buffer = undefined;\r\n\r\n var indicesAndEdges;\r\n if (this._skirtHeight > 0.0) {\r\n indicesAndEdges = TerrainProvider.getRegularGridAndSkirtIndicesAndEdgeIndices(\r\n this._width,\r\n this._height\r\n );\r\n } else {\r\n indicesAndEdges = TerrainProvider.getRegularGridIndicesAndEdgeIndices(\r\n this._width,\r\n this._height\r\n );\r\n }\r\n\r\n var vertexCountWithoutSkirts = result.gridWidth * result.gridHeight;\r\n\r\n // No need to clone here (as we do in the async version) because the result\r\n // is not coming from a web worker.\r\n return new TerrainMesh(\r\n center,\r\n result.vertices,\r\n indicesAndEdges.indices,\r\n indicesAndEdges.indexCountWithoutSkirts,\r\n vertexCountWithoutSkirts,\r\n result.minimumHeight,\r\n result.maximumHeight,\r\n result.boundingSphere3D,\r\n result.occludeePointInScaledSpace,\r\n result.encoding.getStride(),\r\n result.orientedBoundingBox,\r\n result.encoding,\r\n exaggeration,\r\n indicesAndEdges.westIndicesSouthToNorth,\r\n indicesAndEdges.southIndicesEastToWest,\r\n indicesAndEdges.eastIndicesNorthToSouth,\r\n indicesAndEdges.northIndicesWestToEast\r\n );\r\n};\r\n\r\n/**\r\n * Computes the terrain height at a specified longitude and latitude.\r\n *\r\n * @param {Rectangle} rectangle The rectangle covered by this terrain data.\r\n * @param {Number} longitude The longitude in radians.\r\n * @param {Number} latitude The latitude in radians.\r\n * @returns {Number} The terrain height at the specified position. If the position\r\n * is outside the rectangle, this method will extrapolate the height, which is likely to be wildly\r\n * incorrect for positions far outside the rectangle.\r\n */\r\nHeightmapTerrainData.prototype.interpolateHeight = function (\r\n rectangle,\r\n longitude,\r\n latitude\r\n) {\r\n var width = this._width;\r\n var height = this._height;\r\n\r\n var structure = this._structure;\r\n var stride = structure.stride;\r\n var elementsPerHeight = structure.elementsPerHeight;\r\n var elementMultiplier = structure.elementMultiplier;\r\n var isBigEndian = structure.isBigEndian;\r\n var heightOffset = structure.heightOffset;\r\n var heightScale = structure.heightScale;\r\n\r\n var isMeshCreated = defined(this._mesh);\r\n var isLERCEncoding = this._encoding === HeightmapEncoding.LERC;\r\n var isInterpolationImpossible = !isMeshCreated && isLERCEncoding;\r\n if (isInterpolationImpossible) {\r\n // We can't interpolate using the buffer because it's LERC encoded\r\n // so please call createMesh() first and interpolate using the mesh;\r\n // as mesh creation will decode the LERC buffer\r\n return undefined;\r\n }\r\n\r\n var heightSample;\r\n if (isMeshCreated) {\r\n var buffer = this._mesh.vertices;\r\n var encoding = this._mesh.encoding;\r\n var exaggeration = this._mesh.exaggeration;\r\n heightSample = interpolateMeshHeight(\r\n buffer,\r\n encoding,\r\n heightOffset,\r\n heightScale,\r\n rectangle,\r\n width,\r\n height,\r\n longitude,\r\n latitude,\r\n exaggeration\r\n );\r\n } else {\r\n heightSample = interpolateHeight(\r\n this._buffer,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n stride,\r\n isBigEndian,\r\n rectangle,\r\n width,\r\n height,\r\n longitude,\r\n latitude\r\n );\r\n heightSample = heightSample * heightScale + heightOffset;\r\n }\r\n\r\n return heightSample;\r\n};\r\n\r\n/**\r\n * Upsamples this terrain data for use by a descendant tile. The resulting instance will contain a subset of the\r\n * height samples in this instance, interpolated if necessary.\r\n *\r\n * @param {TilingScheme} tilingScheme The tiling scheme of this terrain data.\r\n * @param {Number} thisX The X coordinate of this tile in the tiling scheme.\r\n * @param {Number} thisY The Y coordinate of this tile in the tiling scheme.\r\n * @param {Number} thisLevel The level of this tile in the tiling scheme.\r\n * @param {Number} descendantX The X coordinate within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @param {Number} descendantY The Y coordinate within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @param {Number} descendantLevel The level within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @returns {Promise.|undefined} A promise for upsampled heightmap terrain data for the descendant tile,\r\n * or undefined if too many asynchronous upsample operations are in progress and the request has been\r\n * deferred.\r\n */\r\nHeightmapTerrainData.prototype.upsample = function (\r\n tilingScheme,\r\n thisX,\r\n thisY,\r\n thisLevel,\r\n descendantX,\r\n descendantY,\r\n descendantLevel\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(tilingScheme)) {\r\n throw new DeveloperError(\"tilingScheme is required.\");\r\n }\r\n if (!defined(thisX)) {\r\n throw new DeveloperError(\"thisX is required.\");\r\n }\r\n if (!defined(thisY)) {\r\n throw new DeveloperError(\"thisY is required.\");\r\n }\r\n if (!defined(thisLevel)) {\r\n throw new DeveloperError(\"thisLevel is required.\");\r\n }\r\n if (!defined(descendantX)) {\r\n throw new DeveloperError(\"descendantX is required.\");\r\n }\r\n if (!defined(descendantY)) {\r\n throw new DeveloperError(\"descendantY is required.\");\r\n }\r\n if (!defined(descendantLevel)) {\r\n throw new DeveloperError(\"descendantLevel is required.\");\r\n }\r\n var levelDifference = descendantLevel - thisLevel;\r\n if (levelDifference > 1) {\r\n throw new DeveloperError(\r\n \"Upsampling through more than one level at a time is not currently supported.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var meshData = this._mesh;\r\n if (!defined(meshData)) {\r\n return undefined;\r\n }\r\n\r\n var width = this._width;\r\n var height = this._height;\r\n var structure = this._structure;\r\n var stride = structure.stride;\r\n\r\n var heights = new this._bufferType(width * height * stride);\r\n\r\n var buffer = meshData.vertices;\r\n var encoding = meshData.encoding;\r\n\r\n // PERFORMANCE_IDEA: don't recompute these rectangles - the caller already knows them.\r\n var sourceRectangle = tilingScheme.tileXYToRectangle(thisX, thisY, thisLevel);\r\n var destinationRectangle = tilingScheme.tileXYToRectangle(\r\n descendantX,\r\n descendantY,\r\n descendantLevel\r\n );\r\n\r\n var heightOffset = structure.heightOffset;\r\n var heightScale = structure.heightScale;\r\n var exaggeration = meshData.exaggeration;\r\n\r\n var elementsPerHeight = structure.elementsPerHeight;\r\n var elementMultiplier = structure.elementMultiplier;\r\n var isBigEndian = structure.isBigEndian;\r\n\r\n var divisor = Math.pow(elementMultiplier, elementsPerHeight - 1);\r\n\r\n for (var j = 0; j < height; ++j) {\r\n var latitude = CesiumMath.lerp(\r\n destinationRectangle.north,\r\n destinationRectangle.south,\r\n j / (height - 1)\r\n );\r\n for (var i = 0; i < width; ++i) {\r\n var longitude = CesiumMath.lerp(\r\n destinationRectangle.west,\r\n destinationRectangle.east,\r\n i / (width - 1)\r\n );\r\n var heightSample = interpolateMeshHeight(\r\n buffer,\r\n encoding,\r\n heightOffset,\r\n heightScale,\r\n sourceRectangle,\r\n width,\r\n height,\r\n longitude,\r\n latitude,\r\n exaggeration\r\n );\r\n\r\n // Use conditionals here instead of Math.min and Math.max so that an undefined\r\n // lowestEncodedHeight or highestEncodedHeight has no effect.\r\n heightSample =\r\n heightSample < structure.lowestEncodedHeight\r\n ? structure.lowestEncodedHeight\r\n : heightSample;\r\n heightSample =\r\n heightSample > structure.highestEncodedHeight\r\n ? structure.highestEncodedHeight\r\n : heightSample;\r\n\r\n setHeight(\r\n heights,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n divisor,\r\n stride,\r\n isBigEndian,\r\n j * width + i,\r\n heightSample\r\n );\r\n }\r\n }\r\n\r\n return new HeightmapTerrainData({\r\n buffer: heights,\r\n width: width,\r\n height: height,\r\n childTileMask: 0,\r\n structure: this._structure,\r\n createdByUpsampling: true,\r\n });\r\n};\r\n\r\n/**\r\n * Determines if a given child tile is available, based on the\r\n * {@link HeightmapTerrainData.childTileMask}. The given child tile coordinates are assumed\r\n * to be one of the four children of this tile. If non-child tile coordinates are\r\n * given, the availability of the southeast child tile is returned.\r\n *\r\n * @param {Number} thisX The tile X coordinate of this (the parent) tile.\r\n * @param {Number} thisY The tile Y coordinate of this (the parent) tile.\r\n * @param {Number} childX The tile X coordinate of the child tile to check for availability.\r\n * @param {Number} childY The tile Y coordinate of the child tile to check for availability.\r\n * @returns {Boolean} True if the child tile is available; otherwise, false.\r\n */\r\nHeightmapTerrainData.prototype.isChildAvailable = function (\r\n thisX,\r\n thisY,\r\n childX,\r\n childY\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(thisX)) {\r\n throw new DeveloperError(\"thisX is required.\");\r\n }\r\n if (!defined(thisY)) {\r\n throw new DeveloperError(\"thisY is required.\");\r\n }\r\n if (!defined(childX)) {\r\n throw new DeveloperError(\"childX is required.\");\r\n }\r\n if (!defined(childY)) {\r\n throw new DeveloperError(\"childY is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var bitNumber = 2; // northwest child\r\n if (childX !== thisX * 2) {\r\n ++bitNumber; // east child\r\n }\r\n if (childY !== thisY * 2) {\r\n bitNumber -= 2; // south child\r\n }\r\n\r\n return (this._childTileMask & (1 << bitNumber)) !== 0;\r\n};\r\n\r\n/**\r\n * Gets a value indicating whether or not this terrain data was created by upsampling lower resolution\r\n * terrain data. If this value is false, the data was obtained from some other source, such\r\n * as by downloading it from a remote server. This method should return true for instances\r\n * returned from a call to {@link HeightmapTerrainData#upsample}.\r\n *\r\n * @returns {Boolean} True if this instance was created by upsampling; otherwise, false.\r\n */\r\nHeightmapTerrainData.prototype.wasCreatedByUpsampling = function () {\r\n return this._createdByUpsampling;\r\n};\r\n\r\nfunction interpolateHeight(\r\n sourceHeights,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n stride,\r\n isBigEndian,\r\n sourceRectangle,\r\n width,\r\n height,\r\n longitude,\r\n latitude\r\n) {\r\n var fromWest =\r\n ((longitude - sourceRectangle.west) * (width - 1)) /\r\n (sourceRectangle.east - sourceRectangle.west);\r\n var fromSouth =\r\n ((latitude - sourceRectangle.south) * (height - 1)) /\r\n (sourceRectangle.north - sourceRectangle.south);\r\n\r\n var westInteger = fromWest | 0;\r\n var eastInteger = westInteger + 1;\r\n if (eastInteger >= width) {\r\n eastInteger = width - 1;\r\n westInteger = width - 2;\r\n }\r\n\r\n var southInteger = fromSouth | 0;\r\n var northInteger = southInteger + 1;\r\n if (northInteger >= height) {\r\n northInteger = height - 1;\r\n southInteger = height - 2;\r\n }\r\n\r\n var dx = fromWest - westInteger;\r\n var dy = fromSouth - southInteger;\r\n\r\n southInteger = height - 1 - southInteger;\r\n northInteger = height - 1 - northInteger;\r\n\r\n var southwestHeight = getHeight(\r\n sourceHeights,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n stride,\r\n isBigEndian,\r\n southInteger * width + westInteger\r\n );\r\n var southeastHeight = getHeight(\r\n sourceHeights,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n stride,\r\n isBigEndian,\r\n southInteger * width + eastInteger\r\n );\r\n var northwestHeight = getHeight(\r\n sourceHeights,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n stride,\r\n isBigEndian,\r\n northInteger * width + westInteger\r\n );\r\n var northeastHeight = getHeight(\r\n sourceHeights,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n stride,\r\n isBigEndian,\r\n northInteger * width + eastInteger\r\n );\r\n\r\n return triangleInterpolateHeight(\r\n dx,\r\n dy,\r\n southwestHeight,\r\n southeastHeight,\r\n northwestHeight,\r\n northeastHeight\r\n );\r\n}\r\n\r\nfunction interpolateMeshHeight(\r\n buffer,\r\n encoding,\r\n heightOffset,\r\n heightScale,\r\n sourceRectangle,\r\n width,\r\n height,\r\n longitude,\r\n latitude,\r\n exaggeration\r\n) {\r\n // returns a height encoded according to the structure's heightScale and heightOffset.\r\n var fromWest =\r\n ((longitude - sourceRectangle.west) * (width - 1)) /\r\n (sourceRectangle.east - sourceRectangle.west);\r\n var fromSouth =\r\n ((latitude - sourceRectangle.south) * (height - 1)) /\r\n (sourceRectangle.north - sourceRectangle.south);\r\n\r\n var westInteger = fromWest | 0;\r\n var eastInteger = westInteger + 1;\r\n if (eastInteger >= width) {\r\n eastInteger = width - 1;\r\n westInteger = width - 2;\r\n }\r\n\r\n var southInteger = fromSouth | 0;\r\n var northInteger = southInteger + 1;\r\n if (northInteger >= height) {\r\n northInteger = height - 1;\r\n southInteger = height - 2;\r\n }\r\n\r\n var dx = fromWest - westInteger;\r\n var dy = fromSouth - southInteger;\r\n\r\n southInteger = height - 1 - southInteger;\r\n northInteger = height - 1 - northInteger;\r\n\r\n var southwestHeight =\r\n (encoding.decodeHeight(buffer, southInteger * width + westInteger) /\r\n exaggeration -\r\n heightOffset) /\r\n heightScale;\r\n var southeastHeight =\r\n (encoding.decodeHeight(buffer, southInteger * width + eastInteger) /\r\n exaggeration -\r\n heightOffset) /\r\n heightScale;\r\n var northwestHeight =\r\n (encoding.decodeHeight(buffer, northInteger * width + westInteger) /\r\n exaggeration -\r\n heightOffset) /\r\n heightScale;\r\n var northeastHeight =\r\n (encoding.decodeHeight(buffer, northInteger * width + eastInteger) /\r\n exaggeration -\r\n heightOffset) /\r\n heightScale;\r\n\r\n return triangleInterpolateHeight(\r\n dx,\r\n dy,\r\n southwestHeight,\r\n southeastHeight,\r\n northwestHeight,\r\n northeastHeight\r\n );\r\n}\r\n\r\nfunction triangleInterpolateHeight(\r\n dX,\r\n dY,\r\n southwestHeight,\r\n southeastHeight,\r\n northwestHeight,\r\n northeastHeight\r\n) {\r\n // The HeightmapTessellator bisects the quad from southwest to northeast.\r\n if (dY < dX) {\r\n // Lower right triangle\r\n return (\r\n southwestHeight +\r\n dX * (southeastHeight - southwestHeight) +\r\n dY * (northeastHeight - southeastHeight)\r\n );\r\n }\r\n\r\n // Upper left triangle\r\n return (\r\n southwestHeight +\r\n dX * (northeastHeight - northwestHeight) +\r\n dY * (northwestHeight - southwestHeight)\r\n );\r\n}\r\n\r\nfunction getHeight(\r\n heights,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n stride,\r\n isBigEndian,\r\n index\r\n) {\r\n index *= stride;\r\n\r\n var height = 0;\r\n var i;\r\n\r\n if (isBigEndian) {\r\n for (i = 0; i < elementsPerHeight; ++i) {\r\n height = height * elementMultiplier + heights[index + i];\r\n }\r\n } else {\r\n for (i = elementsPerHeight - 1; i >= 0; --i) {\r\n height = height * elementMultiplier + heights[index + i];\r\n }\r\n }\r\n\r\n return height;\r\n}\r\n\r\nfunction setHeight(\r\n heights,\r\n elementsPerHeight,\r\n elementMultiplier,\r\n divisor,\r\n stride,\r\n isBigEndian,\r\n index,\r\n height\r\n) {\r\n index *= stride;\r\n\r\n var i;\r\n if (isBigEndian) {\r\n for (i = 0; i < elementsPerHeight - 1; ++i) {\r\n heights[index + i] = (height / divisor) | 0;\r\n height -= heights[index + i] * divisor;\r\n divisor /= elementMultiplier;\r\n }\r\n } else {\r\n for (i = elementsPerHeight - 1; i > 0; --i) {\r\n heights[index + i] = (height / divisor) | 0;\r\n height -= heights[index + i] * divisor;\r\n divisor /= elementMultiplier;\r\n }\r\n }\r\n heights[index + i] = height;\r\n}\r\nexport default HeightmapTerrainData;\r\n","import binarySearch from \"./binarySearch.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport defined from \"./defined.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\n\r\n/**\r\n * Reports the availability of tiles in a {@link TilingScheme}.\r\n *\r\n * @alias TileAvailability\r\n * @constructor\r\n *\r\n * @param {TilingScheme} tilingScheme The tiling scheme in which to report availability.\r\n * @param {Number} maximumLevel The maximum tile level that is potentially available.\r\n */\r\nfunction TileAvailability(tilingScheme, maximumLevel) {\r\n this._tilingScheme = tilingScheme;\r\n this._maximumLevel = maximumLevel;\r\n\r\n this._rootNodes = [];\r\n}\r\n\r\nvar rectangleScratch = new Rectangle();\r\n\r\nfunction findNode(level, x, y, nodes) {\r\n var count = nodes.length;\r\n for (var i = 0; i < count; ++i) {\r\n var node = nodes[i];\r\n if (node.x === x && node.y === y && node.level === level) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Marks a rectangular range of tiles in a particular level as being available. For best performance,\r\n * add your ranges in order of increasing level.\r\n *\r\n * @param {Number} level The level.\r\n * @param {Number} startX The X coordinate of the first available tiles at the level.\r\n * @param {Number} startY The Y coordinate of the first available tiles at the level.\r\n * @param {Number} endX The X coordinate of the last available tiles at the level.\r\n * @param {Number} endY The Y coordinate of the last available tiles at the level.\r\n */\r\nTileAvailability.prototype.addAvailableTileRange = function (\r\n level,\r\n startX,\r\n startY,\r\n endX,\r\n endY\r\n) {\r\n var tilingScheme = this._tilingScheme;\r\n\r\n var rootNodes = this._rootNodes;\r\n if (level === 0) {\r\n for (var y = startY; y <= endY; ++y) {\r\n for (var x = startX; x <= endX; ++x) {\r\n if (!findNode(level, x, y, rootNodes)) {\r\n rootNodes.push(new QuadtreeNode(tilingScheme, undefined, 0, x, y));\r\n }\r\n }\r\n }\r\n }\r\n\r\n tilingScheme.tileXYToRectangle(startX, startY, level, rectangleScratch);\r\n var west = rectangleScratch.west;\r\n var north = rectangleScratch.north;\r\n\r\n tilingScheme.tileXYToRectangle(endX, endY, level, rectangleScratch);\r\n var east = rectangleScratch.east;\r\n var south = rectangleScratch.south;\r\n\r\n var rectangleWithLevel = new RectangleWithLevel(\r\n level,\r\n west,\r\n south,\r\n east,\r\n north\r\n );\r\n\r\n for (var i = 0; i < rootNodes.length; ++i) {\r\n var rootNode = rootNodes[i];\r\n if (rectanglesOverlap(rootNode.extent, rectangleWithLevel)) {\r\n putRectangleInQuadtree(this._maximumLevel, rootNode, rectangleWithLevel);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Determines the level of the most detailed tile covering the position. This function\r\n * usually completes in time logarithmic to the number of rectangles added with\r\n * {@link TileAvailability#addAvailableTileRange}.\r\n *\r\n * @param {Cartographic} position The position for which to determine the maximum available level. The height component is ignored.\r\n * @return {Number} The level of the most detailed tile covering the position.\r\n * @throws {DeveloperError} If position is outside any tile according to the tiling scheme.\r\n */\r\nTileAvailability.prototype.computeMaximumLevelAtPosition = function (position) {\r\n // Find the root node that contains this position.\r\n var node;\r\n for (var nodeIndex = 0; nodeIndex < this._rootNodes.length; ++nodeIndex) {\r\n var rootNode = this._rootNodes[nodeIndex];\r\n if (rectangleContainsPosition(rootNode.extent, position)) {\r\n node = rootNode;\r\n break;\r\n }\r\n }\r\n\r\n if (!defined(node)) {\r\n return -1;\r\n }\r\n\r\n return findMaxLevelFromNode(undefined, node, position);\r\n};\r\n\r\nvar rectanglesScratch = [];\r\nvar remainingToCoverByLevelScratch = [];\r\nvar westScratch = new Rectangle();\r\nvar eastScratch = new Rectangle();\r\n\r\n/**\r\n * Finds the most detailed level that is available _everywhere_ within a given rectangle. More detailed\r\n * tiles may be available in parts of the rectangle, but not the whole thing. The return value of this\r\n * function may be safely passed to {@link sampleTerrain} for any position within the rectangle. This function\r\n * usually completes in time logarithmic to the number of rectangles added with\r\n * {@link TileAvailability#addAvailableTileRange}.\r\n *\r\n * @param {Rectangle} rectangle The rectangle.\r\n * @return {Number} The best available level for the entire rectangle.\r\n */\r\nTileAvailability.prototype.computeBestAvailableLevelOverRectangle = function (\r\n rectangle\r\n) {\r\n var rectangles = rectanglesScratch;\r\n rectangles.length = 0;\r\n\r\n if (rectangle.east < rectangle.west) {\r\n // Rectangle crosses the IDL, make it two rectangles.\r\n rectangles.push(\r\n Rectangle.fromRadians(\r\n -Math.PI,\r\n rectangle.south,\r\n rectangle.east,\r\n rectangle.north,\r\n westScratch\r\n )\r\n );\r\n rectangles.push(\r\n Rectangle.fromRadians(\r\n rectangle.west,\r\n rectangle.south,\r\n Math.PI,\r\n rectangle.north,\r\n eastScratch\r\n )\r\n );\r\n } else {\r\n rectangles.push(rectangle);\r\n }\r\n\r\n var remainingToCoverByLevel = remainingToCoverByLevelScratch;\r\n remainingToCoverByLevel.length = 0;\r\n\r\n var i;\r\n for (i = 0; i < this._rootNodes.length; ++i) {\r\n updateCoverageWithNode(\r\n remainingToCoverByLevel,\r\n this._rootNodes[i],\r\n rectangles\r\n );\r\n }\r\n\r\n for (i = remainingToCoverByLevel.length - 1; i >= 0; --i) {\r\n if (\r\n defined(remainingToCoverByLevel[i]) &&\r\n remainingToCoverByLevel[i].length === 0\r\n ) {\r\n return i;\r\n }\r\n }\r\n\r\n return 0;\r\n};\r\n\r\nvar cartographicScratch = new Cartographic();\r\n\r\n/**\r\n * Determines if a particular tile is available.\r\n * @param {Number} level The tile level to check.\r\n * @param {Number} x The X coordinate of the tile to check.\r\n * @param {Number} y The Y coordinate of the tile to check.\r\n * @return {Boolean} True if the tile is available; otherwise, false.\r\n */\r\nTileAvailability.prototype.isTileAvailable = function (level, x, y) {\r\n // Get the center of the tile and find the maximum level at that position.\r\n // Because availability is by tile, if the level is available at that point, it\r\n // is sure to be available for the whole tile. We assume that if a tile at level n exists,\r\n // then all its parent tiles back to level 0 exist too. This isn't really enforced\r\n // anywhere, but Cesium would never load a tile for which this is not true.\r\n var rectangle = this._tilingScheme.tileXYToRectangle(\r\n x,\r\n y,\r\n level,\r\n rectangleScratch\r\n );\r\n Rectangle.center(rectangle, cartographicScratch);\r\n return this.computeMaximumLevelAtPosition(cartographicScratch) >= level;\r\n};\r\n\r\n/**\r\n * Computes a bit mask indicating which of a tile's four children exist.\r\n * If a child's bit is set, a tile is available for that child. If it is cleared,\r\n * the tile is not available. The bit values are as follows:\r\n * \r\n * \r\n * \r\n * \r\n * \r\n * \r\n *
Bit PositionBit ValueChild Tile
01Southwest
12Southeast
24Northwest
38Northeast
\r\n *\r\n * @param {Number} level The level of the parent tile.\r\n * @param {Number} x The X coordinate of the parent tile.\r\n * @param {Number} y The Y coordinate of the parent tile.\r\n * @return {Number} The bit mask indicating child availability.\r\n */\r\nTileAvailability.prototype.computeChildMaskForTile = function (level, x, y) {\r\n var childLevel = level + 1;\r\n if (childLevel >= this._maximumLevel) {\r\n return 0;\r\n }\r\n\r\n var mask = 0;\r\n\r\n mask |= this.isTileAvailable(childLevel, 2 * x, 2 * y + 1) ? 1 : 0;\r\n mask |= this.isTileAvailable(childLevel, 2 * x + 1, 2 * y + 1) ? 2 : 0;\r\n mask |= this.isTileAvailable(childLevel, 2 * x, 2 * y) ? 4 : 0;\r\n mask |= this.isTileAvailable(childLevel, 2 * x + 1, 2 * y) ? 8 : 0;\r\n\r\n return mask;\r\n};\r\n\r\nfunction QuadtreeNode(tilingScheme, parent, level, x, y) {\r\n this.tilingScheme = tilingScheme;\r\n this.parent = parent;\r\n this.level = level;\r\n this.x = x;\r\n this.y = y;\r\n this.extent = tilingScheme.tileXYToRectangle(x, y, level);\r\n\r\n this.rectangles = [];\r\n this._sw = undefined;\r\n this._se = undefined;\r\n this._nw = undefined;\r\n this._ne = undefined;\r\n}\r\n\r\nObject.defineProperties(QuadtreeNode.prototype, {\r\n nw: {\r\n get: function () {\r\n if (!this._nw) {\r\n this._nw = new QuadtreeNode(\r\n this.tilingScheme,\r\n this,\r\n this.level + 1,\r\n this.x * 2,\r\n this.y * 2\r\n );\r\n }\r\n return this._nw;\r\n },\r\n },\r\n\r\n ne: {\r\n get: function () {\r\n if (!this._ne) {\r\n this._ne = new QuadtreeNode(\r\n this.tilingScheme,\r\n this,\r\n this.level + 1,\r\n this.x * 2 + 1,\r\n this.y * 2\r\n );\r\n }\r\n return this._ne;\r\n },\r\n },\r\n\r\n sw: {\r\n get: function () {\r\n if (!this._sw) {\r\n this._sw = new QuadtreeNode(\r\n this.tilingScheme,\r\n this,\r\n this.level + 1,\r\n this.x * 2,\r\n this.y * 2 + 1\r\n );\r\n }\r\n return this._sw;\r\n },\r\n },\r\n\r\n se: {\r\n get: function () {\r\n if (!this._se) {\r\n this._se = new QuadtreeNode(\r\n this.tilingScheme,\r\n this,\r\n this.level + 1,\r\n this.x * 2 + 1,\r\n this.y * 2 + 1\r\n );\r\n }\r\n return this._se;\r\n },\r\n },\r\n});\r\n\r\nfunction RectangleWithLevel(level, west, south, east, north) {\r\n this.level = level;\r\n this.west = west;\r\n this.south = south;\r\n this.east = east;\r\n this.north = north;\r\n}\r\n\r\nfunction rectanglesOverlap(rectangle1, rectangle2) {\r\n var west = Math.max(rectangle1.west, rectangle2.west);\r\n var south = Math.max(rectangle1.south, rectangle2.south);\r\n var east = Math.min(rectangle1.east, rectangle2.east);\r\n var north = Math.min(rectangle1.north, rectangle2.north);\r\n return south < north && west < east;\r\n}\r\n\r\nfunction putRectangleInQuadtree(maxDepth, node, rectangle) {\r\n while (node.level < maxDepth) {\r\n if (rectangleFullyContainsRectangle(node.nw.extent, rectangle)) {\r\n node = node.nw;\r\n } else if (rectangleFullyContainsRectangle(node.ne.extent, rectangle)) {\r\n node = node.ne;\r\n } else if (rectangleFullyContainsRectangle(node.sw.extent, rectangle)) {\r\n node = node.sw;\r\n } else if (rectangleFullyContainsRectangle(node.se.extent, rectangle)) {\r\n node = node.se;\r\n } else {\r\n break;\r\n }\r\n }\r\n\r\n if (\r\n node.rectangles.length === 0 ||\r\n node.rectangles[node.rectangles.length - 1].level <= rectangle.level\r\n ) {\r\n node.rectangles.push(rectangle);\r\n } else {\r\n // Maintain ordering by level when inserting.\r\n var index = binarySearch(\r\n node.rectangles,\r\n rectangle.level,\r\n rectangleLevelComparator\r\n );\r\n if (index < 0) {\r\n index = ~index;\r\n }\r\n node.rectangles.splice(index, 0, rectangle);\r\n }\r\n}\r\n\r\nfunction rectangleLevelComparator(a, b) {\r\n return a.level - b;\r\n}\r\n\r\nfunction rectangleFullyContainsRectangle(potentialContainer, rectangleToTest) {\r\n return (\r\n rectangleToTest.west >= potentialContainer.west &&\r\n rectangleToTest.east <= potentialContainer.east &&\r\n rectangleToTest.south >= potentialContainer.south &&\r\n rectangleToTest.north <= potentialContainer.north\r\n );\r\n}\r\n\r\nfunction rectangleContainsPosition(potentialContainer, positionToTest) {\r\n return (\r\n positionToTest.longitude >= potentialContainer.west &&\r\n positionToTest.longitude <= potentialContainer.east &&\r\n positionToTest.latitude >= potentialContainer.south &&\r\n positionToTest.latitude <= potentialContainer.north\r\n );\r\n}\r\n\r\nfunction findMaxLevelFromNode(stopNode, node, position) {\r\n var maxLevel = 0;\r\n\r\n // Find the deepest quadtree node containing this point.\r\n var found = false;\r\n while (!found) {\r\n var nw = node._nw && rectangleContainsPosition(node._nw.extent, position);\r\n var ne = node._ne && rectangleContainsPosition(node._ne.extent, position);\r\n var sw = node._sw && rectangleContainsPosition(node._sw.extent, position);\r\n var se = node._se && rectangleContainsPosition(node._se.extent, position);\r\n\r\n // The common scenario is that the point is in only one quadrant and we can simply\r\n // iterate down the tree. But if the point is on a boundary between tiles, it is\r\n // in multiple tiles and we need to check all of them, so use recursion.\r\n if (nw + ne + sw + se > 1) {\r\n if (nw) {\r\n maxLevel = Math.max(\r\n maxLevel,\r\n findMaxLevelFromNode(node, node._nw, position)\r\n );\r\n }\r\n if (ne) {\r\n maxLevel = Math.max(\r\n maxLevel,\r\n findMaxLevelFromNode(node, node._ne, position)\r\n );\r\n }\r\n if (sw) {\r\n maxLevel = Math.max(\r\n maxLevel,\r\n findMaxLevelFromNode(node, node._sw, position)\r\n );\r\n }\r\n if (se) {\r\n maxLevel = Math.max(\r\n maxLevel,\r\n findMaxLevelFromNode(node, node._se, position)\r\n );\r\n }\r\n break;\r\n } else if (nw) {\r\n node = node._nw;\r\n } else if (ne) {\r\n node = node._ne;\r\n } else if (sw) {\r\n node = node._sw;\r\n } else if (se) {\r\n node = node._se;\r\n } else {\r\n found = true;\r\n }\r\n }\r\n\r\n // Work up the tree until we find a rectangle that contains this point.\r\n while (node !== stopNode) {\r\n var rectangles = node.rectangles;\r\n\r\n // Rectangles are sorted by level, lowest first.\r\n for (\r\n var i = rectangles.length - 1;\r\n i >= 0 && rectangles[i].level > maxLevel;\r\n --i\r\n ) {\r\n var rectangle = rectangles[i];\r\n if (rectangleContainsPosition(rectangle, position)) {\r\n maxLevel = rectangle.level;\r\n }\r\n }\r\n\r\n node = node.parent;\r\n }\r\n\r\n return maxLevel;\r\n}\r\n\r\nfunction updateCoverageWithNode(\r\n remainingToCoverByLevel,\r\n node,\r\n rectanglesToCover\r\n) {\r\n if (!node) {\r\n return;\r\n }\r\n\r\n var i;\r\n var anyOverlap = false;\r\n for (i = 0; i < rectanglesToCover.length; ++i) {\r\n anyOverlap =\r\n anyOverlap || rectanglesOverlap(node.extent, rectanglesToCover[i]);\r\n }\r\n\r\n if (!anyOverlap) {\r\n // This node is not applicable to the rectangle(s).\r\n return;\r\n }\r\n\r\n var rectangles = node.rectangles;\r\n for (i = 0; i < rectangles.length; ++i) {\r\n var rectangle = rectangles[i];\r\n\r\n if (!remainingToCoverByLevel[rectangle.level]) {\r\n remainingToCoverByLevel[rectangle.level] = rectanglesToCover;\r\n }\r\n\r\n remainingToCoverByLevel[rectangle.level] = subtractRectangle(\r\n remainingToCoverByLevel[rectangle.level],\r\n rectangle\r\n );\r\n }\r\n\r\n // Update with child nodes.\r\n updateCoverageWithNode(remainingToCoverByLevel, node._nw, rectanglesToCover);\r\n updateCoverageWithNode(remainingToCoverByLevel, node._ne, rectanglesToCover);\r\n updateCoverageWithNode(remainingToCoverByLevel, node._sw, rectanglesToCover);\r\n updateCoverageWithNode(remainingToCoverByLevel, node._se, rectanglesToCover);\r\n}\r\n\r\nfunction subtractRectangle(rectangleList, rectangleToSubtract) {\r\n var result = [];\r\n for (var i = 0; i < rectangleList.length; ++i) {\r\n var rectangle = rectangleList[i];\r\n if (!rectanglesOverlap(rectangle, rectangleToSubtract)) {\r\n // Disjoint rectangles. Original rectangle is unmodified.\r\n result.push(rectangle);\r\n } else {\r\n // rectangleToSubtract partially or completely overlaps rectangle.\r\n if (rectangle.west < rectangleToSubtract.west) {\r\n result.push(\r\n new Rectangle(\r\n rectangle.west,\r\n rectangle.south,\r\n rectangleToSubtract.west,\r\n rectangle.north\r\n )\r\n );\r\n }\r\n if (rectangle.east > rectangleToSubtract.east) {\r\n result.push(\r\n new Rectangle(\r\n rectangleToSubtract.east,\r\n rectangle.south,\r\n rectangle.east,\r\n rectangle.north\r\n )\r\n );\r\n }\r\n if (rectangle.south < rectangleToSubtract.south) {\r\n result.push(\r\n new Rectangle(\r\n Math.max(rectangleToSubtract.west, rectangle.west),\r\n rectangle.south,\r\n Math.min(rectangleToSubtract.east, rectangle.east),\r\n rectangleToSubtract.south\r\n )\r\n );\r\n }\r\n if (rectangle.north > rectangleToSubtract.north) {\r\n result.push(\r\n new Rectangle(\r\n Math.max(rectangleToSubtract.west, rectangle.west),\r\n rectangleToSubtract.north,\r\n Math.min(rectangleToSubtract.east, rectangle.east),\r\n rectangle.north\r\n )\r\n );\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\nexport default TileAvailability;\r\n","import defined from \"./defined.js\";\r\n\r\n/**\r\n * Formats an error object into a String. If available, uses name, message, and stack\r\n * properties, otherwise, falls back on toString().\r\n *\r\n * @function\r\n *\r\n * @param {*} object The item to find in the array.\r\n * @returns {String} A string containing the formatted error.\r\n */\r\nfunction formatError(object) {\r\n var result;\r\n\r\n var name = object.name;\r\n var message = object.message;\r\n if (defined(name) && defined(message)) {\r\n result = name + \": \" + message;\r\n } else {\r\n result = object.toString();\r\n }\r\n\r\n var stack = object.stack;\r\n if (defined(stack)) {\r\n result += \"\\n\" + stack;\r\n }\r\n\r\n return result;\r\n}\r\nexport default formatError;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport formatError from \"./formatError.js\";\r\n\r\n/**\r\n * Provides details about an error that occurred in an {@link ImageryProvider} or a {@link TerrainProvider}.\r\n *\r\n * @alias TileProviderError\r\n * @constructor\r\n *\r\n * @param {ImageryProvider|TerrainProvider} provider The imagery or terrain provider that experienced the error.\r\n * @param {String} message A message describing the error.\r\n * @param {Number} [x] The X coordinate of the tile that experienced the error, or undefined if the error\r\n * is not specific to a particular tile.\r\n * @param {Number} [y] The Y coordinate of the tile that experienced the error, or undefined if the error\r\n * is not specific to a particular tile.\r\n * @param {Number} [level] The level of the tile that experienced the error, or undefined if the error\r\n * is not specific to a particular tile.\r\n * @param {Number} [timesRetried=0] The number of times this operation has been retried.\r\n * @param {Error} [error] The error or exception that occurred, if any.\r\n */\r\nfunction TileProviderError(\r\n provider,\r\n message,\r\n x,\r\n y,\r\n level,\r\n timesRetried,\r\n error\r\n) {\r\n /**\r\n * The {@link ImageryProvider} or {@link TerrainProvider} that experienced the error.\r\n * @type {ImageryProvider|TerrainProvider}\r\n */\r\n this.provider = provider;\r\n\r\n /**\r\n * The message describing the error.\r\n * @type {String}\r\n */\r\n this.message = message;\r\n\r\n /**\r\n * The X coordinate of the tile that experienced the error. If the error is not specific\r\n * to a particular tile, this property will be undefined.\r\n * @type {Number}\r\n */\r\n this.x = x;\r\n\r\n /**\r\n * The Y coordinate of the tile that experienced the error. If the error is not specific\r\n * to a particular tile, this property will be undefined.\r\n * @type {Number}\r\n */\r\n this.y = y;\r\n\r\n /**\r\n * The level-of-detail of the tile that experienced the error. If the error is not specific\r\n * to a particular tile, this property will be undefined.\r\n * @type {Number}\r\n */\r\n this.level = level;\r\n\r\n /**\r\n * The number of times this operation has been retried.\r\n * @type {Number}\r\n * @default 0\r\n */\r\n this.timesRetried = defaultValue(timesRetried, 0);\r\n\r\n /**\r\n * True if the failed operation should be retried; otherwise, false. The imagery or terrain provider\r\n * will set the initial value of this property before raising the event, but any listeners\r\n * can change it. The value after the last listener is invoked will be acted upon.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.retry = false;\r\n\r\n /**\r\n * The error or exception that occurred, if any.\r\n * @type {Error}\r\n */\r\n this.error = error;\r\n}\r\n\r\n/**\r\n * Handles an error in an {@link ImageryProvider} or {@link TerrainProvider} by raising an event if it has any listeners, or by\r\n * logging the error to the console if the event has no listeners. This method also tracks the number\r\n * of times the operation has been retried and will automatically retry if requested to do so by the\r\n * event listeners.\r\n *\r\n * @param {TileProviderError} previousError The error instance returned by this function the last\r\n * time it was called for this error, or undefined if this is the first time this error has\r\n * occurred.\r\n * @param {ImageryProvider|TerrainProvider} provider The imagery or terrain provider that encountered the error.\r\n * @param {Event} event The event to raise to inform listeners of the error.\r\n * @param {String} message The message describing the error.\r\n * @param {Number} x The X coordinate of the tile that experienced the error, or undefined if the\r\n * error is not specific to a particular tile.\r\n * @param {Number} y The Y coordinate of the tile that experienced the error, or undefined if the\r\n * error is not specific to a particular tile.\r\n * @param {Number} level The level-of-detail of the tile that experienced the error, or undefined if the\r\n * error is not specific to a particular tile.\r\n * @param {TileProviderError.RetryFunction} retryFunction The function to call to retry the operation. If undefined, the\r\n * operation will not be retried.\r\n * @param {Error} [errorDetails] The error or exception that occurred, if any.\r\n * @returns {TileProviderError} The error instance that was passed to the event listeners and that\r\n * should be passed to this function the next time it is called for the same error in order\r\n * to track retry counts.\r\n */\r\nTileProviderError.handleError = function (\r\n previousError,\r\n provider,\r\n event,\r\n message,\r\n x,\r\n y,\r\n level,\r\n retryFunction,\r\n errorDetails\r\n) {\r\n var error = previousError;\r\n if (!defined(previousError)) {\r\n error = new TileProviderError(\r\n provider,\r\n message,\r\n x,\r\n y,\r\n level,\r\n 0,\r\n errorDetails\r\n );\r\n } else {\r\n error.provider = provider;\r\n error.message = message;\r\n error.x = x;\r\n error.y = y;\r\n error.level = level;\r\n error.retry = false;\r\n error.error = errorDetails;\r\n ++error.timesRetried;\r\n }\r\n\r\n if (event.numberOfListeners > 0) {\r\n event.raiseEvent(error);\r\n } else {\r\n console.log(\r\n 'An error occurred in \"' +\r\n provider.constructor.name +\r\n '\": ' +\r\n formatError(message)\r\n );\r\n }\r\n\r\n if (error.retry && defined(retryFunction)) {\r\n retryFunction();\r\n }\r\n\r\n return error;\r\n};\r\n\r\n/**\r\n * Handles success of an operation by resetting the retry count of a previous error, if any. This way,\r\n * if the error occurs again in the future, the listeners will be informed that it has not yet been retried.\r\n *\r\n * @param {TileProviderError} previousError The previous error, or undefined if this operation has\r\n * not previously resulted in an error.\r\n */\r\nTileProviderError.handleSuccess = function (previousError) {\r\n if (defined(previousError)) {\r\n previousError.timesRetried = -1;\r\n }\r\n};\r\n\r\n/**\r\n * A function that will be called to retry the operation.\r\n * @callback TileProviderError.RetryFunction\r\n */\r\nexport default TileProviderError;\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport WebMercatorProjection from \"./WebMercatorProjection.js\";\r\n\r\n/**\r\n * A tiling scheme for geometry referenced to a {@link WebMercatorProjection}, EPSG:3857. This is\r\n * the tiling scheme used by Google Maps, Microsoft Bing Maps, and most of ESRI ArcGIS Online.\r\n *\r\n * @alias WebMercatorTilingScheme\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid whose surface is being tiled. Defaults to\r\n * the WGS84 ellipsoid.\r\n * @param {Number} [options.numberOfLevelZeroTilesX=1] The number of tiles in the X direction at level zero of\r\n * the tile tree.\r\n * @param {Number} [options.numberOfLevelZeroTilesY=1] The number of tiles in the Y direction at level zero of\r\n * the tile tree.\r\n * @param {Cartesian2} [options.rectangleSouthwestInMeters] The southwest corner of the rectangle covered by the\r\n * tiling scheme, in meters. If this parameter or rectangleNortheastInMeters is not specified, the entire\r\n * globe is covered in the longitude direction and an equal distance is covered in the latitude\r\n * direction, resulting in a square projection.\r\n * @param {Cartesian2} [options.rectangleNortheastInMeters] The northeast corner of the rectangle covered by the\r\n * tiling scheme, in meters. If this parameter or rectangleSouthwestInMeters is not specified, the entire\r\n * globe is covered in the longitude direction and an equal distance is covered in the latitude\r\n * direction, resulting in a square projection.\r\n */\r\nfunction WebMercatorTilingScheme(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n this._numberOfLevelZeroTilesX = defaultValue(\r\n options.numberOfLevelZeroTilesX,\r\n 1\r\n );\r\n this._numberOfLevelZeroTilesY = defaultValue(\r\n options.numberOfLevelZeroTilesY,\r\n 1\r\n );\r\n\r\n this._projection = new WebMercatorProjection(this._ellipsoid);\r\n\r\n if (\r\n defined(options.rectangleSouthwestInMeters) &&\r\n defined(options.rectangleNortheastInMeters)\r\n ) {\r\n this._rectangleSouthwestInMeters = options.rectangleSouthwestInMeters;\r\n this._rectangleNortheastInMeters = options.rectangleNortheastInMeters;\r\n } else {\r\n var semimajorAxisTimesPi = this._ellipsoid.maximumRadius * Math.PI;\r\n this._rectangleSouthwestInMeters = new Cartesian2(\r\n -semimajorAxisTimesPi,\r\n -semimajorAxisTimesPi\r\n );\r\n this._rectangleNortheastInMeters = new Cartesian2(\r\n semimajorAxisTimesPi,\r\n semimajorAxisTimesPi\r\n );\r\n }\r\n\r\n var southwest = this._projection.unproject(this._rectangleSouthwestInMeters);\r\n var northeast = this._projection.unproject(this._rectangleNortheastInMeters);\r\n this._rectangle = new Rectangle(\r\n southwest.longitude,\r\n southwest.latitude,\r\n northeast.longitude,\r\n northeast.latitude\r\n );\r\n}\r\n\r\nObject.defineProperties(WebMercatorTilingScheme.prototype, {\r\n /**\r\n * Gets the ellipsoid that is tiled by this tiling scheme.\r\n * @memberof WebMercatorTilingScheme.prototype\r\n * @type {Ellipsoid}\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the rectangle, in radians, covered by this tiling scheme.\r\n * @memberof WebMercatorTilingScheme.prototype\r\n * @type {Rectangle}\r\n */\r\n rectangle: {\r\n get: function () {\r\n return this._rectangle;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the map projection used by this tiling scheme.\r\n * @memberof WebMercatorTilingScheme.prototype\r\n * @type {MapProjection}\r\n */\r\n projection: {\r\n get: function () {\r\n return this._projection;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the total number of tiles in the X direction at a specified level-of-detail.\r\n *\r\n * @param {Number} level The level-of-detail.\r\n * @returns {Number} The number of tiles in the X direction at the given level.\r\n */\r\nWebMercatorTilingScheme.prototype.getNumberOfXTilesAtLevel = function (level) {\r\n return this._numberOfLevelZeroTilesX << level;\r\n};\r\n\r\n/**\r\n * Gets the total number of tiles in the Y direction at a specified level-of-detail.\r\n *\r\n * @param {Number} level The level-of-detail.\r\n * @returns {Number} The number of tiles in the Y direction at the given level.\r\n */\r\nWebMercatorTilingScheme.prototype.getNumberOfYTilesAtLevel = function (level) {\r\n return this._numberOfLevelZeroTilesY << level;\r\n};\r\n\r\n/**\r\n * Transforms a rectangle specified in geodetic radians to the native coordinate system\r\n * of this tiling scheme.\r\n *\r\n * @param {Rectangle} rectangle The rectangle to transform.\r\n * @param {Rectangle} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the native rectangle if 'result'\r\n * is undefined.\r\n */\r\nWebMercatorTilingScheme.prototype.rectangleToNativeRectangle = function (\r\n rectangle,\r\n result\r\n) {\r\n var projection = this._projection;\r\n var southwest = projection.project(Rectangle.southwest(rectangle));\r\n var northeast = projection.project(Rectangle.northeast(rectangle));\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(southwest.x, southwest.y, northeast.x, northeast.y);\r\n }\r\n\r\n result.west = southwest.x;\r\n result.south = southwest.y;\r\n result.east = northeast.x;\r\n result.north = northeast.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Converts tile x, y coordinates and level to a rectangle expressed in the native coordinates\r\n * of the tiling scheme.\r\n *\r\n * @param {Number} x The integer x coordinate of the tile.\r\n * @param {Number} y The integer y coordinate of the tile.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Object} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the rectangle\r\n * if 'result' is undefined.\r\n */\r\nWebMercatorTilingScheme.prototype.tileXYToNativeRectangle = function (\r\n x,\r\n y,\r\n level,\r\n result\r\n) {\r\n var xTiles = this.getNumberOfXTilesAtLevel(level);\r\n var yTiles = this.getNumberOfYTilesAtLevel(level);\r\n\r\n var xTileWidth =\r\n (this._rectangleNortheastInMeters.x - this._rectangleSouthwestInMeters.x) /\r\n xTiles;\r\n var west = this._rectangleSouthwestInMeters.x + x * xTileWidth;\r\n var east = this._rectangleSouthwestInMeters.x + (x + 1) * xTileWidth;\r\n\r\n var yTileHeight =\r\n (this._rectangleNortheastInMeters.y - this._rectangleSouthwestInMeters.y) /\r\n yTiles;\r\n var north = this._rectangleNortheastInMeters.y - y * yTileHeight;\r\n var south = this._rectangleNortheastInMeters.y - (y + 1) * yTileHeight;\r\n\r\n if (!defined(result)) {\r\n return new Rectangle(west, south, east, north);\r\n }\r\n\r\n result.west = west;\r\n result.south = south;\r\n result.east = east;\r\n result.north = north;\r\n return result;\r\n};\r\n\r\n/**\r\n * Converts tile x, y coordinates and level to a cartographic rectangle in radians.\r\n *\r\n * @param {Number} x The integer x coordinate of the tile.\r\n * @param {Number} y The integer y coordinate of the tile.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Object} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the rectangle\r\n * if 'result' is undefined.\r\n */\r\nWebMercatorTilingScheme.prototype.tileXYToRectangle = function (\r\n x,\r\n y,\r\n level,\r\n result\r\n) {\r\n var nativeRectangle = this.tileXYToNativeRectangle(x, y, level, result);\r\n\r\n var projection = this._projection;\r\n var southwest = projection.unproject(\r\n new Cartesian2(nativeRectangle.west, nativeRectangle.south)\r\n );\r\n var northeast = projection.unproject(\r\n new Cartesian2(nativeRectangle.east, nativeRectangle.north)\r\n );\r\n\r\n nativeRectangle.west = southwest.longitude;\r\n nativeRectangle.south = southwest.latitude;\r\n nativeRectangle.east = northeast.longitude;\r\n nativeRectangle.north = northeast.latitude;\r\n return nativeRectangle;\r\n};\r\n\r\n/**\r\n * Calculates the tile x, y coordinates of the tile containing\r\n * a given cartographic position.\r\n *\r\n * @param {Cartographic} position The position.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Cartesian2} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Cartesian2} The specified 'result', or a new object containing the tile x, y coordinates\r\n * if 'result' is undefined.\r\n */\r\nWebMercatorTilingScheme.prototype.positionToTileXY = function (\r\n position,\r\n level,\r\n result\r\n) {\r\n var rectangle = this._rectangle;\r\n if (!Rectangle.contains(rectangle, position)) {\r\n // outside the bounds of the tiling scheme\r\n return undefined;\r\n }\r\n\r\n var xTiles = this.getNumberOfXTilesAtLevel(level);\r\n var yTiles = this.getNumberOfYTilesAtLevel(level);\r\n\r\n var overallWidth =\r\n this._rectangleNortheastInMeters.x - this._rectangleSouthwestInMeters.x;\r\n var xTileWidth = overallWidth / xTiles;\r\n var overallHeight =\r\n this._rectangleNortheastInMeters.y - this._rectangleSouthwestInMeters.y;\r\n var yTileHeight = overallHeight / yTiles;\r\n\r\n var projection = this._projection;\r\n\r\n var webMercatorPosition = projection.project(position);\r\n var distanceFromWest =\r\n webMercatorPosition.x - this._rectangleSouthwestInMeters.x;\r\n var distanceFromNorth =\r\n this._rectangleNortheastInMeters.y - webMercatorPosition.y;\r\n\r\n var xTileCoordinate = (distanceFromWest / xTileWidth) | 0;\r\n if (xTileCoordinate >= xTiles) {\r\n xTileCoordinate = xTiles - 1;\r\n }\r\n var yTileCoordinate = (distanceFromNorth / yTileHeight) | 0;\r\n if (yTileCoordinate >= yTiles) {\r\n yTileCoordinate = yTiles - 1;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Cartesian2(xTileCoordinate, yTileCoordinate);\r\n }\r\n\r\n result.x = xTileCoordinate;\r\n result.y = yTileCoordinate;\r\n return result;\r\n};\r\nexport default WebMercatorTilingScheme;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Credit from \"./Credit.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Event from \"./Event.js\";\r\nimport GeographicTilingScheme from \"./GeographicTilingScheme.js\";\r\nimport HeightmapEncoding from \"./HeightmapEncoding.js\";\r\nimport HeightmapTerrainData from \"./HeightmapTerrainData.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Request from \"./Request.js\";\r\nimport RequestState from \"./RequestState.js\";\r\nimport RequestType from \"./RequestType.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\nimport TerrainProvider from \"./TerrainProvider.js\";\r\nimport TileAvailability from \"./TileAvailability.js\";\r\nimport TileProviderError from \"./TileProviderError.js\";\r\nimport WebMercatorTilingScheme from \"./WebMercatorTilingScheme.js\";\r\n\r\nvar ALL_CHILDREN = 15;\r\n\r\n/**\r\n * A {@link TerrainProvider} that produces terrain geometry by tessellating height maps\r\n * retrieved from Elevation Tiles of an an ArcGIS ImageService.\r\n *\r\n * @alias ArcGISTiledElevationTerrainProvider\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Resource|String|Promise|Promise} options.url The URL of the ArcGIS ImageServer service.\r\n * @param {String} [options.token] The authorization token to use to connect to the service.\r\n * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If the tilingScheme is specified,\r\n * this parameter is ignored and the tiling scheme's ellipsoid is used instead.\r\n * If neither parameter is specified, the WGS84 ellipsoid is used.\r\n *\r\n * @example\r\n * var terrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider({\r\n * url : 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',\r\n * token : 'KED1aF_I4UzXOHy3BnhwyBHU4l5oY6rO6walkmHoYqGp4XyIWUd5YZUC1ZrLAzvV40pR6gBXQayh0eFA8m6vPg..'\r\n * });\r\n * viewer.terrainProvider = terrainProvider;\r\n *\r\n * @see TerrainProvider\r\n */\r\nfunction ArcGISTiledElevationTerrainProvider(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options) || !defined(options.url)) {\r\n throw new DeveloperError(\"options.url is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._resource = undefined;\r\n this._credit = undefined;\r\n this._tilingScheme = undefined;\r\n this._levelZeroMaximumGeometricError = undefined;\r\n this._maxLevel = undefined;\r\n this._terrainDataStructure = undefined;\r\n this._ready = false;\r\n this._width = undefined;\r\n this._height = undefined;\r\n this._encoding = undefined;\r\n var token = options.token;\r\n\r\n this._hasAvailability = false;\r\n this._tilesAvailable = undefined;\r\n this._tilesAvailablityLoaded = undefined;\r\n this._availableCache = {};\r\n\r\n var that = this;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n this._readyPromise = when(options.url)\r\n .then(function (url) {\r\n var resource = Resource.createIfNeeded(url);\r\n resource.appendForwardSlash();\r\n if (defined(token)) {\r\n resource = resource.getDerivedResource({\r\n queryParameters: {\r\n token: token,\r\n },\r\n });\r\n }\r\n that._resource = resource;\r\n\r\n var metadataResource = resource.getDerivedResource({\r\n queryParameters: {\r\n f: \"pjson\",\r\n },\r\n });\r\n\r\n return metadataResource.fetchJson();\r\n })\r\n .then(function (metadata) {\r\n var copyrightText = metadata.copyrightText;\r\n if (defined(copyrightText)) {\r\n that._credit = new Credit(copyrightText);\r\n }\r\n\r\n var spatialReference = metadata.spatialReference;\r\n var wkid = defaultValue(\r\n spatialReference.latestWkid,\r\n spatialReference.wkid\r\n );\r\n var extent = metadata.extent;\r\n var tilingSchemeOptions = {\r\n ellipsoid: ellipsoid,\r\n };\r\n if (wkid === 4326) {\r\n tilingSchemeOptions.rectangle = Rectangle.fromDegrees(\r\n extent.xmin,\r\n extent.ymin,\r\n extent.xmax,\r\n extent.ymax\r\n );\r\n that._tilingScheme = new GeographicTilingScheme(tilingSchemeOptions);\r\n } else if (wkid === 3857) {\r\n tilingSchemeOptions.rectangleSouthwestInMeters = new Cartesian2(\r\n extent.xmin,\r\n extent.ymin\r\n );\r\n tilingSchemeOptions.rectangleNortheastInMeters = new Cartesian2(\r\n extent.xmax,\r\n extent.ymax\r\n );\r\n that._tilingScheme = new WebMercatorTilingScheme(tilingSchemeOptions);\r\n } else {\r\n return when.reject(new RuntimeError(\"Invalid spatial reference\"));\r\n }\r\n\r\n var tileInfo = metadata.tileInfo;\r\n if (!defined(tileInfo)) {\r\n return when.reject(new RuntimeError(\"tileInfo is required\"));\r\n }\r\n\r\n that._width = tileInfo.rows + 1;\r\n that._height = tileInfo.cols + 1;\r\n that._encoding =\r\n tileInfo.format === \"LERC\"\r\n ? HeightmapEncoding.LERC\r\n : HeightmapEncoding.NONE;\r\n that._lodCount = tileInfo.lods.length - 1;\r\n\r\n var hasAvailability = (that._hasAvailability =\r\n metadata.capabilities.indexOf(\"Tilemap\") !== -1);\r\n if (hasAvailability) {\r\n that._tilesAvailable = new TileAvailability(\r\n that._tilingScheme,\r\n that._lodCount\r\n );\r\n that._tilesAvailable.addAvailableTileRange(\r\n 0,\r\n 0,\r\n 0,\r\n that._tilingScheme.getNumberOfXTilesAtLevel(0),\r\n that._tilingScheme.getNumberOfYTilesAtLevel(0)\r\n );\r\n that._tilesAvailablityLoaded = new TileAvailability(\r\n that._tilingScheme,\r\n that._lodCount\r\n );\r\n }\r\n\r\n that._levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(\r\n that._tilingScheme.ellipsoid,\r\n that._width,\r\n that._tilingScheme.getNumberOfXTilesAtLevel(0)\r\n );\r\n\r\n if (metadata.bandCount > 1) {\r\n console.log(\r\n \"ArcGISTiledElevationTerrainProvider: Terrain data has more than 1 band. Using the first one.\"\r\n );\r\n }\r\n\r\n that._terrainDataStructure = {\r\n elementMultiplier: 1.0,\r\n lowestEncodedHeight: metadata.minValues[0],\r\n highestEncodedHeight: metadata.maxValues[0],\r\n };\r\n\r\n that._ready = true;\r\n\r\n return true;\r\n })\r\n .otherwise(function (error) {\r\n var message =\r\n \"An error occurred while accessing \" + that._resource.url + \".\";\r\n TileProviderError.handleError(undefined, that, that._errorEvent, message);\r\n return when.reject(error);\r\n });\r\n\r\n this._errorEvent = new Event();\r\n}\r\n\r\nObject.defineProperties(ArcGISTiledElevationTerrainProvider.prototype, {\r\n /**\r\n * Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing\r\n * to the event, you will be notified of the error and can potentially recover from it. Event listeners\r\n * are passed an instance of {@link TileProviderError}.\r\n * @memberof ArcGISTiledElevationTerrainProvider.prototype\r\n * @type {Event}\r\n */\r\n errorEvent: {\r\n get: function () {\r\n return this._errorEvent;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the credit to display when this terrain provider is active. Typically this is used to credit\r\n * the source of the terrain. This function should not be called before {@link ArcGISTiledElevationTerrainProvider#ready} returns true.\r\n * @memberof ArcGISTiledElevationTerrainProvider.prototype\r\n * @type {Credit}\r\n */\r\n credit: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"credit must not be called before ready returns true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return this._credit;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tiling scheme used by this provider. This function should\r\n * not be called before {@link ArcGISTiledElevationTerrainProvider#ready} returns true.\r\n * @memberof ArcGISTiledElevationTerrainProvider.prototype\r\n * @type {GeographicTilingScheme}\r\n */\r\n tilingScheme: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"tilingScheme must not be called before ready returns true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return this._tilingScheme;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider is ready for use.\r\n * @memberof ArcGISTiledElevationTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves to true when the provider is ready for use.\r\n * @memberof ArcGISTiledElevationTerrainProvider.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider includes a water mask. The water mask\r\n * indicates which areas of the globe are water rather than land, so they can be rendered\r\n * as a reflective surface with animated waves. This function should not be\r\n * called before {@link ArcGISTiledElevationTerrainProvider#ready} returns true.\r\n * @memberof ArcGISTiledElevationTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasWaterMask: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the requested tiles include vertex normals.\r\n * This function should not be called before {@link ArcGISTiledElevationTerrainProvider#ready} returns true.\r\n * @memberof ArcGISTiledElevationTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasVertexNormals: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n /**\r\n * Gets an object that can be used to determine availability of terrain from this provider, such as\r\n * at points and in rectangles. This function should not be called before\r\n * {@link TerrainProvider#ready} returns true. This property may be undefined if availability\r\n * information is not available.\r\n * @memberof ArcGISTiledElevationTerrainProvider.prototype\r\n * @type {TileAvailability}\r\n */\r\n availability: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"availability must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return this._tilesAvailable;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Requests the geometry for a given tile. This function should not be called before\r\n * {@link ArcGISTiledElevationTerrainProvider#ready} returns true. The result includes terrain\r\n * data and indicates that all child tiles are available.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @param {Request} [request] The request object. Intended for internal use only.\r\n * @returns {Promise.|undefined} A promise for the requested geometry. If this method\r\n * returns undefined instead of a promise, it is an indication that too many requests are already\r\n * pending and the request will be retried later.\r\n */\r\nArcGISTiledElevationTerrainProvider.prototype.requestTileGeometry = function (\r\n x,\r\n y,\r\n level,\r\n request\r\n) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"requestTileGeometry must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var tileResource = this._resource.getDerivedResource({\r\n url: \"tile/\" + level + \"/\" + y + \"/\" + x,\r\n request: request,\r\n });\r\n\r\n var hasAvailability = this._hasAvailability;\r\n var availabilityPromise = when.resolve(true);\r\n var availabilityRequest;\r\n if (\r\n hasAvailability &&\r\n !defined(isTileAvailable(this, level + 1, x * 2, y * 2))\r\n ) {\r\n // We need to load child availability\r\n var availabilityResult = requestAvailability(this, level + 1, x * 2, y * 2);\r\n\r\n availabilityPromise = availabilityResult.promise;\r\n availabilityRequest = availabilityResult.request;\r\n }\r\n\r\n var promise = tileResource.fetchArrayBuffer();\r\n if (!defined(promise) || !defined(availabilityPromise)) {\r\n return undefined;\r\n }\r\n\r\n var that = this;\r\n var tilesAvailable = this._tilesAvailable;\r\n return when\r\n .join(promise, availabilityPromise)\r\n .then(function (result) {\r\n return new HeightmapTerrainData({\r\n buffer: result[0],\r\n width: that._width,\r\n height: that._height,\r\n childTileMask: hasAvailability\r\n ? tilesAvailable.computeChildMaskForTile(level, x, y)\r\n : ALL_CHILDREN,\r\n structure: that._terrainDataStructure,\r\n encoding: that._encoding,\r\n });\r\n })\r\n .otherwise(function (error) {\r\n if (\r\n defined(availabilityRequest) &&\r\n availabilityRequest.state === RequestState.CANCELLED\r\n ) {\r\n request.cancel();\r\n\r\n // Don't reject the promise till the request is actually cancelled\r\n // Otherwise it will think the request failed, but it didn't.\r\n return request.deferred.promise.always(function () {\r\n request.state = RequestState.CANCELLED;\r\n return when.reject(error);\r\n });\r\n }\r\n return when.reject(error);\r\n });\r\n};\r\n\r\nfunction isTileAvailable(that, level, x, y) {\r\n if (!that._hasAvailability) {\r\n return undefined;\r\n }\r\n\r\n var tilesAvailablityLoaded = that._tilesAvailablityLoaded;\r\n var tilesAvailable = that._tilesAvailable;\r\n\r\n if (level > that._lodCount) {\r\n return false;\r\n }\r\n\r\n // Check if tiles are known to be available\r\n if (tilesAvailable.isTileAvailable(level, x, y)) {\r\n return true;\r\n }\r\n\r\n // or to not be available\r\n if (tilesAvailablityLoaded.isTileAvailable(level, x, y)) {\r\n return false;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Gets the maximum geometric error allowed in a tile at a given level.\r\n *\r\n * @param {Number} level The tile level for which to get the maximum geometric error.\r\n * @returns {Number} The maximum geometric error.\r\n */\r\nArcGISTiledElevationTerrainProvider.prototype.getLevelMaximumGeometricError = function (\r\n level\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"getLevelMaximumGeometricError must not be called before ready returns true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._levelZeroMaximumGeometricError / (1 << level);\r\n};\r\n\r\n/**\r\n * Determines whether data for a tile is available to be loaded.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {Boolean} Undefined if not supported, otherwise true or false.\r\n */\r\nArcGISTiledElevationTerrainProvider.prototype.getTileDataAvailable = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n if (!this._hasAvailability) {\r\n return undefined;\r\n }\r\n\r\n var result = isTileAvailable(this, level, x, y);\r\n if (defined(result)) {\r\n return result;\r\n }\r\n\r\n requestAvailability(this, level, x, y);\r\n\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Makes sure we load availability data for a tile\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {undefined|Promise} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded\r\n */\r\nArcGISTiledElevationTerrainProvider.prototype.loadTileDataAvailability = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n return undefined;\r\n};\r\n\r\nfunction findRange(origin, width, height, data) {\r\n var endCol = width - 1;\r\n var endRow = height - 1;\r\n\r\n var value = data[origin.y * width + origin.x];\r\n var endingIndices = [];\r\n var range = {\r\n startX: origin.x,\r\n startY: origin.y,\r\n endX: 0,\r\n endY: 0,\r\n };\r\n\r\n var corner = new Cartesian2(origin.x + 1, origin.y + 1);\r\n var doneX = false;\r\n var doneY = false;\r\n while (!(doneX && doneY)) {\r\n // We want to use the original value when checking Y,\r\n // so get it before it possibly gets incremented\r\n var endX = corner.x;\r\n\r\n // If we no longer move in the Y direction we need to check the corner tile in X pass\r\n var endY = doneY ? corner.y + 1 : corner.y;\r\n\r\n // Check X range\r\n if (!doneX) {\r\n for (var y = origin.y; y < endY; ++y) {\r\n if (data[y * width + corner.x] !== value) {\r\n doneX = true;\r\n break;\r\n }\r\n }\r\n\r\n if (doneX) {\r\n endingIndices.push(new Cartesian2(corner.x, origin.y));\r\n\r\n // Use the last good column so we can continue with Y\r\n --corner.x;\r\n --endX;\r\n range.endX = corner.x;\r\n } else if (corner.x === endCol) {\r\n range.endX = corner.x;\r\n doneX = true;\r\n } else {\r\n ++corner.x;\r\n }\r\n }\r\n\r\n // Check Y range - The corner tile is checked here\r\n if (!doneY) {\r\n var col = corner.y * width;\r\n for (var x = origin.x; x <= endX; ++x) {\r\n if (data[col + x] !== value) {\r\n doneY = true;\r\n break;\r\n }\r\n }\r\n\r\n if (doneY) {\r\n endingIndices.push(new Cartesian2(origin.x, corner.y));\r\n\r\n // Use the last good row so we can continue with X\r\n --corner.y;\r\n range.endY = corner.y;\r\n } else if (corner.y === endRow) {\r\n range.endY = corner.y;\r\n doneY = true;\r\n } else {\r\n ++corner.y;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n endingIndices: endingIndices,\r\n range: range,\r\n value: value,\r\n };\r\n}\r\n\r\nfunction computeAvailability(x, y, width, height, data) {\r\n var ranges = [];\r\n\r\n var singleValue = data.every(function (val) {\r\n return val === data[0];\r\n });\r\n if (singleValue) {\r\n if (data[0] === 1) {\r\n ranges.push({\r\n startX: x,\r\n startY: y,\r\n endX: x + width - 1,\r\n endY: y + height - 1,\r\n });\r\n }\r\n\r\n return ranges;\r\n }\r\n\r\n var positions = [new Cartesian2(0, 0)];\r\n while (positions.length > 0) {\r\n var origin = positions.pop();\r\n var result = findRange(origin, width, height, data);\r\n\r\n if (result.value === 1) {\r\n // Convert range into the array into global tile coordinates\r\n var range = result.range;\r\n range.startX += x;\r\n range.endX += x;\r\n range.startY += y;\r\n range.endY += y;\r\n ranges.push(range);\r\n }\r\n\r\n var endingIndices = result.endingIndices;\r\n if (endingIndices.length > 0) {\r\n positions = positions.concat(endingIndices);\r\n }\r\n }\r\n\r\n return ranges;\r\n}\r\n\r\nfunction requestAvailability(that, level, x, y) {\r\n if (!that._hasAvailability) {\r\n return {};\r\n }\r\n\r\n // Fetch 128x128 availability list, so we make the minimum amount of requests\r\n var xOffset = Math.floor(x / 128) * 128;\r\n var yOffset = Math.floor(y / 128) * 128;\r\n\r\n var dim = Math.min(1 << level, 128);\r\n var url =\r\n \"tilemap/\" + level + \"/\" + yOffset + \"/\" + xOffset + \"/\" + dim + \"/\" + dim;\r\n\r\n var availableCache = that._availableCache;\r\n if (defined(availableCache[url])) {\r\n return availableCache[url];\r\n }\r\n\r\n var request = new Request({\r\n throttle: false,\r\n throttleByServer: true,\r\n type: RequestType.TERRAIN,\r\n });\r\n\r\n var tilemapResource = that._resource.getDerivedResource({\r\n url: url,\r\n request: request,\r\n });\r\n\r\n var promise = tilemapResource.fetchJson();\r\n if (!defined(promise)) {\r\n return {};\r\n }\r\n\r\n promise = promise.then(function (result) {\r\n var available = computeAvailability(\r\n xOffset,\r\n yOffset,\r\n dim,\r\n dim,\r\n result.data\r\n );\r\n\r\n // Mark whole area as having availability loaded\r\n that._tilesAvailablityLoaded.addAvailableTileRange(\r\n level,\r\n xOffset,\r\n yOffset,\r\n xOffset + dim,\r\n yOffset + dim\r\n );\r\n\r\n var tilesAvailable = that._tilesAvailable;\r\n for (var i = 0; i < available.length; ++i) {\r\n var range = available[i];\r\n tilesAvailable.addAvailableTileRange(\r\n level,\r\n range.startX,\r\n range.startY,\r\n range.endX,\r\n range.endY\r\n );\r\n }\r\n\r\n // Conveniently return availability of original tile\r\n return isTileAvailable(that, level, x, y);\r\n });\r\n\r\n availableCache[url] = {\r\n promise: promise,\r\n request: request,\r\n };\r\n\r\n promise = promise.always(function (result) {\r\n delete availableCache[url];\r\n\r\n return result;\r\n });\r\n\r\n return {\r\n promise: promise,\r\n request: request,\r\n };\r\n}\r\nexport default ArcGISTiledElevationTerrainProvider;\r\n","/**\r\n * ArcType defines the path that should be taken connecting vertices.\r\n *\r\n * @enum {Number}\r\n */\r\nvar ArcType = {\r\n /**\r\n * Straight line that does not conform to the surface of the ellipsoid.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NONE: 0,\r\n\r\n /**\r\n * Follow geodesic path.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n GEODESIC: 1,\r\n\r\n /**\r\n * Follow rhumb or loxodrome path.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RHUMB: 2,\r\n};\r\nexport default Object.freeze(ArcType);\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * Fill an array or a portion of an array with a given value.\r\n *\r\n * @param {Array} array The array to fill.\r\n * @param {*} value The value to fill the array with.\r\n * @param {Number} [start=0] The index to start filling at.\r\n * @param {Number} [end=array.length] The index to end stop at.\r\n *\r\n * @returns {Array} The resulting array.\r\n * @private\r\n */\r\nfunction arrayFill(array, value, start, end) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n Check.defined(\"value\", value);\r\n if (defined(start)) {\r\n Check.typeOf.number(\"start\", start);\r\n }\r\n if (defined(end)) {\r\n Check.typeOf.number(\"end\", end);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (typeof array.fill === \"function\") {\r\n return array.fill(value, start, end);\r\n }\r\n\r\n var length = array.length >>> 0;\r\n var relativeStart = defaultValue(start, 0);\r\n // If negative, find wrap around position\r\n var k =\r\n relativeStart < 0\r\n ? Math.max(length + relativeStart, 0)\r\n : Math.min(relativeStart, length);\r\n var relativeEnd = defaultValue(end, length);\r\n // If negative, find wrap around position\r\n var last =\r\n relativeEnd < 0\r\n ? Math.max(length + relativeEnd, 0)\r\n : Math.min(relativeEnd, length);\r\n\r\n // Fill array accordingly\r\n while (k < last) {\r\n array[k] = value;\r\n k++;\r\n }\r\n return array;\r\n}\r\nexport default arrayFill;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nvar removeDuplicatesEpsilon = CesiumMath.EPSILON10;\r\n\r\n/**\r\n * Removes adjacent duplicate values in an array of values.\r\n *\r\n * @param {Array.<*>} [values] The array of values.\r\n * @param {Function} equalsEpsilon Function to compare values with an epsilon. Boolean equalsEpsilon(left, right, epsilon).\r\n * @param {Boolean} [wrapAround=false] Compare the last value in the array against the first value.\r\n * @returns {Array.<*>|undefined} A new array of values with no adjacent duplicate values or the input array if no duplicates were found.\r\n *\r\n * @example\r\n * // Returns [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0), (3.0, 3.0, 3.0), (1.0, 1.0, 1.0)]\r\n * var values = [\r\n * new Cesium.Cartesian3(1.0, 1.0, 1.0),\r\n * new Cesium.Cartesian3(1.0, 1.0, 1.0),\r\n * new Cesium.Cartesian3(2.0, 2.0, 2.0),\r\n * new Cesium.Cartesian3(3.0, 3.0, 3.0),\r\n * new Cesium.Cartesian3(1.0, 1.0, 1.0)];\r\n * var nonDuplicatevalues = Cesium.PolylinePipeline.removeDuplicates(values, Cartesian3.equalsEpsilon);\r\n *\r\n * @example\r\n * // Returns [(1.0, 1.0, 1.0), (2.0, 2.0, 2.0), (3.0, 3.0, 3.0)]\r\n * var values = [\r\n * new Cesium.Cartesian3(1.0, 1.0, 1.0),\r\n * new Cesium.Cartesian3(1.0, 1.0, 1.0),\r\n * new Cesium.Cartesian3(2.0, 2.0, 2.0),\r\n * new Cesium.Cartesian3(3.0, 3.0, 3.0),\r\n * new Cesium.Cartesian3(1.0, 1.0, 1.0)];\r\n * var nonDuplicatevalues = Cesium.PolylinePipeline.removeDuplicates(values, Cartesian3.equalsEpsilon, true);\r\n *\r\n * @private\r\n */\r\nfunction arrayRemoveDuplicates(values, equalsEpsilon, wrapAround) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"equalsEpsilon\", equalsEpsilon);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(values)) {\r\n return undefined;\r\n }\r\n\r\n wrapAround = defaultValue(wrapAround, false);\r\n\r\n var length = values.length;\r\n if (length < 2) {\r\n return values;\r\n }\r\n\r\n var i;\r\n var v0;\r\n var v1;\r\n\r\n for (i = 1; i < length; ++i) {\r\n v0 = values[i - 1];\r\n v1 = values[i];\r\n if (equalsEpsilon(v0, v1, removeDuplicatesEpsilon)) {\r\n break;\r\n }\r\n }\r\n\r\n if (i === length) {\r\n if (\r\n wrapAround &&\r\n equalsEpsilon(\r\n values[0],\r\n values[values.length - 1],\r\n removeDuplicatesEpsilon\r\n )\r\n ) {\r\n return values.slice(1);\r\n }\r\n return values;\r\n }\r\n\r\n var cleanedvalues = values.slice(0, i);\r\n for (; i < length; ++i) {\r\n // v0 is set by either the previous loop, or the previous clean point.\r\n v1 = values[i];\r\n if (!equalsEpsilon(v0, v1, removeDuplicatesEpsilon)) {\r\n cleanedvalues.push(v1);\r\n v0 = v1;\r\n }\r\n }\r\n\r\n if (\r\n wrapAround &&\r\n cleanedvalues.length > 1 &&\r\n equalsEpsilon(\r\n cleanedvalues[0],\r\n cleanedvalues[cleanedvalues.length - 1],\r\n removeDuplicatesEpsilon\r\n )\r\n ) {\r\n cleanedvalues.shift();\r\n }\r\n\r\n return cleanedvalues;\r\n}\r\nexport default arrayRemoveDuplicates;\r\n","import Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\nimport FeatureDetection from \"./FeatureDetection.js\";\r\n\r\n/**\r\n * Create a shallow copy of an array from begin to end.\r\n *\r\n * @param {Array} array The array to fill.\r\n * @param {Number} [begin=0] The index to start at.\r\n * @param {Number} [end=array.length] The index to end at which is not included.\r\n *\r\n * @returns {Array} The resulting array.\r\n * @private\r\n */\r\nfunction arraySlice(array, begin, end) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n if (defined(begin)) {\r\n Check.typeOf.number(\"begin\", begin);\r\n }\r\n if (defined(end)) {\r\n Check.typeOf.number(\"end\", end);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (typeof array.slice === \"function\") {\r\n return array.slice(begin, end);\r\n }\r\n\r\n var copy = Array.prototype.slice.call(array, begin, end);\r\n var typedArrayTypes = FeatureDetection.typedArrayTypes;\r\n var length = typedArrayTypes.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (array instanceof typedArrayTypes[i]) {\r\n copy = new typedArrayTypes[i](copy);\r\n break;\r\n }\r\n }\r\n\r\n return copy;\r\n}\r\nexport default arraySlice;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * A collection of key-value pairs that is stored as a hash for easy\r\n * lookup but also provides an array for fast iteration.\r\n * @alias AssociativeArray\r\n * @constructor\r\n */\r\nfunction AssociativeArray() {\r\n this._array = [];\r\n this._hash = {};\r\n}\r\n\r\nObject.defineProperties(AssociativeArray.prototype, {\r\n /**\r\n * Gets the number of items in the collection.\r\n * @memberof AssociativeArray.prototype\r\n *\r\n * @type {Number}\r\n */\r\n length: {\r\n get: function () {\r\n return this._array.length;\r\n },\r\n },\r\n /**\r\n * Gets an unordered array of all values in the collection.\r\n * This is a live array that will automatically reflect the values in the collection,\r\n * it should not be modified directly.\r\n * @memberof AssociativeArray.prototype\r\n *\r\n * @type {Array}\r\n */\r\n values: {\r\n get: function () {\r\n return this._array;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Determines if the provided key is in the array.\r\n *\r\n * @param {String|Number} key The key to check.\r\n * @returns {Boolean} true if the key is in the array, false otherwise.\r\n */\r\nAssociativeArray.prototype.contains = function (key) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof key !== \"string\" && typeof key !== \"number\") {\r\n throw new DeveloperError(\"key is required to be a string or number.\");\r\n }\r\n //>>includeEnd('debug');\r\n return defined(this._hash[key]);\r\n};\r\n\r\n/**\r\n * Associates the provided key with the provided value. If the key already\r\n * exists, it is overwritten with the new value.\r\n *\r\n * @param {String|Number} key A unique identifier.\r\n * @param {*} value The value to associate with the provided key.\r\n */\r\nAssociativeArray.prototype.set = function (key, value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof key !== \"string\" && typeof key !== \"number\") {\r\n throw new DeveloperError(\"key is required to be a string or number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var oldValue = this._hash[key];\r\n if (value !== oldValue) {\r\n this.remove(key);\r\n this._hash[key] = value;\r\n this._array.push(value);\r\n }\r\n};\r\n\r\n/**\r\n * Retrieves the value associated with the provided key.\r\n *\r\n * @param {String|Number} key The key whose value is to be retrieved.\r\n * @returns {*} The associated value, or undefined if the key does not exist in the collection.\r\n */\r\nAssociativeArray.prototype.get = function (key) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof key !== \"string\" && typeof key !== \"number\") {\r\n throw new DeveloperError(\"key is required to be a string or number.\");\r\n }\r\n //>>includeEnd('debug');\r\n return this._hash[key];\r\n};\r\n\r\n/**\r\n * Removes a key-value pair from the collection.\r\n *\r\n * @param {String|Number} key The key to be removed.\r\n * @returns {Boolean} True if it was removed, false if the key was not in the collection.\r\n */\r\nAssociativeArray.prototype.remove = function (key) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(key) && typeof key !== \"string\" && typeof key !== \"number\") {\r\n throw new DeveloperError(\"key is required to be a string or number.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var value = this._hash[key];\r\n var hasValue = defined(value);\r\n if (hasValue) {\r\n var array = this._array;\r\n array.splice(array.indexOf(value), 1);\r\n delete this._hash[key];\r\n }\r\n return hasValue;\r\n};\r\n\r\n/**\r\n * Clears the collection.\r\n */\r\nAssociativeArray.prototype.removeAll = function () {\r\n var array = this._array;\r\n if (array.length > 0) {\r\n this._hash = {};\r\n array.length = 0;\r\n }\r\n};\r\nexport default AssociativeArray;\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nvar scratchCartesian1 = new Cartesian3();\r\nvar scratchCartesian2 = new Cartesian3();\r\nvar scratchCartesian3 = new Cartesian3();\r\n\r\n/**\r\n * Computes the barycentric coordinates for a point with respect to a triangle.\r\n *\r\n * @function\r\n *\r\n * @param {Cartesian2|Cartesian3} point The point to test.\r\n * @param {Cartesian2|Cartesian3} p0 The first point of the triangle, corresponding to the barycentric x-axis.\r\n * @param {Cartesian2|Cartesian3} p1 The second point of the triangle, corresponding to the barycentric y-axis.\r\n * @param {Cartesian2|Cartesian3} p2 The third point of the triangle, corresponding to the barycentric z-axis.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided.\r\n *\r\n * @example\r\n * // Returns Cartesian3.UNIT_X\r\n * var p = new Cesium.Cartesian3(-1.0, 0.0, 0.0);\r\n * var b = Cesium.barycentricCoordinates(p,\r\n * new Cesium.Cartesian3(-1.0, 0.0, 0.0),\r\n * new Cesium.Cartesian3( 1.0, 0.0, 0.0),\r\n * new Cesium.Cartesian3( 0.0, 1.0, 1.0));\r\n */\r\nfunction barycentricCoordinates(point, p0, p1, p2, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"point\", point);\r\n Check.defined(\"p0\", p0);\r\n Check.defined(\"p1\", p1);\r\n Check.defined(\"p2\", p2);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n // Implementation based on http://www.blackpawn.com/texts/pointinpoly/default.html.\r\n var v0;\r\n var v1;\r\n var v2;\r\n var dot00;\r\n var dot01;\r\n var dot02;\r\n var dot11;\r\n var dot12;\r\n\r\n if (!defined(p0.z)) {\r\n if (Cartesian2.equalsEpsilon(point, p0, CesiumMath.EPSILON14)) {\r\n return Cartesian3.clone(Cartesian3.UNIT_X, result);\r\n }\r\n if (Cartesian2.equalsEpsilon(point, p1, CesiumMath.EPSILON14)) {\r\n return Cartesian3.clone(Cartesian3.UNIT_Y, result);\r\n }\r\n if (Cartesian2.equalsEpsilon(point, p2, CesiumMath.EPSILON14)) {\r\n return Cartesian3.clone(Cartesian3.UNIT_Z, result);\r\n }\r\n\r\n v0 = Cartesian2.subtract(p1, p0, scratchCartesian1);\r\n v1 = Cartesian2.subtract(p2, p0, scratchCartesian2);\r\n v2 = Cartesian2.subtract(point, p0, scratchCartesian3);\r\n\r\n dot00 = Cartesian2.dot(v0, v0);\r\n dot01 = Cartesian2.dot(v0, v1);\r\n dot02 = Cartesian2.dot(v0, v2);\r\n dot11 = Cartesian2.dot(v1, v1);\r\n dot12 = Cartesian2.dot(v1, v2);\r\n } else {\r\n if (Cartesian3.equalsEpsilon(point, p0, CesiumMath.EPSILON14)) {\r\n return Cartesian3.clone(Cartesian3.UNIT_X, result);\r\n }\r\n if (Cartesian3.equalsEpsilon(point, p1, CesiumMath.EPSILON14)) {\r\n return Cartesian3.clone(Cartesian3.UNIT_Y, result);\r\n }\r\n if (Cartesian3.equalsEpsilon(point, p2, CesiumMath.EPSILON14)) {\r\n return Cartesian3.clone(Cartesian3.UNIT_Z, result);\r\n }\r\n\r\n v0 = Cartesian3.subtract(p1, p0, scratchCartesian1);\r\n v1 = Cartesian3.subtract(p2, p0, scratchCartesian2);\r\n v2 = Cartesian3.subtract(point, p0, scratchCartesian3);\r\n\r\n dot00 = Cartesian3.dot(v0, v0);\r\n dot01 = Cartesian3.dot(v0, v1);\r\n dot02 = Cartesian3.dot(v0, v2);\r\n dot11 = Cartesian3.dot(v1, v1);\r\n dot12 = Cartesian3.dot(v1, v2);\r\n }\r\n\r\n result.y = dot11 * dot02 - dot01 * dot12;\r\n result.z = dot00 * dot12 - dot01 * dot02;\r\n var q = dot00 * dot11 - dot01 * dot01;\r\n\r\n // This is done to avoid dividing by infinity causing a NaN\r\n if (result.y !== 0) {\r\n result.y /= q;\r\n }\r\n if (result.z !== 0) {\r\n result.z /= q;\r\n }\r\n\r\n result.x = 1.0 - result.y - result.z;\r\n return result;\r\n}\r\nexport default barycentricCoordinates;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\nvar url = \"https://dev.virtualearth.net/REST/v1/Locations\";\r\n\r\n/**\r\n * Provides geocoding through Bing Maps.\r\n * @alias BingMapsGeocoderService\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {String} options.key A key to use with the Bing Maps geocoding service\r\n */\r\nfunction BingMapsGeocoderService(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var key = options.key;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(key)) {\r\n throw new DeveloperError(\"options.key is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._key = key;\r\n\r\n this._resource = new Resource({\r\n url: url,\r\n queryParameters: {\r\n key: key,\r\n },\r\n });\r\n}\r\n\r\nObject.defineProperties(BingMapsGeocoderService.prototype, {\r\n /**\r\n * The URL endpoint for the Bing geocoder service\r\n * @type {String}\r\n * @memberof BingMapsGeocoderService.prototype\r\n * @readonly\r\n */\r\n url: {\r\n get: function () {\r\n return url;\r\n },\r\n },\r\n\r\n /**\r\n * The key for the Bing geocoder service\r\n * @type {String}\r\n * @memberof BingMapsGeocoderService.prototype\r\n * @readonly\r\n */\r\n key: {\r\n get: function () {\r\n return this._key;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @function\r\n *\r\n * @param {String} query The query to be sent to the geocoder service\r\n * @returns {Promise}\r\n */\r\nBingMapsGeocoderService.prototype.geocode = function (query) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"query\", query);\r\n //>>includeEnd('debug');\r\n\r\n var resource = this._resource.getDerivedResource({\r\n queryParameters: {\r\n query: query,\r\n },\r\n });\r\n\r\n return resource.fetchJsonp(\"jsonp\").then(function (result) {\r\n if (result.resourceSets.length === 0) {\r\n return [];\r\n }\r\n\r\n var results = result.resourceSets[0].resources;\r\n\r\n return results.map(function (resource) {\r\n var bbox = resource.bbox;\r\n var south = bbox[0];\r\n var west = bbox[1];\r\n var north = bbox[2];\r\n var east = bbox[3];\r\n return {\r\n displayName: resource.name,\r\n destination: Rectangle.fromDegrees(west, south, east, north),\r\n };\r\n });\r\n });\r\n};\r\nexport default BingMapsGeocoderService;\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport GeographicProjection from \"./GeographicProjection.js\";\r\nimport Intersect from \"./Intersect.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\n\r\n/**\r\n * A bounding rectangle given by a corner, width and height.\r\n * @alias BoundingRectangle\r\n * @constructor\r\n *\r\n * @param {Number} [x=0.0] The x coordinate of the rectangle.\r\n * @param {Number} [y=0.0] The y coordinate of the rectangle.\r\n * @param {Number} [width=0.0] The width of the rectangle.\r\n * @param {Number} [height=0.0] The height of the rectangle.\r\n *\r\n * @see BoundingSphere\r\n * @see Packable\r\n */\r\nfunction BoundingRectangle(x, y, width, height) {\r\n /**\r\n * The x coordinate of the rectangle.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.x = defaultValue(x, 0.0);\r\n\r\n /**\r\n * The y coordinate of the rectangle.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.y = defaultValue(y, 0.0);\r\n\r\n /**\r\n * The width of the rectangle.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.width = defaultValue(width, 0.0);\r\n\r\n /**\r\n * The height of the rectangle.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.height = defaultValue(height, 0.0);\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nBoundingRectangle.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {BoundingRectangle} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nBoundingRectangle.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.x;\r\n array[startingIndex++] = value.y;\r\n array[startingIndex++] = value.width;\r\n array[startingIndex] = value.height;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {BoundingRectangle} [result] The object into which to store the result.\r\n * @returns {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.\r\n */\r\nBoundingRectangle.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new BoundingRectangle();\r\n }\r\n result.x = array[startingIndex++];\r\n result.y = array[startingIndex++];\r\n result.width = array[startingIndex++];\r\n result.height = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a bounding rectangle enclosing the list of 2D points.\r\n * The rectangle is oriented with the corner at the bottom left.\r\n *\r\n * @param {Cartesian2[]} positions List of points that the bounding rectangle will enclose. Each point must have x and y properties.\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.\r\n */\r\nBoundingRectangle.fromPoints = function (positions, result) {\r\n if (!defined(result)) {\r\n result = new BoundingRectangle();\r\n }\r\n\r\n if (!defined(positions) || positions.length === 0) {\r\n result.x = 0;\r\n result.y = 0;\r\n result.width = 0;\r\n result.height = 0;\r\n return result;\r\n }\r\n\r\n var length = positions.length;\r\n\r\n var minimumX = positions[0].x;\r\n var minimumY = positions[0].y;\r\n\r\n var maximumX = positions[0].x;\r\n var maximumY = positions[0].y;\r\n\r\n for (var i = 1; i < length; i++) {\r\n var p = positions[i];\r\n var x = p.x;\r\n var y = p.y;\r\n\r\n minimumX = Math.min(x, minimumX);\r\n maximumX = Math.max(x, maximumX);\r\n minimumY = Math.min(y, minimumY);\r\n maximumY = Math.max(y, maximumY);\r\n }\r\n\r\n result.x = minimumX;\r\n result.y = minimumY;\r\n result.width = maximumX - minimumX;\r\n result.height = maximumY - minimumY;\r\n return result;\r\n};\r\n\r\nvar defaultProjection = new GeographicProjection();\r\nvar fromRectangleLowerLeft = new Cartographic();\r\nvar fromRectangleUpperRight = new Cartographic();\r\n/**\r\n * Computes a bounding rectangle from a rectangle.\r\n *\r\n * @param {Rectangle} rectangle The valid rectangle used to create a bounding rectangle.\r\n * @param {Object} [projection=GeographicProjection] The projection used to project the rectangle into 2D.\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.\r\n */\r\nBoundingRectangle.fromRectangle = function (rectangle, projection, result) {\r\n if (!defined(result)) {\r\n result = new BoundingRectangle();\r\n }\r\n\r\n if (!defined(rectangle)) {\r\n result.x = 0;\r\n result.y = 0;\r\n result.width = 0;\r\n result.height = 0;\r\n return result;\r\n }\r\n\r\n projection = defaultValue(projection, defaultProjection);\r\n\r\n var lowerLeft = projection.project(\r\n Rectangle.southwest(rectangle, fromRectangleLowerLeft)\r\n );\r\n var upperRight = projection.project(\r\n Rectangle.northeast(rectangle, fromRectangleUpperRight)\r\n );\r\n\r\n Cartesian2.subtract(upperRight, lowerLeft, upperRight);\r\n\r\n result.x = lowerLeft.x;\r\n result.y = lowerLeft.y;\r\n result.width = upperRight.x;\r\n result.height = upperRight.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a BoundingRectangle instance.\r\n *\r\n * @param {BoundingRectangle} rectangle The bounding rectangle to duplicate.\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided. (Returns undefined if rectangle is undefined)\r\n */\r\nBoundingRectangle.clone = function (rectangle, result) {\r\n if (!defined(rectangle)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new BoundingRectangle(\r\n rectangle.x,\r\n rectangle.y,\r\n rectangle.width,\r\n rectangle.height\r\n );\r\n }\r\n\r\n result.x = rectangle.x;\r\n result.y = rectangle.y;\r\n result.width = rectangle.width;\r\n result.height = rectangle.height;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a bounding rectangle that is the union of the left and right bounding rectangles.\r\n *\r\n * @param {BoundingRectangle} left A rectangle to enclose in bounding rectangle.\r\n * @param {BoundingRectangle} right A rectangle to enclose in a bounding rectangle.\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.\r\n */\r\nBoundingRectangle.union = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new BoundingRectangle();\r\n }\r\n\r\n var lowerLeftX = Math.min(left.x, right.x);\r\n var lowerLeftY = Math.min(left.y, right.y);\r\n var upperRightX = Math.max(left.x + left.width, right.x + right.width);\r\n var upperRightY = Math.max(left.y + left.height, right.y + right.height);\r\n\r\n result.x = lowerLeftX;\r\n result.y = lowerLeftY;\r\n result.width = upperRightX - lowerLeftX;\r\n result.height = upperRightY - lowerLeftY;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a bounding rectangle by enlarging the provided rectangle until it contains the provided point.\r\n *\r\n * @param {BoundingRectangle} rectangle A rectangle to expand.\r\n * @param {Cartesian2} point A point to enclose in a bounding rectangle.\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.\r\n */\r\nBoundingRectangle.expand = function (rectangle, point, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n Check.typeOf.object(\"point\", point);\r\n //>>includeEnd('debug');\r\n\r\n result = BoundingRectangle.clone(rectangle, result);\r\n\r\n var width = point.x - result.x;\r\n var height = point.y - result.y;\r\n\r\n if (width > result.width) {\r\n result.width = width;\r\n } else if (width < 0) {\r\n result.width -= width;\r\n result.x = point.x;\r\n }\r\n\r\n if (height > result.height) {\r\n result.height = height;\r\n } else if (height < 0) {\r\n result.height -= height;\r\n result.y = point.y;\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines if two rectangles intersect.\r\n *\r\n * @param {BoundingRectangle} left A rectangle to check for intersection.\r\n * @param {BoundingRectangle} right The other rectangle to check for intersection.\r\n * @returns {Intersect} Intersect.INTERSECTING if the rectangles intersect, Intersect.OUTSIDE otherwise.\r\n */\r\nBoundingRectangle.intersect = function (left, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n //>>includeEnd('debug');\r\n\r\n var leftX = left.x;\r\n var leftY = left.y;\r\n var rightX = right.x;\r\n var rightY = right.y;\r\n if (\r\n !(\r\n leftX > rightX + right.width ||\r\n leftX + left.width < rightX ||\r\n leftY + left.height < rightY ||\r\n leftY > rightY + right.height\r\n )\r\n ) {\r\n return Intersect.INTERSECTING;\r\n }\r\n\r\n return Intersect.OUTSIDE;\r\n};\r\n\r\n/**\r\n * Compares the provided BoundingRectangles componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {BoundingRectangle} [left] The first BoundingRectangle.\r\n * @param {BoundingRectangle} [right] The second BoundingRectangle.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nBoundingRectangle.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.x === right.x &&\r\n left.y === right.y &&\r\n left.width === right.width &&\r\n left.height === right.height)\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates this BoundingRectangle instance.\r\n *\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The modified result parameter or a new BoundingRectangle instance if one was not provided.\r\n */\r\nBoundingRectangle.prototype.clone = function (result) {\r\n return BoundingRectangle.clone(this, result);\r\n};\r\n\r\n/**\r\n * Determines if this rectangle intersects with another.\r\n *\r\n * @param {BoundingRectangle} right A rectangle to check for intersection.\r\n * @returns {Intersect} Intersect.INTERSECTING if the rectangles intersect, Intersect.OUTSIDE otherwise.\r\n */\r\nBoundingRectangle.prototype.intersect = function (right) {\r\n return BoundingRectangle.intersect(this, right);\r\n};\r\n\r\n/**\r\n * Compares this BoundingRectangle against the provided BoundingRectangle componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {BoundingRectangle} [right] The right hand side BoundingRectangle.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nBoundingRectangle.prototype.equals = function (right) {\r\n return BoundingRectangle.equals(this, right);\r\n};\r\nexport default BoundingRectangle;\r\n","/**\r\n * @private\r\n */\r\nvar GeometryType = {\r\n NONE: 0,\r\n TRIANGLES: 1,\r\n LINES: 2,\r\n POLYLINES: 3,\r\n};\r\nexport default Object.freeze(GeometryType);\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * A 2x2 matrix, indexable as a column-major order array.\r\n * Constructor parameters are in row-major order for code readability.\r\n * @alias Matrix2\r\n * @constructor\r\n * @implements {ArrayLike}\r\n *\r\n * @param {Number} [column0Row0=0.0] The value for column 0, row 0.\r\n * @param {Number} [column1Row0=0.0] The value for column 1, row 0.\r\n * @param {Number} [column0Row1=0.0] The value for column 0, row 1.\r\n * @param {Number} [column1Row1=0.0] The value for column 1, row 1.\r\n *\r\n * @see Matrix2.fromColumnMajorArray\r\n * @see Matrix2.fromRowMajorArray\r\n * @see Matrix2.fromScale\r\n * @see Matrix2.fromUniformScale\r\n * @see Matrix3\r\n * @see Matrix4\r\n */\r\nfunction Matrix2(column0Row0, column1Row0, column0Row1, column1Row1) {\r\n this[0] = defaultValue(column0Row0, 0.0);\r\n this[1] = defaultValue(column0Row1, 0.0);\r\n this[2] = defaultValue(column1Row0, 0.0);\r\n this[3] = defaultValue(column1Row1, 0.0);\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nMatrix2.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Matrix2} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nMatrix2.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value[0];\r\n array[startingIndex++] = value[1];\r\n array[startingIndex++] = value[2];\r\n array[startingIndex++] = value[3];\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Matrix2} [result] The object into which to store the result.\r\n * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided.\r\n */\r\nMatrix2.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Matrix2();\r\n }\r\n\r\n result[0] = array[startingIndex++];\r\n result[1] = array[startingIndex++];\r\n result[2] = array[startingIndex++];\r\n result[3] = array[startingIndex++];\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a Matrix2 instance.\r\n *\r\n * @param {Matrix2} matrix The matrix to duplicate.\r\n * @param {Matrix2} [result] The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided. (Returns undefined if matrix is undefined)\r\n */\r\nMatrix2.clone = function (matrix, result) {\r\n if (!defined(matrix)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new Matrix2(matrix[0], matrix[2], matrix[1], matrix[3]);\r\n }\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[3];\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Matrix2 from 4 consecutive elements in an array.\r\n *\r\n * @param {Number[]} array The array whose 4 consecutive elements correspond to the positions of the matrix. Assumes column-major order.\r\n * @param {Number} [startingIndex=0] The offset into the array of the first element, which corresponds to first column first row position in the matrix.\r\n * @param {Matrix2} [result] The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided.\r\n *\r\n * @example\r\n * // Create the Matrix2:\r\n * // [1.0, 2.0]\r\n * // [1.0, 2.0]\r\n *\r\n * var v = [1.0, 1.0, 2.0, 2.0];\r\n * var m = Cesium.Matrix2.fromArray(v);\r\n *\r\n * // Create same Matrix2 with using an offset into an array\r\n * var v2 = [0.0, 0.0, 1.0, 1.0, 2.0, 2.0];\r\n * var m2 = Cesium.Matrix2.fromArray(v2, 2);\r\n */\r\nMatrix2.fromArray = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new Matrix2();\r\n }\r\n\r\n result[0] = array[startingIndex];\r\n result[1] = array[startingIndex + 1];\r\n result[2] = array[startingIndex + 2];\r\n result[3] = array[startingIndex + 3];\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a Matrix2 instance from a column-major order array.\r\n *\r\n * @param {Number[]} values The column-major order array.\r\n * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.\r\n */\r\nMatrix2.fromColumnMajorArray = function (values, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"values\", values);\r\n //>>includeEnd('debug');\r\n\r\n return Matrix2.clone(values, result);\r\n};\r\n\r\n/**\r\n * Creates a Matrix2 instance from a row-major order array.\r\n * The resulting matrix will be in column-major order.\r\n *\r\n * @param {Number[]} values The row-major order array.\r\n * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.\r\n */\r\nMatrix2.fromRowMajorArray = function (values, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"values\", values);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix2(values[0], values[1], values[2], values[3]);\r\n }\r\n result[0] = values[0];\r\n result[1] = values[2];\r\n result[2] = values[1];\r\n result[3] = values[3];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix2 instance representing a non-uniform scale.\r\n *\r\n * @param {Cartesian2} scale The x and y scale factors.\r\n * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.\r\n *\r\n * @example\r\n * // Creates\r\n * // [7.0, 0.0]\r\n * // [0.0, 8.0]\r\n * var m = Cesium.Matrix2.fromScale(new Cesium.Cartesian2(7.0, 8.0));\r\n */\r\nMatrix2.fromScale = function (scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"scale\", scale);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix2(scale.x, 0.0, 0.0, scale.y);\r\n }\r\n\r\n result[0] = scale.x;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = scale.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a Matrix2 instance representing a uniform scale.\r\n *\r\n * @param {Number} scale The uniform scale factor.\r\n * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.\r\n *\r\n * @example\r\n * // Creates\r\n * // [2.0, 0.0]\r\n * // [0.0, 2.0]\r\n * var m = Cesium.Matrix2.fromUniformScale(2.0);\r\n */\r\nMatrix2.fromUniformScale = function (scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"scale\", scale);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Matrix2(scale, 0.0, 0.0, scale);\r\n }\r\n\r\n result[0] = scale;\r\n result[1] = 0.0;\r\n result[2] = 0.0;\r\n result[3] = scale;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a rotation matrix.\r\n *\r\n * @param {Number} angle The angle, in radians, of the rotation. Positive angles are counterclockwise.\r\n * @param {Matrix2} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Matrix2} The modified result parameter, or a new Matrix2 instance if one was not provided.\r\n *\r\n * @example\r\n * // Rotate a point 45 degrees counterclockwise.\r\n * var p = new Cesium.Cartesian2(5, 6);\r\n * var m = Cesium.Matrix2.fromRotation(Cesium.Math.toRadians(45.0));\r\n * var rotated = Cesium.Matrix2.multiplyByVector(m, p, new Cesium.Cartesian2());\r\n */\r\nMatrix2.fromRotation = function (angle, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"angle\", angle);\r\n //>>includeEnd('debug');\r\n\r\n var cosAngle = Math.cos(angle);\r\n var sinAngle = Math.sin(angle);\r\n\r\n if (!defined(result)) {\r\n return new Matrix2(cosAngle, -sinAngle, sinAngle, cosAngle);\r\n }\r\n result[0] = cosAngle;\r\n result[1] = sinAngle;\r\n result[2] = -sinAngle;\r\n result[3] = cosAngle;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates an Array from the provided Matrix2 instance.\r\n * The array will be in column-major order.\r\n *\r\n * @param {Matrix2} matrix The matrix to use..\r\n * @param {Number[]} [result] The Array onto which to store the result.\r\n * @returns {Number[]} The modified Array parameter or a new Array instance if one was not provided.\r\n */\r\nMatrix2.toArray = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return [matrix[0], matrix[1], matrix[2], matrix[3]];\r\n }\r\n result[0] = matrix[0];\r\n result[1] = matrix[1];\r\n result[2] = matrix[2];\r\n result[3] = matrix[3];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the array index of the element at the provided row and column.\r\n *\r\n * @param {Number} row The zero-based index of the row.\r\n * @param {Number} column The zero-based index of the column.\r\n * @returns {Number} The index of the element at the provided row and column.\r\n *\r\n * @exception {DeveloperError} row must be 0 or 1.\r\n * @exception {DeveloperError} column must be 0 or 1.\r\n *\r\n * @example\r\n * var myMatrix = new Cesium.Matrix2();\r\n * var column1Row0Index = Cesium.Matrix2.getElementIndex(1, 0);\r\n * var column1Row0 = myMatrix[column1Row0Index]\r\n * myMatrix[column1Row0Index] = 10.0;\r\n */\r\nMatrix2.getElementIndex = function (column, row) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"row\", row, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"row\", row, 1);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"column\", column, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"column\", column, 1);\r\n //>>includeEnd('debug');\r\n\r\n return column * 2 + row;\r\n};\r\n\r\n/**\r\n * Retrieves a copy of the matrix column at the provided index as a Cartesian2 instance.\r\n *\r\n * @param {Matrix2} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the column to retrieve.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0 or 1.\r\n */\r\nMatrix2.getColumn = function (matrix, index, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 1);\r\n\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var startIndex = index * 2;\r\n var x = matrix[startIndex];\r\n var y = matrix[startIndex + 1];\r\n\r\n result.x = x;\r\n result.y = y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a new matrix that replaces the specified column in the provided matrix with the provided Cartesian2 instance.\r\n *\r\n * @param {Matrix2} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the column to set.\r\n * @param {Cartesian2} cartesian The Cartesian whose values will be assigned to the specified column.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0 or 1.\r\n */\r\nMatrix2.setColumn = function (matrix, index, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 1);\r\n\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result = Matrix2.clone(matrix, result);\r\n var startIndex = index * 2;\r\n result[startIndex] = cartesian.x;\r\n result[startIndex + 1] = cartesian.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Retrieves a copy of the matrix row at the provided index as a Cartesian2 instance.\r\n *\r\n * @param {Matrix2} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the row to retrieve.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0 or 1.\r\n */\r\nMatrix2.getRow = function (matrix, index, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 1);\r\n\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var x = matrix[index];\r\n var y = matrix[index + 2];\r\n\r\n result.x = x;\r\n result.y = y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a new matrix that replaces the specified row in the provided matrix with the provided Cartesian2 instance.\r\n *\r\n * @param {Matrix2} matrix The matrix to use.\r\n * @param {Number} index The zero-based index of the row to set.\r\n * @param {Cartesian2} cartesian The Cartesian whose values will be assigned to the specified row.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n *\r\n * @exception {DeveloperError} index must be 0 or 1.\r\n */\r\nMatrix2.setRow = function (matrix, index, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n Check.typeOf.number.lessThanOrEquals(\"index\", index, 1);\r\n\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result = Matrix2.clone(matrix, result);\r\n result[index] = cartesian.x;\r\n result[index + 2] = cartesian.y;\r\n return result;\r\n};\r\n\r\nvar scratchColumn = new Cartesian2();\r\n\r\n/**\r\n * Extracts the non-uniform scale assuming the matrix is an affine transformation.\r\n *\r\n * @param {Matrix2} matrix The matrix.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nMatrix2.getScale = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.x = Cartesian2.magnitude(\r\n Cartesian2.fromElements(matrix[0], matrix[1], scratchColumn)\r\n );\r\n result.y = Cartesian2.magnitude(\r\n Cartesian2.fromElements(matrix[2], matrix[3], scratchColumn)\r\n );\r\n return result;\r\n};\r\n\r\nvar scratchScale = new Cartesian2();\r\n\r\n/**\r\n * Computes the maximum scale assuming the matrix is an affine transformation.\r\n * The maximum scale is the maximum length of the column vectors.\r\n *\r\n * @param {Matrix2} matrix The matrix.\r\n * @returns {Number} The maximum scale.\r\n */\r\nMatrix2.getMaximumScale = function (matrix) {\r\n Matrix2.getScale(matrix, scratchScale);\r\n return Cartesian2.maximumComponent(scratchScale);\r\n};\r\n\r\n/**\r\n * Computes the product of two matrices.\r\n *\r\n * @param {Matrix2} left The first matrix.\r\n * @param {Matrix2} right The second matrix.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n */\r\nMatrix2.multiply = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var column0Row0 = left[0] * right[0] + left[2] * right[1];\r\n var column1Row0 = left[0] * right[2] + left[2] * right[3];\r\n var column0Row1 = left[1] * right[0] + left[3] * right[1];\r\n var column1Row1 = left[1] * right[2] + left[3] * right[3];\r\n\r\n result[0] = column0Row0;\r\n result[1] = column0Row1;\r\n result[2] = column1Row0;\r\n result[3] = column1Row1;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the sum of two matrices.\r\n *\r\n * @param {Matrix2} left The first matrix.\r\n * @param {Matrix2} right The second matrix.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n */\r\nMatrix2.add = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = left[0] + right[0];\r\n result[1] = left[1] + right[1];\r\n result[2] = left[2] + right[2];\r\n result[3] = left[3] + right[3];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the difference of two matrices.\r\n *\r\n * @param {Matrix2} left The first matrix.\r\n * @param {Matrix2} right The second matrix.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n */\r\nMatrix2.subtract = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = left[0] - right[0];\r\n result[1] = left[1] - right[1];\r\n result[2] = left[2] - right[2];\r\n result[3] = left[3] - right[3];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix and a column vector.\r\n *\r\n * @param {Matrix2} matrix The matrix.\r\n * @param {Cartesian2} cartesian The column.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter.\r\n */\r\nMatrix2.multiplyByVector = function (matrix, cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var x = matrix[0] * cartesian.x + matrix[2] * cartesian.y;\r\n var y = matrix[1] * cartesian.x + matrix[3] * cartesian.y;\r\n\r\n result.x = x;\r\n result.y = y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix and a scalar.\r\n *\r\n * @param {Matrix2} matrix The matrix.\r\n * @param {Number} scalar The number to multiply by.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n */\r\nMatrix2.multiplyByScalar = function (matrix, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = matrix[0] * scalar;\r\n result[1] = matrix[1] * scalar;\r\n result[2] = matrix[2] * scalar;\r\n result[3] = matrix[3] * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the product of a matrix times a (non-uniform) scale, as if the scale were a scale matrix.\r\n *\r\n * @param {Matrix2} matrix The matrix on the left-hand side.\r\n * @param {Cartesian2} scale The non-uniform scale on the right-hand side.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n *\r\n *\r\n * @example\r\n * // Instead of Cesium.Matrix2.multiply(m, Cesium.Matrix2.fromScale(scale), m);\r\n * Cesium.Matrix2.multiplyByScale(m, scale, m);\r\n *\r\n * @see Matrix2.fromScale\r\n * @see Matrix2.multiplyByUniformScale\r\n */\r\nMatrix2.multiplyByScale = function (matrix, scale, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"scale\", scale);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = matrix[0] * scale.x;\r\n result[1] = matrix[1] * scale.x;\r\n result[2] = matrix[2] * scale.y;\r\n result[3] = matrix[3] * scale.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a negated copy of the provided matrix.\r\n *\r\n * @param {Matrix2} matrix The matrix to negate.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n */\r\nMatrix2.negate = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = -matrix[0];\r\n result[1] = -matrix[1];\r\n result[2] = -matrix[2];\r\n result[3] = -matrix[3];\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the transpose of the provided matrix.\r\n *\r\n * @param {Matrix2} matrix The matrix to transpose.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n */\r\nMatrix2.transpose = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var column0Row0 = matrix[0];\r\n var column0Row1 = matrix[2];\r\n var column1Row0 = matrix[1];\r\n var column1Row1 = matrix[3];\r\n\r\n result[0] = column0Row0;\r\n result[1] = column0Row1;\r\n result[2] = column1Row0;\r\n result[3] = column1Row1;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes a matrix, which contains the absolute (unsigned) values of the provided matrix's elements.\r\n *\r\n * @param {Matrix2} matrix The matrix with signed elements.\r\n * @param {Matrix2} result The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter.\r\n */\r\nMatrix2.abs = function (matrix, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"matrix\", matrix);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result[0] = Math.abs(matrix[0]);\r\n result[1] = Math.abs(matrix[1]);\r\n result[2] = Math.abs(matrix[2]);\r\n result[3] = Math.abs(matrix[3]);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided matrices componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Matrix2} [left] The first matrix.\r\n * @param {Matrix2} [right] The second matrix.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nMatrix2.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left[0] === right[0] &&\r\n left[1] === right[1] &&\r\n left[2] === right[2] &&\r\n left[3] === right[3])\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nMatrix2.equalsArray = function (matrix, array, offset) {\r\n return (\r\n matrix[0] === array[offset] &&\r\n matrix[1] === array[offset + 1] &&\r\n matrix[2] === array[offset + 2] &&\r\n matrix[3] === array[offset + 3]\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided matrices componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Matrix2} [left] The first matrix.\r\n * @param {Matrix2} [right] The second matrix.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if left and right are within the provided epsilon, false otherwise.\r\n */\r\nMatrix2.equalsEpsilon = function (left, right, epsilon) {\r\n epsilon = defaultValue(epsilon, 0);\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Math.abs(left[0] - right[0]) <= epsilon &&\r\n Math.abs(left[1] - right[1]) <= epsilon &&\r\n Math.abs(left[2] - right[2]) <= epsilon &&\r\n Math.abs(left[3] - right[3]) <= epsilon)\r\n );\r\n};\r\n\r\n/**\r\n * An immutable Matrix2 instance initialized to the identity matrix.\r\n *\r\n * @type {Matrix2}\r\n * @constant\r\n */\r\nMatrix2.IDENTITY = Object.freeze(new Matrix2(1.0, 0.0, 0.0, 1.0));\r\n\r\n/**\r\n * An immutable Matrix2 instance initialized to the zero matrix.\r\n *\r\n * @type {Matrix2}\r\n * @constant\r\n */\r\nMatrix2.ZERO = Object.freeze(new Matrix2(0.0, 0.0, 0.0, 0.0));\r\n\r\n/**\r\n * The index into Matrix2 for column 0, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n *\r\n * @example\r\n * var matrix = new Cesium.Matrix2();\r\n * matrix[Cesium.Matrix2.COLUMN0ROW0] = 5.0; // set column 0, row 0 to 5.0\r\n */\r\nMatrix2.COLUMN0ROW0 = 0;\r\n\r\n/**\r\n * The index into Matrix2 for column 0, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n *\r\n * @example\r\n * var matrix = new Cesium.Matrix2();\r\n * matrix[Cesium.Matrix2.COLUMN0ROW1] = 5.0; // set column 0, row 1 to 5.0\r\n */\r\nMatrix2.COLUMN0ROW1 = 1;\r\n\r\n/**\r\n * The index into Matrix2 for column 1, row 0.\r\n *\r\n * @type {Number}\r\n * @constant\r\n *\r\n * @example\r\n * var matrix = new Cesium.Matrix2();\r\n * matrix[Cesium.Matrix2.COLUMN1ROW0] = 5.0; // set column 1, row 0 to 5.0\r\n */\r\nMatrix2.COLUMN1ROW0 = 2;\r\n\r\n/**\r\n * The index into Matrix2 for column 1, row 1.\r\n *\r\n * @type {Number}\r\n * @constant\r\n *\r\n * @example\r\n * var matrix = new Cesium.Matrix2();\r\n * matrix[Cesium.Matrix2.COLUMN1ROW1] = 5.0; // set column 1, row 1 to 5.0\r\n */\r\nMatrix2.COLUMN1ROW1 = 3;\r\n\r\nObject.defineProperties(Matrix2.prototype, {\r\n /**\r\n * Gets the number of items in the collection.\r\n * @memberof Matrix2.prototype\r\n *\r\n * @type {Number}\r\n */\r\n length: {\r\n get: function () {\r\n return Matrix2.packedLength;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Duplicates the provided Matrix2 instance.\r\n *\r\n * @param {Matrix2} [result] The object onto which to store the result.\r\n * @returns {Matrix2} The modified result parameter or a new Matrix2 instance if one was not provided.\r\n */\r\nMatrix2.prototype.clone = function (result) {\r\n return Matrix2.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this matrix to the provided matrix componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Matrix2} [right] The right hand side matrix.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nMatrix2.prototype.equals = function (right) {\r\n return Matrix2.equals(this, right);\r\n};\r\n\r\n/**\r\n * Compares this matrix to the provided matrix componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {Matrix2} [right] The right hand side matrix.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if they are within the provided epsilon, false otherwise.\r\n */\r\nMatrix2.prototype.equalsEpsilon = function (right, epsilon) {\r\n return Matrix2.equalsEpsilon(this, right, epsilon);\r\n};\r\n\r\n/**\r\n * Creates a string representing this Matrix with each row being\r\n * on a separate line and in the format '(column0, column1)'.\r\n *\r\n * @returns {String} A string representing the provided Matrix with each row being on a separate line and in the format '(column0, column1)'.\r\n */\r\nMatrix2.prototype.toString = function () {\r\n return (\r\n \"(\" +\r\n this[0] +\r\n \", \" +\r\n this[2] +\r\n \")\\n\" +\r\n \"(\" +\r\n this[1] +\r\n \", \" +\r\n this[3] +\r\n \")\"\r\n );\r\n};\r\nexport default Matrix2;\r\n","import WebGLConstants from \"./WebGLConstants.js\";\r\n\r\n/**\r\n * The type of a geometric primitive, i.e., points, lines, and triangles.\r\n *\r\n * @enum {Number}\r\n */\r\nvar PrimitiveType = {\r\n /**\r\n * Points primitive where each vertex (or index) is a separate point.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n POINTS: WebGLConstants.POINTS,\r\n\r\n /**\r\n * Lines primitive where each two vertices (or indices) is a line segment. Line segments are not necessarily connected.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LINES: WebGLConstants.LINES,\r\n\r\n /**\r\n * Line loop primitive where each vertex (or index) after the first connects a line to\r\n * the previous vertex, and the last vertex implicitly connects to the first.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LINE_LOOP: WebGLConstants.LINE_LOOP,\r\n\r\n /**\r\n * Line strip primitive where each vertex (or index) after the first connects a line to the previous vertex.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LINE_STRIP: WebGLConstants.LINE_STRIP,\r\n\r\n /**\r\n * Triangles primitive where each three vertices (or indices) is a triangle. Triangles do not necessarily share edges.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n TRIANGLES: WebGLConstants.TRIANGLES,\r\n\r\n /**\r\n * Triangle strip primitive where each vertex (or index) after the first two connect to\r\n * the previous two vertices forming a triangle. For example, this can be used to model a wall.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n TRIANGLE_STRIP: WebGLConstants.TRIANGLE_STRIP,\r\n\r\n /**\r\n * Triangle fan primitive where each vertex (or index) after the first two connect to\r\n * the previous vertex and the first vertex forming a triangle. For example, this can be used\r\n * to model a cone or circle.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n TRIANGLE_FAN: WebGLConstants.TRIANGLE_FAN,\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitiveType.validate = function (primitiveType) {\r\n return (\r\n primitiveType === PrimitiveType.POINTS ||\r\n primitiveType === PrimitiveType.LINES ||\r\n primitiveType === PrimitiveType.LINE_LOOP ||\r\n primitiveType === PrimitiveType.LINE_STRIP ||\r\n primitiveType === PrimitiveType.TRIANGLES ||\r\n primitiveType === PrimitiveType.TRIANGLE_STRIP ||\r\n primitiveType === PrimitiveType.TRIANGLE_FAN\r\n );\r\n};\r\n\r\nexport default Object.freeze(PrimitiveType);\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport GeometryType from \"./GeometryType.js\";\r\nimport Matrix2 from \"./Matrix2.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Transforms from \"./Transforms.js\";\r\n\r\n/**\r\n * A geometry representation with attributes forming vertices and optional index data\r\n * defining primitives. Geometries and an {@link Appearance}, which describes the shading,\r\n * can be assigned to a {@link Primitive} for visualization. A Primitive can\r\n * be created from many heterogeneous - in many cases - geometries for performance.\r\n *

\r\n * Geometries can be transformed and optimized using functions in {@link GeometryPipeline}.\r\n *

\r\n *\r\n * @alias Geometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {GeometryAttributes} options.attributes Attributes, which make up the geometry's vertices.\r\n * @param {PrimitiveType} [options.primitiveType=PrimitiveType.TRIANGLES] The type of primitives in the geometry.\r\n * @param {Uint16Array|Uint32Array} [options.indices] Optional index data that determines the primitives in the geometry.\r\n * @param {BoundingSphere} [options.boundingSphere] An optional bounding sphere that fully enclosed the geometry.\r\n *\r\n * @see PolygonGeometry\r\n * @see RectangleGeometry\r\n * @see EllipseGeometry\r\n * @see CircleGeometry\r\n * @see WallGeometry\r\n * @see SimplePolylineGeometry\r\n * @see BoxGeometry\r\n * @see EllipsoidGeometry\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Geometry%20and%20Appearances.html|Geometry and Appearances Demo}\r\n *\r\n * @example\r\n * // Create geometry with a position attribute and indexed lines.\r\n * var positions = new Float64Array([\r\n * 0.0, 0.0, 0.0,\r\n * 7500000.0, 0.0, 0.0,\r\n * 0.0, 7500000.0, 0.0\r\n * ]);\r\n *\r\n * var geometry = new Cesium.Geometry({\r\n * attributes : {\r\n * position : new Cesium.GeometryAttribute({\r\n * componentDatatype : Cesium.ComponentDatatype.DOUBLE,\r\n * componentsPerAttribute : 3,\r\n * values : positions\r\n * })\r\n * },\r\n * indices : new Uint16Array([0, 1, 1, 2, 2, 0]),\r\n * primitiveType : Cesium.PrimitiveType.LINES,\r\n * boundingSphere : Cesium.BoundingSphere.fromVertices(positions)\r\n * });\r\n */\r\nfunction Geometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options.attributes\", options.attributes);\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * Attributes, which make up the geometry's vertices. Each property in this object corresponds to a\r\n * {@link GeometryAttribute} containing the attribute's data.\r\n *

\r\n * Attributes are always stored non-interleaved in a Geometry.\r\n *

\r\n *

\r\n * There are reserved attribute names with well-known semantics. The following attributes\r\n * are created by a Geometry (depending on the provided {@link VertexFormat}.\r\n *

    \r\n *
  • position - 3D vertex position. 64-bit floating-point (for precision). 3 components per attribute. See {@link VertexFormat#position}.
  • \r\n *
  • normal - Normal (normalized), commonly used for lighting. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat#normal}.
  • \r\n *
  • st - 2D texture coordinate. 32-bit floating-point. 2 components per attribute. See {@link VertexFormat#st}.
  • \r\n *
  • bitangent - Bitangent (normalized), used for tangent-space effects like bump mapping. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat#bitangent}.
  • \r\n *
  • tangent - Tangent (normalized), used for tangent-space effects like bump mapping. 32-bit floating-point. 3 components per attribute. See {@link VertexFormat#tangent}.
  • \r\n *
\r\n *

\r\n *

\r\n * The following attribute names are generally not created by a Geometry, but are added\r\n * to a Geometry by a {@link Primitive} or {@link GeometryPipeline} functions to prepare\r\n * the geometry for rendering.\r\n *

    \r\n *
  • position3DHigh - High 32 bits for encoded 64-bit position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
  • \r\n *
  • position3DLow - Low 32 bits for encoded 64-bit position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
  • \r\n *
  • position3DHigh - High 32 bits for encoded 64-bit 2D (Columbus view) position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
  • \r\n *
  • position2DLow - Low 32 bits for encoded 64-bit 2D (Columbus view) position computed with {@link GeometryPipeline.encodeAttribute}. 32-bit floating-point. 4 components per attribute.
  • \r\n *
  • color - RGBA color (normalized) usually from {@link GeometryInstance#color}. 32-bit floating-point. 4 components per attribute.
  • \r\n *
  • pickColor - RGBA color used for picking. 32-bit floating-point. 4 components per attribute.
  • \r\n *
\r\n *

\r\n *\r\n * @type GeometryAttributes\r\n *\r\n * @default undefined\r\n *\r\n *\r\n * @example\r\n * geometry.attributes.position = new Cesium.GeometryAttribute({\r\n * componentDatatype : Cesium.ComponentDatatype.FLOAT,\r\n * componentsPerAttribute : 3,\r\n * values : new Float32Array(0)\r\n * });\r\n *\r\n * @see GeometryAttribute\r\n * @see VertexFormat\r\n */\r\n this.attributes = options.attributes;\r\n\r\n /**\r\n * Optional index data that - along with {@link Geometry#primitiveType} -\r\n * determines the primitives in the geometry.\r\n *\r\n * @type Array\r\n *\r\n * @default undefined\r\n */\r\n this.indices = options.indices;\r\n\r\n /**\r\n * The type of primitives in the geometry. This is most often {@link PrimitiveType.TRIANGLES},\r\n * but can varying based on the specific geometry.\r\n *\r\n * @type PrimitiveType\r\n *\r\n * @default undefined\r\n */\r\n this.primitiveType = defaultValue(\r\n options.primitiveType,\r\n PrimitiveType.TRIANGLES\r\n );\r\n\r\n /**\r\n * An optional bounding sphere that fully encloses the geometry. This is\r\n * commonly used for culling.\r\n *\r\n * @type BoundingSphere\r\n *\r\n * @default undefined\r\n */\r\n this.boundingSphere = options.boundingSphere;\r\n\r\n /**\r\n * @private\r\n */\r\n this.geometryType = defaultValue(options.geometryType, GeometryType.NONE);\r\n\r\n /**\r\n * @private\r\n */\r\n this.boundingSphereCV = options.boundingSphereCV;\r\n\r\n /**\r\n * Used for computing the bounding sphere for geometry using the applyOffset vertex attribute\r\n * @private\r\n */\r\n this.offsetAttribute = options.offsetAttribute;\r\n}\r\n\r\n/**\r\n * Computes the number of vertices in a geometry. The runtime is linear with\r\n * respect to the number of attributes in a vertex, not the number of vertices.\r\n *\r\n * @param {Geometry} geometry The geometry.\r\n * @returns {Number} The number of vertices in the geometry.\r\n *\r\n * @example\r\n * var numVertices = Cesium.Geometry.computeNumberOfVertices(geometry);\r\n */\r\nGeometry.computeNumberOfVertices = function (geometry) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"geometry\", geometry);\r\n //>>includeEnd('debug');\r\n\r\n var numberOfVertices = -1;\r\n for (var property in geometry.attributes) {\r\n if (\r\n geometry.attributes.hasOwnProperty(property) &&\r\n defined(geometry.attributes[property]) &&\r\n defined(geometry.attributes[property].values)\r\n ) {\r\n var attribute = geometry.attributes[property];\r\n var num = attribute.values.length / attribute.componentsPerAttribute;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numberOfVertices !== num && numberOfVertices !== -1) {\r\n throw new DeveloperError(\r\n \"All attribute lists must have the same number of attributes.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n numberOfVertices = num;\r\n }\r\n }\r\n\r\n return numberOfVertices;\r\n};\r\n\r\nvar rectangleCenterScratch = new Cartographic();\r\nvar enuCenterScratch = new Cartesian3();\r\nvar fixedFrameToEnuScratch = new Matrix4();\r\nvar boundingRectanglePointsCartographicScratch = [\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n];\r\nvar boundingRectanglePointsEnuScratch = [\r\n new Cartesian2(),\r\n new Cartesian2(),\r\n new Cartesian2(),\r\n];\r\nvar points2DScratch = [new Cartesian2(), new Cartesian2(), new Cartesian2()];\r\nvar pointEnuScratch = new Cartesian3();\r\nvar enuRotationScratch = new Quaternion();\r\nvar enuRotationMatrixScratch = new Matrix4();\r\nvar rotation2DScratch = new Matrix2();\r\n\r\n/**\r\n * For remapping texture coordinates when rendering GroundPrimitives with materials.\r\n * GroundPrimitive texture coordinates are computed to align with the cartographic coordinate system on the globe.\r\n * However, EllipseGeometry, RectangleGeometry, and PolygonGeometry all bake rotations to per-vertex texture coordinates\r\n * using different strategies.\r\n *\r\n * This method is used by EllipseGeometry and PolygonGeometry to approximate the same visual effect.\r\n * We encapsulate rotation and scale by computing a \"transformed\" texture coordinate system and computing\r\n * a set of reference points from which \"cartographic\" texture coordinates can be remapped to the \"transformed\"\r\n * system using distances to lines in 2D.\r\n *\r\n * This approximation becomes less accurate as the covered area increases, especially for GroundPrimitives near the poles,\r\n * but is generally reasonable for polygons and ellipses around the size of USA states.\r\n *\r\n * RectangleGeometry has its own version of this method that computes remapping coordinates using cartographic space\r\n * as an intermediary instead of local ENU, which is more accurate for large-area rectangles.\r\n *\r\n * @param {Cartesian3[]} positions Array of positions outlining the geometry\r\n * @param {Number} stRotation Texture coordinate rotation.\r\n * @param {Ellipsoid} ellipsoid Ellipsoid for projecting and generating local vectors.\r\n * @param {Rectangle} boundingRectangle Bounding rectangle around the positions.\r\n * @returns {Number[]} An array of 6 numbers specifying [minimum point, u extent, v extent] as points in the \"cartographic\" system.\r\n * @private\r\n */\r\nGeometry._textureCoordinateRotationPoints = function (\r\n positions,\r\n stRotation,\r\n ellipsoid,\r\n boundingRectangle\r\n) {\r\n var i;\r\n\r\n // Create a local east-north-up coordinate system centered on the polygon's bounding rectangle.\r\n // Project the southwest, northwest, and southeast corners of the bounding rectangle into the plane of ENU as 2D points.\r\n // These are the equivalents of (0,0), (0,1), and (1,0) in the texture coordiante system computed in ShadowVolumeAppearanceFS,\r\n // aka \"ENU texture space.\"\r\n var rectangleCenter = Rectangle.center(\r\n boundingRectangle,\r\n rectangleCenterScratch\r\n );\r\n var enuCenter = Cartographic.toCartesian(\r\n rectangleCenter,\r\n ellipsoid,\r\n enuCenterScratch\r\n );\r\n var enuToFixedFrame = Transforms.eastNorthUpToFixedFrame(\r\n enuCenter,\r\n ellipsoid,\r\n fixedFrameToEnuScratch\r\n );\r\n var fixedFrameToEnu = Matrix4.inverse(\r\n enuToFixedFrame,\r\n fixedFrameToEnuScratch\r\n );\r\n\r\n var boundingPointsEnu = boundingRectanglePointsEnuScratch;\r\n var boundingPointsCarto = boundingRectanglePointsCartographicScratch;\r\n\r\n boundingPointsCarto[0].longitude = boundingRectangle.west;\r\n boundingPointsCarto[0].latitude = boundingRectangle.south;\r\n\r\n boundingPointsCarto[1].longitude = boundingRectangle.west;\r\n boundingPointsCarto[1].latitude = boundingRectangle.north;\r\n\r\n boundingPointsCarto[2].longitude = boundingRectangle.east;\r\n boundingPointsCarto[2].latitude = boundingRectangle.south;\r\n\r\n var posEnu = pointEnuScratch;\r\n\r\n for (i = 0; i < 3; i++) {\r\n Cartographic.toCartesian(boundingPointsCarto[i], ellipsoid, posEnu);\r\n posEnu = Matrix4.multiplyByPointAsVector(fixedFrameToEnu, posEnu, posEnu);\r\n boundingPointsEnu[i].x = posEnu.x;\r\n boundingPointsEnu[i].y = posEnu.y;\r\n }\r\n\r\n // Rotate each point in the polygon around the up vector in the ENU by -stRotation and project into ENU as 2D.\r\n // Compute the bounding box of these rotated points in the 2D ENU plane.\r\n // Rotate the corners back by stRotation, then compute their equivalents in the ENU texture space using the corners computed earlier.\r\n var rotation = Quaternion.fromAxisAngle(\r\n Cartesian3.UNIT_Z,\r\n -stRotation,\r\n enuRotationScratch\r\n );\r\n var textureMatrix = Matrix3.fromQuaternion(\r\n rotation,\r\n enuRotationMatrixScratch\r\n );\r\n\r\n var positionsLength = positions.length;\r\n var enuMinX = Number.POSITIVE_INFINITY;\r\n var enuMinY = Number.POSITIVE_INFINITY;\r\n var enuMaxX = Number.NEGATIVE_INFINITY;\r\n var enuMaxY = Number.NEGATIVE_INFINITY;\r\n for (i = 0; i < positionsLength; i++) {\r\n posEnu = Matrix4.multiplyByPointAsVector(\r\n fixedFrameToEnu,\r\n positions[i],\r\n posEnu\r\n );\r\n posEnu = Matrix3.multiplyByVector(textureMatrix, posEnu, posEnu);\r\n\r\n enuMinX = Math.min(enuMinX, posEnu.x);\r\n enuMinY = Math.min(enuMinY, posEnu.y);\r\n enuMaxX = Math.max(enuMaxX, posEnu.x);\r\n enuMaxY = Math.max(enuMaxY, posEnu.y);\r\n }\r\n\r\n var toDesiredInComputed = Matrix2.fromRotation(stRotation, rotation2DScratch);\r\n\r\n var points2D = points2DScratch;\r\n points2D[0].x = enuMinX;\r\n points2D[0].y = enuMinY;\r\n\r\n points2D[1].x = enuMinX;\r\n points2D[1].y = enuMaxY;\r\n\r\n points2D[2].x = enuMaxX;\r\n points2D[2].y = enuMinY;\r\n\r\n var boundingEnuMin = boundingPointsEnu[0];\r\n var boundingPointsWidth = boundingPointsEnu[2].x - boundingEnuMin.x;\r\n var boundingPointsHeight = boundingPointsEnu[1].y - boundingEnuMin.y;\r\n\r\n for (i = 0; i < 3; i++) {\r\n var point2D = points2D[i];\r\n // rotate back\r\n Matrix2.multiplyByVector(toDesiredInComputed, point2D, point2D);\r\n\r\n // Convert point into east-north texture coordinate space\r\n point2D.x = (point2D.x - boundingEnuMin.x) / boundingPointsWidth;\r\n point2D.y = (point2D.y - boundingEnuMin.y) / boundingPointsHeight;\r\n }\r\n\r\n var minXYCorner = points2D[0];\r\n var maxYCorner = points2D[1];\r\n var maxXCorner = points2D[2];\r\n var result = new Array(6);\r\n Cartesian2.pack(minXYCorner, result);\r\n Cartesian2.pack(maxYCorner, result, 2);\r\n Cartesian2.pack(maxXCorner, result, 4);\r\n\r\n return result;\r\n};\r\nexport default Geometry;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Values and type information for geometry attributes. A {@link Geometry}\r\n * generally contains one or more attributes. All attributes together form\r\n * the geometry's vertices.\r\n *\r\n * @alias GeometryAttribute\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {ComponentDatatype} [options.componentDatatype] The datatype of each component in the attribute, e.g., individual elements in values.\r\n * @param {Number} [options.componentsPerAttribute] A number between 1 and 4 that defines the number of components in an attributes.\r\n * @param {Boolean} [options.normalize=false] When true and componentDatatype is an integer format, indicate that the components should be mapped to the range [0, 1] (unsigned) or [-1, 1] (signed) when they are accessed as floating-point for rendering.\r\n * @param {number[]|Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array} [options.values] The values for the attributes stored in a typed array.\r\n *\r\n * @exception {DeveloperError} options.componentsPerAttribute must be between 1 and 4.\r\n *\r\n *\r\n * @example\r\n * var geometry = new Cesium.Geometry({\r\n * attributes : {\r\n * position : new Cesium.GeometryAttribute({\r\n * componentDatatype : Cesium.ComponentDatatype.FLOAT,\r\n * componentsPerAttribute : 3,\r\n * values : new Float32Array([\r\n * 0.0, 0.0, 0.0,\r\n * 7500000.0, 0.0, 0.0,\r\n * 0.0, 7500000.0, 0.0\r\n * ])\r\n * })\r\n * },\r\n * primitiveType : Cesium.PrimitiveType.LINE_LOOP\r\n * });\r\n *\r\n * @see Geometry\r\n */\r\nfunction GeometryAttribute(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options.componentDatatype)) {\r\n throw new DeveloperError(\"options.componentDatatype is required.\");\r\n }\r\n if (!defined(options.componentsPerAttribute)) {\r\n throw new DeveloperError(\"options.componentsPerAttribute is required.\");\r\n }\r\n if (\r\n options.componentsPerAttribute < 1 ||\r\n options.componentsPerAttribute > 4\r\n ) {\r\n throw new DeveloperError(\r\n \"options.componentsPerAttribute must be between 1 and 4.\"\r\n );\r\n }\r\n if (!defined(options.values)) {\r\n throw new DeveloperError(\"options.values is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * The datatype of each component in the attribute, e.g., individual elements in\r\n * {@link GeometryAttribute#values}.\r\n *\r\n * @type ComponentDatatype\r\n *\r\n * @default undefined\r\n */\r\n this.componentDatatype = options.componentDatatype;\r\n\r\n /**\r\n * A number between 1 and 4 that defines the number of components in an attributes.\r\n * For example, a position attribute with x, y, and z components would have 3 as\r\n * shown in the code example.\r\n *\r\n * @type Number\r\n *\r\n * @default undefined\r\n *\r\n * @example\r\n * attribute.componentDatatype = Cesium.ComponentDatatype.FLOAT;\r\n * attribute.componentsPerAttribute = 3;\r\n * attribute.values = new Float32Array([\r\n * 0.0, 0.0, 0.0,\r\n * 7500000.0, 0.0, 0.0,\r\n * 0.0, 7500000.0, 0.0\r\n * ]);\r\n */\r\n this.componentsPerAttribute = options.componentsPerAttribute;\r\n\r\n /**\r\n * When true and componentDatatype is an integer format,\r\n * indicate that the components should be mapped to the range [0, 1] (unsigned)\r\n * or [-1, 1] (signed) when they are accessed as floating-point for rendering.\r\n *

\r\n * This is commonly used when storing colors using {@link ComponentDatatype.UNSIGNED_BYTE}.\r\n *

\r\n *\r\n * @type Boolean\r\n *\r\n * @default false\r\n *\r\n * @example\r\n * attribute.componentDatatype = Cesium.ComponentDatatype.UNSIGNED_BYTE;\r\n * attribute.componentsPerAttribute = 4;\r\n * attribute.normalize = true;\r\n * attribute.values = new Uint8Array([\r\n * Cesium.Color.floatToByte(color.red),\r\n * Cesium.Color.floatToByte(color.green),\r\n * Cesium.Color.floatToByte(color.blue),\r\n * Cesium.Color.floatToByte(color.alpha)\r\n * ]);\r\n */\r\n this.normalize = defaultValue(options.normalize, false);\r\n\r\n /**\r\n * The values for the attributes stored in a typed array. In the code example,\r\n * every three elements in values defines one attributes since\r\n * componentsPerAttribute is 3.\r\n *\r\n * @type {number[]|Int8Array|Uint8Array|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array}\r\n *\r\n * @default undefined\r\n *\r\n * @example\r\n * attribute.componentDatatype = Cesium.ComponentDatatype.FLOAT;\r\n * attribute.componentsPerAttribute = 3;\r\n * attribute.values = new Float32Array([\r\n * 0.0, 0.0, 0.0,\r\n * 7500000.0, 0.0, 0.0,\r\n * 0.0, 7500000.0, 0.0\r\n * ]);\r\n */\r\n this.values = options.values;\r\n}\r\nexport default GeometryAttribute;\r\n","import defaultValue from \"./defaultValue.js\";\r\n\r\n/**\r\n * Attributes, which make up a geometry's vertices. Each property in this object corresponds to a\r\n * {@link GeometryAttribute} containing the attribute's data.\r\n *

\r\n * Attributes are always stored non-interleaved in a Geometry.\r\n *

\r\n *\r\n * @alias GeometryAttributes\r\n * @constructor\r\n */\r\nfunction GeometryAttributes(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * The 3D position attribute.\r\n *

\r\n * 64-bit floating-point (for precision). 3 components per attribute.\r\n *

\r\n *\r\n * @type GeometryAttribute\r\n *\r\n * @default undefined\r\n */\r\n this.position = options.position;\r\n\r\n /**\r\n * The normal attribute (normalized), which is commonly used for lighting.\r\n *

\r\n * 32-bit floating-point. 3 components per attribute.\r\n *

\r\n *\r\n * @type GeometryAttribute\r\n *\r\n * @default undefined\r\n */\r\n this.normal = options.normal;\r\n\r\n /**\r\n * The 2D texture coordinate attribute.\r\n *

\r\n * 32-bit floating-point. 2 components per attribute\r\n *

\r\n *\r\n * @type GeometryAttribute\r\n *\r\n * @default undefined\r\n */\r\n this.st = options.st;\r\n\r\n /**\r\n * The bitangent attribute (normalized), which is used for tangent-space effects like bump mapping.\r\n *

\r\n * 32-bit floating-point. 3 components per attribute.\r\n *

\r\n *\r\n * @type GeometryAttribute\r\n *\r\n * @default undefined\r\n */\r\n this.bitangent = options.bitangent;\r\n\r\n /**\r\n * The tangent attribute (normalized), which is used for tangent-space effects like bump mapping.\r\n *

\r\n * 32-bit floating-point. 3 components per attribute.\r\n *

\r\n *\r\n * @type GeometryAttribute\r\n *\r\n * @default undefined\r\n */\r\n this.tangent = options.tangent;\r\n\r\n /**\r\n * The color attribute.\r\n *

\r\n * 8-bit unsigned integer. 4 components per attribute.\r\n *

\r\n *\r\n * @type GeometryAttribute\r\n *\r\n * @default undefined\r\n */\r\n this.color = options.color;\r\n}\r\nexport default GeometryAttributes;\r\n","/**\r\n * Represents which vertices should have a value of `true` for the `applyOffset` attribute\r\n * @private\r\n */\r\nvar GeometryOffsetAttribute = {\r\n NONE: 0,\r\n TOP: 1,\r\n ALL: 2,\r\n};\r\nexport default Object.freeze(GeometryOffsetAttribute);\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * A vertex format defines what attributes make up a vertex. A VertexFormat can be provided\r\n * to a {@link Geometry} to request that certain properties be computed, e.g., just position,\r\n * position and normal, etc.\r\n *\r\n * @param {Object} [options] An object with boolean properties corresponding to VertexFormat properties as shown in the code example.\r\n *\r\n * @alias VertexFormat\r\n * @constructor\r\n *\r\n * @example\r\n * // Create a vertex format with position and 2D texture coordinate attributes.\r\n * var format = new Cesium.VertexFormat({\r\n * position : true,\r\n * st : true\r\n * });\r\n *\r\n * @see Geometry#attributes\r\n * @see Packable\r\n */\r\nfunction VertexFormat(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * When true, the vertex has a 3D position attribute.\r\n *

\r\n * 64-bit floating-point (for precision). 3 components per attribute.\r\n *

\r\n *\r\n * @type Boolean\r\n *\r\n * @default false\r\n */\r\n this.position = defaultValue(options.position, false);\r\n\r\n /**\r\n * When true, the vertex has a normal attribute (normalized), which is commonly used for lighting.\r\n *

\r\n * 32-bit floating-point. 3 components per attribute.\r\n *

\r\n *\r\n * @type Boolean\r\n *\r\n * @default false\r\n */\r\n this.normal = defaultValue(options.normal, false);\r\n\r\n /**\r\n * When true, the vertex has a 2D texture coordinate attribute.\r\n *

\r\n * 32-bit floating-point. 2 components per attribute\r\n *

\r\n *\r\n * @type Boolean\r\n *\r\n * @default false\r\n */\r\n this.st = defaultValue(options.st, false);\r\n\r\n /**\r\n * When true, the vertex has a bitangent attribute (normalized), which is used for tangent-space effects like bump mapping.\r\n *

\r\n * 32-bit floating-point. 3 components per attribute.\r\n *

\r\n *\r\n * @type Boolean\r\n *\r\n * @default false\r\n */\r\n this.bitangent = defaultValue(options.bitangent, false);\r\n\r\n /**\r\n * When true, the vertex has a tangent attribute (normalized), which is used for tangent-space effects like bump mapping.\r\n *

\r\n * 32-bit floating-point. 3 components per attribute.\r\n *

\r\n *\r\n * @type Boolean\r\n *\r\n * @default false\r\n */\r\n this.tangent = defaultValue(options.tangent, false);\r\n\r\n /**\r\n * When true, the vertex has an RGB color attribute.\r\n *

\r\n * 8-bit unsigned byte. 3 components per attribute.\r\n *

\r\n *\r\n * @type Boolean\r\n *\r\n * @default false\r\n */\r\n this.color = defaultValue(options.color, false);\r\n}\r\n\r\n/**\r\n * An immutable vertex format with only a position attribute.\r\n *\r\n * @type {VertexFormat}\r\n * @constant\r\n *\r\n * @see VertexFormat#position\r\n */\r\nVertexFormat.POSITION_ONLY = Object.freeze(\r\n new VertexFormat({\r\n position: true,\r\n })\r\n);\r\n\r\n/**\r\n * An immutable vertex format with position and normal attributes.\r\n * This is compatible with per-instance color appearances like {@link PerInstanceColorAppearance}.\r\n *\r\n * @type {VertexFormat}\r\n * @constant\r\n *\r\n * @see VertexFormat#position\r\n * @see VertexFormat#normal\r\n */\r\nVertexFormat.POSITION_AND_NORMAL = Object.freeze(\r\n new VertexFormat({\r\n position: true,\r\n normal: true,\r\n })\r\n);\r\n\r\n/**\r\n * An immutable vertex format with position, normal, and st attributes.\r\n * This is compatible with {@link MaterialAppearance} when {@link MaterialAppearance#materialSupport}\r\n * is TEXTURED/code>.\r\n *\r\n * @type {VertexFormat}\r\n * @constant\r\n *\r\n * @see VertexFormat#position\r\n * @see VertexFormat#normal\r\n * @see VertexFormat#st\r\n */\r\nVertexFormat.POSITION_NORMAL_AND_ST = Object.freeze(\r\n new VertexFormat({\r\n position: true,\r\n normal: true,\r\n st: true,\r\n })\r\n);\r\n\r\n/**\r\n * An immutable vertex format with position and st attributes.\r\n * This is compatible with {@link EllipsoidSurfaceAppearance}.\r\n *\r\n * @type {VertexFormat}\r\n * @constant\r\n *\r\n * @see VertexFormat#position\r\n * @see VertexFormat#st\r\n */\r\nVertexFormat.POSITION_AND_ST = Object.freeze(\r\n new VertexFormat({\r\n position: true,\r\n st: true,\r\n })\r\n);\r\n\r\n/**\r\n * An immutable vertex format with position and color attributes.\r\n *\r\n * @type {VertexFormat}\r\n * @constant\r\n *\r\n * @see VertexFormat#position\r\n * @see VertexFormat#color\r\n */\r\nVertexFormat.POSITION_AND_COLOR = Object.freeze(\r\n new VertexFormat({\r\n position: true,\r\n color: true,\r\n })\r\n);\r\n\r\n/**\r\n * An immutable vertex format with well-known attributes: position, normal, st, tangent, and bitangent.\r\n *\r\n * @type {VertexFormat}\r\n * @constant\r\n *\r\n * @see VertexFormat#position\r\n * @see VertexFormat#normal\r\n * @see VertexFormat#st\r\n * @see VertexFormat#tangent\r\n * @see VertexFormat#bitangent\r\n */\r\nVertexFormat.ALL = Object.freeze(\r\n new VertexFormat({\r\n position: true,\r\n normal: true,\r\n st: true,\r\n tangent: true,\r\n bitangent: true,\r\n })\r\n);\r\n\r\n/**\r\n * An immutable vertex format with position, normal, and st attributes.\r\n * This is compatible with most appearances and materials; however\r\n * normal and st attributes are not always required. When this is\r\n * known in advance, another VertexFormat should be used.\r\n *\r\n * @type {VertexFormat}\r\n * @constant\r\n *\r\n * @see VertexFormat#position\r\n * @see VertexFormat#normal\r\n */\r\nVertexFormat.DEFAULT = VertexFormat.POSITION_NORMAL_AND_ST;\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nVertexFormat.packedLength = 6;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {VertexFormat} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nVertexFormat.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.position ? 1.0 : 0.0;\r\n array[startingIndex++] = value.normal ? 1.0 : 0.0;\r\n array[startingIndex++] = value.st ? 1.0 : 0.0;\r\n array[startingIndex++] = value.tangent ? 1.0 : 0.0;\r\n array[startingIndex++] = value.bitangent ? 1.0 : 0.0;\r\n array[startingIndex] = value.color ? 1.0 : 0.0;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {VertexFormat} [result] The object into which to store the result.\r\n * @returns {VertexFormat} The modified result parameter or a new VertexFormat instance if one was not provided.\r\n */\r\nVertexFormat.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new VertexFormat();\r\n }\r\n\r\n result.position = array[startingIndex++] === 1.0;\r\n result.normal = array[startingIndex++] === 1.0;\r\n result.st = array[startingIndex++] === 1.0;\r\n result.tangent = array[startingIndex++] === 1.0;\r\n result.bitangent = array[startingIndex++] === 1.0;\r\n result.color = array[startingIndex] === 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates a VertexFormat instance.\r\n *\r\n * @param {VertexFormat} vertexFormat The vertex format to duplicate.\r\n * @param {VertexFormat} [result] The object onto which to store the result.\r\n * @returns {VertexFormat} The modified result parameter or a new VertexFormat instance if one was not provided. (Returns undefined if vertexFormat is undefined)\r\n */\r\nVertexFormat.clone = function (vertexFormat, result) {\r\n if (!defined(vertexFormat)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n result = new VertexFormat();\r\n }\r\n\r\n result.position = vertexFormat.position;\r\n result.normal = vertexFormat.normal;\r\n result.st = vertexFormat.st;\r\n result.tangent = vertexFormat.tangent;\r\n result.bitangent = vertexFormat.bitangent;\r\n result.color = vertexFormat.color;\r\n return result;\r\n};\r\nexport default VertexFormat;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar diffScratch = new Cartesian3();\r\n\r\n/**\r\n * Describes a cube centered at the origin.\r\n *\r\n * @alias BoxGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.minimum The minimum x, y, and z coordinates of the box.\r\n * @param {Cartesian3} options.maximum The maximum x, y, and z coordinates of the box.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n *\r\n * @see BoxGeometry.fromDimensions\r\n * @see BoxGeometry.createGeometry\r\n * @see Packable\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Box.html|Cesium Sandcastle Box Demo}\r\n *\r\n * @example\r\n * var box = new Cesium.BoxGeometry({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_ONLY,\r\n * maximum : new Cesium.Cartesian3(250000.0, 250000.0, 250000.0),\r\n * minimum : new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0)\r\n * });\r\n * var geometry = Cesium.BoxGeometry.createGeometry(box);\r\n */\r\nfunction BoxGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var min = options.minimum;\r\n var max = options.maximum;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"min\", min);\r\n Check.typeOf.object(\"max\", max);\r\n if (\r\n defined(options.offsetAttribute) &&\r\n options.offsetAttribute === GeometryOffsetAttribute.TOP\r\n ) {\r\n throw new DeveloperError(\r\n \"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n\r\n this._minimum = Cartesian3.clone(min);\r\n this._maximum = Cartesian3.clone(max);\r\n this._vertexFormat = vertexFormat;\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createBoxGeometry\";\r\n}\r\n\r\n/**\r\n * Creates a cube centered at the origin given its dimensions.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.dimensions The width, depth, and height of the box stored in the x, y, and z coordinates of the Cartesian3, respectively.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @returns {BoxGeometry}\r\n *\r\n * @exception {DeveloperError} All dimensions components must be greater than or equal to zero.\r\n *\r\n *\r\n * @example\r\n * var box = Cesium.BoxGeometry.fromDimensions({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_ONLY,\r\n * dimensions : new Cesium.Cartesian3(500000.0, 500000.0, 500000.0)\r\n * });\r\n * var geometry = Cesium.BoxGeometry.createGeometry(box);\r\n *\r\n * @see BoxGeometry.createGeometry\r\n */\r\nBoxGeometry.fromDimensions = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var dimensions = options.dimensions;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"dimensions\", dimensions);\r\n Check.typeOf.number.greaterThanOrEquals(\"dimensions.x\", dimensions.x, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\"dimensions.y\", dimensions.y, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\"dimensions.z\", dimensions.z, 0);\r\n //>>includeEnd('debug');\r\n\r\n var corner = Cartesian3.multiplyByScalar(dimensions, 0.5, new Cartesian3());\r\n\r\n return new BoxGeometry({\r\n minimum: Cartesian3.negate(corner, new Cartesian3()),\r\n maximum: corner,\r\n vertexFormat: options.vertexFormat,\r\n offsetAttribute: options.offsetAttribute,\r\n });\r\n};\r\n\r\n/**\r\n * Creates a cube from the dimensions of an AxisAlignedBoundingBox.\r\n *\r\n * @param {AxisAlignedBoundingBox} boundingBox A description of the AxisAlignedBoundingBox.\r\n * @returns {BoxGeometry}\r\n *\r\n *\r\n *\r\n * @example\r\n * var aabb = Cesium.AxisAlignedBoundingBox.fromPoints(Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ]));\r\n * var box = Cesium.BoxGeometry.fromAxisAlignedBoundingBox(aabb);\r\n *\r\n * @see BoxGeometry.createGeometry\r\n */\r\nBoxGeometry.fromAxisAlignedBoundingBox = function (boundingBox) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"boundingBox\", boundingBox);\r\n //>>includeEnd('debug');\r\n\r\n return new BoxGeometry({\r\n minimum: boundingBox.minimum,\r\n maximum: boundingBox.maximum,\r\n });\r\n};\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nBoxGeometry.packedLength =\r\n 2 * Cartesian3.packedLength + VertexFormat.packedLength + 1;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {BoxGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nBoxGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Cartesian3.pack(value._minimum, array, startingIndex);\r\n Cartesian3.pack(\r\n value._maximum,\r\n array,\r\n startingIndex + Cartesian3.packedLength\r\n );\r\n VertexFormat.pack(\r\n value._vertexFormat,\r\n array,\r\n startingIndex + 2 * Cartesian3.packedLength\r\n );\r\n array[\r\n startingIndex + 2 * Cartesian3.packedLength + VertexFormat.packedLength\r\n ] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchMin = new Cartesian3();\r\nvar scratchMax = new Cartesian3();\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n minimum: scratchMin,\r\n maximum: scratchMax,\r\n vertexFormat: scratchVertexFormat,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {BoxGeometry} [result] The object into which to store the result.\r\n * @returns {BoxGeometry} The modified result parameter or a new BoxGeometry instance if one was not provided.\r\n */\r\nBoxGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var min = Cartesian3.unpack(array, startingIndex, scratchMin);\r\n var max = Cartesian3.unpack(\r\n array,\r\n startingIndex + Cartesian3.packedLength,\r\n scratchMax\r\n );\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex + 2 * Cartesian3.packedLength,\r\n scratchVertexFormat\r\n );\r\n var offsetAttribute =\r\n array[\r\n startingIndex + 2 * Cartesian3.packedLength + VertexFormat.packedLength\r\n ];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n return new BoxGeometry(scratchOptions);\r\n }\r\n\r\n result._minimum = Cartesian3.clone(min, result._minimum);\r\n result._maximum = Cartesian3.clone(max, result._maximum);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a box, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {BoxGeometry} boxGeometry A description of the box.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nBoxGeometry.createGeometry = function (boxGeometry) {\r\n var min = boxGeometry._minimum;\r\n var max = boxGeometry._maximum;\r\n var vertexFormat = boxGeometry._vertexFormat;\r\n\r\n if (Cartesian3.equals(min, max)) {\r\n return;\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n var indices;\r\n var positions;\r\n\r\n if (\r\n vertexFormat.position &&\r\n (vertexFormat.st ||\r\n vertexFormat.normal ||\r\n vertexFormat.tangent ||\r\n vertexFormat.bitangent)\r\n ) {\r\n if (vertexFormat.position) {\r\n // 8 corner points. Duplicated 3 times each for each incident edge/face.\r\n positions = new Float64Array(6 * 4 * 3);\r\n\r\n // +z face\r\n positions[0] = min.x;\r\n positions[1] = min.y;\r\n positions[2] = max.z;\r\n positions[3] = max.x;\r\n positions[4] = min.y;\r\n positions[5] = max.z;\r\n positions[6] = max.x;\r\n positions[7] = max.y;\r\n positions[8] = max.z;\r\n positions[9] = min.x;\r\n positions[10] = max.y;\r\n positions[11] = max.z;\r\n\r\n // -z face\r\n positions[12] = min.x;\r\n positions[13] = min.y;\r\n positions[14] = min.z;\r\n positions[15] = max.x;\r\n positions[16] = min.y;\r\n positions[17] = min.z;\r\n positions[18] = max.x;\r\n positions[19] = max.y;\r\n positions[20] = min.z;\r\n positions[21] = min.x;\r\n positions[22] = max.y;\r\n positions[23] = min.z;\r\n\r\n // +x face\r\n positions[24] = max.x;\r\n positions[25] = min.y;\r\n positions[26] = min.z;\r\n positions[27] = max.x;\r\n positions[28] = max.y;\r\n positions[29] = min.z;\r\n positions[30] = max.x;\r\n positions[31] = max.y;\r\n positions[32] = max.z;\r\n positions[33] = max.x;\r\n positions[34] = min.y;\r\n positions[35] = max.z;\r\n\r\n // -x face\r\n positions[36] = min.x;\r\n positions[37] = min.y;\r\n positions[38] = min.z;\r\n positions[39] = min.x;\r\n positions[40] = max.y;\r\n positions[41] = min.z;\r\n positions[42] = min.x;\r\n positions[43] = max.y;\r\n positions[44] = max.z;\r\n positions[45] = min.x;\r\n positions[46] = min.y;\r\n positions[47] = max.z;\r\n\r\n // +y face\r\n positions[48] = min.x;\r\n positions[49] = max.y;\r\n positions[50] = min.z;\r\n positions[51] = max.x;\r\n positions[52] = max.y;\r\n positions[53] = min.z;\r\n positions[54] = max.x;\r\n positions[55] = max.y;\r\n positions[56] = max.z;\r\n positions[57] = min.x;\r\n positions[58] = max.y;\r\n positions[59] = max.z;\r\n\r\n // -y face\r\n positions[60] = min.x;\r\n positions[61] = min.y;\r\n positions[62] = min.z;\r\n positions[63] = max.x;\r\n positions[64] = min.y;\r\n positions[65] = min.z;\r\n positions[66] = max.x;\r\n positions[67] = min.y;\r\n positions[68] = max.z;\r\n positions[69] = min.x;\r\n positions[70] = min.y;\r\n positions[71] = max.z;\r\n\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n var normals = new Float32Array(6 * 4 * 3);\r\n\r\n // +z face\r\n normals[0] = 0.0;\r\n normals[1] = 0.0;\r\n normals[2] = 1.0;\r\n normals[3] = 0.0;\r\n normals[4] = 0.0;\r\n normals[5] = 1.0;\r\n normals[6] = 0.0;\r\n normals[7] = 0.0;\r\n normals[8] = 1.0;\r\n normals[9] = 0.0;\r\n normals[10] = 0.0;\r\n normals[11] = 1.0;\r\n\r\n // -z face\r\n normals[12] = 0.0;\r\n normals[13] = 0.0;\r\n normals[14] = -1.0;\r\n normals[15] = 0.0;\r\n normals[16] = 0.0;\r\n normals[17] = -1.0;\r\n normals[18] = 0.0;\r\n normals[19] = 0.0;\r\n normals[20] = -1.0;\r\n normals[21] = 0.0;\r\n normals[22] = 0.0;\r\n normals[23] = -1.0;\r\n\r\n // +x face\r\n normals[24] = 1.0;\r\n normals[25] = 0.0;\r\n normals[26] = 0.0;\r\n normals[27] = 1.0;\r\n normals[28] = 0.0;\r\n normals[29] = 0.0;\r\n normals[30] = 1.0;\r\n normals[31] = 0.0;\r\n normals[32] = 0.0;\r\n normals[33] = 1.0;\r\n normals[34] = 0.0;\r\n normals[35] = 0.0;\r\n\r\n // -x face\r\n normals[36] = -1.0;\r\n normals[37] = 0.0;\r\n normals[38] = 0.0;\r\n normals[39] = -1.0;\r\n normals[40] = 0.0;\r\n normals[41] = 0.0;\r\n normals[42] = -1.0;\r\n normals[43] = 0.0;\r\n normals[44] = 0.0;\r\n normals[45] = -1.0;\r\n normals[46] = 0.0;\r\n normals[47] = 0.0;\r\n\r\n // +y face\r\n normals[48] = 0.0;\r\n normals[49] = 1.0;\r\n normals[50] = 0.0;\r\n normals[51] = 0.0;\r\n normals[52] = 1.0;\r\n normals[53] = 0.0;\r\n normals[54] = 0.0;\r\n normals[55] = 1.0;\r\n normals[56] = 0.0;\r\n normals[57] = 0.0;\r\n normals[58] = 1.0;\r\n normals[59] = 0.0;\r\n\r\n // -y face\r\n normals[60] = 0.0;\r\n normals[61] = -1.0;\r\n normals[62] = 0.0;\r\n normals[63] = 0.0;\r\n normals[64] = -1.0;\r\n normals[65] = 0.0;\r\n normals[66] = 0.0;\r\n normals[67] = -1.0;\r\n normals[68] = 0.0;\r\n normals[69] = 0.0;\r\n normals[70] = -1.0;\r\n normals[71] = 0.0;\r\n\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.st) {\r\n var texCoords = new Float32Array(6 * 4 * 2);\r\n\r\n // +z face\r\n texCoords[0] = 0.0;\r\n texCoords[1] = 0.0;\r\n texCoords[2] = 1.0;\r\n texCoords[3] = 0.0;\r\n texCoords[4] = 1.0;\r\n texCoords[5] = 1.0;\r\n texCoords[6] = 0.0;\r\n texCoords[7] = 1.0;\r\n\r\n // -z face\r\n texCoords[8] = 1.0;\r\n texCoords[9] = 0.0;\r\n texCoords[10] = 0.0;\r\n texCoords[11] = 0.0;\r\n texCoords[12] = 0.0;\r\n texCoords[13] = 1.0;\r\n texCoords[14] = 1.0;\r\n texCoords[15] = 1.0;\r\n\r\n //+x face\r\n texCoords[16] = 0.0;\r\n texCoords[17] = 0.0;\r\n texCoords[18] = 1.0;\r\n texCoords[19] = 0.0;\r\n texCoords[20] = 1.0;\r\n texCoords[21] = 1.0;\r\n texCoords[22] = 0.0;\r\n texCoords[23] = 1.0;\r\n\r\n // -x face\r\n texCoords[24] = 1.0;\r\n texCoords[25] = 0.0;\r\n texCoords[26] = 0.0;\r\n texCoords[27] = 0.0;\r\n texCoords[28] = 0.0;\r\n texCoords[29] = 1.0;\r\n texCoords[30] = 1.0;\r\n texCoords[31] = 1.0;\r\n\r\n // +y face\r\n texCoords[32] = 1.0;\r\n texCoords[33] = 0.0;\r\n texCoords[34] = 0.0;\r\n texCoords[35] = 0.0;\r\n texCoords[36] = 0.0;\r\n texCoords[37] = 1.0;\r\n texCoords[38] = 1.0;\r\n texCoords[39] = 1.0;\r\n\r\n // -y face\r\n texCoords[40] = 0.0;\r\n texCoords[41] = 0.0;\r\n texCoords[42] = 1.0;\r\n texCoords[43] = 0.0;\r\n texCoords[44] = 1.0;\r\n texCoords[45] = 1.0;\r\n texCoords[46] = 0.0;\r\n texCoords[47] = 1.0;\r\n\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: texCoords,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n var tangents = new Float32Array(6 * 4 * 3);\r\n\r\n // +z face\r\n tangents[0] = 1.0;\r\n tangents[1] = 0.0;\r\n tangents[2] = 0.0;\r\n tangents[3] = 1.0;\r\n tangents[4] = 0.0;\r\n tangents[5] = 0.0;\r\n tangents[6] = 1.0;\r\n tangents[7] = 0.0;\r\n tangents[8] = 0.0;\r\n tangents[9] = 1.0;\r\n tangents[10] = 0.0;\r\n tangents[11] = 0.0;\r\n\r\n // -z face\r\n tangents[12] = -1.0;\r\n tangents[13] = 0.0;\r\n tangents[14] = 0.0;\r\n tangents[15] = -1.0;\r\n tangents[16] = 0.0;\r\n tangents[17] = 0.0;\r\n tangents[18] = -1.0;\r\n tangents[19] = 0.0;\r\n tangents[20] = 0.0;\r\n tangents[21] = -1.0;\r\n tangents[22] = 0.0;\r\n tangents[23] = 0.0;\r\n\r\n // +x face\r\n tangents[24] = 0.0;\r\n tangents[25] = 1.0;\r\n tangents[26] = 0.0;\r\n tangents[27] = 0.0;\r\n tangents[28] = 1.0;\r\n tangents[29] = 0.0;\r\n tangents[30] = 0.0;\r\n tangents[31] = 1.0;\r\n tangents[32] = 0.0;\r\n tangents[33] = 0.0;\r\n tangents[34] = 1.0;\r\n tangents[35] = 0.0;\r\n\r\n // -x face\r\n tangents[36] = 0.0;\r\n tangents[37] = -1.0;\r\n tangents[38] = 0.0;\r\n tangents[39] = 0.0;\r\n tangents[40] = -1.0;\r\n tangents[41] = 0.0;\r\n tangents[42] = 0.0;\r\n tangents[43] = -1.0;\r\n tangents[44] = 0.0;\r\n tangents[45] = 0.0;\r\n tangents[46] = -1.0;\r\n tangents[47] = 0.0;\r\n\r\n // +y face\r\n tangents[48] = -1.0;\r\n tangents[49] = 0.0;\r\n tangents[50] = 0.0;\r\n tangents[51] = -1.0;\r\n tangents[52] = 0.0;\r\n tangents[53] = 0.0;\r\n tangents[54] = -1.0;\r\n tangents[55] = 0.0;\r\n tangents[56] = 0.0;\r\n tangents[57] = -1.0;\r\n tangents[58] = 0.0;\r\n tangents[59] = 0.0;\r\n\r\n // -y face\r\n tangents[60] = 1.0;\r\n tangents[61] = 0.0;\r\n tangents[62] = 0.0;\r\n tangents[63] = 1.0;\r\n tangents[64] = 0.0;\r\n tangents[65] = 0.0;\r\n tangents[66] = 1.0;\r\n tangents[67] = 0.0;\r\n tangents[68] = 0.0;\r\n tangents[69] = 1.0;\r\n tangents[70] = 0.0;\r\n tangents[71] = 0.0;\r\n\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n var bitangents = new Float32Array(6 * 4 * 3);\r\n\r\n // +z face\r\n bitangents[0] = 0.0;\r\n bitangents[1] = 1.0;\r\n bitangents[2] = 0.0;\r\n bitangents[3] = 0.0;\r\n bitangents[4] = 1.0;\r\n bitangents[5] = 0.0;\r\n bitangents[6] = 0.0;\r\n bitangents[7] = 1.0;\r\n bitangents[8] = 0.0;\r\n bitangents[9] = 0.0;\r\n bitangents[10] = 1.0;\r\n bitangents[11] = 0.0;\r\n\r\n // -z face\r\n bitangents[12] = 0.0;\r\n bitangents[13] = 1.0;\r\n bitangents[14] = 0.0;\r\n bitangents[15] = 0.0;\r\n bitangents[16] = 1.0;\r\n bitangents[17] = 0.0;\r\n bitangents[18] = 0.0;\r\n bitangents[19] = 1.0;\r\n bitangents[20] = 0.0;\r\n bitangents[21] = 0.0;\r\n bitangents[22] = 1.0;\r\n bitangents[23] = 0.0;\r\n\r\n // +x face\r\n bitangents[24] = 0.0;\r\n bitangents[25] = 0.0;\r\n bitangents[26] = 1.0;\r\n bitangents[27] = 0.0;\r\n bitangents[28] = 0.0;\r\n bitangents[29] = 1.0;\r\n bitangents[30] = 0.0;\r\n bitangents[31] = 0.0;\r\n bitangents[32] = 1.0;\r\n bitangents[33] = 0.0;\r\n bitangents[34] = 0.0;\r\n bitangents[35] = 1.0;\r\n\r\n // -x face\r\n bitangents[36] = 0.0;\r\n bitangents[37] = 0.0;\r\n bitangents[38] = 1.0;\r\n bitangents[39] = 0.0;\r\n bitangents[40] = 0.0;\r\n bitangents[41] = 1.0;\r\n bitangents[42] = 0.0;\r\n bitangents[43] = 0.0;\r\n bitangents[44] = 1.0;\r\n bitangents[45] = 0.0;\r\n bitangents[46] = 0.0;\r\n bitangents[47] = 1.0;\r\n\r\n // +y face\r\n bitangents[48] = 0.0;\r\n bitangents[49] = 0.0;\r\n bitangents[50] = 1.0;\r\n bitangents[51] = 0.0;\r\n bitangents[52] = 0.0;\r\n bitangents[53] = 1.0;\r\n bitangents[54] = 0.0;\r\n bitangents[55] = 0.0;\r\n bitangents[56] = 1.0;\r\n bitangents[57] = 0.0;\r\n bitangents[58] = 0.0;\r\n bitangents[59] = 1.0;\r\n\r\n // -y face\r\n bitangents[60] = 0.0;\r\n bitangents[61] = 0.0;\r\n bitangents[62] = 1.0;\r\n bitangents[63] = 0.0;\r\n bitangents[64] = 0.0;\r\n bitangents[65] = 1.0;\r\n bitangents[66] = 0.0;\r\n bitangents[67] = 0.0;\r\n bitangents[68] = 1.0;\r\n bitangents[69] = 0.0;\r\n bitangents[70] = 0.0;\r\n bitangents[71] = 1.0;\r\n\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n\r\n // 12 triangles: 6 faces, 2 triangles each.\r\n indices = new Uint16Array(6 * 2 * 3);\r\n\r\n // +z face\r\n indices[0] = 0;\r\n indices[1] = 1;\r\n indices[2] = 2;\r\n indices[3] = 0;\r\n indices[4] = 2;\r\n indices[5] = 3;\r\n\r\n // -z face\r\n indices[6] = 4 + 2;\r\n indices[7] = 4 + 1;\r\n indices[8] = 4 + 0;\r\n indices[9] = 4 + 3;\r\n indices[10] = 4 + 2;\r\n indices[11] = 4 + 0;\r\n\r\n // +x face\r\n indices[12] = 8 + 0;\r\n indices[13] = 8 + 1;\r\n indices[14] = 8 + 2;\r\n indices[15] = 8 + 0;\r\n indices[16] = 8 + 2;\r\n indices[17] = 8 + 3;\r\n\r\n // -x face\r\n indices[18] = 12 + 2;\r\n indices[19] = 12 + 1;\r\n indices[20] = 12 + 0;\r\n indices[21] = 12 + 3;\r\n indices[22] = 12 + 2;\r\n indices[23] = 12 + 0;\r\n\r\n // +y face\r\n indices[24] = 16 + 2;\r\n indices[25] = 16 + 1;\r\n indices[26] = 16 + 0;\r\n indices[27] = 16 + 3;\r\n indices[28] = 16 + 2;\r\n indices[29] = 16 + 0;\r\n\r\n // -y face\r\n indices[30] = 20 + 0;\r\n indices[31] = 20 + 1;\r\n indices[32] = 20 + 2;\r\n indices[33] = 20 + 0;\r\n indices[34] = 20 + 2;\r\n indices[35] = 20 + 3;\r\n } else {\r\n // Positions only - no need to duplicate corner points\r\n positions = new Float64Array(8 * 3);\r\n\r\n positions[0] = min.x;\r\n positions[1] = min.y;\r\n positions[2] = min.z;\r\n positions[3] = max.x;\r\n positions[4] = min.y;\r\n positions[5] = min.z;\r\n positions[6] = max.x;\r\n positions[7] = max.y;\r\n positions[8] = min.z;\r\n positions[9] = min.x;\r\n positions[10] = max.y;\r\n positions[11] = min.z;\r\n positions[12] = min.x;\r\n positions[13] = min.y;\r\n positions[14] = max.z;\r\n positions[15] = max.x;\r\n positions[16] = min.y;\r\n positions[17] = max.z;\r\n positions[18] = max.x;\r\n positions[19] = max.y;\r\n positions[20] = max.z;\r\n positions[21] = min.x;\r\n positions[22] = max.y;\r\n positions[23] = max.z;\r\n\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n\r\n // 12 triangles: 6 faces, 2 triangles each.\r\n indices = new Uint16Array(6 * 2 * 3);\r\n\r\n // plane z = corner.Z\r\n indices[0] = 4;\r\n indices[1] = 5;\r\n indices[2] = 6;\r\n indices[3] = 4;\r\n indices[4] = 6;\r\n indices[5] = 7;\r\n\r\n // plane z = -corner.Z\r\n indices[6] = 1;\r\n indices[7] = 0;\r\n indices[8] = 3;\r\n indices[9] = 1;\r\n indices[10] = 3;\r\n indices[11] = 2;\r\n\r\n // plane x = corner.X\r\n indices[12] = 1;\r\n indices[13] = 6;\r\n indices[14] = 5;\r\n indices[15] = 1;\r\n indices[16] = 2;\r\n indices[17] = 6;\r\n\r\n // plane y = corner.Y\r\n indices[18] = 2;\r\n indices[19] = 3;\r\n indices[20] = 7;\r\n indices[21] = 2;\r\n indices[22] = 7;\r\n indices[23] = 6;\r\n\r\n // plane x = -corner.X\r\n indices[24] = 3;\r\n indices[25] = 0;\r\n indices[26] = 4;\r\n indices[27] = 3;\r\n indices[28] = 4;\r\n indices[29] = 7;\r\n\r\n // plane y = -corner.Y\r\n indices[30] = 0;\r\n indices[31] = 1;\r\n indices[32] = 5;\r\n indices[33] = 0;\r\n indices[34] = 5;\r\n indices[35] = 4;\r\n }\r\n\r\n var diff = Cartesian3.subtract(max, min, diffScratch);\r\n var radius = Cartesian3.magnitude(diff) * 0.5;\r\n\r\n if (defined(boxGeometry._offsetAttribute)) {\r\n var length = positions.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n boxGeometry._offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: new BoundingSphere(Cartesian3.ZERO, radius),\r\n offsetAttribute: boxGeometry._offsetAttribute,\r\n });\r\n};\r\n\r\nvar unitBoxGeometry;\r\n\r\n/**\r\n * Returns the geometric representation of a unit box, including its vertices, indices, and a bounding sphere.\r\n * @returns {Geometry} The computed vertices and indices.\r\n *\r\n * @private\r\n */\r\nBoxGeometry.getUnitBox = function () {\r\n if (!defined(unitBoxGeometry)) {\r\n unitBoxGeometry = BoxGeometry.createGeometry(\r\n BoxGeometry.fromDimensions({\r\n dimensions: new Cartesian3(1.0, 1.0, 1.0),\r\n vertexFormat: VertexFormat.POSITION_ONLY,\r\n })\r\n );\r\n }\r\n return unitBoxGeometry;\r\n};\r\nexport default BoxGeometry;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\n\r\nvar diffScratch = new Cartesian3();\r\n\r\n/**\r\n * A description of the outline of a cube centered at the origin.\r\n *\r\n * @alias BoxOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.minimum The minimum x, y, and z coordinates of the box.\r\n * @param {Cartesian3} options.maximum The maximum x, y, and z coordinates of the box.\r\n *\r\n * @see BoxOutlineGeometry.fromDimensions\r\n * @see BoxOutlineGeometry.createGeometry\r\n * @see Packable\r\n *\r\n * @example\r\n * var box = new Cesium.BoxOutlineGeometry({\r\n * maximum : new Cesium.Cartesian3(250000.0, 250000.0, 250000.0),\r\n * minimum : new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0)\r\n * });\r\n * var geometry = Cesium.BoxOutlineGeometry.createGeometry(box);\r\n */\r\nfunction BoxOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var min = options.minimum;\r\n var max = options.maximum;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"min\", min);\r\n Check.typeOf.object(\"max\", max);\r\n if (\r\n defined(options.offsetAttribute) &&\r\n options.offsetAttribute === GeometryOffsetAttribute.TOP\r\n ) {\r\n throw new DeveloperError(\r\n \"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._min = Cartesian3.clone(min);\r\n this._max = Cartesian3.clone(max);\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createBoxOutlineGeometry\";\r\n}\r\n\r\n/**\r\n * Creates an outline of a cube centered at the origin given its dimensions.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.dimensions The width, depth, and height of the box stored in the x, y, and z coordinates of the Cartesian3, respectively.\r\n * @returns {BoxOutlineGeometry}\r\n *\r\n * @exception {DeveloperError} All dimensions components must be greater than or equal to zero.\r\n *\r\n *\r\n * @example\r\n * var box = Cesium.BoxOutlineGeometry.fromDimensions({\r\n * dimensions : new Cesium.Cartesian3(500000.0, 500000.0, 500000.0)\r\n * });\r\n * var geometry = Cesium.BoxOutlineGeometry.createGeometry(box);\r\n *\r\n * @see BoxOutlineGeometry.createGeometry\r\n */\r\nBoxOutlineGeometry.fromDimensions = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var dimensions = options.dimensions;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"dimensions\", dimensions);\r\n Check.typeOf.number.greaterThanOrEquals(\"dimensions.x\", dimensions.x, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\"dimensions.y\", dimensions.y, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\"dimensions.z\", dimensions.z, 0);\r\n //>>includeEnd('debug');\r\n\r\n var corner = Cartesian3.multiplyByScalar(dimensions, 0.5, new Cartesian3());\r\n\r\n return new BoxOutlineGeometry({\r\n minimum: Cartesian3.negate(corner, new Cartesian3()),\r\n maximum: corner,\r\n offsetAttribute: options.offsetAttribute,\r\n });\r\n};\r\n\r\n/**\r\n * Creates an outline of a cube from the dimensions of an AxisAlignedBoundingBox.\r\n *\r\n * @param {AxisAlignedBoundingBox} boundingBox A description of the AxisAlignedBoundingBox.\r\n * @returns {BoxOutlineGeometry}\r\n *\r\n *\r\n *\r\n * @example\r\n * var aabb = Cesium.AxisAlignedBoundingBox.fromPoints(Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ]));\r\n * var box = Cesium.BoxOutlineGeometry.fromAxisAlignedBoundingBox(aabb);\r\n *\r\n * @see BoxOutlineGeometry.createGeometry\r\n */\r\nBoxOutlineGeometry.fromAxisAlignedBoundingBox = function (boundingBox) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"boundindBox\", boundingBox);\r\n //>>includeEnd('debug');\r\n\r\n return new BoxOutlineGeometry({\r\n minimum: boundingBox.minimum,\r\n maximum: boundingBox.maximum,\r\n });\r\n};\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nBoxOutlineGeometry.packedLength = 2 * Cartesian3.packedLength + 1;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {BoxOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nBoxOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Cartesian3.pack(value._min, array, startingIndex);\r\n Cartesian3.pack(value._max, array, startingIndex + Cartesian3.packedLength);\r\n array[startingIndex + Cartesian3.packedLength * 2] = defaultValue(\r\n value._offsetAttribute,\r\n -1\r\n );\r\n\r\n return array;\r\n};\r\n\r\nvar scratchMin = new Cartesian3();\r\nvar scratchMax = new Cartesian3();\r\nvar scratchOptions = {\r\n minimum: scratchMin,\r\n maximum: scratchMax,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {BoxOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {BoxOutlineGeometry} The modified result parameter or a new BoxOutlineGeometry instance if one was not provided.\r\n */\r\nBoxOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var min = Cartesian3.unpack(array, startingIndex, scratchMin);\r\n var max = Cartesian3.unpack(\r\n array,\r\n startingIndex + Cartesian3.packedLength,\r\n scratchMax\r\n );\r\n var offsetAttribute = array[startingIndex + Cartesian3.packedLength * 2];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n return new BoxOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._min = Cartesian3.clone(min, result._min);\r\n result._max = Cartesian3.clone(max, result._max);\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an outline of a box, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {BoxOutlineGeometry} boxGeometry A description of the box outline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nBoxOutlineGeometry.createGeometry = function (boxGeometry) {\r\n var min = boxGeometry._min;\r\n var max = boxGeometry._max;\r\n\r\n if (Cartesian3.equals(min, max)) {\r\n return;\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n var indices = new Uint16Array(12 * 2);\r\n var positions = new Float64Array(8 * 3);\r\n\r\n positions[0] = min.x;\r\n positions[1] = min.y;\r\n positions[2] = min.z;\r\n positions[3] = max.x;\r\n positions[4] = min.y;\r\n positions[5] = min.z;\r\n positions[6] = max.x;\r\n positions[7] = max.y;\r\n positions[8] = min.z;\r\n positions[9] = min.x;\r\n positions[10] = max.y;\r\n positions[11] = min.z;\r\n\r\n positions[12] = min.x;\r\n positions[13] = min.y;\r\n positions[14] = max.z;\r\n positions[15] = max.x;\r\n positions[16] = min.y;\r\n positions[17] = max.z;\r\n positions[18] = max.x;\r\n positions[19] = max.y;\r\n positions[20] = max.z;\r\n positions[21] = min.x;\r\n positions[22] = max.y;\r\n positions[23] = max.z;\r\n\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n\r\n // top\r\n indices[0] = 4;\r\n indices[1] = 5;\r\n indices[2] = 5;\r\n indices[3] = 6;\r\n indices[4] = 6;\r\n indices[5] = 7;\r\n indices[6] = 7;\r\n indices[7] = 4;\r\n\r\n // bottom\r\n indices[8] = 0;\r\n indices[9] = 1;\r\n indices[10] = 1;\r\n indices[11] = 2;\r\n indices[12] = 2;\r\n indices[13] = 3;\r\n indices[14] = 3;\r\n indices[15] = 0;\r\n\r\n // left\r\n indices[16] = 0;\r\n indices[17] = 4;\r\n indices[18] = 1;\r\n indices[19] = 5;\r\n\r\n //right\r\n indices[20] = 2;\r\n indices[21] = 6;\r\n indices[22] = 3;\r\n indices[23] = 7;\r\n\r\n var diff = Cartesian3.subtract(max, min, diffScratch);\r\n var radius = Cartesian3.magnitude(diff) * 0.5;\r\n\r\n if (defined(boxGeometry._offsetAttribute)) {\r\n var length = positions.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n boxGeometry._offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: new BoundingSphere(Cartesian3.ZERO, radius),\r\n offsetAttribute: boxGeometry._offsetAttribute,\r\n });\r\n};\r\nexport default BoxOutlineGeometry;\r\n","import defined from \"./defined.js\";\r\n\r\nvar implementation;\r\nif (typeof cancelAnimationFrame !== \"undefined\") {\r\n implementation = cancelAnimationFrame;\r\n}\r\n\r\n(function () {\r\n // look for vendor prefixed function\r\n if (!defined(implementation) && typeof window !== \"undefined\") {\r\n var vendors = [\"webkit\", \"moz\", \"ms\", \"o\"];\r\n var i = 0;\r\n var len = vendors.length;\r\n while (i < len && !defined(implementation)) {\r\n implementation = window[vendors[i] + \"CancelAnimationFrame\"];\r\n if (!defined(implementation)) {\r\n implementation = window[vendors[i] + \"CancelRequestAnimationFrame\"];\r\n }\r\n ++i;\r\n }\r\n }\r\n\r\n // otherwise, assume requestAnimationFrame is based on setTimeout, so use clearTimeout\r\n if (!defined(implementation)) {\r\n implementation = clearTimeout;\r\n }\r\n})();\r\n\r\n/**\r\n * A browser-independent function to cancel an animation frame requested using {@link requestAnimationFrame}.\r\n *\r\n * @function cancelAnimationFrame\r\n *\r\n * @param {Number} requestID The value returned by {@link requestAnimationFrame}.\r\n *\r\n * @see {@link http://www.w3.org/TR/animation-timing/#the-WindowAnimationTiming-interface|The WindowAnimationTiming interface}\r\n */\r\nfunction cancelAnimationFramePolyfill(requestID) {\r\n // we need this extra wrapper function because the native cancelAnimationFrame\r\n // functions must be invoked on the global scope (window), which is not the case\r\n // if invoked as Cesium.cancelAnimationFrame(requestID)\r\n implementation(requestID);\r\n}\r\nexport default cancelAnimationFramePolyfill;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\n\r\n/**\r\n * Geocodes queries containing longitude and latitude coordinates and an optional height.\r\n * Query format: `longitude latitude (height)` with longitude/latitude in degrees and height in meters.\r\n *\r\n * @alias CartographicGeocoderService\r\n * @constructor\r\n */\r\nfunction CartographicGeocoderService() {}\r\n\r\n/**\r\n * @function\r\n *\r\n * @param {String} query The query to be sent to the geocoder service\r\n * @returns {Promise}\r\n */\r\nCartographicGeocoderService.prototype.geocode = function (query) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"query\", query);\r\n //>>includeEnd('debug');\r\n\r\n var splitQuery = query.match(/[^\\s,\\n]+/g);\r\n if (splitQuery.length === 2 || splitQuery.length === 3) {\r\n var longitude = +splitQuery[0];\r\n var latitude = +splitQuery[1];\r\n var height = splitQuery.length === 3 ? +splitQuery[2] : 300.0;\r\n\r\n if (isNaN(longitude) && isNaN(latitude)) {\r\n var coordTest = /^(\\d+.?\\d*)([nsew])/i;\r\n for (var i = 0; i < splitQuery.length; ++i) {\r\n var splitCoord = splitQuery[i].match(coordTest);\r\n if (coordTest.test(splitQuery[i]) && splitCoord.length === 3) {\r\n if (/^[ns]/i.test(splitCoord[2])) {\r\n latitude = /^[n]/i.test(splitCoord[2])\r\n ? +splitCoord[1]\r\n : -splitCoord[1];\r\n } else if (/^[ew]/i.test(splitCoord[2])) {\r\n longitude = /^[e]/i.test(splitCoord[2])\r\n ? +splitCoord[1]\r\n : -splitCoord[1];\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!isNaN(longitude) && !isNaN(latitude) && !isNaN(height)) {\r\n var result = {\r\n displayName: query,\r\n destination: Cartesian3.fromDegrees(longitude, latitude, height),\r\n };\r\n return when.resolve([result]);\r\n }\r\n }\r\n return when.resolve([]);\r\n};\r\nexport default CartographicGeocoderService;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * Creates a curve parameterized and evaluated by time. This type describes an interface\r\n * and is not intended to be instantiated directly.\r\n *\r\n * @alias Spline\r\n * @constructor\r\n *\r\n * @see CatmullRomSpline\r\n * @see HermiteSpline\r\n * @see LinearSpline\r\n * @see QuaternionSpline\r\n */\r\nfunction Spline() {\r\n /**\r\n * An array of times for the control points.\r\n * @type {Number[]}\r\n * @default undefined\r\n */\r\n this.times = undefined;\r\n\r\n /**\r\n * An array of control points.\r\n * @type {Cartesian3[]|Quaternion[]}\r\n * @default undefined\r\n */\r\n this.points = undefined;\r\n\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\n/**\r\n * Evaluates the curve at a given time.\r\n * @function\r\n *\r\n * @param {Number} time The time at which to evaluate the curve.\r\n * @param {Cartesian3|Quaternion|Number[]} [result] The object onto which to store the result.\r\n * @returns {Cartesian3|Quaternion|Number[]} The modified result parameter or a new instance of the point on the curve at the given time.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nSpline.prototype.evaluate = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Finds an index i in times such that the parameter\r\n * time is in the interval [times[i], times[i + 1]].\r\n *\r\n * @param {Number} time The time.\r\n * @param {Number} startIndex The index from which to start the search.\r\n * @returns {Number} The index for the element at the start of the interval.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nSpline.prototype.findTimeInterval = function (time, startIndex) {\r\n var times = this.times;\r\n var length = times.length;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n if (time < times[0] || time > times[length - 1]) {\r\n throw new DeveloperError(\"time is out of range.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Take advantage of temporal coherence by checking current, next and previous intervals\r\n // for containment of time.\r\n startIndex = defaultValue(startIndex, 0);\r\n\r\n if (time >= times[startIndex]) {\r\n if (startIndex + 1 < length && time < times[startIndex + 1]) {\r\n return startIndex;\r\n } else if (startIndex + 2 < length && time < times[startIndex + 2]) {\r\n return startIndex + 1;\r\n }\r\n } else if (startIndex - 1 >= 0 && time >= times[startIndex - 1]) {\r\n return startIndex - 1;\r\n }\r\n\r\n // The above failed so do a linear search. For the use cases so far, the\r\n // length of the list is less than 10. In the future, if there is a bottle neck,\r\n // it might be here.\r\n\r\n var i;\r\n if (time > times[startIndex]) {\r\n for (i = startIndex; i < length - 1; ++i) {\r\n if (time >= times[i] && time < times[i + 1]) {\r\n break;\r\n }\r\n }\r\n } else {\r\n for (i = startIndex - 1; i >= 0; --i) {\r\n if (time >= times[i] && time < times[i + 1]) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (i === length - 1) {\r\n i = length - 2;\r\n }\r\n\r\n return i;\r\n};\r\n\r\n/**\r\n * Wraps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, wrapped around the animation period.\r\n */\r\nSpline.prototype.wrapTime = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var times = this.times;\r\n var timeEnd = times[times.length - 1];\r\n var timeStart = times[0];\r\n var timeStretch = timeEnd - timeStart;\r\n var divs;\r\n if (time < timeStart) {\r\n divs = Math.floor((timeStart - time) / timeStretch) + 1;\r\n time += divs * timeStretch;\r\n }\r\n if (time > timeEnd) {\r\n divs = Math.floor((time - timeEnd) / timeStretch) + 1;\r\n time -= divs * timeStretch;\r\n }\r\n return time;\r\n};\r\n\r\n/**\r\n * Clamps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, clamped to the animation period.\r\n */\r\nSpline.prototype.clampTime = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var times = this.times;\r\n return CesiumMath.clamp(time, times[0], times[times.length - 1]);\r\n};\r\nexport default Spline;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Spline from \"./Spline.js\";\r\n\r\n/**\r\n * A spline that uses piecewise linear interpolation to create a curve.\r\n *\r\n * @alias LinearSpline\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.times An array of strictly increasing, unit-less, floating-point times at each point.\r\n * The values are in no way connected to the clock time. They are the parameterization for the curve.\r\n * @param {Cartesian3[]} options.points The array of {@link Cartesian3} control points.\r\n *\r\n * @exception {DeveloperError} points.length must be greater than or equal to 2.\r\n * @exception {DeveloperError} times.length must be equal to points.length.\r\n *\r\n *\r\n * @example\r\n * var times = [ 0.0, 1.5, 3.0, 4.5, 6.0 ];\r\n * var spline = new Cesium.LinearSpline({\r\n * times : times,\r\n * points : [\r\n * new Cesium.Cartesian3(1235398.0, -4810983.0, 4146266.0),\r\n * new Cesium.Cartesian3(1372574.0, -5345182.0, 4606657.0),\r\n * new Cesium.Cartesian3(-757983.0, -5542796.0, 4514323.0),\r\n * new Cesium.Cartesian3(-2821260.0, -5248423.0, 4021290.0),\r\n * new Cesium.Cartesian3(-2539788.0, -4724797.0, 3620093.0)\r\n * ]\r\n * });\r\n *\r\n * var p0 = spline.evaluate(times[0]);\r\n *\r\n * @see HermiteSpline\r\n * @see CatmullRomSpline\r\n * @see QuaternionSpline\r\n * @see WeightSpline\r\n */\r\nfunction LinearSpline(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var points = options.points;\r\n var times = options.times;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(points) || !defined(times)) {\r\n throw new DeveloperError(\"points and times are required.\");\r\n }\r\n if (points.length < 2) {\r\n throw new DeveloperError(\r\n \"points.length must be greater than or equal to 2.\"\r\n );\r\n }\r\n if (times.length !== points.length) {\r\n throw new DeveloperError(\"times.length must be equal to points.length.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._times = times;\r\n this._points = points;\r\n\r\n this._lastTimeIndex = 0;\r\n}\r\n\r\nObject.defineProperties(LinearSpline.prototype, {\r\n /**\r\n * An array of times for the control points.\r\n *\r\n * @memberof LinearSpline.prototype\r\n *\r\n * @type {Number[]}\r\n * @readonly\r\n */\r\n times: {\r\n get: function () {\r\n return this._times;\r\n },\r\n },\r\n\r\n /**\r\n * An array of {@link Cartesian3} control points.\r\n *\r\n * @memberof LinearSpline.prototype\r\n *\r\n * @type {Cartesian3[]}\r\n * @readonly\r\n */\r\n points: {\r\n get: function () {\r\n return this._points;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Finds an index i in times such that the parameter\r\n * time is in the interval [times[i], times[i + 1]].\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @returns {Number} The index for the element at the start of the interval.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nLinearSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;\r\n\r\n/**\r\n * Wraps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, wrapped around to the updated animation.\r\n */\r\nLinearSpline.prototype.wrapTime = Spline.prototype.wrapTime;\r\n\r\n/**\r\n * Clamps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, clamped to the animation period.\r\n */\r\nLinearSpline.prototype.clampTime = Spline.prototype.clampTime;\r\n\r\n/**\r\n * Evaluates the curve at a given time.\r\n *\r\n * @param {Number} time The time at which to evaluate the curve.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new instance of the point on the curve at the given time.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nLinearSpline.prototype.evaluate = function (time, result) {\r\n var points = this.points;\r\n var times = this.times;\r\n\r\n var i = (this._lastTimeIndex = this.findTimeInterval(\r\n time,\r\n this._lastTimeIndex\r\n ));\r\n var u = (time - times[i]) / (times[i + 1] - times[i]);\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n return Cartesian3.lerp(points[i], points[i + 1], u, result);\r\n};\r\nexport default LinearSpline;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Uses the Tridiagonal Matrix Algorithm, also known as the Thomas Algorithm, to solve\r\n * a system of linear equations where the coefficient matrix is a tridiagonal matrix.\r\n *\r\n * @namespace TridiagonalSystemSolver\r\n */\r\nvar TridiagonalSystemSolver = {};\r\n\r\n/**\r\n * Solves a tridiagonal system of linear equations.\r\n *\r\n * @param {Number[]} diagonal An array with length n that contains the diagonal of the coefficient matrix.\r\n * @param {Number[]} lower An array with length n - 1 that contains the lower diagonal of the coefficient matrix.\r\n * @param {Number[]} upper An array with length n - 1 that contains the upper diagonal of the coefficient matrix.\r\n * @param {Cartesian3[]} right An array of Cartesians with length n that is the right side of the system of equations.\r\n *\r\n * @exception {DeveloperError} diagonal and right must have the same lengths.\r\n * @exception {DeveloperError} lower and upper must have the same lengths.\r\n * @exception {DeveloperError} lower and upper must be one less than the length of diagonal.\r\n *\r\n * @performance Linear time.\r\n *\r\n * @example\r\n * var lowerDiagonal = [1.0, 1.0, 1.0, 1.0];\r\n * var diagonal = [2.0, 4.0, 4.0, 4.0, 2.0];\r\n * var upperDiagonal = [1.0, 1.0, 1.0, 1.0];\r\n * var rightHandSide = [\r\n * new Cesium.Cartesian3(410757.0, -1595711.0, 1375302.0),\r\n * new Cesium.Cartesian3(-5986705.0, -2190640.0, 1099600.0),\r\n * new Cesium.Cartesian3(-12593180.0, 288588.0, -1755549.0),\r\n * new Cesium.Cartesian3(-5349898.0, 2457005.0, -2685438.0),\r\n * new Cesium.Cartesian3(845820.0, 1573488.0, -1205591.0)\r\n * ];\r\n *\r\n * var solution = Cesium.TridiagonalSystemSolver.solve(lowerDiagonal, diagonal, upperDiagonal, rightHandSide);\r\n *\r\n * @returns {Cartesian3[]} An array of Cartesians with length n that is the solution to the tridiagonal system of equations.\r\n */\r\nTridiagonalSystemSolver.solve = function (lower, diagonal, upper, right) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(lower) || !(lower instanceof Array)) {\r\n throw new DeveloperError(\"The array lower is required.\");\r\n }\r\n if (!defined(diagonal) || !(diagonal instanceof Array)) {\r\n throw new DeveloperError(\"The array diagonal is required.\");\r\n }\r\n if (!defined(upper) || !(upper instanceof Array)) {\r\n throw new DeveloperError(\"The array upper is required.\");\r\n }\r\n if (!defined(right) || !(right instanceof Array)) {\r\n throw new DeveloperError(\"The array right is required.\");\r\n }\r\n if (diagonal.length !== right.length) {\r\n throw new DeveloperError(\"diagonal and right must have the same lengths.\");\r\n }\r\n if (lower.length !== upper.length) {\r\n throw new DeveloperError(\"lower and upper must have the same lengths.\");\r\n } else if (lower.length !== diagonal.length - 1) {\r\n throw new DeveloperError(\r\n \"lower and upper must be one less than the length of diagonal.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var c = new Array(upper.length);\r\n var d = new Array(right.length);\r\n var x = new Array(right.length);\r\n\r\n var i;\r\n for (i = 0; i < d.length; i++) {\r\n d[i] = new Cartesian3();\r\n x[i] = new Cartesian3();\r\n }\r\n\r\n c[0] = upper[0] / diagonal[0];\r\n d[0] = Cartesian3.multiplyByScalar(right[0], 1.0 / diagonal[0], d[0]);\r\n\r\n var scalar;\r\n for (i = 1; i < c.length; ++i) {\r\n scalar = 1.0 / (diagonal[i] - c[i - 1] * lower[i - 1]);\r\n c[i] = upper[i] * scalar;\r\n d[i] = Cartesian3.subtract(\r\n right[i],\r\n Cartesian3.multiplyByScalar(d[i - 1], lower[i - 1], d[i]),\r\n d[i]\r\n );\r\n d[i] = Cartesian3.multiplyByScalar(d[i], scalar, d[i]);\r\n }\r\n\r\n scalar = 1.0 / (diagonal[i] - c[i - 1] * lower[i - 1]);\r\n d[i] = Cartesian3.subtract(\r\n right[i],\r\n Cartesian3.multiplyByScalar(d[i - 1], lower[i - 1], d[i]),\r\n d[i]\r\n );\r\n d[i] = Cartesian3.multiplyByScalar(d[i], scalar, d[i]);\r\n\r\n x[x.length - 1] = d[d.length - 1];\r\n for (i = x.length - 2; i >= 0; --i) {\r\n x[i] = Cartesian3.subtract(\r\n d[i],\r\n Cartesian3.multiplyByScalar(x[i + 1], c[i], x[i]),\r\n x[i]\r\n );\r\n }\r\n\r\n return x;\r\n};\r\nexport default TridiagonalSystemSolver;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport LinearSpline from \"./LinearSpline.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport Spline from \"./Spline.js\";\r\nimport TridiagonalSystemSolver from \"./TridiagonalSystemSolver.js\";\r\n\r\nvar scratchLower = [];\r\nvar scratchDiagonal = [];\r\nvar scratchUpper = [];\r\nvar scratchRight = [];\r\n\r\nfunction generateClamped(points, firstTangent, lastTangent) {\r\n var l = scratchLower;\r\n var u = scratchUpper;\r\n var d = scratchDiagonal;\r\n var r = scratchRight;\r\n\r\n l.length = u.length = points.length - 1;\r\n d.length = r.length = points.length;\r\n\r\n var i;\r\n l[0] = d[0] = 1.0;\r\n u[0] = 0.0;\r\n\r\n var right = r[0];\r\n if (!defined(right)) {\r\n right = r[0] = new Cartesian3();\r\n }\r\n Cartesian3.clone(firstTangent, right);\r\n\r\n for (i = 1; i < l.length - 1; ++i) {\r\n l[i] = u[i] = 1.0;\r\n d[i] = 4.0;\r\n\r\n right = r[i];\r\n if (!defined(right)) {\r\n right = r[i] = new Cartesian3();\r\n }\r\n Cartesian3.subtract(points[i + 1], points[i - 1], right);\r\n Cartesian3.multiplyByScalar(right, 3.0, right);\r\n }\r\n\r\n l[i] = 0.0;\r\n u[i] = 1.0;\r\n d[i] = 4.0;\r\n\r\n right = r[i];\r\n if (!defined(right)) {\r\n right = r[i] = new Cartesian3();\r\n }\r\n Cartesian3.subtract(points[i + 1], points[i - 1], right);\r\n Cartesian3.multiplyByScalar(right, 3.0, right);\r\n\r\n d[i + 1] = 1.0;\r\n right = r[i + 1];\r\n if (!defined(right)) {\r\n right = r[i + 1] = new Cartesian3();\r\n }\r\n Cartesian3.clone(lastTangent, right);\r\n\r\n return TridiagonalSystemSolver.solve(l, d, u, r);\r\n}\r\n\r\nfunction generateNatural(points) {\r\n var l = scratchLower;\r\n var u = scratchUpper;\r\n var d = scratchDiagonal;\r\n var r = scratchRight;\r\n\r\n l.length = u.length = points.length - 1;\r\n d.length = r.length = points.length;\r\n\r\n var i;\r\n l[0] = u[0] = 1.0;\r\n d[0] = 2.0;\r\n\r\n var right = r[0];\r\n if (!defined(right)) {\r\n right = r[0] = new Cartesian3();\r\n }\r\n Cartesian3.subtract(points[1], points[0], right);\r\n Cartesian3.multiplyByScalar(right, 3.0, right);\r\n\r\n for (i = 1; i < l.length; ++i) {\r\n l[i] = u[i] = 1.0;\r\n d[i] = 4.0;\r\n\r\n right = r[i];\r\n if (!defined(right)) {\r\n right = r[i] = new Cartesian3();\r\n }\r\n Cartesian3.subtract(points[i + 1], points[i - 1], right);\r\n Cartesian3.multiplyByScalar(right, 3.0, right);\r\n }\r\n\r\n d[i] = 2.0;\r\n\r\n right = r[i];\r\n if (!defined(right)) {\r\n right = r[i] = new Cartesian3();\r\n }\r\n Cartesian3.subtract(points[i], points[i - 1], right);\r\n Cartesian3.multiplyByScalar(right, 3.0, right);\r\n\r\n return TridiagonalSystemSolver.solve(l, d, u, r);\r\n}\r\n\r\n/**\r\n * A Hermite spline is a cubic interpolating spline. Points, incoming tangents, outgoing tangents, and times\r\n * must be defined for each control point. The outgoing tangents are defined for points [0, n - 2] and the incoming\r\n * tangents are defined for points [1, n - 1]. For example, when interpolating a segment of the curve between points[i] and\r\n * points[i + 1], the tangents at the points will be outTangents[i] and inTangents[i],\r\n * respectively.\r\n *\r\n * @alias HermiteSpline\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.times An array of strictly increasing, unit-less, floating-point times at each point.\r\n * The values are in no way connected to the clock time. They are the parameterization for the curve.\r\n * @param {Cartesian3[]} options.points The array of {@link Cartesian3} control points.\r\n * @param {Cartesian3[]} options.inTangents The array of {@link Cartesian3} incoming tangents at each control point.\r\n * @param {Cartesian3[]} options.outTangents The array of {@link Cartesian3} outgoing tangents at each control point.\r\n *\r\n * @exception {DeveloperError} points.length must be greater than or equal to 2.\r\n * @exception {DeveloperError} times.length must be equal to points.length.\r\n * @exception {DeveloperError} inTangents and outTangents must have a length equal to points.length - 1.\r\n *\r\n *\r\n * @example\r\n * // Create a G1 continuous Hermite spline\r\n * var times = [ 0.0, 1.5, 3.0, 4.5, 6.0 ];\r\n * var spline = new Cesium.HermiteSpline({\r\n * times : times,\r\n * points : [\r\n * new Cesium.Cartesian3(1235398.0, -4810983.0, 4146266.0),\r\n * new Cesium.Cartesian3(1372574.0, -5345182.0, 4606657.0),\r\n * new Cesium.Cartesian3(-757983.0, -5542796.0, 4514323.0),\r\n * new Cesium.Cartesian3(-2821260.0, -5248423.0, 4021290.0),\r\n * new Cesium.Cartesian3(-2539788.0, -4724797.0, 3620093.0)\r\n * ],\r\n * outTangents : [\r\n * new Cesium.Cartesian3(1125196, -161816, 270551),\r\n * new Cesium.Cartesian3(-996690.5, -365906.5, 184028.5),\r\n * new Cesium.Cartesian3(-2096917, 48379.5, -292683.5),\r\n * new Cesium.Cartesian3(-890902.5, 408999.5, -447115)\r\n * ],\r\n * inTangents : [\r\n * new Cesium.Cartesian3(-1993381, -731813, 368057),\r\n * new Cesium.Cartesian3(-4193834, 96759, -585367),\r\n * new Cesium.Cartesian3(-1781805, 817999, -894230),\r\n * new Cesium.Cartesian3(1165345, 112641, 47281)\r\n * ]\r\n * });\r\n *\r\n * var p0 = spline.evaluate(times[0]);\r\n *\r\n * @see CatmullRomSpline\r\n * @see LinearSpline\r\n * @see QuaternionSpline\r\n * @see WeightSpline\r\n */\r\nfunction HermiteSpline(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var points = options.points;\r\n var times = options.times;\r\n var inTangents = options.inTangents;\r\n var outTangents = options.outTangents;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(points) ||\r\n !defined(times) ||\r\n !defined(inTangents) ||\r\n !defined(outTangents)\r\n ) {\r\n throw new DeveloperError(\r\n \"times, points, inTangents, and outTangents are required.\"\r\n );\r\n }\r\n if (points.length < 2) {\r\n throw new DeveloperError(\r\n \"points.length must be greater than or equal to 2.\"\r\n );\r\n }\r\n if (times.length !== points.length) {\r\n throw new DeveloperError(\"times.length must be equal to points.length.\");\r\n }\r\n if (\r\n inTangents.length !== outTangents.length ||\r\n inTangents.length !== points.length - 1\r\n ) {\r\n throw new DeveloperError(\r\n \"inTangents and outTangents must have a length equal to points.length - 1.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._times = times;\r\n this._points = points;\r\n this._inTangents = inTangents;\r\n this._outTangents = outTangents;\r\n\r\n this._lastTimeIndex = 0;\r\n}\r\n\r\nObject.defineProperties(HermiteSpline.prototype, {\r\n /**\r\n * An array of times for the control points.\r\n *\r\n * @memberof HermiteSpline.prototype\r\n *\r\n * @type {Number[]}\r\n * @readonly\r\n */\r\n times: {\r\n get: function () {\r\n return this._times;\r\n },\r\n },\r\n\r\n /**\r\n * An array of {@link Cartesian3} control points.\r\n *\r\n * @memberof HermiteSpline.prototype\r\n *\r\n * @type {Cartesian3[]}\r\n * @readonly\r\n */\r\n points: {\r\n get: function () {\r\n return this._points;\r\n },\r\n },\r\n\r\n /**\r\n * An array of {@link Cartesian3} incoming tangents at each control point.\r\n *\r\n * @memberof HermiteSpline.prototype\r\n *\r\n * @type {Cartesian3[]}\r\n * @readonly\r\n */\r\n inTangents: {\r\n get: function () {\r\n return this._inTangents;\r\n },\r\n },\r\n\r\n /**\r\n * An array of {@link Cartesian3} outgoing tangents at each control point.\r\n *\r\n * @memberof HermiteSpline.prototype\r\n *\r\n * @type {Cartesian3[]}\r\n * @readonly\r\n */\r\n outTangents: {\r\n get: function () {\r\n return this._outTangents;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates a spline where the tangents at each control point are the same.\r\n * The curves are guaranteed to be at least in the class C1.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.times The array of control point times.\r\n * @param {Cartesian3[]} options.points The array of control points.\r\n * @param {Cartesian3[]} options.tangents The array of tangents at the control points.\r\n * @returns {HermiteSpline} A hermite spline.\r\n *\r\n * @exception {DeveloperError} points, times and tangents are required.\r\n * @exception {DeveloperError} points.length must be greater than or equal to 2.\r\n * @exception {DeveloperError} times, points and tangents must have the same length.\r\n *\r\n * @example\r\n * var points = [\r\n * new Cesium.Cartesian3(1235398.0, -4810983.0, 4146266.0),\r\n * new Cesium.Cartesian3(1372574.0, -5345182.0, 4606657.0),\r\n * new Cesium.Cartesian3(-757983.0, -5542796.0, 4514323.0),\r\n * new Cesium.Cartesian3(-2821260.0, -5248423.0, 4021290.0),\r\n * new Cesium.Cartesian3(-2539788.0, -4724797.0, 3620093.0)\r\n * ];\r\n *\r\n * // Add tangents\r\n * var tangents = new Array(points.length);\r\n * tangents[0] = new Cesium.Cartesian3(1125196, -161816, 270551);\r\n * var temp = new Cesium.Cartesian3();\r\n * for (var i = 1; i < tangents.length - 1; ++i) {\r\n * tangents[i] = Cesium.Cartesian3.multiplyByScalar(Cesium.Cartesian3.subtract(points[i + 1], points[i - 1], temp), 0.5, new Cesium.Cartesian3());\r\n * }\r\n * tangents[tangents.length - 1] = new Cesium.Cartesian3(1165345, 112641, 47281);\r\n *\r\n * var spline = Cesium.HermiteSpline.createC1({\r\n * times : times,\r\n * points : points,\r\n * tangents : tangents\r\n * });\r\n */\r\nHermiteSpline.createC1 = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var times = options.times;\r\n var points = options.points;\r\n var tangents = options.tangents;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(points) || !defined(times) || !defined(tangents)) {\r\n throw new DeveloperError(\"points, times and tangents are required.\");\r\n }\r\n if (points.length < 2) {\r\n throw new DeveloperError(\r\n \"points.length must be greater than or equal to 2.\"\r\n );\r\n }\r\n if (times.length !== points.length || times.length !== tangents.length) {\r\n throw new DeveloperError(\r\n \"times, points and tangents must have the same length.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var outTangents = tangents.slice(0, tangents.length - 1);\r\n var inTangents = tangents.slice(1, tangents.length);\r\n\r\n return new HermiteSpline({\r\n times: times,\r\n points: points,\r\n inTangents: inTangents,\r\n outTangents: outTangents,\r\n });\r\n};\r\n\r\n/**\r\n * Creates a natural cubic spline. The tangents at the control points are generated\r\n * to create a curve in the class C2.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.times The array of control point times.\r\n * @param {Cartesian3[]} options.points The array of control points.\r\n * @returns {HermiteSpline|LinearSpline} A hermite spline or a linear spline if less than 3 control points were given.\r\n *\r\n * @exception {DeveloperError} points and times are required.\r\n * @exception {DeveloperError} points.length must be greater than or equal to 2.\r\n * @exception {DeveloperError} times.length must be equal to points.length.\r\n *\r\n * @example\r\n * // Create a natural cubic spline above the earth from Philadelphia to Los Angeles.\r\n * var spline = Cesium.HermiteSpline.createNaturalCubic({\r\n * times : [ 0.0, 1.5, 3.0, 4.5, 6.0 ],\r\n * points : [\r\n * new Cesium.Cartesian3(1235398.0, -4810983.0, 4146266.0),\r\n * new Cesium.Cartesian3(1372574.0, -5345182.0, 4606657.0),\r\n * new Cesium.Cartesian3(-757983.0, -5542796.0, 4514323.0),\r\n * new Cesium.Cartesian3(-2821260.0, -5248423.0, 4021290.0),\r\n * new Cesium.Cartesian3(-2539788.0, -4724797.0, 3620093.0)\r\n * ]\r\n * });\r\n */\r\nHermiteSpline.createNaturalCubic = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var times = options.times;\r\n var points = options.points;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(points) || !defined(times)) {\r\n throw new DeveloperError(\"points and times are required.\");\r\n }\r\n if (points.length < 2) {\r\n throw new DeveloperError(\r\n \"points.length must be greater than or equal to 2.\"\r\n );\r\n }\r\n if (times.length !== points.length) {\r\n throw new DeveloperError(\"times.length must be equal to points.length.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (points.length < 3) {\r\n return new LinearSpline({\r\n points: points,\r\n times: times,\r\n });\r\n }\r\n\r\n var tangents = generateNatural(points);\r\n var outTangents = tangents.slice(0, tangents.length - 1);\r\n var inTangents = tangents.slice(1, tangents.length);\r\n\r\n return new HermiteSpline({\r\n times: times,\r\n points: points,\r\n inTangents: inTangents,\r\n outTangents: outTangents,\r\n });\r\n};\r\n\r\n/**\r\n * Creates a clamped cubic spline. The tangents at the interior control points are generated\r\n * to create a curve in the class C2.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.times The array of control point times.\r\n * @param {Cartesian3[]} options.points The array of control points.\r\n * @param {Cartesian3} options.firstTangent The outgoing tangent of the first control point.\r\n * @param {Cartesian3} options.lastTangent The incoming tangent of the last control point.\r\n * @returns {HermiteSpline|LinearSpline} A hermite spline or a linear spline if less than 3 control points were given.\r\n *\r\n * @exception {DeveloperError} points, times, firstTangent and lastTangent are required.\r\n * @exception {DeveloperError} points.length must be greater than or equal to 2.\r\n * @exception {DeveloperError} times.length must be equal to points.length.\r\n *\r\n * @example\r\n * // Create a clamped cubic spline above the earth from Philadelphia to Los Angeles.\r\n * var spline = Cesium.HermiteSpline.createClampedCubic({\r\n * times : [ 0.0, 1.5, 3.0, 4.5, 6.0 ],\r\n * points : [\r\n * new Cesium.Cartesian3(1235398.0, -4810983.0, 4146266.0),\r\n * new Cesium.Cartesian3(1372574.0, -5345182.0, 4606657.0),\r\n * new Cesium.Cartesian3(-757983.0, -5542796.0, 4514323.0),\r\n * new Cesium.Cartesian3(-2821260.0, -5248423.0, 4021290.0),\r\n * new Cesium.Cartesian3(-2539788.0, -4724797.0, 3620093.0)\r\n * ],\r\n * firstTangent : new Cesium.Cartesian3(1125196, -161816, 270551),\r\n * lastTangent : new Cesium.Cartesian3(1165345, 112641, 47281)\r\n * });\r\n */\r\nHermiteSpline.createClampedCubic = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var times = options.times;\r\n var points = options.points;\r\n var firstTangent = options.firstTangent;\r\n var lastTangent = options.lastTangent;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(points) ||\r\n !defined(times) ||\r\n !defined(firstTangent) ||\r\n !defined(lastTangent)\r\n ) {\r\n throw new DeveloperError(\r\n \"points, times, firstTangent and lastTangent are required.\"\r\n );\r\n }\r\n if (points.length < 2) {\r\n throw new DeveloperError(\r\n \"points.length must be greater than or equal to 2.\"\r\n );\r\n }\r\n if (times.length !== points.length) {\r\n throw new DeveloperError(\"times.length must be equal to points.length.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (points.length < 3) {\r\n return new LinearSpline({\r\n points: points,\r\n times: times,\r\n });\r\n }\r\n\r\n var tangents = generateClamped(points, firstTangent, lastTangent);\r\n var outTangents = tangents.slice(0, tangents.length - 1);\r\n var inTangents = tangents.slice(1, tangents.length);\r\n\r\n return new HermiteSpline({\r\n times: times,\r\n points: points,\r\n inTangents: inTangents,\r\n outTangents: outTangents,\r\n });\r\n};\r\n\r\nHermiteSpline.hermiteCoefficientMatrix = new Matrix4(\r\n 2.0,\r\n -3.0,\r\n 0.0,\r\n 1.0,\r\n -2.0,\r\n 3.0,\r\n 0.0,\r\n 0.0,\r\n 1.0,\r\n -2.0,\r\n 1.0,\r\n 0.0,\r\n 1.0,\r\n -1.0,\r\n 0.0,\r\n 0.0\r\n);\r\n\r\n/**\r\n * Finds an index i in times such that the parameter\r\n * time is in the interval [times[i], times[i + 1]].\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @returns {Number} The index for the element at the start of the interval.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nHermiteSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;\r\n\r\nvar scratchTimeVec = new Cartesian4();\r\nvar scratchTemp = new Cartesian3();\r\n\r\n/**\r\n * Wraps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, wrapped around to the updated animation.\r\n */\r\nHermiteSpline.prototype.wrapTime = Spline.prototype.wrapTime;\r\n\r\n/**\r\n * Clamps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, clamped to the animation period.\r\n */\r\nHermiteSpline.prototype.clampTime = Spline.prototype.clampTime;\r\n\r\n/**\r\n * Evaluates the curve at a given time.\r\n *\r\n * @param {Number} time The time at which to evaluate the curve.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new instance of the point on the curve at the given time.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nHermiteSpline.prototype.evaluate = function (time, result) {\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n var points = this.points;\r\n var times = this.times;\r\n var inTangents = this.inTangents;\r\n var outTangents = this.outTangents;\r\n\r\n var i = (this._lastTimeIndex = this.findTimeInterval(\r\n time,\r\n this._lastTimeIndex\r\n ));\r\n var u = (time - times[i]) / (times[i + 1] - times[i]);\r\n\r\n var timeVec = scratchTimeVec;\r\n timeVec.z = u;\r\n timeVec.y = u * u;\r\n timeVec.x = timeVec.y * u;\r\n timeVec.w = 1.0;\r\n\r\n var coefs = Matrix4.multiplyByVector(\r\n HermiteSpline.hermiteCoefficientMatrix,\r\n timeVec,\r\n timeVec\r\n );\r\n\r\n result = Cartesian3.multiplyByScalar(points[i], coefs.x, result);\r\n Cartesian3.multiplyByScalar(points[i + 1], coefs.y, scratchTemp);\r\n Cartesian3.add(result, scratchTemp, result);\r\n Cartesian3.multiplyByScalar(outTangents[i], coefs.z, scratchTemp);\r\n Cartesian3.add(result, scratchTemp, result);\r\n Cartesian3.multiplyByScalar(inTangents[i], coefs.w, scratchTemp);\r\n return Cartesian3.add(result, scratchTemp, result);\r\n};\r\nexport default HermiteSpline;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport HermiteSpline from \"./HermiteSpline.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport Spline from \"./Spline.js\";\r\n\r\nvar scratchTimeVec = new Cartesian4();\r\nvar scratchTemp0 = new Cartesian3();\r\nvar scratchTemp1 = new Cartesian3();\r\n\r\nfunction createEvaluateFunction(spline) {\r\n var points = spline.points;\r\n var times = spline.times;\r\n\r\n if (points.length < 3) {\r\n var t0 = times[0];\r\n var invSpan = 1.0 / (times[1] - t0);\r\n\r\n var p0 = points[0];\r\n var p1 = points[1];\r\n\r\n return function (time, result) {\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n var u = (time - t0) * invSpan;\r\n return Cartesian3.lerp(p0, p1, u, result);\r\n };\r\n }\r\n\r\n return function (time, result) {\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n var i = (spline._lastTimeIndex = spline.findTimeInterval(\r\n time,\r\n spline._lastTimeIndex\r\n ));\r\n var u = (time - times[i]) / (times[i + 1] - times[i]);\r\n\r\n var timeVec = scratchTimeVec;\r\n timeVec.z = u;\r\n timeVec.y = u * u;\r\n timeVec.x = timeVec.y * u;\r\n timeVec.w = 1.0;\r\n\r\n var p0;\r\n var p1;\r\n var p2;\r\n var p3;\r\n var coefs;\r\n\r\n if (i === 0) {\r\n p0 = points[0];\r\n p1 = points[1];\r\n p2 = spline.firstTangent;\r\n\r\n p3 = Cartesian3.subtract(points[2], p0, scratchTemp0);\r\n Cartesian3.multiplyByScalar(p3, 0.5, p3);\r\n\r\n coefs = Matrix4.multiplyByVector(\r\n HermiteSpline.hermiteCoefficientMatrix,\r\n timeVec,\r\n timeVec\r\n );\r\n } else if (i === points.length - 2) {\r\n p0 = points[i];\r\n p1 = points[i + 1];\r\n p3 = spline.lastTangent;\r\n\r\n p2 = Cartesian3.subtract(p1, points[i - 1], scratchTemp0);\r\n Cartesian3.multiplyByScalar(p2, 0.5, p2);\r\n\r\n coefs = Matrix4.multiplyByVector(\r\n HermiteSpline.hermiteCoefficientMatrix,\r\n timeVec,\r\n timeVec\r\n );\r\n } else {\r\n p0 = points[i - 1];\r\n p1 = points[i];\r\n p2 = points[i + 1];\r\n p3 = points[i + 2];\r\n coefs = Matrix4.multiplyByVector(\r\n CatmullRomSpline.catmullRomCoefficientMatrix,\r\n timeVec,\r\n timeVec\r\n );\r\n }\r\n result = Cartesian3.multiplyByScalar(p0, coefs.x, result);\r\n Cartesian3.multiplyByScalar(p1, coefs.y, scratchTemp1);\r\n Cartesian3.add(result, scratchTemp1, result);\r\n Cartesian3.multiplyByScalar(p2, coefs.z, scratchTemp1);\r\n Cartesian3.add(result, scratchTemp1, result);\r\n Cartesian3.multiplyByScalar(p3, coefs.w, scratchTemp1);\r\n return Cartesian3.add(result, scratchTemp1, result);\r\n };\r\n}\r\n\r\nvar firstTangentScratch = new Cartesian3();\r\nvar lastTangentScratch = new Cartesian3();\r\n\r\n/**\r\n * A Catmull-Rom spline is a cubic spline where the tangent at control points,\r\n * except the first and last, are computed using the previous and next control points.\r\n * Catmull-Rom splines are in the class C1.\r\n *\r\n * @alias CatmullRomSpline\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.times An array of strictly increasing, unit-less, floating-point times at each point.\r\n * The values are in no way connected to the clock time. They are the parameterization for the curve.\r\n * @param {Cartesian3[]} options.points The array of {@link Cartesian3} control points.\r\n * @param {Cartesian3} [options.firstTangent] The tangent of the curve at the first control point.\r\n * If the tangent is not given, it will be estimated.\r\n * @param {Cartesian3} [options.lastTangent] The tangent of the curve at the last control point.\r\n * If the tangent is not given, it will be estimated.\r\n *\r\n * @exception {DeveloperError} points.length must be greater than or equal to 2.\r\n * @exception {DeveloperError} times.length must be equal to points.length.\r\n *\r\n *\r\n * @example\r\n * // spline above the earth from Philadelphia to Los Angeles\r\n * var spline = new Cesium.CatmullRomSpline({\r\n * times : [ 0.0, 1.5, 3.0, 4.5, 6.0 ],\r\n * points : [\r\n * new Cesium.Cartesian3(1235398.0, -4810983.0, 4146266.0),\r\n * new Cesium.Cartesian3(1372574.0, -5345182.0, 4606657.0),\r\n * new Cesium.Cartesian3(-757983.0, -5542796.0, 4514323.0),\r\n * new Cesium.Cartesian3(-2821260.0, -5248423.0, 4021290.0),\r\n * new Cesium.Cartesian3(-2539788.0, -4724797.0, 3620093.0)\r\n * ]\r\n * });\r\n *\r\n * var p0 = spline.evaluate(times[i]); // equal to positions[i]\r\n * var p1 = spline.evaluate(times[i] + delta); // interpolated value when delta < times[i + 1] - times[i]\r\n *\r\n * @see HermiteSpline\r\n * @see LinearSpline\r\n * @see QuaternionSpline\r\n * @see WeightSpline\r\n */\r\nfunction CatmullRomSpline(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var points = options.points;\r\n var times = options.times;\r\n var firstTangent = options.firstTangent;\r\n var lastTangent = options.lastTangent;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"points\", points);\r\n Check.defined(\"times\", times);\r\n Check.typeOf.number.greaterThanOrEquals(\"points.length\", points.length, 2);\r\n Check.typeOf.number.equals(\r\n \"times.length\",\r\n \"points.length\",\r\n times.length,\r\n points.length\r\n );\r\n //>>includeEnd('debug');\r\n\r\n if (points.length > 2) {\r\n if (!defined(firstTangent)) {\r\n firstTangent = firstTangentScratch;\r\n Cartesian3.multiplyByScalar(points[1], 2.0, firstTangent);\r\n Cartesian3.subtract(firstTangent, points[2], firstTangent);\r\n Cartesian3.subtract(firstTangent, points[0], firstTangent);\r\n Cartesian3.multiplyByScalar(firstTangent, 0.5, firstTangent);\r\n }\r\n\r\n if (!defined(lastTangent)) {\r\n var n = points.length - 1;\r\n lastTangent = lastTangentScratch;\r\n Cartesian3.multiplyByScalar(points[n - 1], 2.0, lastTangent);\r\n Cartesian3.subtract(points[n], lastTangent, lastTangent);\r\n Cartesian3.add(lastTangent, points[n - 2], lastTangent);\r\n Cartesian3.multiplyByScalar(lastTangent, 0.5, lastTangent);\r\n }\r\n }\r\n\r\n this._times = times;\r\n this._points = points;\r\n this._firstTangent = Cartesian3.clone(firstTangent);\r\n this._lastTangent = Cartesian3.clone(lastTangent);\r\n\r\n this._evaluateFunction = createEvaluateFunction(this);\r\n this._lastTimeIndex = 0;\r\n}\r\n\r\nObject.defineProperties(CatmullRomSpline.prototype, {\r\n /**\r\n * An array of times for the control points.\r\n *\r\n * @memberof CatmullRomSpline.prototype\r\n *\r\n * @type {Number[]}\r\n * @readonly\r\n */\r\n times: {\r\n get: function () {\r\n return this._times;\r\n },\r\n },\r\n\r\n /**\r\n * An array of {@link Cartesian3} control points.\r\n *\r\n * @memberof CatmullRomSpline.prototype\r\n *\r\n * @type {Cartesian3[]}\r\n * @readonly\r\n */\r\n points: {\r\n get: function () {\r\n return this._points;\r\n },\r\n },\r\n\r\n /**\r\n * The tangent at the first control point.\r\n *\r\n * @memberof CatmullRomSpline.prototype\r\n *\r\n * @type {Cartesian3}\r\n * @readonly\r\n */\r\n firstTangent: {\r\n get: function () {\r\n return this._firstTangent;\r\n },\r\n },\r\n\r\n /**\r\n * The tangent at the last control point.\r\n *\r\n * @memberof CatmullRomSpline.prototype\r\n *\r\n * @type {Cartesian3}\r\n * @readonly\r\n */\r\n lastTangent: {\r\n get: function () {\r\n return this._lastTangent;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @private\r\n */\r\nCatmullRomSpline.catmullRomCoefficientMatrix = new Matrix4(\r\n -0.5,\r\n 1.0,\r\n -0.5,\r\n 0.0,\r\n 1.5,\r\n -2.5,\r\n 0.0,\r\n 1.0,\r\n -1.5,\r\n 2.0,\r\n 0.5,\r\n 0.0,\r\n 0.5,\r\n -0.5,\r\n 0.0,\r\n 0.0\r\n);\r\n\r\n/**\r\n * Finds an index i in times such that the parameter\r\n * time is in the interval [times[i], times[i + 1]].\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @returns {Number} The index for the element at the start of the interval.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nCatmullRomSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;\r\n\r\n/**\r\n * Wraps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, wrapped around to the updated animation.\r\n */\r\nCatmullRomSpline.prototype.wrapTime = Spline.prototype.wrapTime;\r\n\r\n/**\r\n * Clamps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, clamped to the animation period.\r\n */\r\nCatmullRomSpline.prototype.clampTime = Spline.prototype.clampTime;\r\n\r\n/**\r\n * Evaluates the curve at a given time.\r\n *\r\n * @param {Number} time The time at which to evaluate the curve.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} The modified result parameter or a new instance of the point on the curve at the given time.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nCatmullRomSpline.prototype.evaluate = function (time, result) {\r\n return this._evaluateFunction(time, result);\r\n};\r\nexport default CatmullRomSpline;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\n\r\n/**\r\n * Reads a string from a Uint8Array.\r\n *\r\n * @function\r\n *\r\n * @param {Uint8Array} uint8Array The Uint8Array to read from.\r\n * @param {Number} [byteOffset=0] The byte offset to start reading from.\r\n * @param {Number} [byteLength] The byte length to read. If byteLength is omitted the remainder of the buffer is read.\r\n * @returns {String} The string.\r\n *\r\n * @private\r\n */\r\nfunction getStringFromTypedArray(uint8Array, byteOffset, byteLength) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(uint8Array)) {\r\n throw new DeveloperError(\"uint8Array is required.\");\r\n }\r\n if (byteOffset < 0) {\r\n throw new DeveloperError(\"byteOffset cannot be negative.\");\r\n }\r\n if (byteLength < 0) {\r\n throw new DeveloperError(\"byteLength cannot be negative.\");\r\n }\r\n if (byteOffset + byteLength > uint8Array.byteLength) {\r\n throw new DeveloperError(\"sub-region exceeds array bounds.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n byteOffset = defaultValue(byteOffset, 0);\r\n byteLength = defaultValue(byteLength, uint8Array.byteLength - byteOffset);\r\n\r\n uint8Array = uint8Array.subarray(byteOffset, byteOffset + byteLength);\r\n\r\n return getStringFromTypedArray.decode(uint8Array);\r\n}\r\n\r\n// Exposed functions for testing\r\ngetStringFromTypedArray.decodeWithTextDecoder = function (view) {\r\n var decoder = new TextDecoder(\"utf-8\");\r\n return decoder.decode(view);\r\n};\r\n\r\ngetStringFromTypedArray.decodeWithFromCharCode = function (view) {\r\n var result = \"\";\r\n var codePoints = utf8Handler(view);\r\n var length = codePoints.length;\r\n for (var i = 0; i < length; ++i) {\r\n var cp = codePoints[i];\r\n if (cp <= 0xffff) {\r\n result += String.fromCharCode(cp);\r\n } else {\r\n cp -= 0x10000;\r\n result += String.fromCharCode((cp >> 10) + 0xd800, (cp & 0x3ff) + 0xdc00);\r\n }\r\n }\r\n return result;\r\n};\r\n\r\nfunction inRange(a, min, max) {\r\n return min <= a && a <= max;\r\n}\r\n\r\n// This code is inspired by public domain code found here: https://github.com/inexorabletash/text-encoding\r\nfunction utf8Handler(utfBytes) {\r\n var codePoint = 0;\r\n var bytesSeen = 0;\r\n var bytesNeeded = 0;\r\n var lowerBoundary = 0x80;\r\n var upperBoundary = 0xbf;\r\n\r\n var codePoints = [];\r\n var length = utfBytes.length;\r\n for (var i = 0; i < length; ++i) {\r\n var currentByte = utfBytes[i];\r\n\r\n // If bytesNeeded = 0, then we are starting a new character\r\n if (bytesNeeded === 0) {\r\n // 1 Byte Ascii character\r\n if (inRange(currentByte, 0x00, 0x7f)) {\r\n // Return a code point whose value is byte.\r\n codePoints.push(currentByte);\r\n continue;\r\n }\r\n\r\n // 2 Byte character\r\n if (inRange(currentByte, 0xc2, 0xdf)) {\r\n bytesNeeded = 1;\r\n codePoint = currentByte & 0x1f;\r\n continue;\r\n }\r\n\r\n // 3 Byte character\r\n if (inRange(currentByte, 0xe0, 0xef)) {\r\n // If byte is 0xE0, set utf-8 lower boundary to 0xA0.\r\n if (currentByte === 0xe0) {\r\n lowerBoundary = 0xa0;\r\n }\r\n // If byte is 0xED, set utf-8 upper boundary to 0x9F.\r\n if (currentByte === 0xed) {\r\n upperBoundary = 0x9f;\r\n }\r\n\r\n bytesNeeded = 2;\r\n codePoint = currentByte & 0xf;\r\n continue;\r\n }\r\n\r\n // 4 Byte character\r\n if (inRange(currentByte, 0xf0, 0xf4)) {\r\n // If byte is 0xF0, set utf-8 lower boundary to 0x90.\r\n if (currentByte === 0xf0) {\r\n lowerBoundary = 0x90;\r\n }\r\n // If byte is 0xF4, set utf-8 upper boundary to 0x8F.\r\n if (currentByte === 0xf4) {\r\n upperBoundary = 0x8f;\r\n }\r\n\r\n bytesNeeded = 3;\r\n codePoint = currentByte & 0x7;\r\n continue;\r\n }\r\n\r\n throw new RuntimeError(\"String decoding failed.\");\r\n }\r\n\r\n // Out of range, so ignore the first part(s) of the character and continue with this byte on its own\r\n if (!inRange(currentByte, lowerBoundary, upperBoundary)) {\r\n codePoint = bytesNeeded = bytesSeen = 0;\r\n lowerBoundary = 0x80;\r\n upperBoundary = 0xbf;\r\n --i;\r\n continue;\r\n }\r\n\r\n // Set appropriate boundaries, since we've now checked byte 2 of a potential longer character\r\n lowerBoundary = 0x80;\r\n upperBoundary = 0xbf;\r\n\r\n // Add byte to code point\r\n codePoint = (codePoint << 6) | (currentByte & 0x3f);\r\n\r\n // We have the correct number of bytes, so push and reset for next character\r\n ++bytesSeen;\r\n if (bytesSeen === bytesNeeded) {\r\n codePoints.push(codePoint);\r\n codePoint = bytesNeeded = bytesSeen = 0;\r\n }\r\n }\r\n\r\n return codePoints;\r\n}\r\n\r\nif (typeof TextDecoder !== \"undefined\") {\r\n getStringFromTypedArray.decode =\r\n getStringFromTypedArray.decodeWithTextDecoder;\r\n} else {\r\n getStringFromTypedArray.decode =\r\n getStringFromTypedArray.decodeWithFromCharCode;\r\n}\r\nexport default getStringFromTypedArray;\r\n","import getStringFromTypedArray from \"./getStringFromTypedArray.js\";\r\n\r\n/**\r\n * Parses JSON from a Uint8Array.\r\n *\r\n * @function\r\n *\r\n * @param {Uint8Array} uint8Array The Uint8Array to read from.\r\n * @param {Number} [byteOffset=0] The byte offset to start reading from.\r\n * @param {Number} [byteLength] The byte length to read. If byteLength is omitted the remainder of the buffer is read.\r\n * @returns {Object} An object containing the parsed JSON.\r\n *\r\n * @private\r\n */\r\nfunction getJsonFromTypedArray(uint8Array, byteOffset, byteLength) {\r\n return JSON.parse(\r\n getStringFromTypedArray(uint8Array, byteOffset, byteLength)\r\n );\r\n}\r\n\r\nexport default getJsonFromTypedArray;\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Contains functions for operating on 2D triangles.\r\n *\r\n * @namespace Intersections2D\r\n */\r\nvar Intersections2D = {};\r\n\r\n/**\r\n * Splits a 2D triangle at given axis-aligned threshold value and returns the resulting\r\n * polygon on a given side of the threshold. The resulting polygon may have 0, 1, 2,\r\n * 3, or 4 vertices.\r\n *\r\n * @param {Number} threshold The threshold coordinate value at which to clip the triangle.\r\n * @param {Boolean} keepAbove true to keep the portion of the triangle above the threshold, or false\r\n * to keep the portion below.\r\n * @param {Number} u0 The coordinate of the first vertex in the triangle, in counter-clockwise order.\r\n * @param {Number} u1 The coordinate of the second vertex in the triangle, in counter-clockwise order.\r\n * @param {Number} u2 The coordinate of the third vertex in the triangle, in counter-clockwise order.\r\n * @param {Number[]} [result] The array into which to copy the result. If this parameter is not supplied,\r\n * a new array is constructed and returned.\r\n * @returns {Number[]} The polygon that results after the clip, specified as a list of\r\n * vertices. The vertices are specified in counter-clockwise order.\r\n * Each vertex is either an index from the existing list (identified as\r\n * a 0, 1, or 2) or -1 indicating a new vertex not in the original triangle.\r\n * For new vertices, the -1 is followed by three additional numbers: the\r\n * index of each of the two original vertices forming the line segment that\r\n * the new vertex lies on, and the fraction of the distance from the first\r\n * vertex to the second one.\r\n *\r\n * @example\r\n * var result = Cesium.Intersections2D.clipTriangleAtAxisAlignedThreshold(0.5, false, 0.2, 0.6, 0.4);\r\n * // result === [2, 0, -1, 1, 0, 0.25, -1, 1, 2, 0.5]\r\n */\r\nIntersections2D.clipTriangleAtAxisAlignedThreshold = function (\r\n threshold,\r\n keepAbove,\r\n u0,\r\n u1,\r\n u2,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(threshold)) {\r\n throw new DeveloperError(\"threshold is required.\");\r\n }\r\n if (!defined(keepAbove)) {\r\n throw new DeveloperError(\"keepAbove is required.\");\r\n }\r\n if (!defined(u0)) {\r\n throw new DeveloperError(\"u0 is required.\");\r\n }\r\n if (!defined(u1)) {\r\n throw new DeveloperError(\"u1 is required.\");\r\n }\r\n if (!defined(u2)) {\r\n throw new DeveloperError(\"u2 is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = [];\r\n } else {\r\n result.length = 0;\r\n }\r\n\r\n var u0Behind;\r\n var u1Behind;\r\n var u2Behind;\r\n if (keepAbove) {\r\n u0Behind = u0 < threshold;\r\n u1Behind = u1 < threshold;\r\n u2Behind = u2 < threshold;\r\n } else {\r\n u0Behind = u0 > threshold;\r\n u1Behind = u1 > threshold;\r\n u2Behind = u2 > threshold;\r\n }\r\n\r\n var numBehind = u0Behind + u1Behind + u2Behind;\r\n\r\n var u01Ratio;\r\n var u02Ratio;\r\n var u12Ratio;\r\n var u10Ratio;\r\n var u20Ratio;\r\n var u21Ratio;\r\n\r\n if (numBehind === 1) {\r\n if (u0Behind) {\r\n u01Ratio = (threshold - u0) / (u1 - u0);\r\n u02Ratio = (threshold - u0) / (u2 - u0);\r\n\r\n result.push(1);\r\n\r\n result.push(2);\r\n\r\n if (u02Ratio !== 1.0) {\r\n result.push(-1);\r\n result.push(0);\r\n result.push(2);\r\n result.push(u02Ratio);\r\n }\r\n\r\n if (u01Ratio !== 1.0) {\r\n result.push(-1);\r\n result.push(0);\r\n result.push(1);\r\n result.push(u01Ratio);\r\n }\r\n } else if (u1Behind) {\r\n u12Ratio = (threshold - u1) / (u2 - u1);\r\n u10Ratio = (threshold - u1) / (u0 - u1);\r\n\r\n result.push(2);\r\n\r\n result.push(0);\r\n\r\n if (u10Ratio !== 1.0) {\r\n result.push(-1);\r\n result.push(1);\r\n result.push(0);\r\n result.push(u10Ratio);\r\n }\r\n\r\n if (u12Ratio !== 1.0) {\r\n result.push(-1);\r\n result.push(1);\r\n result.push(2);\r\n result.push(u12Ratio);\r\n }\r\n } else if (u2Behind) {\r\n u20Ratio = (threshold - u2) / (u0 - u2);\r\n u21Ratio = (threshold - u2) / (u1 - u2);\r\n\r\n result.push(0);\r\n\r\n result.push(1);\r\n\r\n if (u21Ratio !== 1.0) {\r\n result.push(-1);\r\n result.push(2);\r\n result.push(1);\r\n result.push(u21Ratio);\r\n }\r\n\r\n if (u20Ratio !== 1.0) {\r\n result.push(-1);\r\n result.push(2);\r\n result.push(0);\r\n result.push(u20Ratio);\r\n }\r\n }\r\n } else if (numBehind === 2) {\r\n if (!u0Behind && u0 !== threshold) {\r\n u10Ratio = (threshold - u1) / (u0 - u1);\r\n u20Ratio = (threshold - u2) / (u0 - u2);\r\n\r\n result.push(0);\r\n\r\n result.push(-1);\r\n result.push(1);\r\n result.push(0);\r\n result.push(u10Ratio);\r\n\r\n result.push(-1);\r\n result.push(2);\r\n result.push(0);\r\n result.push(u20Ratio);\r\n } else if (!u1Behind && u1 !== threshold) {\r\n u21Ratio = (threshold - u2) / (u1 - u2);\r\n u01Ratio = (threshold - u0) / (u1 - u0);\r\n\r\n result.push(1);\r\n\r\n result.push(-1);\r\n result.push(2);\r\n result.push(1);\r\n result.push(u21Ratio);\r\n\r\n result.push(-1);\r\n result.push(0);\r\n result.push(1);\r\n result.push(u01Ratio);\r\n } else if (!u2Behind && u2 !== threshold) {\r\n u02Ratio = (threshold - u0) / (u2 - u0);\r\n u12Ratio = (threshold - u1) / (u2 - u1);\r\n\r\n result.push(2);\r\n\r\n result.push(-1);\r\n result.push(0);\r\n result.push(2);\r\n result.push(u02Ratio);\r\n\r\n result.push(-1);\r\n result.push(1);\r\n result.push(2);\r\n result.push(u12Ratio);\r\n }\r\n } else if (numBehind !== 3) {\r\n // Completely in front of threshold\r\n result.push(0);\r\n result.push(1);\r\n result.push(2);\r\n }\r\n // else Completely behind threshold\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compute the barycentric coordinates of a 2D position within a 2D triangle.\r\n *\r\n * @param {Number} x The x coordinate of the position for which to find the barycentric coordinates.\r\n * @param {Number} y The y coordinate of the position for which to find the barycentric coordinates.\r\n * @param {Number} x1 The x coordinate of the triangle's first vertex.\r\n * @param {Number} y1 The y coordinate of the triangle's first vertex.\r\n * @param {Number} x2 The x coordinate of the triangle's second vertex.\r\n * @param {Number} y2 The y coordinate of the triangle's second vertex.\r\n * @param {Number} x3 The x coordinate of the triangle's third vertex.\r\n * @param {Number} y3 The y coordinate of the triangle's third vertex.\r\n * @param {Cartesian3} [result] The instance into to which to copy the result. If this parameter\r\n * is undefined, a new instance is created and returned.\r\n * @returns {Cartesian3} The barycentric coordinates of the position within the triangle.\r\n *\r\n * @example\r\n * var result = Cesium.Intersections2D.computeBarycentricCoordinates(0.0, 0.0, 0.0, 1.0, -1, -0.5, 1, -0.5);\r\n * // result === new Cesium.Cartesian3(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0);\r\n */\r\nIntersections2D.computeBarycentricCoordinates = function (\r\n x,\r\n y,\r\n x1,\r\n y1,\r\n x2,\r\n y2,\r\n x3,\r\n y3,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(x)) {\r\n throw new DeveloperError(\"x is required.\");\r\n }\r\n if (!defined(y)) {\r\n throw new DeveloperError(\"y is required.\");\r\n }\r\n if (!defined(x1)) {\r\n throw new DeveloperError(\"x1 is required.\");\r\n }\r\n if (!defined(y1)) {\r\n throw new DeveloperError(\"y1 is required.\");\r\n }\r\n if (!defined(x2)) {\r\n throw new DeveloperError(\"x2 is required.\");\r\n }\r\n if (!defined(y2)) {\r\n throw new DeveloperError(\"y2 is required.\");\r\n }\r\n if (!defined(x3)) {\r\n throw new DeveloperError(\"x3 is required.\");\r\n }\r\n if (!defined(y3)) {\r\n throw new DeveloperError(\"y3 is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var x1mx3 = x1 - x3;\r\n var x3mx2 = x3 - x2;\r\n var y2my3 = y2 - y3;\r\n var y1my3 = y1 - y3;\r\n var inverseDeterminant = 1.0 / (y2my3 * x1mx3 + x3mx2 * y1my3);\r\n var ymy3 = y - y3;\r\n var xmx3 = x - x3;\r\n var l1 = (y2my3 * xmx3 + x3mx2 * ymy3) * inverseDeterminant;\r\n var l2 = (-y1my3 * xmx3 + x1mx3 * ymy3) * inverseDeterminant;\r\n var l3 = 1.0 - l1 - l2;\r\n\r\n if (defined(result)) {\r\n result.x = l1;\r\n result.y = l2;\r\n result.z = l3;\r\n return result;\r\n }\r\n return new Cartesian3(l1, l2, l3);\r\n};\r\n\r\n/**\r\n * Compute the intersection between 2 line segments\r\n *\r\n * @param {Number} x00 The x coordinate of the first line's first vertex.\r\n * @param {Number} y00 The y coordinate of the first line's first vertex.\r\n * @param {Number} x01 The x coordinate of the first line's second vertex.\r\n * @param {Number} y01 The y coordinate of the first line's second vertex.\r\n * @param {Number} x10 The x coordinate of the second line's first vertex.\r\n * @param {Number} y10 The y coordinate of the second line's first vertex.\r\n * @param {Number} x11 The x coordinate of the second line's second vertex.\r\n * @param {Number} y11 The y coordinate of the second line's second vertex.\r\n * @param {Cartesian2} [result] The instance into to which to copy the result. If this parameter\r\n * is undefined, a new instance is created and returned.\r\n * @returns {Cartesian2} The intersection point, undefined if there is no intersection point or lines are coincident.\r\n *\r\n * @example\r\n * var result = Cesium.Intersections2D.computeLineSegmentLineSegmentIntersection(0.0, 0.0, 0.0, 2.0, -1, 1, 1, 1);\r\n * // result === new Cesium.Cartesian2(0.0, 1.0);\r\n */\r\nIntersections2D.computeLineSegmentLineSegmentIntersection = function (\r\n x00,\r\n y00,\r\n x01,\r\n y01,\r\n x10,\r\n y10,\r\n x11,\r\n y11,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"x00\", x00);\r\n Check.typeOf.number(\"y00\", y00);\r\n Check.typeOf.number(\"x01\", x01);\r\n Check.typeOf.number(\"y01\", y01);\r\n Check.typeOf.number(\"x10\", x10);\r\n Check.typeOf.number(\"y10\", y10);\r\n Check.typeOf.number(\"x11\", x11);\r\n Check.typeOf.number(\"y11\", y11);\r\n //>>includeEnd('debug');\r\n\r\n var numerator1A = (x11 - x10) * (y00 - y10) - (y11 - y10) * (x00 - x10);\r\n var numerator1B = (x01 - x00) * (y00 - y10) - (y01 - y00) * (x00 - x10);\r\n var denominator1 = (y11 - y10) * (x01 - x00) - (x11 - x10) * (y01 - y00);\r\n\r\n // If denominator = 0, then lines are parallel. If denominator = 0 and both numerators are 0, then coincident\r\n if (denominator1 === 0) {\r\n return;\r\n }\r\n\r\n var ua1 = numerator1A / denominator1;\r\n var ub1 = numerator1B / denominator1;\r\n\r\n if (ua1 >= 0 && ua1 <= 1 && ub1 >= 0 && ub1 <= 1) {\r\n if (!defined(result)) {\r\n result = new Cartesian2();\r\n }\r\n\r\n result.x = x00 + ua1 * (x01 - x00);\r\n result.y = y00 + ua1 * (y01 - y00);\r\n\r\n return result;\r\n }\r\n};\r\nexport default Intersections2D;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport Intersections2D from \"./Intersections2D.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport OrientedBoundingBox from \"./OrientedBoundingBox.js\";\r\nimport TaskProcessor from \"./TaskProcessor.js\";\r\nimport TerrainData from \"./TerrainData.js\";\r\nimport TerrainEncoding from \"./TerrainEncoding.js\";\r\nimport TerrainMesh from \"./TerrainMesh.js\";\r\n\r\n/**\r\n * Terrain data for a single tile where the terrain data is represented as a quantized mesh. A quantized\r\n * mesh consists of three vertex attributes, longitude, latitude, and height. All attributes are expressed\r\n * as 16-bit values in the range 0 to 32767. Longitude and latitude are zero at the southwest corner\r\n * of the tile and 32767 at the northeast corner. Height is zero at the minimum height in the tile\r\n * and 32767 at the maximum height in the tile.\r\n *\r\n * @alias QuantizedMeshTerrainData\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Uint16Array} options.quantizedVertices The buffer containing the quantized mesh.\r\n * @param {Uint16Array|Uint32Array} options.indices The indices specifying how the quantized vertices are linked\r\n * together into triangles. Each three indices specifies one triangle.\r\n * @param {Number} options.minimumHeight The minimum terrain height within the tile, in meters above the ellipsoid.\r\n * @param {Number} options.maximumHeight The maximum terrain height within the tile, in meters above the ellipsoid.\r\n * @param {BoundingSphere} options.boundingSphere A sphere bounding all of the vertices in the mesh.\r\n * @param {OrientedBoundingBox} [options.orientedBoundingBox] An OrientedBoundingBox bounding all of the vertices in the mesh.\r\n * @param {Cartesian3} options.horizonOcclusionPoint The horizon occlusion point of the mesh. If this point\r\n * is below the horizon, the entire tile is assumed to be below the horizon as well.\r\n * The point is expressed in ellipsoid-scaled coordinates.\r\n * @param {Number[]} options.westIndices The indices of the vertices on the western edge of the tile.\r\n * @param {Number[]} options.southIndices The indices of the vertices on the southern edge of the tile.\r\n * @param {Number[]} options.eastIndices The indices of the vertices on the eastern edge of the tile.\r\n * @param {Number[]} options.northIndices The indices of the vertices on the northern edge of the tile.\r\n * @param {Number} options.westSkirtHeight The height of the skirt to add on the western edge of the tile.\r\n * @param {Number} options.southSkirtHeight The height of the skirt to add on the southern edge of the tile.\r\n * @param {Number} options.eastSkirtHeight The height of the skirt to add on the eastern edge of the tile.\r\n * @param {Number} options.northSkirtHeight The height of the skirt to add on the northern edge of the tile.\r\n * @param {Number} [options.childTileMask=15] A bit mask indicating which of this tile's four children exist.\r\n * If a child's bit is set, geometry will be requested for that tile as well when it\r\n * is needed. If the bit is cleared, the child tile is not requested and geometry is\r\n * instead upsampled from the parent. The bit values are as follows:\r\n * \r\n * \r\n * \r\n * \r\n * \r\n * \r\n *
Bit PositionBit ValueChild Tile
01Southwest
12Southeast
24Northwest
38Northeast
\r\n * @param {Boolean} [options.createdByUpsampling=false] True if this instance was created by upsampling another instance;\r\n * otherwise, false.\r\n * @param {Uint8Array} [options.encodedNormals] The buffer containing per vertex normals, encoded using 'oct' encoding\r\n * @param {Uint8Array} [options.waterMask] The buffer containing the watermask.\r\n * @param {Credit[]} [options.credits] Array of credits for this tile.\r\n *\r\n *\r\n * @example\r\n * var data = new Cesium.QuantizedMeshTerrainData({\r\n * minimumHeight : -100,\r\n * maximumHeight : 2101,\r\n * quantizedVertices : new Uint16Array([// order is SW NW SE NE\r\n * // longitude\r\n * 0, 0, 32767, 32767,\r\n * // latitude\r\n * 0, 32767, 0, 32767,\r\n * // heights\r\n * 16384, 0, 32767, 16384]),\r\n * indices : new Uint16Array([0, 3, 1,\r\n * 0, 2, 3]),\r\n * boundingSphere : new Cesium.BoundingSphere(new Cesium.Cartesian3(1.0, 2.0, 3.0), 10000),\r\n * orientedBoundingBox : new Cesium.OrientedBoundingBox(new Cesium.Cartesian3(1.0, 2.0, 3.0), Cesium.Matrix3.fromRotationX(Cesium.Math.PI, new Cesium.Matrix3())),\r\n * horizonOcclusionPoint : new Cesium.Cartesian3(3.0, 2.0, 1.0),\r\n * westIndices : [0, 1],\r\n * southIndices : [0, 1],\r\n * eastIndices : [2, 3],\r\n * northIndices : [1, 3],\r\n * westSkirtHeight : 1.0,\r\n * southSkirtHeight : 1.0,\r\n * eastSkirtHeight : 1.0,\r\n * northSkirtHeight : 1.0\r\n * });\r\n *\r\n * @see TerrainData\r\n * @see HeightmapTerrainData\r\n * @see GoogleEarthEnterpriseTerrainData\r\n */\r\nfunction QuantizedMeshTerrainData(options) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!defined(options) || !defined(options.quantizedVertices)) {\r\n throw new DeveloperError(\"options.quantizedVertices is required.\");\r\n }\r\n if (!defined(options.indices)) {\r\n throw new DeveloperError(\"options.indices is required.\");\r\n }\r\n if (!defined(options.minimumHeight)) {\r\n throw new DeveloperError(\"options.minimumHeight is required.\");\r\n }\r\n if (!defined(options.maximumHeight)) {\r\n throw new DeveloperError(\"options.maximumHeight is required.\");\r\n }\r\n if (!defined(options.maximumHeight)) {\r\n throw new DeveloperError(\"options.maximumHeight is required.\");\r\n }\r\n if (!defined(options.boundingSphere)) {\r\n throw new DeveloperError(\"options.boundingSphere is required.\");\r\n }\r\n if (!defined(options.horizonOcclusionPoint)) {\r\n throw new DeveloperError(\"options.horizonOcclusionPoint is required.\");\r\n }\r\n if (!defined(options.westIndices)) {\r\n throw new DeveloperError(\"options.westIndices is required.\");\r\n }\r\n if (!defined(options.southIndices)) {\r\n throw new DeveloperError(\"options.southIndices is required.\");\r\n }\r\n if (!defined(options.eastIndices)) {\r\n throw new DeveloperError(\"options.eastIndices is required.\");\r\n }\r\n if (!defined(options.northIndices)) {\r\n throw new DeveloperError(\"options.northIndices is required.\");\r\n }\r\n if (!defined(options.westSkirtHeight)) {\r\n throw new DeveloperError(\"options.westSkirtHeight is required.\");\r\n }\r\n if (!defined(options.southSkirtHeight)) {\r\n throw new DeveloperError(\"options.southSkirtHeight is required.\");\r\n }\r\n if (!defined(options.eastSkirtHeight)) {\r\n throw new DeveloperError(\"options.eastSkirtHeight is required.\");\r\n }\r\n if (!defined(options.northSkirtHeight)) {\r\n throw new DeveloperError(\"options.northSkirtHeight is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._quantizedVertices = options.quantizedVertices;\r\n this._encodedNormals = options.encodedNormals;\r\n this._indices = options.indices;\r\n this._minimumHeight = options.minimumHeight;\r\n this._maximumHeight = options.maximumHeight;\r\n this._boundingSphere = options.boundingSphere;\r\n this._orientedBoundingBox = options.orientedBoundingBox;\r\n this._horizonOcclusionPoint = options.horizonOcclusionPoint;\r\n this._credits = options.credits;\r\n\r\n var vertexCount = this._quantizedVertices.length / 3;\r\n var uValues = (this._uValues = this._quantizedVertices.subarray(\r\n 0,\r\n vertexCount\r\n ));\r\n var vValues = (this._vValues = this._quantizedVertices.subarray(\r\n vertexCount,\r\n 2 * vertexCount\r\n ));\r\n this._heightValues = this._quantizedVertices.subarray(\r\n 2 * vertexCount,\r\n 3 * vertexCount\r\n );\r\n\r\n // We don't assume that we can count on the edge vertices being sorted by u or v.\r\n function sortByV(a, b) {\r\n return vValues[a] - vValues[b];\r\n }\r\n\r\n function sortByU(a, b) {\r\n return uValues[a] - uValues[b];\r\n }\r\n\r\n this._westIndices = sortIndicesIfNecessary(\r\n options.westIndices,\r\n sortByV,\r\n vertexCount\r\n );\r\n this._southIndices = sortIndicesIfNecessary(\r\n options.southIndices,\r\n sortByU,\r\n vertexCount\r\n );\r\n this._eastIndices = sortIndicesIfNecessary(\r\n options.eastIndices,\r\n sortByV,\r\n vertexCount\r\n );\r\n this._northIndices = sortIndicesIfNecessary(\r\n options.northIndices,\r\n sortByU,\r\n vertexCount\r\n );\r\n\r\n this._westSkirtHeight = options.westSkirtHeight;\r\n this._southSkirtHeight = options.southSkirtHeight;\r\n this._eastSkirtHeight = options.eastSkirtHeight;\r\n this._northSkirtHeight = options.northSkirtHeight;\r\n\r\n this._childTileMask = defaultValue(options.childTileMask, 15);\r\n\r\n this._createdByUpsampling = defaultValue(options.createdByUpsampling, false);\r\n this._waterMask = options.waterMask;\r\n\r\n this._mesh = undefined;\r\n}\r\n\r\nObject.defineProperties(QuantizedMeshTerrainData.prototype, {\r\n /**\r\n * An array of credits for this tile.\r\n * @memberof QuantizedMeshTerrainData.prototype\r\n * @type {Credit[]}\r\n */\r\n credits: {\r\n get: function () {\r\n return this._credits;\r\n },\r\n },\r\n /**\r\n * The water mask included in this terrain data, if any. A water mask is a rectangular\r\n * Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.\r\n * Values in between 0 and 255 are allowed as well to smoothly blend between land and water.\r\n * @memberof QuantizedMeshTerrainData.prototype\r\n * @type {Uint8Array|HTMLImageElement|HTMLCanvasElement}\r\n */\r\n waterMask: {\r\n get: function () {\r\n return this._waterMask;\r\n },\r\n },\r\n\r\n childTileMask: {\r\n get: function () {\r\n return this._childTileMask;\r\n },\r\n },\r\n\r\n canUpsample: {\r\n get: function () {\r\n return defined(this._mesh);\r\n },\r\n },\r\n});\r\n\r\nvar arrayScratch = [];\r\n\r\nfunction sortIndicesIfNecessary(indices, sortFunction, vertexCount) {\r\n arrayScratch.length = indices.length;\r\n\r\n var needsSort = false;\r\n for (var i = 0, len = indices.length; i < len; ++i) {\r\n arrayScratch[i] = indices[i];\r\n needsSort =\r\n needsSort || (i > 0 && sortFunction(indices[i - 1], indices[i]) > 0);\r\n }\r\n\r\n if (needsSort) {\r\n arrayScratch.sort(sortFunction);\r\n return IndexDatatype.createTypedArray(vertexCount, arrayScratch);\r\n }\r\n return indices;\r\n}\r\n\r\nvar createMeshTaskName = \"createVerticesFromQuantizedTerrainMesh\";\r\nvar createMeshTaskProcessorNoThrottle = new TaskProcessor(createMeshTaskName);\r\nvar createMeshTaskProcessorThrottle = new TaskProcessor(\r\n createMeshTaskName,\r\n TerrainData.maximumAsynchronousTasks\r\n);\r\n\r\n/**\r\n * Creates a {@link TerrainMesh} from this terrain data.\r\n *\r\n * @private\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {TilingScheme} options.tilingScheme The tiling scheme to which this tile belongs.\r\n * @param {Number} options.x The X coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.y The Y coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.level The level of the tile for which to create the terrain data.\r\n * @param {Number} [options.exaggeration=1.0] The scale used to exaggerate the terrain.\r\n * @param {Boolean} [options.throttle=true] If true, indicates that this operation will need to be retried if too many asynchronous mesh creations are already in progress.\r\n * @returns {Promise.|undefined} A promise for the terrain mesh, or undefined if too many\r\n * asynchronous mesh creations are already in progress and the operation should\r\n * be retried later.\r\n */\r\nQuantizedMeshTerrainData.prototype.createMesh = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options.tilingScheme\", options.tilingScheme);\r\n Check.typeOf.number(\"options.x\", options.x);\r\n Check.typeOf.number(\"options.y\", options.y);\r\n Check.typeOf.number(\"options.level\", options.level);\r\n //>>includeEnd('debug');\r\n\r\n var tilingScheme = options.tilingScheme;\r\n var x = options.x;\r\n var y = options.y;\r\n var level = options.level;\r\n var exaggeration = defaultValue(options.exaggeration, 1.0);\r\n var throttle = defaultValue(options.throttle, true);\r\n\r\n var ellipsoid = tilingScheme.ellipsoid;\r\n var rectangle = tilingScheme.tileXYToRectangle(x, y, level);\r\n\r\n var createMeshTaskProcessor = throttle\r\n ? createMeshTaskProcessorThrottle\r\n : createMeshTaskProcessorNoThrottle;\r\n\r\n var verticesPromise = createMeshTaskProcessor.scheduleTask({\r\n minimumHeight: this._minimumHeight,\r\n maximumHeight: this._maximumHeight,\r\n quantizedVertices: this._quantizedVertices,\r\n octEncodedNormals: this._encodedNormals,\r\n includeWebMercatorT: true,\r\n indices: this._indices,\r\n westIndices: this._westIndices,\r\n southIndices: this._southIndices,\r\n eastIndices: this._eastIndices,\r\n northIndices: this._northIndices,\r\n westSkirtHeight: this._westSkirtHeight,\r\n southSkirtHeight: this._southSkirtHeight,\r\n eastSkirtHeight: this._eastSkirtHeight,\r\n northSkirtHeight: this._northSkirtHeight,\r\n rectangle: rectangle,\r\n relativeToCenter: this._boundingSphere.center,\r\n ellipsoid: ellipsoid,\r\n exaggeration: exaggeration,\r\n });\r\n\r\n if (!defined(verticesPromise)) {\r\n // Postponed\r\n return undefined;\r\n }\r\n\r\n var that = this;\r\n return when(verticesPromise, function (result) {\r\n var vertexCountWithoutSkirts = that._quantizedVertices.length / 3;\r\n var vertexCount =\r\n vertexCountWithoutSkirts +\r\n that._westIndices.length +\r\n that._southIndices.length +\r\n that._eastIndices.length +\r\n that._northIndices.length;\r\n var indicesTypedArray = IndexDatatype.createTypedArray(\r\n vertexCount,\r\n result.indices\r\n );\r\n\r\n var vertices = new Float32Array(result.vertices);\r\n var rtc = result.center;\r\n var minimumHeight = result.minimumHeight;\r\n var maximumHeight = result.maximumHeight;\r\n var boundingSphere = defaultValue(\r\n BoundingSphere.clone(result.boundingSphere),\r\n that._boundingSphere\r\n );\r\n var obb = defaultValue(\r\n OrientedBoundingBox.clone(result.orientedBoundingBox),\r\n that._orientedBoundingBox\r\n );\r\n var occludeePointInScaledSpace = defaultValue(\r\n Cartesian3.clone(result.occludeePointInScaledSpace),\r\n that._horizonOcclusionPoint\r\n );\r\n var stride = result.vertexStride;\r\n var terrainEncoding = TerrainEncoding.clone(result.encoding);\r\n\r\n // Clone complex result objects because the transfer from the web worker\r\n // has stripped them down to JSON-style objects.\r\n that._mesh = new TerrainMesh(\r\n rtc,\r\n vertices,\r\n indicesTypedArray,\r\n result.indexCountWithoutSkirts,\r\n vertexCountWithoutSkirts,\r\n minimumHeight,\r\n maximumHeight,\r\n boundingSphere,\r\n occludeePointInScaledSpace,\r\n stride,\r\n obb,\r\n terrainEncoding,\r\n exaggeration,\r\n result.westIndicesSouthToNorth,\r\n result.southIndicesEastToWest,\r\n result.eastIndicesNorthToSouth,\r\n result.northIndicesWestToEast\r\n );\r\n\r\n // Free memory received from server after mesh is created.\r\n that._quantizedVertices = undefined;\r\n that._encodedNormals = undefined;\r\n that._indices = undefined;\r\n\r\n that._uValues = undefined;\r\n that._vValues = undefined;\r\n that._heightValues = undefined;\r\n\r\n that._westIndices = undefined;\r\n that._southIndices = undefined;\r\n that._eastIndices = undefined;\r\n that._northIndices = undefined;\r\n\r\n return that._mesh;\r\n });\r\n};\r\n\r\nvar upsampleTaskProcessor = new TaskProcessor(\r\n \"upsampleQuantizedTerrainMesh\",\r\n TerrainData.maximumAsynchronousTasks\r\n);\r\n\r\n/**\r\n * Upsamples this terrain data for use by a descendant tile. The resulting instance will contain a subset of the\r\n * vertices in this instance, interpolated if necessary.\r\n *\r\n * @param {TilingScheme} tilingScheme The tiling scheme of this terrain data.\r\n * @param {Number} thisX The X coordinate of this tile in the tiling scheme.\r\n * @param {Number} thisY The Y coordinate of this tile in the tiling scheme.\r\n * @param {Number} thisLevel The level of this tile in the tiling scheme.\r\n * @param {Number} descendantX The X coordinate within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @param {Number} descendantY The Y coordinate within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @param {Number} descendantLevel The level within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @returns {Promise.|undefined} A promise for upsampled heightmap terrain data for the descendant tile,\r\n * or undefined if too many asynchronous upsample operations are in progress and the request has been\r\n * deferred.\r\n */\r\nQuantizedMeshTerrainData.prototype.upsample = function (\r\n tilingScheme,\r\n thisX,\r\n thisY,\r\n thisLevel,\r\n descendantX,\r\n descendantY,\r\n descendantLevel\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(tilingScheme)) {\r\n throw new DeveloperError(\"tilingScheme is required.\");\r\n }\r\n if (!defined(thisX)) {\r\n throw new DeveloperError(\"thisX is required.\");\r\n }\r\n if (!defined(thisY)) {\r\n throw new DeveloperError(\"thisY is required.\");\r\n }\r\n if (!defined(thisLevel)) {\r\n throw new DeveloperError(\"thisLevel is required.\");\r\n }\r\n if (!defined(descendantX)) {\r\n throw new DeveloperError(\"descendantX is required.\");\r\n }\r\n if (!defined(descendantY)) {\r\n throw new DeveloperError(\"descendantY is required.\");\r\n }\r\n if (!defined(descendantLevel)) {\r\n throw new DeveloperError(\"descendantLevel is required.\");\r\n }\r\n var levelDifference = descendantLevel - thisLevel;\r\n if (levelDifference > 1) {\r\n throw new DeveloperError(\r\n \"Upsampling through more than one level at a time is not currently supported.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var mesh = this._mesh;\r\n if (!defined(this._mesh)) {\r\n return undefined;\r\n }\r\n\r\n var isEastChild = thisX * 2 !== descendantX;\r\n var isNorthChild = thisY * 2 === descendantY;\r\n\r\n var ellipsoid = tilingScheme.ellipsoid;\r\n var childRectangle = tilingScheme.tileXYToRectangle(\r\n descendantX,\r\n descendantY,\r\n descendantLevel\r\n );\r\n\r\n var upsamplePromise = upsampleTaskProcessor.scheduleTask({\r\n vertices: mesh.vertices,\r\n vertexCountWithoutSkirts: mesh.vertexCountWithoutSkirts,\r\n indices: mesh.indices,\r\n indexCountWithoutSkirts: mesh.indexCountWithoutSkirts,\r\n encoding: mesh.encoding,\r\n minimumHeight: this._minimumHeight,\r\n maximumHeight: this._maximumHeight,\r\n isEastChild: isEastChild,\r\n isNorthChild: isNorthChild,\r\n childRectangle: childRectangle,\r\n ellipsoid: ellipsoid,\r\n exaggeration: mesh.exaggeration,\r\n });\r\n\r\n if (!defined(upsamplePromise)) {\r\n // Postponed\r\n return undefined;\r\n }\r\n\r\n var shortestSkirt = Math.min(this._westSkirtHeight, this._eastSkirtHeight);\r\n shortestSkirt = Math.min(shortestSkirt, this._southSkirtHeight);\r\n shortestSkirt = Math.min(shortestSkirt, this._northSkirtHeight);\r\n\r\n var westSkirtHeight = isEastChild\r\n ? shortestSkirt * 0.5\r\n : this._westSkirtHeight;\r\n var southSkirtHeight = isNorthChild\r\n ? shortestSkirt * 0.5\r\n : this._southSkirtHeight;\r\n var eastSkirtHeight = isEastChild\r\n ? this._eastSkirtHeight\r\n : shortestSkirt * 0.5;\r\n var northSkirtHeight = isNorthChild\r\n ? this._northSkirtHeight\r\n : shortestSkirt * 0.5;\r\n var credits = this._credits;\r\n\r\n return when(upsamplePromise).then(function (result) {\r\n var quantizedVertices = new Uint16Array(result.vertices);\r\n var indicesTypedArray = IndexDatatype.createTypedArray(\r\n quantizedVertices.length / 3,\r\n result.indices\r\n );\r\n var encodedNormals;\r\n if (defined(result.encodedNormals)) {\r\n encodedNormals = new Uint8Array(result.encodedNormals);\r\n }\r\n\r\n return new QuantizedMeshTerrainData({\r\n quantizedVertices: quantizedVertices,\r\n indices: indicesTypedArray,\r\n encodedNormals: encodedNormals,\r\n minimumHeight: result.minimumHeight,\r\n maximumHeight: result.maximumHeight,\r\n boundingSphere: BoundingSphere.clone(result.boundingSphere),\r\n orientedBoundingBox: OrientedBoundingBox.clone(\r\n result.orientedBoundingBox\r\n ),\r\n horizonOcclusionPoint: Cartesian3.clone(result.horizonOcclusionPoint),\r\n westIndices: result.westIndices,\r\n southIndices: result.southIndices,\r\n eastIndices: result.eastIndices,\r\n northIndices: result.northIndices,\r\n westSkirtHeight: westSkirtHeight,\r\n southSkirtHeight: southSkirtHeight,\r\n eastSkirtHeight: eastSkirtHeight,\r\n northSkirtHeight: northSkirtHeight,\r\n childTileMask: 0,\r\n credits: credits,\r\n createdByUpsampling: true,\r\n });\r\n });\r\n};\r\n\r\nvar maxShort = 32767;\r\nvar barycentricCoordinateScratch = new Cartesian3();\r\n\r\n/**\r\n * Computes the terrain height at a specified longitude and latitude.\r\n *\r\n * @param {Rectangle} rectangle The rectangle covered by this terrain data.\r\n * @param {Number} longitude The longitude in radians.\r\n * @param {Number} latitude The latitude in radians.\r\n * @returns {Number} The terrain height at the specified position. The position is clamped to\r\n * the rectangle, so expect incorrect results for positions far outside the rectangle.\r\n */\r\nQuantizedMeshTerrainData.prototype.interpolateHeight = function (\r\n rectangle,\r\n longitude,\r\n latitude\r\n) {\r\n var u = CesiumMath.clamp(\r\n (longitude - rectangle.west) / rectangle.width,\r\n 0.0,\r\n 1.0\r\n );\r\n u *= maxShort;\r\n var v = CesiumMath.clamp(\r\n (latitude - rectangle.south) / rectangle.height,\r\n 0.0,\r\n 1.0\r\n );\r\n v *= maxShort;\r\n\r\n if (!defined(this._mesh)) {\r\n return interpolateHeight(this, u, v);\r\n }\r\n\r\n return interpolateMeshHeight(this, u, v);\r\n};\r\n\r\nfunction pointInBoundingBox(u, v, u0, v0, u1, v1, u2, v2) {\r\n var minU = Math.min(u0, u1, u2);\r\n var maxU = Math.max(u0, u1, u2);\r\n var minV = Math.min(v0, v1, v2);\r\n var maxV = Math.max(v0, v1, v2);\r\n return u >= minU && u <= maxU && v >= minV && v <= maxV;\r\n}\r\n\r\nvar texCoordScratch0 = new Cartesian2();\r\nvar texCoordScratch1 = new Cartesian2();\r\nvar texCoordScratch2 = new Cartesian2();\r\n\r\nfunction interpolateMeshHeight(terrainData, u, v) {\r\n var mesh = terrainData._mesh;\r\n var vertices = mesh.vertices;\r\n var encoding = mesh.encoding;\r\n var indices = mesh.indices;\r\n\r\n for (var i = 0, len = indices.length; i < len; i += 3) {\r\n var i0 = indices[i];\r\n var i1 = indices[i + 1];\r\n var i2 = indices[i + 2];\r\n\r\n var uv0 = encoding.decodeTextureCoordinates(vertices, i0, texCoordScratch0);\r\n var uv1 = encoding.decodeTextureCoordinates(vertices, i1, texCoordScratch1);\r\n var uv2 = encoding.decodeTextureCoordinates(vertices, i2, texCoordScratch2);\r\n\r\n if (pointInBoundingBox(u, v, uv0.x, uv0.y, uv1.x, uv1.y, uv2.x, uv2.y)) {\r\n var barycentric = Intersections2D.computeBarycentricCoordinates(\r\n u,\r\n v,\r\n uv0.x,\r\n uv0.y,\r\n uv1.x,\r\n uv1.y,\r\n uv2.x,\r\n uv2.y,\r\n barycentricCoordinateScratch\r\n );\r\n if (\r\n barycentric.x >= -1e-15 &&\r\n barycentric.y >= -1e-15 &&\r\n barycentric.z >= -1e-15\r\n ) {\r\n var h0 = encoding.decodeHeight(vertices, i0);\r\n var h1 = encoding.decodeHeight(vertices, i1);\r\n var h2 = encoding.decodeHeight(vertices, i2);\r\n return barycentric.x * h0 + barycentric.y * h1 + barycentric.z * h2;\r\n }\r\n }\r\n }\r\n\r\n // Position does not lie in any triangle in this mesh.\r\n return undefined;\r\n}\r\n\r\nfunction interpolateHeight(terrainData, u, v) {\r\n var uBuffer = terrainData._uValues;\r\n var vBuffer = terrainData._vValues;\r\n var heightBuffer = terrainData._heightValues;\r\n\r\n var indices = terrainData._indices;\r\n for (var i = 0, len = indices.length; i < len; i += 3) {\r\n var i0 = indices[i];\r\n var i1 = indices[i + 1];\r\n var i2 = indices[i + 2];\r\n\r\n var u0 = uBuffer[i0];\r\n var u1 = uBuffer[i1];\r\n var u2 = uBuffer[i2];\r\n\r\n var v0 = vBuffer[i0];\r\n var v1 = vBuffer[i1];\r\n var v2 = vBuffer[i2];\r\n\r\n if (pointInBoundingBox(u, v, u0, v0, u1, v1, u2, v2)) {\r\n var barycentric = Intersections2D.computeBarycentricCoordinates(\r\n u,\r\n v,\r\n u0,\r\n v0,\r\n u1,\r\n v1,\r\n u2,\r\n v2,\r\n barycentricCoordinateScratch\r\n );\r\n if (\r\n barycentric.x >= -1e-15 &&\r\n barycentric.y >= -1e-15 &&\r\n barycentric.z >= -1e-15\r\n ) {\r\n var quantizedHeight =\r\n barycentric.x * heightBuffer[i0] +\r\n barycentric.y * heightBuffer[i1] +\r\n barycentric.z * heightBuffer[i2];\r\n return CesiumMath.lerp(\r\n terrainData._minimumHeight,\r\n terrainData._maximumHeight,\r\n quantizedHeight / maxShort\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Position does not lie in any triangle in this mesh.\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Determines if a given child tile is available, based on the\r\n * {@link HeightmapTerrainData.childTileMask}. The given child tile coordinates are assumed\r\n * to be one of the four children of this tile. If non-child tile coordinates are\r\n * given, the availability of the southeast child tile is returned.\r\n *\r\n * @param {Number} thisX The tile X coordinate of this (the parent) tile.\r\n * @param {Number} thisY The tile Y coordinate of this (the parent) tile.\r\n * @param {Number} childX The tile X coordinate of the child tile to check for availability.\r\n * @param {Number} childY The tile Y coordinate of the child tile to check for availability.\r\n * @returns {Boolean} True if the child tile is available; otherwise, false.\r\n */\r\nQuantizedMeshTerrainData.prototype.isChildAvailable = function (\r\n thisX,\r\n thisY,\r\n childX,\r\n childY\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(thisX)) {\r\n throw new DeveloperError(\"thisX is required.\");\r\n }\r\n if (!defined(thisY)) {\r\n throw new DeveloperError(\"thisY is required.\");\r\n }\r\n if (!defined(childX)) {\r\n throw new DeveloperError(\"childX is required.\");\r\n }\r\n if (!defined(childY)) {\r\n throw new DeveloperError(\"childY is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var bitNumber = 2; // northwest child\r\n if (childX !== thisX * 2) {\r\n ++bitNumber; // east child\r\n }\r\n if (childY !== thisY * 2) {\r\n bitNumber -= 2; // south child\r\n }\r\n\r\n return (this._childTileMask & (1 << bitNumber)) !== 0;\r\n};\r\n\r\n/**\r\n * Gets a value indicating whether or not this terrain data was created by upsampling lower resolution\r\n * terrain data. If this value is false, the data was obtained from some other source, such\r\n * as by downloading it from a remote server. This method should return true for instances\r\n * returned from a call to {@link HeightmapTerrainData#upsample}.\r\n *\r\n * @returns {Boolean} True if this instance was created by upsampling; otherwise, false.\r\n */\r\nQuantizedMeshTerrainData.prototype.wasCreatedByUpsampling = function () {\r\n return this._createdByUpsampling;\r\n};\r\nexport default QuantizedMeshTerrainData;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport AttributeCompression from \"./AttributeCompression.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Credit from \"./Credit.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Event from \"./Event.js\";\r\nimport GeographicTilingScheme from \"./GeographicTilingScheme.js\";\r\nimport WebMercatorTilingScheme from \"./WebMercatorTilingScheme.js\";\r\nimport getJsonFromTypedArray from \"./getJsonFromTypedArray.js\";\r\nimport HeightmapTerrainData from \"./HeightmapTerrainData.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport OrientedBoundingBox from \"./OrientedBoundingBox.js\";\r\nimport QuantizedMeshTerrainData from \"./QuantizedMeshTerrainData.js\";\r\nimport Request from \"./Request.js\";\r\nimport RequestType from \"./RequestType.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\nimport TerrainProvider from \"./TerrainProvider.js\";\r\nimport TileAvailability from \"./TileAvailability.js\";\r\nimport TileProviderError from \"./TileProviderError.js\";\r\n\r\nfunction LayerInformation(layer) {\r\n this.resource = layer.resource;\r\n this.version = layer.version;\r\n this.isHeightmap = layer.isHeightmap;\r\n this.tileUrlTemplates = layer.tileUrlTemplates;\r\n this.availability = layer.availability;\r\n this.hasVertexNormals = layer.hasVertexNormals;\r\n this.hasWaterMask = layer.hasWaterMask;\r\n this.hasMetadata = layer.hasMetadata;\r\n this.availabilityLevels = layer.availabilityLevels;\r\n this.availabilityTilesLoaded = layer.availabilityTilesLoaded;\r\n this.littleEndianExtensionSize = layer.littleEndianExtensionSize;\r\n this.availabilityPromiseCache = {};\r\n}\r\n\r\n/**\r\n * A {@link TerrainProvider} that accesses terrain data in a Cesium terrain format.\r\n *\r\n * @alias CesiumTerrainProvider\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Resource|String|Promise|Promise} options.url The URL of the Cesium terrain server.\r\n * @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available.\r\n * @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server, if available.\r\n * @param {Boolean} [options.requestMetadata=true] Flag that indicates if the client should request per tile metadata from the server, if available.\r\n * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used.\r\n * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas.\r\n *\r\n *\r\n * @example\r\n * // Create Arctic DEM terrain with normals.\r\n * var viewer = new Cesium.Viewer('cesiumContainer', {\r\n * terrainProvider : new Cesium.CesiumTerrainProvider({\r\n * url : Cesium.IonResource.fromAssetId(3956),\r\n * requestVertexNormals : true\r\n * })\r\n * });\r\n *\r\n * @see createWorldTerrain\r\n * @see TerrainProvider\r\n */\r\nfunction CesiumTerrainProvider(options) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!defined(options) || !defined(options.url)) {\r\n throw new DeveloperError(\"options.url is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._heightmapWidth = 65;\r\n this._heightmapStructure = undefined;\r\n this._hasWaterMask = false;\r\n this._hasVertexNormals = false;\r\n this._ellipsoid = options.ellipsoid;\r\n\r\n /**\r\n * Boolean flag that indicates if the client should request vertex normals from the server.\r\n * @type {Boolean}\r\n * @default false\r\n * @private\r\n */\r\n this._requestVertexNormals = defaultValue(\r\n options.requestVertexNormals,\r\n false\r\n );\r\n\r\n /**\r\n * Boolean flag that indicates if the client should request tile watermasks from the server.\r\n * @type {Boolean}\r\n * @default false\r\n * @private\r\n */\r\n this._requestWaterMask = defaultValue(options.requestWaterMask, false);\r\n\r\n /**\r\n * Boolean flag that indicates if the client should request tile metadata from the server.\r\n * @type {Boolean}\r\n * @default true\r\n * @private\r\n */\r\n this._requestMetadata = defaultValue(options.requestMetadata, true);\r\n\r\n this._errorEvent = new Event();\r\n\r\n var credit = options.credit;\r\n if (typeof credit === \"string\") {\r\n credit = new Credit(credit);\r\n }\r\n this._credit = credit;\r\n\r\n this._availability = undefined;\r\n\r\n var deferred = when.defer();\r\n this._ready = false;\r\n this._readyPromise = deferred;\r\n this._tileCredits = undefined;\r\n\r\n var that = this;\r\n var lastResource;\r\n var layerJsonResource;\r\n var metadataError;\r\n\r\n var layers = (this._layers = []);\r\n var attribution = \"\";\r\n var overallAvailability = [];\r\n var overallMaxZoom = 0;\r\n when(options.url)\r\n .then(function (url) {\r\n var resource = Resource.createIfNeeded(url);\r\n resource.appendForwardSlash();\r\n lastResource = resource;\r\n layerJsonResource = lastResource.getDerivedResource({\r\n url: \"layer.json\",\r\n });\r\n\r\n // ion resources have a credits property we can use for additional attribution.\r\n that._tileCredits = resource.credits;\r\n\r\n requestLayerJson();\r\n })\r\n .otherwise(function (e) {\r\n deferred.reject(e);\r\n });\r\n\r\n function parseMetadataSuccess(data) {\r\n var message;\r\n\r\n if (!data.format) {\r\n message = \"The tile format is not specified in the layer.json file.\";\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n requestLayerJson\r\n );\r\n return;\r\n }\r\n\r\n if (!data.tiles || data.tiles.length === 0) {\r\n message = \"The layer.json file does not specify any tile URL templates.\";\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n requestLayerJson\r\n );\r\n return;\r\n }\r\n\r\n var hasVertexNormals = false;\r\n var hasWaterMask = false;\r\n var hasMetadata = false;\r\n var littleEndianExtensionSize = true;\r\n var isHeightmap = false;\r\n if (data.format === \"heightmap-1.0\") {\r\n isHeightmap = true;\r\n if (!defined(that._heightmapStructure)) {\r\n that._heightmapStructure = {\r\n heightScale: 1.0 / 5.0,\r\n heightOffset: -1000.0,\r\n elementsPerHeight: 1,\r\n stride: 1,\r\n elementMultiplier: 256.0,\r\n isBigEndian: false,\r\n lowestEncodedHeight: 0,\r\n highestEncodedHeight: 256 * 256 - 1,\r\n };\r\n }\r\n hasWaterMask = true;\r\n that._requestWaterMask = true;\r\n } else if (data.format.indexOf(\"quantized-mesh-1.\") !== 0) {\r\n message =\r\n 'The tile format \"' + data.format + '\" is invalid or not supported.';\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n requestLayerJson\r\n );\r\n return;\r\n }\r\n\r\n var tileUrlTemplates = data.tiles;\r\n\r\n var maxZoom = data.maxzoom;\r\n overallMaxZoom = Math.max(overallMaxZoom, maxZoom);\r\n // Keeps track of which of the availablity containing tiles have been loaded\r\n\r\n if (!data.projection || data.projection === \"EPSG:4326\") {\r\n that._tilingScheme = new GeographicTilingScheme({\r\n numberOfLevelZeroTilesX: 2,\r\n numberOfLevelZeroTilesY: 1,\r\n ellipsoid: that._ellipsoid,\r\n });\r\n } else if (data.projection === \"EPSG:3857\") {\r\n that._tilingScheme = new WebMercatorTilingScheme({\r\n numberOfLevelZeroTilesX: 1,\r\n numberOfLevelZeroTilesY: 1,\r\n ellipsoid: that._ellipsoid,\r\n });\r\n } else {\r\n message =\r\n 'The projection \"' + data.projection + '\" is invalid or not supported.';\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n requestLayerJson\r\n );\r\n return;\r\n }\r\n\r\n that._levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(\r\n that._tilingScheme.ellipsoid,\r\n that._heightmapWidth,\r\n that._tilingScheme.getNumberOfXTilesAtLevel(0)\r\n );\r\n if (!data.scheme || data.scheme === \"tms\" || data.scheme === \"slippyMap\") {\r\n that._scheme = data.scheme;\r\n } else {\r\n message = 'The scheme \"' + data.scheme + '\" is invalid or not supported.';\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n requestLayerJson\r\n );\r\n return;\r\n }\r\n\r\n var availabilityTilesLoaded;\r\n\r\n // The vertex normals defined in the 'octvertexnormals' extension is identical to the original\r\n // contents of the original 'vertexnormals' extension. 'vertexnormals' extension is now\r\n // deprecated, as the extensionLength for this extension was incorrectly using big endian.\r\n // We maintain backwards compatibility with the legacy 'vertexnormal' implementation\r\n // by setting the _littleEndianExtensionSize to false. Always prefer 'octvertexnormals'\r\n // over 'vertexnormals' if both extensions are supported by the server.\r\n if (\r\n defined(data.extensions) &&\r\n data.extensions.indexOf(\"octvertexnormals\") !== -1\r\n ) {\r\n hasVertexNormals = true;\r\n } else if (\r\n defined(data.extensions) &&\r\n data.extensions.indexOf(\"vertexnormals\") !== -1\r\n ) {\r\n hasVertexNormals = true;\r\n littleEndianExtensionSize = false;\r\n }\r\n if (\r\n defined(data.extensions) &&\r\n data.extensions.indexOf(\"watermask\") !== -1\r\n ) {\r\n hasWaterMask = true;\r\n }\r\n if (\r\n defined(data.extensions) &&\r\n data.extensions.indexOf(\"metadata\") !== -1\r\n ) {\r\n hasMetadata = true;\r\n }\r\n\r\n var availabilityLevels = data.metadataAvailability;\r\n var availableTiles = data.available;\r\n var availability;\r\n if (defined(availableTiles) && !defined(availabilityLevels)) {\r\n availability = new TileAvailability(\r\n that._tilingScheme,\r\n availableTiles.length\r\n );\r\n for (var level = 0; level < availableTiles.length; ++level) {\r\n var rangesAtLevel = availableTiles[level];\r\n var yTiles = that._tilingScheme.getNumberOfYTilesAtLevel(level);\r\n if (!defined(overallAvailability[level])) {\r\n overallAvailability[level] = [];\r\n }\r\n\r\n for (\r\n var rangeIndex = 0;\r\n rangeIndex < rangesAtLevel.length;\r\n ++rangeIndex\r\n ) {\r\n var range = rangesAtLevel[rangeIndex];\r\n var yStart = yTiles - range.endY - 1;\r\n var yEnd = yTiles - range.startY - 1;\r\n overallAvailability[level].push([\r\n range.startX,\r\n yStart,\r\n range.endX,\r\n yEnd,\r\n ]);\r\n availability.addAvailableTileRange(\r\n level,\r\n range.startX,\r\n yStart,\r\n range.endX,\r\n yEnd\r\n );\r\n }\r\n }\r\n } else if (defined(availabilityLevels)) {\r\n availabilityTilesLoaded = new TileAvailability(\r\n that._tilingScheme,\r\n maxZoom\r\n );\r\n availability = new TileAvailability(that._tilingScheme, maxZoom);\r\n overallAvailability[0] = [[0, 0, 1, 0]];\r\n availability.addAvailableTileRange(0, 0, 0, 1, 0);\r\n }\r\n\r\n that._hasWaterMask = that._hasWaterMask || hasWaterMask;\r\n that._hasVertexNormals = that._hasVertexNormals || hasVertexNormals;\r\n that._hasMetadata = that._hasMetadata || hasMetadata;\r\n if (defined(data.attribution)) {\r\n if (attribution.length > 0) {\r\n attribution += \" \";\r\n }\r\n attribution += data.attribution;\r\n }\r\n\r\n layers.push(\r\n new LayerInformation({\r\n resource: lastResource,\r\n version: data.version,\r\n isHeightmap: isHeightmap,\r\n tileUrlTemplates: tileUrlTemplates,\r\n availability: availability,\r\n hasVertexNormals: hasVertexNormals,\r\n hasWaterMask: hasWaterMask,\r\n hasMetadata: hasMetadata,\r\n availabilityLevels: availabilityLevels,\r\n availabilityTilesLoaded: availabilityTilesLoaded,\r\n littleEndianExtensionSize: littleEndianExtensionSize,\r\n })\r\n );\r\n\r\n var parentUrl = data.parentUrl;\r\n if (defined(parentUrl)) {\r\n if (!defined(availability)) {\r\n console.log(\r\n \"A layer.json can't have a parentUrl if it does't have an available array.\"\r\n );\r\n return when.resolve();\r\n }\r\n lastResource = lastResource.getDerivedResource({\r\n url: parentUrl,\r\n });\r\n lastResource.appendForwardSlash(); // Terrain always expects a directory\r\n layerJsonResource = lastResource.getDerivedResource({\r\n url: \"layer.json\",\r\n });\r\n var parentMetadata = layerJsonResource.fetchJson();\r\n return when(parentMetadata, parseMetadataSuccess, parseMetadataFailure);\r\n }\r\n\r\n return when.resolve();\r\n }\r\n\r\n function parseMetadataFailure(data) {\r\n var message =\r\n \"An error occurred while accessing \" + layerJsonResource.url + \".\";\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n requestLayerJson\r\n );\r\n }\r\n\r\n function metadataSuccess(data) {\r\n parseMetadataSuccess(data).then(function () {\r\n if (defined(metadataError)) {\r\n return;\r\n }\r\n\r\n var length = overallAvailability.length;\r\n if (length > 0) {\r\n var availability = (that._availability = new TileAvailability(\r\n that._tilingScheme,\r\n overallMaxZoom\r\n ));\r\n for (var level = 0; level < length; ++level) {\r\n var levelRanges = overallAvailability[level];\r\n for (var i = 0; i < levelRanges.length; ++i) {\r\n var range = levelRanges[i];\r\n availability.addAvailableTileRange(\r\n level,\r\n range[0],\r\n range[1],\r\n range[2],\r\n range[3]\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (attribution.length > 0) {\r\n var layerJsonCredit = new Credit(attribution);\r\n\r\n if (defined(that._tileCredits)) {\r\n that._tileCredits.push(layerJsonCredit);\r\n } else {\r\n that._tileCredits = [layerJsonCredit];\r\n }\r\n }\r\n\r\n that._ready = true;\r\n that._readyPromise.resolve(true);\r\n });\r\n }\r\n\r\n function metadataFailure(data) {\r\n // If the metadata is not found, assume this is a pre-metadata heightmap tileset.\r\n if (defined(data) && data.statusCode === 404) {\r\n metadataSuccess({\r\n tilejson: \"2.1.0\",\r\n format: \"heightmap-1.0\",\r\n version: \"1.0.0\",\r\n scheme: \"tms\",\r\n tiles: [\"{z}/{x}/{y}.terrain?v={version}\"],\r\n });\r\n return;\r\n }\r\n parseMetadataFailure(data);\r\n }\r\n\r\n function requestLayerJson() {\r\n when(layerJsonResource.fetchJson())\r\n .then(metadataSuccess)\r\n .otherwise(metadataFailure);\r\n }\r\n}\r\n\r\n/**\r\n * When using the Quantized-Mesh format, a tile may be returned that includes additional extensions, such as PerVertexNormals, watermask, etc.\r\n * This enumeration defines the unique identifiers for each type of extension data that has been appended to the standard mesh data.\r\n *\r\n * @namespace QuantizedMeshExtensionIds\r\n * @see CesiumTerrainProvider\r\n * @private\r\n */\r\nvar QuantizedMeshExtensionIds = {\r\n /**\r\n * Oct-Encoded Per-Vertex Normals are included as an extension to the tile mesh\r\n *\r\n * @type {Number}\r\n * @constant\r\n * @default 1\r\n */\r\n OCT_VERTEX_NORMALS: 1,\r\n /**\r\n * A watermask is included as an extension to the tile mesh\r\n *\r\n * @type {Number}\r\n * @constant\r\n * @default 2\r\n */\r\n WATER_MASK: 2,\r\n /**\r\n * A json object contain metadata about the tile\r\n *\r\n * @type {Number}\r\n * @constant\r\n * @default 4\r\n */\r\n METADATA: 4,\r\n};\r\n\r\nfunction getRequestHeader(extensionsList) {\r\n if (!defined(extensionsList) || extensionsList.length === 0) {\r\n return {\r\n Accept:\r\n \"application/vnd.quantized-mesh,application/octet-stream;q=0.9,*/*;q=0.01\",\r\n };\r\n }\r\n var extensions = extensionsList.join(\"-\");\r\n return {\r\n Accept:\r\n \"application/vnd.quantized-mesh;extensions=\" +\r\n extensions +\r\n \",application/octet-stream;q=0.9,*/*;q=0.01\",\r\n };\r\n}\r\n\r\nfunction createHeightmapTerrainData(provider, buffer, level, x, y) {\r\n var heightBuffer = new Uint16Array(\r\n buffer,\r\n 0,\r\n provider._heightmapWidth * provider._heightmapWidth\r\n );\r\n return new HeightmapTerrainData({\r\n buffer: heightBuffer,\r\n childTileMask: new Uint8Array(buffer, heightBuffer.byteLength, 1)[0],\r\n waterMask: new Uint8Array(\r\n buffer,\r\n heightBuffer.byteLength + 1,\r\n buffer.byteLength - heightBuffer.byteLength - 1\r\n ),\r\n width: provider._heightmapWidth,\r\n height: provider._heightmapWidth,\r\n structure: provider._heightmapStructure,\r\n credits: provider._tileCredits,\r\n });\r\n}\r\n\r\nfunction createQuantizedMeshTerrainData(provider, buffer, level, x, y, layer) {\r\n var littleEndianExtensionSize = layer.littleEndianExtensionSize;\r\n var pos = 0;\r\n var cartesian3Elements = 3;\r\n var boundingSphereElements = cartesian3Elements + 1;\r\n var cartesian3Length = Float64Array.BYTES_PER_ELEMENT * cartesian3Elements;\r\n var boundingSphereLength =\r\n Float64Array.BYTES_PER_ELEMENT * boundingSphereElements;\r\n var encodedVertexElements = 3;\r\n var encodedVertexLength =\r\n Uint16Array.BYTES_PER_ELEMENT * encodedVertexElements;\r\n var triangleElements = 3;\r\n var bytesPerIndex = Uint16Array.BYTES_PER_ELEMENT;\r\n var triangleLength = bytesPerIndex * triangleElements;\r\n\r\n var view = new DataView(buffer);\r\n var center = new Cartesian3(\r\n view.getFloat64(pos, true),\r\n view.getFloat64(pos + 8, true),\r\n view.getFloat64(pos + 16, true)\r\n );\r\n pos += cartesian3Length;\r\n\r\n var minimumHeight = view.getFloat32(pos, true);\r\n pos += Float32Array.BYTES_PER_ELEMENT;\r\n var maximumHeight = view.getFloat32(pos, true);\r\n pos += Float32Array.BYTES_PER_ELEMENT;\r\n\r\n var boundingSphere = new BoundingSphere(\r\n new Cartesian3(\r\n view.getFloat64(pos, true),\r\n view.getFloat64(pos + 8, true),\r\n view.getFloat64(pos + 16, true)\r\n ),\r\n view.getFloat64(pos + cartesian3Length, true)\r\n );\r\n pos += boundingSphereLength;\r\n\r\n var horizonOcclusionPoint = new Cartesian3(\r\n view.getFloat64(pos, true),\r\n view.getFloat64(pos + 8, true),\r\n view.getFloat64(pos + 16, true)\r\n );\r\n pos += cartesian3Length;\r\n\r\n var vertexCount = view.getUint32(pos, true);\r\n pos += Uint32Array.BYTES_PER_ELEMENT;\r\n var encodedVertexBuffer = new Uint16Array(buffer, pos, vertexCount * 3);\r\n pos += vertexCount * encodedVertexLength;\r\n\r\n if (vertexCount > 64 * 1024) {\r\n // More than 64k vertices, so indices are 32-bit.\r\n bytesPerIndex = Uint32Array.BYTES_PER_ELEMENT;\r\n triangleLength = bytesPerIndex * triangleElements;\r\n }\r\n\r\n // Decode the vertex buffer.\r\n var uBuffer = encodedVertexBuffer.subarray(0, vertexCount);\r\n var vBuffer = encodedVertexBuffer.subarray(vertexCount, 2 * vertexCount);\r\n var heightBuffer = encodedVertexBuffer.subarray(\r\n vertexCount * 2,\r\n 3 * vertexCount\r\n );\r\n\r\n AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);\r\n\r\n // skip over any additional padding that was added for 2/4 byte alignment\r\n if (pos % bytesPerIndex !== 0) {\r\n pos += bytesPerIndex - (pos % bytesPerIndex);\r\n }\r\n\r\n var triangleCount = view.getUint32(pos, true);\r\n pos += Uint32Array.BYTES_PER_ELEMENT;\r\n var indices = IndexDatatype.createTypedArrayFromArrayBuffer(\r\n vertexCount,\r\n buffer,\r\n pos,\r\n triangleCount * triangleElements\r\n );\r\n pos += triangleCount * triangleLength;\r\n\r\n // High water mark decoding based on decompressIndices_ in webgl-loader's loader.js.\r\n // https://code.google.com/p/webgl-loader/source/browse/trunk/samples/loader.js?r=99#55\r\n // Copyright 2012 Google Inc., Apache 2.0 license.\r\n var highest = 0;\r\n var length = indices.length;\r\n for (var i = 0; i < length; ++i) {\r\n var code = indices[i];\r\n indices[i] = highest - code;\r\n if (code === 0) {\r\n ++highest;\r\n }\r\n }\r\n\r\n var westVertexCount = view.getUint32(pos, true);\r\n pos += Uint32Array.BYTES_PER_ELEMENT;\r\n var westIndices = IndexDatatype.createTypedArrayFromArrayBuffer(\r\n vertexCount,\r\n buffer,\r\n pos,\r\n westVertexCount\r\n );\r\n pos += westVertexCount * bytesPerIndex;\r\n\r\n var southVertexCount = view.getUint32(pos, true);\r\n pos += Uint32Array.BYTES_PER_ELEMENT;\r\n var southIndices = IndexDatatype.createTypedArrayFromArrayBuffer(\r\n vertexCount,\r\n buffer,\r\n pos,\r\n southVertexCount\r\n );\r\n pos += southVertexCount * bytesPerIndex;\r\n\r\n var eastVertexCount = view.getUint32(pos, true);\r\n pos += Uint32Array.BYTES_PER_ELEMENT;\r\n var eastIndices = IndexDatatype.createTypedArrayFromArrayBuffer(\r\n vertexCount,\r\n buffer,\r\n pos,\r\n eastVertexCount\r\n );\r\n pos += eastVertexCount * bytesPerIndex;\r\n\r\n var northVertexCount = view.getUint32(pos, true);\r\n pos += Uint32Array.BYTES_PER_ELEMENT;\r\n var northIndices = IndexDatatype.createTypedArrayFromArrayBuffer(\r\n vertexCount,\r\n buffer,\r\n pos,\r\n northVertexCount\r\n );\r\n pos += northVertexCount * bytesPerIndex;\r\n\r\n var encodedNormalBuffer;\r\n var waterMaskBuffer;\r\n while (pos < view.byteLength) {\r\n var extensionId = view.getUint8(pos, true);\r\n pos += Uint8Array.BYTES_PER_ELEMENT;\r\n var extensionLength = view.getUint32(pos, littleEndianExtensionSize);\r\n pos += Uint32Array.BYTES_PER_ELEMENT;\r\n\r\n if (\r\n extensionId === QuantizedMeshExtensionIds.OCT_VERTEX_NORMALS &&\r\n provider._requestVertexNormals\r\n ) {\r\n encodedNormalBuffer = new Uint8Array(buffer, pos, vertexCount * 2);\r\n } else if (\r\n extensionId === QuantizedMeshExtensionIds.WATER_MASK &&\r\n provider._requestWaterMask\r\n ) {\r\n waterMaskBuffer = new Uint8Array(buffer, pos, extensionLength);\r\n } else if (\r\n extensionId === QuantizedMeshExtensionIds.METADATA &&\r\n provider._requestMetadata\r\n ) {\r\n var stringLength = view.getUint32(pos, true);\r\n if (stringLength > 0) {\r\n var metadata = getJsonFromTypedArray(\r\n new Uint8Array(buffer),\r\n pos + Uint32Array.BYTES_PER_ELEMENT,\r\n stringLength\r\n );\r\n var availableTiles = metadata.available;\r\n if (defined(availableTiles)) {\r\n for (var offset = 0; offset < availableTiles.length; ++offset) {\r\n var availableLevel = level + offset + 1;\r\n var rangesAtLevel = availableTiles[offset];\r\n var yTiles = provider._tilingScheme.getNumberOfYTilesAtLevel(\r\n availableLevel\r\n );\r\n\r\n for (\r\n var rangeIndex = 0;\r\n rangeIndex < rangesAtLevel.length;\r\n ++rangeIndex\r\n ) {\r\n var range = rangesAtLevel[rangeIndex];\r\n var yStart = yTiles - range.endY - 1;\r\n var yEnd = yTiles - range.startY - 1;\r\n provider.availability.addAvailableTileRange(\r\n availableLevel,\r\n range.startX,\r\n yStart,\r\n range.endX,\r\n yEnd\r\n );\r\n layer.availability.addAvailableTileRange(\r\n availableLevel,\r\n range.startX,\r\n yStart,\r\n range.endX,\r\n yEnd\r\n );\r\n }\r\n }\r\n }\r\n }\r\n layer.availabilityTilesLoaded.addAvailableTileRange(level, x, y, x, y);\r\n }\r\n pos += extensionLength;\r\n }\r\n\r\n var skirtHeight = provider.getLevelMaximumGeometricError(level) * 5.0;\r\n\r\n // The skirt is not included in the OBB computation. If this ever\r\n // causes any rendering artifacts (cracks), they are expected to be\r\n // minor and in the corners of the screen. It's possible that this\r\n // might need to be changed - just change to `minimumHeight - skirtHeight`\r\n // A similar change might also be needed in `upsampleQuantizedTerrainMesh.js`.\r\n var rectangle = provider._tilingScheme.tileXYToRectangle(x, y, level);\r\n var orientedBoundingBox = OrientedBoundingBox.fromRectangle(\r\n rectangle,\r\n minimumHeight,\r\n maximumHeight,\r\n provider._tilingScheme.ellipsoid\r\n );\r\n\r\n return new QuantizedMeshTerrainData({\r\n center: center,\r\n minimumHeight: minimumHeight,\r\n maximumHeight: maximumHeight,\r\n boundingSphere: boundingSphere,\r\n orientedBoundingBox: orientedBoundingBox,\r\n horizonOcclusionPoint: horizonOcclusionPoint,\r\n quantizedVertices: encodedVertexBuffer,\r\n encodedNormals: encodedNormalBuffer,\r\n indices: indices,\r\n westIndices: westIndices,\r\n southIndices: southIndices,\r\n eastIndices: eastIndices,\r\n northIndices: northIndices,\r\n westSkirtHeight: skirtHeight,\r\n southSkirtHeight: skirtHeight,\r\n eastSkirtHeight: skirtHeight,\r\n northSkirtHeight: skirtHeight,\r\n childTileMask: provider.availability.computeChildMaskForTile(level, x, y),\r\n waterMask: waterMaskBuffer,\r\n credits: provider._tileCredits,\r\n });\r\n}\r\n\r\n/**\r\n * Requests the geometry for a given tile. This function should not be called before\r\n * {@link CesiumTerrainProvider#ready} returns true. The result must include terrain data and\r\n * may optionally include a water mask and an indication of which child tiles are available.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @param {Request} [request] The request object. Intended for internal use only.\r\n *\r\n * @returns {Promise.|undefined} A promise for the requested geometry. If this method\r\n * returns undefined instead of a promise, it is an indication that too many requests are already\r\n * pending and the request will be retried later.\r\n *\r\n * @exception {DeveloperError} This function must not be called before {@link CesiumTerrainProvider#ready}\r\n * returns true.\r\n */\r\nCesiumTerrainProvider.prototype.requestTileGeometry = function (\r\n x,\r\n y,\r\n level,\r\n request\r\n) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"requestTileGeometry must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var layers = this._layers;\r\n var layerToUse;\r\n var layerCount = layers.length;\r\n\r\n if (layerCount === 1) {\r\n // Optimized path for single layers\r\n layerToUse = layers[0];\r\n } else {\r\n for (var i = 0; i < layerCount; ++i) {\r\n var layer = layers[i];\r\n if (\r\n !defined(layer.availability) ||\r\n layer.availability.isTileAvailable(level, x, y)\r\n ) {\r\n layerToUse = layer;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return requestTileGeometry(this, x, y, level, layerToUse, request);\r\n};\r\n\r\nfunction requestTileGeometry(provider, x, y, level, layerToUse, request) {\r\n if (!defined(layerToUse)) {\r\n return when.reject(new RuntimeError(\"Terrain tile doesn't exist\"));\r\n }\r\n\r\n var urlTemplates = layerToUse.tileUrlTemplates;\r\n if (urlTemplates.length === 0) {\r\n return undefined;\r\n }\r\n\r\n // The TileMapService scheme counts from the bottom left\r\n var terrainY;\r\n if (!provider._scheme || provider._scheme === \"tms\") {\r\n var yTiles = provider._tilingScheme.getNumberOfYTilesAtLevel(level);\r\n terrainY = yTiles - y - 1;\r\n } else {\r\n terrainY = y;\r\n }\r\n\r\n var extensionList = [];\r\n if (provider._requestVertexNormals && layerToUse.hasVertexNormals) {\r\n extensionList.push(\r\n layerToUse.littleEndianExtensionSize\r\n ? \"octvertexnormals\"\r\n : \"vertexnormals\"\r\n );\r\n }\r\n if (provider._requestWaterMask && layerToUse.hasWaterMask) {\r\n extensionList.push(\"watermask\");\r\n }\r\n if (provider._requestMetadata && layerToUse.hasMetadata) {\r\n extensionList.push(\"metadata\");\r\n }\r\n\r\n var headers;\r\n var query;\r\n var url = urlTemplates[(x + terrainY + level) % urlTemplates.length];\r\n\r\n var resource = layerToUse.resource;\r\n if (\r\n defined(resource._ionEndpoint) &&\r\n !defined(resource._ionEndpoint.externalType)\r\n ) {\r\n // ion uses query paremeters to request extensions\r\n if (extensionList.length !== 0) {\r\n query = { extensions: extensionList.join(\"-\") };\r\n }\r\n headers = getRequestHeader(undefined);\r\n } else {\r\n //All other terrain servers\r\n headers = getRequestHeader(extensionList);\r\n }\r\n\r\n var promise = resource\r\n .getDerivedResource({\r\n url: url,\r\n templateValues: {\r\n version: layerToUse.version,\r\n z: level,\r\n x: x,\r\n y: terrainY,\r\n },\r\n queryParameters: query,\r\n headers: headers,\r\n request: request,\r\n })\r\n .fetchArrayBuffer();\r\n\r\n if (!defined(promise)) {\r\n return undefined;\r\n }\r\n\r\n return promise.then(function (buffer) {\r\n if (defined(provider._heightmapStructure)) {\r\n return createHeightmapTerrainData(provider, buffer, level, x, y);\r\n }\r\n return createQuantizedMeshTerrainData(\r\n provider,\r\n buffer,\r\n level,\r\n x,\r\n y,\r\n layerToUse\r\n );\r\n });\r\n}\r\n\r\nObject.defineProperties(CesiumTerrainProvider.prototype, {\r\n /**\r\n * Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing\r\n * to the event, you will be notified of the error and can potentially recover from it. Event listeners\r\n * are passed an instance of {@link TileProviderError}.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Event}\r\n */\r\n errorEvent: {\r\n get: function () {\r\n return this._errorEvent;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the credit to display when this terrain provider is active. Typically this is used to credit\r\n * the source of the terrain. This function should not be called before {@link CesiumTerrainProvider#ready} returns true.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Credit}\r\n */\r\n credit: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"credit must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._credit;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tiling scheme used by this provider. This function should\r\n * not be called before {@link CesiumTerrainProvider#ready} returns true.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {GeographicTilingScheme}\r\n */\r\n tilingScheme: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"tilingScheme must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._tilingScheme;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider is ready for use.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves to true when the provider is ready for use.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider includes a water mask. The water mask\r\n * indicates which areas of the globe are water rather than land, so they can be rendered\r\n * as a reflective surface with animated waves. This function should not be\r\n * called before {@link CesiumTerrainProvider#ready} returns true.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Boolean}\r\n * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready}\r\n */\r\n hasWaterMask: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"hasWaterMask must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._hasWaterMask && this._requestWaterMask;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the requested tiles include vertex normals.\r\n * This function should not be called before {@link CesiumTerrainProvider#ready} returns true.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Boolean}\r\n * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready}\r\n */\r\n hasVertexNormals: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"hasVertexNormals must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // returns true if we can request vertex normals from the server\r\n return this._hasVertexNormals && this._requestVertexNormals;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the requested tiles include metadata.\r\n * This function should not be called before {@link CesiumTerrainProvider#ready} returns true.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Boolean}\r\n * @exception {DeveloperError} This property must not be called before {@link CesiumTerrainProvider#ready}\r\n */\r\n hasMetadata: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"hasMetadata must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // returns true if we can request metadata from the server\r\n return this._hasMetadata && this._requestMetadata;\r\n },\r\n },\r\n\r\n /**\r\n * Boolean flag that indicates if the client should request vertex normals from the server.\r\n * Vertex normals data is appended to the standard tile mesh data only if the client requests the vertex normals and\r\n * if the server provides vertex normals.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n requestVertexNormals: {\r\n get: function () {\r\n return this._requestVertexNormals;\r\n },\r\n },\r\n\r\n /**\r\n * Boolean flag that indicates if the client should request a watermask from the server.\r\n * Watermask data is appended to the standard tile mesh data only if the client requests the watermask and\r\n * if the server provides a watermask.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n requestWaterMask: {\r\n get: function () {\r\n return this._requestWaterMask;\r\n },\r\n },\r\n\r\n /**\r\n * Boolean flag that indicates if the client should request metadata from the server.\r\n * Metadata is appended to the standard tile mesh data only if the client requests the metadata and\r\n * if the server provides a metadata.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n requestMetadata: {\r\n get: function () {\r\n return this._requestMetadata;\r\n },\r\n },\r\n\r\n /**\r\n * Gets an object that can be used to determine availability of terrain from this provider, such as\r\n * at points and in rectangles. This function should not be called before\r\n * {@link CesiumTerrainProvider#ready} returns true. This property may be undefined if availability\r\n * information is not available. Note that this reflects tiles that are known to be available currently.\r\n * Additional tiles may be discovered to be available in the future, e.g. if availability information\r\n * exists deeper in the tree rather than it all being discoverable at the root. However, a tile that\r\n * is available now will not become unavailable in the future.\r\n * @memberof CesiumTerrainProvider.prototype\r\n * @type {TileAvailability}\r\n */\r\n availability: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"availability must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return this._availability;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the maximum geometric error allowed in a tile at a given level.\r\n *\r\n * @param {Number} level The tile level for which to get the maximum geometric error.\r\n * @returns {Number} The maximum geometric error.\r\n */\r\nCesiumTerrainProvider.prototype.getLevelMaximumGeometricError = function (\r\n level\r\n) {\r\n return this._levelZeroMaximumGeometricError / (1 << level);\r\n};\r\n\r\n/**\r\n * Determines whether data for a tile is available to be loaded.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {Boolean} Undefined if not supported or availability is unknown, otherwise true or false.\r\n */\r\nCesiumTerrainProvider.prototype.getTileDataAvailable = function (x, y, level) {\r\n if (!defined(this._availability)) {\r\n return undefined;\r\n }\r\n if (level > this._availability._maximumLevel) {\r\n return false;\r\n }\r\n\r\n if (this._availability.isTileAvailable(level, x, y)) {\r\n // If the tile is listed as available, then we are done\r\n return true;\r\n }\r\n if (!this._hasMetadata) {\r\n // If we don't have any layers with the metadata extension then we don't have this tile\r\n return false;\r\n }\r\n\r\n var layers = this._layers;\r\n var count = layers.length;\r\n for (var i = 0; i < count; ++i) {\r\n var layerResult = checkLayer(this, x, y, level, layers[i], i === 0);\r\n if (layerResult.result) {\r\n // There is a layer that may or may not have the tile\r\n return undefined;\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Makes sure we load availability data for a tile\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {undefined|Promise} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded\r\n */\r\nCesiumTerrainProvider.prototype.loadTileDataAvailability = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n if (\r\n !defined(this._availability) ||\r\n level > this._availability._maximumLevel ||\r\n this._availability.isTileAvailable(level, x, y) ||\r\n !this._hasMetadata\r\n ) {\r\n // We know the tile is either available or not available so nothing to wait on\r\n return undefined;\r\n }\r\n\r\n var layers = this._layers;\r\n var count = layers.length;\r\n for (var i = 0; i < count; ++i) {\r\n var layerResult = checkLayer(this, x, y, level, layers[i], i === 0);\r\n if (defined(layerResult.promise)) {\r\n return layerResult.promise;\r\n }\r\n }\r\n};\r\n\r\nfunction getAvailabilityTile(layer, x, y, level) {\r\n if (level === 0) {\r\n return;\r\n }\r\n\r\n var availabilityLevels = layer.availabilityLevels;\r\n var parentLevel =\r\n level % availabilityLevels === 0\r\n ? level - availabilityLevels\r\n : ((level / availabilityLevels) | 0) * availabilityLevels;\r\n var divisor = 1 << (level - parentLevel);\r\n var parentX = (x / divisor) | 0;\r\n var parentY = (y / divisor) | 0;\r\n\r\n return {\r\n level: parentLevel,\r\n x: parentX,\r\n y: parentY,\r\n };\r\n}\r\n\r\nfunction checkLayer(provider, x, y, level, layer, topLayer) {\r\n if (!defined(layer.availabilityLevels)) {\r\n // It's definitely not in this layer\r\n return {\r\n result: false,\r\n };\r\n }\r\n\r\n var cacheKey;\r\n var deleteFromCache = function () {\r\n delete layer.availabilityPromiseCache[cacheKey];\r\n };\r\n var availabilityTilesLoaded = layer.availabilityTilesLoaded;\r\n var availability = layer.availability;\r\n\r\n var tile = getAvailabilityTile(layer, x, y, level);\r\n while (defined(tile)) {\r\n if (\r\n availability.isTileAvailable(tile.level, tile.x, tile.y) &&\r\n !availabilityTilesLoaded.isTileAvailable(tile.level, tile.x, tile.y)\r\n ) {\r\n var requestPromise;\r\n if (!topLayer) {\r\n cacheKey = tile.level + \"-\" + tile.x + \"-\" + tile.y;\r\n requestPromise = layer.availabilityPromiseCache[cacheKey];\r\n if (!defined(requestPromise)) {\r\n // For cutout terrain, if this isn't the top layer the availability tiles\r\n // may never get loaded, so request it here.\r\n var request = new Request({\r\n throttle: false,\r\n throttleByServer: true,\r\n type: RequestType.TERRAIN,\r\n });\r\n requestPromise = requestTileGeometry(\r\n provider,\r\n tile.x,\r\n tile.y,\r\n tile.level,\r\n layer,\r\n request\r\n );\r\n if (defined(requestPromise)) {\r\n layer.availabilityPromiseCache[cacheKey] = requestPromise;\r\n requestPromise.then(deleteFromCache);\r\n }\r\n }\r\n }\r\n\r\n // The availability tile is available, but not loaded, so there\r\n // is still a chance that it may become available at some point\r\n return {\r\n result: true,\r\n promise: requestPromise,\r\n };\r\n }\r\n\r\n tile = getAvailabilityTile(layer, tile.x, tile.y, tile.level);\r\n }\r\n\r\n return {\r\n result: false,\r\n };\r\n}\r\n\r\n// Used for testing\r\nCesiumTerrainProvider._getAvailabilityTile = getAvailabilityTile;\r\nexport default CesiumTerrainProvider;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\n\r\nvar EllipseGeometryLibrary = {};\r\n\r\nvar rotAxis = new Cartesian3();\r\nvar tempVec = new Cartesian3();\r\nvar unitQuat = new Quaternion();\r\nvar rotMtx = new Matrix3();\r\n\r\nfunction pointOnEllipsoid(\r\n theta,\r\n rotation,\r\n northVec,\r\n eastVec,\r\n aSqr,\r\n ab,\r\n bSqr,\r\n mag,\r\n unitPos,\r\n result\r\n) {\r\n var azimuth = theta + rotation;\r\n\r\n Cartesian3.multiplyByScalar(eastVec, Math.cos(azimuth), rotAxis);\r\n Cartesian3.multiplyByScalar(northVec, Math.sin(azimuth), tempVec);\r\n Cartesian3.add(rotAxis, tempVec, rotAxis);\r\n\r\n var cosThetaSquared = Math.cos(theta);\r\n cosThetaSquared = cosThetaSquared * cosThetaSquared;\r\n\r\n var sinThetaSquared = Math.sin(theta);\r\n sinThetaSquared = sinThetaSquared * sinThetaSquared;\r\n\r\n var radius = ab / Math.sqrt(bSqr * cosThetaSquared + aSqr * sinThetaSquared);\r\n var angle = radius / mag;\r\n\r\n // Create the quaternion to rotate the position vector to the boundary of the ellipse.\r\n Quaternion.fromAxisAngle(rotAxis, angle, unitQuat);\r\n Matrix3.fromQuaternion(unitQuat, rotMtx);\r\n\r\n Matrix3.multiplyByVector(rotMtx, unitPos, result);\r\n Cartesian3.normalize(result, result);\r\n Cartesian3.multiplyByScalar(result, mag, result);\r\n return result;\r\n}\r\n\r\nvar scratchCartesian1 = new Cartesian3();\r\nvar scratchCartesian2 = new Cartesian3();\r\nvar scratchCartesian3 = new Cartesian3();\r\nvar scratchNormal = new Cartesian3();\r\n/**\r\n * Returns the positions raised to the given heights\r\n * @private\r\n */\r\nEllipseGeometryLibrary.raisePositionsToHeight = function (\r\n positions,\r\n options,\r\n extrude\r\n) {\r\n var ellipsoid = options.ellipsoid;\r\n var height = options.height;\r\n var extrudedHeight = options.extrudedHeight;\r\n var size = extrude ? (positions.length / 3) * 2 : positions.length / 3;\r\n\r\n var finalPositions = new Float64Array(size * 3);\r\n\r\n var length = positions.length;\r\n var bottomOffset = extrude ? length : 0;\r\n for (var i = 0; i < length; i += 3) {\r\n var i1 = i + 1;\r\n var i2 = i + 2;\r\n\r\n var position = Cartesian3.fromArray(positions, i, scratchCartesian1);\r\n ellipsoid.scaleToGeodeticSurface(position, position);\r\n\r\n var extrudedPosition = Cartesian3.clone(position, scratchCartesian2);\r\n var normal = ellipsoid.geodeticSurfaceNormal(position, scratchNormal);\r\n var scaledNormal = Cartesian3.multiplyByScalar(\r\n normal,\r\n height,\r\n scratchCartesian3\r\n );\r\n Cartesian3.add(position, scaledNormal, position);\r\n\r\n if (extrude) {\r\n Cartesian3.multiplyByScalar(normal, extrudedHeight, scaledNormal);\r\n Cartesian3.add(extrudedPosition, scaledNormal, extrudedPosition);\r\n\r\n finalPositions[i + bottomOffset] = extrudedPosition.x;\r\n finalPositions[i1 + bottomOffset] = extrudedPosition.y;\r\n finalPositions[i2 + bottomOffset] = extrudedPosition.z;\r\n }\r\n\r\n finalPositions[i] = position.x;\r\n finalPositions[i1] = position.y;\r\n finalPositions[i2] = position.z;\r\n }\r\n\r\n return finalPositions;\r\n};\r\n\r\nvar unitPosScratch = new Cartesian3();\r\nvar eastVecScratch = new Cartesian3();\r\nvar northVecScratch = new Cartesian3();\r\n/**\r\n * Returns an array of positions that make up the ellipse.\r\n * @private\r\n */\r\nEllipseGeometryLibrary.computeEllipsePositions = function (\r\n options,\r\n addFillPositions,\r\n addEdgePositions\r\n) {\r\n var semiMinorAxis = options.semiMinorAxis;\r\n var semiMajorAxis = options.semiMajorAxis;\r\n var rotation = options.rotation;\r\n var center = options.center;\r\n\r\n // Computing the arc-length of the ellipse is too expensive to be practical. Estimating it using the\r\n // arc length of the sphere is too inaccurate and creates sharp edges when either the semi-major or\r\n // semi-minor axis is much bigger than the other. Instead, scale the angle delta to make\r\n // the distance along the ellipse boundary more closely match the granularity.\r\n var granularity = options.granularity * 8.0;\r\n\r\n var aSqr = semiMinorAxis * semiMinorAxis;\r\n var bSqr = semiMajorAxis * semiMajorAxis;\r\n var ab = semiMajorAxis * semiMinorAxis;\r\n\r\n var mag = Cartesian3.magnitude(center);\r\n\r\n var unitPos = Cartesian3.normalize(center, unitPosScratch);\r\n var eastVec = Cartesian3.cross(Cartesian3.UNIT_Z, center, eastVecScratch);\r\n eastVec = Cartesian3.normalize(eastVec, eastVec);\r\n var northVec = Cartesian3.cross(unitPos, eastVec, northVecScratch);\r\n\r\n // The number of points in the first quadrant\r\n var numPts = 1 + Math.ceil(CesiumMath.PI_OVER_TWO / granularity);\r\n\r\n var deltaTheta = CesiumMath.PI_OVER_TWO / (numPts - 1);\r\n var theta = CesiumMath.PI_OVER_TWO - numPts * deltaTheta;\r\n if (theta < 0.0) {\r\n numPts -= Math.ceil(Math.abs(theta) / deltaTheta);\r\n }\r\n\r\n // If the number of points were three, the ellipse\r\n // would be tessellated like below:\r\n //\r\n // *---*\r\n // / | \\ | \\\r\n // *---*---*---*\r\n // / | \\ | \\ | \\ | \\\r\n // / .*---*---*---*. \\\r\n // * ` | \\ | \\ | \\ | `*\r\n // \\`.*---*---*---*.`/\r\n // \\ | \\ | \\ | \\ | /\r\n // *---*---*---*\r\n // \\ | \\ | /\r\n // *---*\r\n // The first and last column have one position and fan to connect to the adjacent column.\r\n // Each other vertical column contains an even number of positions.\r\n var size = 2 * (numPts * (numPts + 2));\r\n var positions = addFillPositions ? new Array(size * 3) : undefined;\r\n var positionIndex = 0;\r\n var position = scratchCartesian1;\r\n var reflectedPosition = scratchCartesian2;\r\n\r\n var outerPositionsLength = numPts * 4 * 3;\r\n var outerRightIndex = outerPositionsLength - 1;\r\n var outerLeftIndex = 0;\r\n var outerPositions = addEdgePositions\r\n ? new Array(outerPositionsLength)\r\n : undefined;\r\n\r\n var i;\r\n var j;\r\n var numInterior;\r\n var t;\r\n var interiorPosition;\r\n\r\n // Compute points in the 'eastern' half of the ellipse\r\n theta = CesiumMath.PI_OVER_TWO;\r\n position = pointOnEllipsoid(\r\n theta,\r\n rotation,\r\n northVec,\r\n eastVec,\r\n aSqr,\r\n ab,\r\n bSqr,\r\n mag,\r\n unitPos,\r\n position\r\n );\r\n if (addFillPositions) {\r\n positions[positionIndex++] = position.x;\r\n positions[positionIndex++] = position.y;\r\n positions[positionIndex++] = position.z;\r\n }\r\n if (addEdgePositions) {\r\n outerPositions[outerRightIndex--] = position.z;\r\n outerPositions[outerRightIndex--] = position.y;\r\n outerPositions[outerRightIndex--] = position.x;\r\n }\r\n theta = CesiumMath.PI_OVER_TWO - deltaTheta;\r\n for (i = 1; i < numPts + 1; ++i) {\r\n position = pointOnEllipsoid(\r\n theta,\r\n rotation,\r\n northVec,\r\n eastVec,\r\n aSqr,\r\n ab,\r\n bSqr,\r\n mag,\r\n unitPos,\r\n position\r\n );\r\n reflectedPosition = pointOnEllipsoid(\r\n Math.PI - theta,\r\n rotation,\r\n northVec,\r\n eastVec,\r\n aSqr,\r\n ab,\r\n bSqr,\r\n mag,\r\n unitPos,\r\n reflectedPosition\r\n );\r\n\r\n if (addFillPositions) {\r\n positions[positionIndex++] = position.x;\r\n positions[positionIndex++] = position.y;\r\n positions[positionIndex++] = position.z;\r\n\r\n numInterior = 2 * i + 2;\r\n for (j = 1; j < numInterior - 1; ++j) {\r\n t = j / (numInterior - 1);\r\n interiorPosition = Cartesian3.lerp(\r\n position,\r\n reflectedPosition,\r\n t,\r\n scratchCartesian3\r\n );\r\n positions[positionIndex++] = interiorPosition.x;\r\n positions[positionIndex++] = interiorPosition.y;\r\n positions[positionIndex++] = interiorPosition.z;\r\n }\r\n\r\n positions[positionIndex++] = reflectedPosition.x;\r\n positions[positionIndex++] = reflectedPosition.y;\r\n positions[positionIndex++] = reflectedPosition.z;\r\n }\r\n\r\n if (addEdgePositions) {\r\n outerPositions[outerRightIndex--] = position.z;\r\n outerPositions[outerRightIndex--] = position.y;\r\n outerPositions[outerRightIndex--] = position.x;\r\n outerPositions[outerLeftIndex++] = reflectedPosition.x;\r\n outerPositions[outerLeftIndex++] = reflectedPosition.y;\r\n outerPositions[outerLeftIndex++] = reflectedPosition.z;\r\n }\r\n\r\n theta = CesiumMath.PI_OVER_TWO - (i + 1) * deltaTheta;\r\n }\r\n\r\n // Compute points in the 'western' half of the ellipse\r\n for (i = numPts; i > 1; --i) {\r\n theta = CesiumMath.PI_OVER_TWO - (i - 1) * deltaTheta;\r\n\r\n position = pointOnEllipsoid(\r\n -theta,\r\n rotation,\r\n northVec,\r\n eastVec,\r\n aSqr,\r\n ab,\r\n bSqr,\r\n mag,\r\n unitPos,\r\n position\r\n );\r\n reflectedPosition = pointOnEllipsoid(\r\n theta + Math.PI,\r\n rotation,\r\n northVec,\r\n eastVec,\r\n aSqr,\r\n ab,\r\n bSqr,\r\n mag,\r\n unitPos,\r\n reflectedPosition\r\n );\r\n\r\n if (addFillPositions) {\r\n positions[positionIndex++] = position.x;\r\n positions[positionIndex++] = position.y;\r\n positions[positionIndex++] = position.z;\r\n\r\n numInterior = 2 * (i - 1) + 2;\r\n for (j = 1; j < numInterior - 1; ++j) {\r\n t = j / (numInterior - 1);\r\n interiorPosition = Cartesian3.lerp(\r\n position,\r\n reflectedPosition,\r\n t,\r\n scratchCartesian3\r\n );\r\n positions[positionIndex++] = interiorPosition.x;\r\n positions[positionIndex++] = interiorPosition.y;\r\n positions[positionIndex++] = interiorPosition.z;\r\n }\r\n\r\n positions[positionIndex++] = reflectedPosition.x;\r\n positions[positionIndex++] = reflectedPosition.y;\r\n positions[positionIndex++] = reflectedPosition.z;\r\n }\r\n\r\n if (addEdgePositions) {\r\n outerPositions[outerRightIndex--] = position.z;\r\n outerPositions[outerRightIndex--] = position.y;\r\n outerPositions[outerRightIndex--] = position.x;\r\n outerPositions[outerLeftIndex++] = reflectedPosition.x;\r\n outerPositions[outerLeftIndex++] = reflectedPosition.y;\r\n outerPositions[outerLeftIndex++] = reflectedPosition.z;\r\n }\r\n }\r\n\r\n theta = CesiumMath.PI_OVER_TWO;\r\n position = pointOnEllipsoid(\r\n -theta,\r\n rotation,\r\n northVec,\r\n eastVec,\r\n aSqr,\r\n ab,\r\n bSqr,\r\n mag,\r\n unitPos,\r\n position\r\n );\r\n\r\n var r = {};\r\n if (addFillPositions) {\r\n positions[positionIndex++] = position.x;\r\n positions[positionIndex++] = position.y;\r\n positions[positionIndex++] = position.z;\r\n r.positions = positions;\r\n r.numPts = numPts;\r\n }\r\n if (addEdgePositions) {\r\n outerPositions[outerRightIndex--] = position.z;\r\n outerPositions[outerRightIndex--] = position.y;\r\n outerPositions[outerRightIndex--] = position.x;\r\n r.outerPositions = outerPositions;\r\n }\r\n\r\n return r;\r\n};\r\nexport default EllipseGeometryLibrary;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\n\r\n/**\r\n * Geometry instancing allows one {@link Geometry} object to be positions in several\r\n * different locations and colored uniquely. For example, one {@link BoxGeometry} can\r\n * be instanced several times, each with a different modelMatrix to change\r\n * its position, rotation, and scale.\r\n *\r\n * @alias GeometryInstance\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Geometry|GeometryFactory} options.geometry The geometry to instance.\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The model matrix that transforms to transform the geometry from model to world coordinates.\r\n * @param {Object} [options.id] A user-defined object to return when the instance is picked with {@link Scene#pick} or get/set per-instance attributes with {@link Primitive#getGeometryInstanceAttributes}.\r\n * @param {Object} [options.attributes] Per-instance attributes like a show or color attribute shown in the example below.\r\n *\r\n *\r\n * @example\r\n * // Create geometry for a box, and two instances that refer to it.\r\n * // One instance positions the box on the bottom and colored aqua.\r\n * // The other instance positions the box on the top and color white.\r\n * var geometry = Cesium.BoxGeometry.fromDimensions({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL,\r\n * dimensions : new Cesium.Cartesian3(1000000.0, 1000000.0, 500000.0)\r\n * });\r\n * var instanceBottom = new Cesium.GeometryInstance({\r\n * geometry : geometry,\r\n * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(\r\n * Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 1000000.0), new Cesium.Matrix4()),\r\n * attributes : {\r\n * color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA)\r\n * },\r\n * id : 'bottom'\r\n * });\r\n * var instanceTop = new Cesium.GeometryInstance({\r\n * geometry : geometry,\r\n * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(\r\n * Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 3000000.0), new Cesium.Matrix4()),\r\n * attributes : {\r\n * color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA)\r\n * },\r\n * id : 'top'\r\n * });\r\n *\r\n * @see Geometry\r\n */\r\nfunction GeometryInstance(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options.geometry)) {\r\n throw new DeveloperError(\"options.geometry is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * The geometry being instanced.\r\n *\r\n * @type Geometry\r\n *\r\n * @default undefined\r\n */\r\n this.geometry = options.geometry;\r\n\r\n /**\r\n * The 4x4 transformation matrix that transforms the geometry from model to world coordinates.\r\n * When this is the identity matrix, the geometry is drawn in world coordinates, i.e., Earth's WGS84 coordinates.\r\n * Local reference frames can be used by providing a different transformation matrix, like that returned\r\n * by {@link Transforms.eastNorthUpToFixedFrame}.\r\n *\r\n * @type Matrix4\r\n *\r\n * @default Matrix4.IDENTITY\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n\r\n /**\r\n * User-defined object returned when the instance is picked or used to get/set per-instance attributes.\r\n *\r\n * @type Object\r\n *\r\n * @default undefined\r\n *\r\n * @see Scene#pick\r\n * @see Primitive#getGeometryInstanceAttributes\r\n */\r\n this.id = options.id;\r\n\r\n /**\r\n * Used for picking primitives that wrap geometry instances.\r\n *\r\n * @private\r\n */\r\n this.pickPrimitive = options.pickPrimitive;\r\n\r\n /**\r\n * Per-instance attributes like {@link ColorGeometryInstanceAttribute} or {@link ShowGeometryInstanceAttribute}.\r\n * {@link Geometry} attributes varying per vertex; these attributes are constant for the entire instance.\r\n *\r\n * @type Object\r\n *\r\n * @default undefined\r\n */\r\n this.attributes = defaultValue(options.attributes, {});\r\n\r\n /**\r\n * @private\r\n */\r\n this.westHemisphereGeometry = undefined;\r\n /**\r\n * @private\r\n */\r\n this.eastHemisphereGeometry = undefined;\r\n}\r\nexport default GeometryInstance;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * A fixed-point encoding of a {@link Cartesian3} with 64-bit floating-point components, as two {@link Cartesian3}\r\n * values that, when converted to 32-bit floating-point and added, approximate the original input.\r\n *

\r\n * This is used to encode positions in vertex buffers for rendering without jittering artifacts\r\n * as described in {@link http://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm|Precisions, Precisions}.\r\n *

\r\n *\r\n * @alias EncodedCartesian3\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction EncodedCartesian3() {\r\n /**\r\n * The high bits for each component. Bits 0 to 22 store the whole value. Bits 23 to 31 are not used.\r\n *\r\n * @type {Cartesian3}\r\n * @default {@link Cartesian3.ZERO}\r\n */\r\n this.high = Cartesian3.clone(Cartesian3.ZERO);\r\n\r\n /**\r\n * The low bits for each component. Bits 7 to 22 store the whole value, and bits 0 to 6 store the fraction. Bits 23 to 31 are not used.\r\n *\r\n * @type {Cartesian3}\r\n * @default {@link Cartesian3.ZERO}\r\n */\r\n this.low = Cartesian3.clone(Cartesian3.ZERO);\r\n}\r\n\r\n/**\r\n * Encodes a 64-bit floating-point value as two floating-point values that, when converted to\r\n * 32-bit floating-point and added, approximate the original input. The returned object\r\n * has high and low properties for the high and low bits, respectively.\r\n *

\r\n * The fixed-point encoding follows {@link http://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm|Precisions, Precisions}.\r\n *

\r\n *\r\n * @param {Number} value The floating-point value to encode.\r\n * @param {Object} [result] The object onto which to store the result.\r\n * @returns {Object} The modified result parameter or a new instance if one was not provided.\r\n *\r\n * @example\r\n * var value = 1234567.1234567;\r\n * var splitValue = Cesium.EncodedCartesian3.encode(value);\r\n */\r\nEncodedCartesian3.encode = function (value, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"value\", value);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = {\r\n high: 0.0,\r\n low: 0.0,\r\n };\r\n }\r\n\r\n var doubleHigh;\r\n if (value >= 0.0) {\r\n doubleHigh = Math.floor(value / 65536.0) * 65536.0;\r\n result.high = doubleHigh;\r\n result.low = value - doubleHigh;\r\n } else {\r\n doubleHigh = Math.floor(-value / 65536.0) * 65536.0;\r\n result.high = -doubleHigh;\r\n result.low = value + doubleHigh;\r\n }\r\n\r\n return result;\r\n};\r\n\r\nvar scratchEncode = {\r\n high: 0.0,\r\n low: 0.0,\r\n};\r\n\r\n/**\r\n * Encodes a {@link Cartesian3} with 64-bit floating-point components as two {@link Cartesian3}\r\n * values that, when converted to 32-bit floating-point and added, approximate the original input.\r\n *

\r\n * The fixed-point encoding follows {@link https://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm|Precisions, Precisions}.\r\n *

\r\n *\r\n * @param {Cartesian3} cartesian The cartesian to encode.\r\n * @param {EncodedCartesian3} [result] The object onto which to store the result.\r\n * @returns {EncodedCartesian3} The modified result parameter or a new EncodedCartesian3 instance if one was not provided.\r\n *\r\n * @example\r\n * var cart = new Cesium.Cartesian3(-10000000.0, 0.0, 10000000.0);\r\n * var encoded = Cesium.EncodedCartesian3.fromCartesian(cart);\r\n */\r\nEncodedCartesian3.fromCartesian = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new EncodedCartesian3();\r\n }\r\n\r\n var high = result.high;\r\n var low = result.low;\r\n\r\n EncodedCartesian3.encode(cartesian.x, scratchEncode);\r\n high.x = scratchEncode.high;\r\n low.x = scratchEncode.low;\r\n\r\n EncodedCartesian3.encode(cartesian.y, scratchEncode);\r\n high.y = scratchEncode.high;\r\n low.y = scratchEncode.low;\r\n\r\n EncodedCartesian3.encode(cartesian.z, scratchEncode);\r\n high.z = scratchEncode.high;\r\n low.z = scratchEncode.low;\r\n\r\n return result;\r\n};\r\n\r\nvar encodedP = new EncodedCartesian3();\r\n\r\n/**\r\n * Encodes the provided cartesian, and writes it to an array with high\r\n * components followed by low components, i.e. [high.x, high.y, high.z, low.x, low.y, low.z].\r\n *

\r\n * This is used to create interleaved high-precision position vertex attributes.\r\n *

\r\n *\r\n * @param {Cartesian3} cartesian The cartesian to encode.\r\n * @param {Number[]} cartesianArray The array to write to.\r\n * @param {Number} index The index into the array to start writing. Six elements will be written.\r\n *\r\n * @exception {DeveloperError} index must be a number greater than or equal to 0.\r\n *\r\n * @example\r\n * var positions = [\r\n * new Cesium.Cartesian3(),\r\n * // ...\r\n * ];\r\n * var encodedPositions = new Float32Array(2 * 3 * positions.length);\r\n * var j = 0;\r\n * for (var i = 0; i < positions.length; ++i) {\r\n * Cesium.EncodedCartesian3.writeElement(positions[i], encodedPositions, j);\r\n * j += 6;\r\n * }\r\n */\r\nEncodedCartesian3.writeElements = function (cartesian, cartesianArray, index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"cartesianArray\", cartesianArray);\r\n Check.typeOf.number(\"index\", index);\r\n Check.typeOf.number.greaterThanOrEquals(\"index\", index, 0);\r\n //>>includeEnd('debug');\r\n\r\n EncodedCartesian3.fromCartesian(cartesian, encodedP);\r\n var high = encodedP.high;\r\n var low = encodedP.low;\r\n\r\n cartesianArray[index] = high.x;\r\n cartesianArray[index + 1] = high.y;\r\n cartesianArray[index + 2] = high.z;\r\n cartesianArray[index + 3] = low.x;\r\n cartesianArray[index + 4] = low.y;\r\n cartesianArray[index + 5] = low.z;\r\n};\r\nexport default EncodedCartesian3;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Encapsulates an algorithm to optimize triangles for the post\r\n * vertex-shader cache. This is based on the 2007 SIGGRAPH paper\r\n * 'Fast Triangle Reordering for Vertex Locality and Reduced Overdraw.'\r\n * The runtime is linear but several passes are made.\r\n *\r\n * @namespace Tipsify\r\n *\r\n * @see \r\n * Fast Triangle Reordering for Vertex Locality and Reduced Overdraw\r\n * by Sander, Nehab, and Barczak\r\n *\r\n * @private\r\n */\r\nvar Tipsify = {};\r\n\r\n/**\r\n * Calculates the average cache miss ratio (ACMR) for a given set of indices.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.indices Lists triads of numbers corresponding to the indices of the vertices\r\n * in the vertex buffer that define the geometry's triangles.\r\n * @param {Number} [options.maximumIndex] The maximum value of the elements in args.indices.\r\n * If not supplied, this value will be computed.\r\n * @param {Number} [options.cacheSize=24] The number of vertices that can be stored in the cache at any one time.\r\n * @returns {Number} The average cache miss ratio (ACMR).\r\n *\r\n * @exception {DeveloperError} indices length must be a multiple of three.\r\n * @exception {DeveloperError} cacheSize must be greater than two.\r\n *\r\n * @example\r\n * var indices = [0, 1, 2, 3, 4, 5];\r\n * var maxIndex = 5;\r\n * var cacheSize = 3;\r\n * var acmr = Cesium.Tipsify.calculateACMR({indices : indices, maxIndex : maxIndex, cacheSize : cacheSize});\r\n */\r\nTipsify.calculateACMR = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var indices = options.indices;\r\n var maximumIndex = options.maximumIndex;\r\n var cacheSize = defaultValue(options.cacheSize, 24);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(indices)) {\r\n throw new DeveloperError(\"indices is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var numIndices = indices.length;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numIndices < 3 || numIndices % 3 !== 0) {\r\n throw new DeveloperError(\"indices length must be a multiple of three.\");\r\n }\r\n if (maximumIndex <= 0) {\r\n throw new DeveloperError(\"maximumIndex must be greater than zero.\");\r\n }\r\n if (cacheSize < 3) {\r\n throw new DeveloperError(\"cacheSize must be greater than two.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Compute the maximumIndex if not given\r\n if (!defined(maximumIndex)) {\r\n maximumIndex = 0;\r\n var currentIndex = 0;\r\n var intoIndices = indices[currentIndex];\r\n while (currentIndex < numIndices) {\r\n if (intoIndices > maximumIndex) {\r\n maximumIndex = intoIndices;\r\n }\r\n ++currentIndex;\r\n intoIndices = indices[currentIndex];\r\n }\r\n }\r\n\r\n // Vertex time stamps\r\n var vertexTimeStamps = [];\r\n for (var i = 0; i < maximumIndex + 1; i++) {\r\n vertexTimeStamps[i] = 0;\r\n }\r\n\r\n // Cache processing\r\n var s = cacheSize + 1;\r\n for (var j = 0; j < numIndices; ++j) {\r\n if (s - vertexTimeStamps[indices[j]] > cacheSize) {\r\n vertexTimeStamps[indices[j]] = s;\r\n ++s;\r\n }\r\n }\r\n\r\n return (s - cacheSize + 1) / (numIndices / 3);\r\n};\r\n\r\n/**\r\n * Optimizes triangles for the post-vertex shader cache.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.indices Lists triads of numbers corresponding to the indices of the vertices\r\n * in the vertex buffer that define the geometry's triangles.\r\n * @param {Number} [options.maximumIndex] The maximum value of the elements in args.indices.\r\n * If not supplied, this value will be computed.\r\n * @param {Number} [options.cacheSize=24] The number of vertices that can be stored in the cache at any one time.\r\n * @returns {Number[]} A list of the input indices in an optimized order.\r\n *\r\n * @exception {DeveloperError} indices length must be a multiple of three.\r\n * @exception {DeveloperError} cacheSize must be greater than two.\r\n *\r\n * @example\r\n * var indices = [0, 1, 2, 3, 4, 5];\r\n * var maxIndex = 5;\r\n * var cacheSize = 3;\r\n * var reorderedIndices = Cesium.Tipsify.tipsify({indices : indices, maxIndex : maxIndex, cacheSize : cacheSize});\r\n */\r\nTipsify.tipsify = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var indices = options.indices;\r\n var maximumIndex = options.maximumIndex;\r\n var cacheSize = defaultValue(options.cacheSize, 24);\r\n\r\n var cursor;\r\n\r\n function skipDeadEnd(vertices, deadEnd, indices, maximumIndexPlusOne) {\r\n while (deadEnd.length >= 1) {\r\n // while the stack is not empty\r\n var d = deadEnd[deadEnd.length - 1]; // top of the stack\r\n deadEnd.splice(deadEnd.length - 1, 1); // pop the stack\r\n\r\n if (vertices[d].numLiveTriangles > 0) {\r\n return d;\r\n }\r\n }\r\n\r\n while (cursor < maximumIndexPlusOne) {\r\n if (vertices[cursor].numLiveTriangles > 0) {\r\n ++cursor;\r\n return cursor - 1;\r\n }\r\n ++cursor;\r\n }\r\n return -1;\r\n }\r\n\r\n function getNextVertex(\r\n indices,\r\n cacheSize,\r\n oneRing,\r\n vertices,\r\n s,\r\n deadEnd,\r\n maximumIndexPlusOne\r\n ) {\r\n var n = -1;\r\n var p;\r\n var m = -1;\r\n var itOneRing = 0;\r\n while (itOneRing < oneRing.length) {\r\n var index = oneRing[itOneRing];\r\n if (vertices[index].numLiveTriangles) {\r\n p = 0;\r\n if (\r\n s -\r\n vertices[index].timeStamp +\r\n 2 * vertices[index].numLiveTriangles <=\r\n cacheSize\r\n ) {\r\n p = s - vertices[index].timeStamp;\r\n }\r\n if (p > m || m === -1) {\r\n m = p;\r\n n = index;\r\n }\r\n }\r\n ++itOneRing;\r\n }\r\n if (n === -1) {\r\n return skipDeadEnd(vertices, deadEnd, indices, maximumIndexPlusOne);\r\n }\r\n return n;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(indices)) {\r\n throw new DeveloperError(\"indices is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var numIndices = indices.length;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numIndices < 3 || numIndices % 3 !== 0) {\r\n throw new DeveloperError(\"indices length must be a multiple of three.\");\r\n }\r\n if (maximumIndex <= 0) {\r\n throw new DeveloperError(\"maximumIndex must be greater than zero.\");\r\n }\r\n if (cacheSize < 3) {\r\n throw new DeveloperError(\"cacheSize must be greater than two.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Determine maximum index\r\n var maximumIndexPlusOne = 0;\r\n var currentIndex = 0;\r\n var intoIndices = indices[currentIndex];\r\n var endIndex = numIndices;\r\n if (defined(maximumIndex)) {\r\n maximumIndexPlusOne = maximumIndex + 1;\r\n } else {\r\n while (currentIndex < endIndex) {\r\n if (intoIndices > maximumIndexPlusOne) {\r\n maximumIndexPlusOne = intoIndices;\r\n }\r\n ++currentIndex;\r\n intoIndices = indices[currentIndex];\r\n }\r\n if (maximumIndexPlusOne === -1) {\r\n return 0;\r\n }\r\n ++maximumIndexPlusOne;\r\n }\r\n\r\n // Vertices\r\n var vertices = [];\r\n var i;\r\n for (i = 0; i < maximumIndexPlusOne; i++) {\r\n vertices[i] = {\r\n numLiveTriangles: 0,\r\n timeStamp: 0,\r\n vertexTriangles: [],\r\n };\r\n }\r\n currentIndex = 0;\r\n var triangle = 0;\r\n while (currentIndex < endIndex) {\r\n vertices[indices[currentIndex]].vertexTriangles.push(triangle);\r\n ++vertices[indices[currentIndex]].numLiveTriangles;\r\n vertices[indices[currentIndex + 1]].vertexTriangles.push(triangle);\r\n ++vertices[indices[currentIndex + 1]].numLiveTriangles;\r\n vertices[indices[currentIndex + 2]].vertexTriangles.push(triangle);\r\n ++vertices[indices[currentIndex + 2]].numLiveTriangles;\r\n ++triangle;\r\n currentIndex += 3;\r\n }\r\n\r\n // Starting index\r\n var f = 0;\r\n\r\n // Time Stamp\r\n var s = cacheSize + 1;\r\n cursor = 1;\r\n\r\n // Process\r\n var oneRing = [];\r\n var deadEnd = []; //Stack\r\n var vertex;\r\n var intoVertices;\r\n var currentOutputIndex = 0;\r\n var outputIndices = [];\r\n var numTriangles = numIndices / 3;\r\n var triangleEmitted = [];\r\n for (i = 0; i < numTriangles; i++) {\r\n triangleEmitted[i] = false;\r\n }\r\n var index;\r\n var limit;\r\n while (f !== -1) {\r\n oneRing = [];\r\n intoVertices = vertices[f];\r\n limit = intoVertices.vertexTriangles.length;\r\n for (var k = 0; k < limit; ++k) {\r\n triangle = intoVertices.vertexTriangles[k];\r\n if (!triangleEmitted[triangle]) {\r\n triangleEmitted[triangle] = true;\r\n currentIndex = triangle + triangle + triangle;\r\n for (var j = 0; j < 3; ++j) {\r\n // Set this index as a possible next index\r\n index = indices[currentIndex];\r\n oneRing.push(index);\r\n deadEnd.push(index);\r\n\r\n // Output index\r\n outputIndices[currentOutputIndex] = index;\r\n ++currentOutputIndex;\r\n\r\n // Cache processing\r\n vertex = vertices[index];\r\n --vertex.numLiveTriangles;\r\n if (s - vertex.timeStamp > cacheSize) {\r\n vertex.timeStamp = s;\r\n ++s;\r\n }\r\n ++currentIndex;\r\n }\r\n }\r\n }\r\n f = getNextVertex(\r\n indices,\r\n cacheSize,\r\n oneRing,\r\n vertices,\r\n s,\r\n deadEnd,\r\n maximumIndexPlusOne\r\n );\r\n }\r\n\r\n return outputIndices;\r\n};\r\nexport default Tipsify;\r\n","import AttributeCompression from \"./AttributeCompression.js\";\r\nimport barycentricCoordinates from \"./barycentricCoordinates.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport EncodedCartesian3 from \"./EncodedCartesian3.js\";\r\nimport GeographicProjection from \"./GeographicProjection.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryType from \"./GeometryType.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport Intersect from \"./Intersect.js\";\r\nimport IntersectionTests from \"./IntersectionTests.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport Plane from \"./Plane.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Tipsify from \"./Tipsify.js\";\r\n\r\n/**\r\n * Content pipeline functions for geometries.\r\n *\r\n * @namespace GeometryPipeline\r\n *\r\n * @see Geometry\r\n */\r\nvar GeometryPipeline = {};\r\n\r\nfunction addTriangle(lines, index, i0, i1, i2) {\r\n lines[index++] = i0;\r\n lines[index++] = i1;\r\n\r\n lines[index++] = i1;\r\n lines[index++] = i2;\r\n\r\n lines[index++] = i2;\r\n lines[index] = i0;\r\n}\r\n\r\nfunction trianglesToLines(triangles) {\r\n var count = triangles.length;\r\n var size = (count / 3) * 6;\r\n var lines = IndexDatatype.createTypedArray(count, size);\r\n\r\n var index = 0;\r\n for (var i = 0; i < count; i += 3, index += 6) {\r\n addTriangle(lines, index, triangles[i], triangles[i + 1], triangles[i + 2]);\r\n }\r\n\r\n return lines;\r\n}\r\n\r\nfunction triangleStripToLines(triangles) {\r\n var count = triangles.length;\r\n if (count >= 3) {\r\n var size = (count - 2) * 6;\r\n var lines = IndexDatatype.createTypedArray(count, size);\r\n\r\n addTriangle(lines, 0, triangles[0], triangles[1], triangles[2]);\r\n var index = 6;\r\n\r\n for (var i = 3; i < count; ++i, index += 6) {\r\n addTriangle(\r\n lines,\r\n index,\r\n triangles[i - 1],\r\n triangles[i],\r\n triangles[i - 2]\r\n );\r\n }\r\n\r\n return lines;\r\n }\r\n\r\n return new Uint16Array();\r\n}\r\n\r\nfunction triangleFanToLines(triangles) {\r\n if (triangles.length > 0) {\r\n var count = triangles.length - 1;\r\n var size = (count - 1) * 6;\r\n var lines = IndexDatatype.createTypedArray(count, size);\r\n\r\n var base = triangles[0];\r\n var index = 0;\r\n for (var i = 1; i < count; ++i, index += 6) {\r\n addTriangle(lines, index, base, triangles[i], triangles[i + 1]);\r\n }\r\n\r\n return lines;\r\n }\r\n\r\n return new Uint16Array();\r\n}\r\n\r\n/**\r\n * Converts a geometry's triangle indices to line indices. If the geometry has an indices\r\n * and its primitiveType is TRIANGLES, TRIANGLE_STRIP,\r\n * TRIANGLE_FAN, it is converted to LINES; otherwise, the geometry is not changed.\r\n *

\r\n * This is commonly used to create a wireframe geometry for visual debugging.\r\n *

\r\n *\r\n * @param {Geometry} geometry The geometry to modify.\r\n * @returns {Geometry} The modified geometry argument, with its triangle indices converted to lines.\r\n *\r\n * @exception {DeveloperError} geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN.\r\n *\r\n * @example\r\n * geometry = Cesium.GeometryPipeline.toWireframe(geometry);\r\n */\r\nGeometryPipeline.toWireframe = function (geometry) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = geometry.indices;\r\n if (defined(indices)) {\r\n switch (geometry.primitiveType) {\r\n case PrimitiveType.TRIANGLES:\r\n geometry.indices = trianglesToLines(indices);\r\n break;\r\n case PrimitiveType.TRIANGLE_STRIP:\r\n geometry.indices = triangleStripToLines(indices);\r\n break;\r\n case PrimitiveType.TRIANGLE_FAN:\r\n geometry.indices = triangleFanToLines(indices);\r\n break;\r\n //>>includeStart('debug', pragmas.debug);\r\n default:\r\n throw new DeveloperError(\r\n \"geometry.primitiveType must be TRIANGLES, TRIANGLE_STRIP, or TRIANGLE_FAN.\"\r\n );\r\n //>>includeEnd('debug');\r\n }\r\n\r\n geometry.primitiveType = PrimitiveType.LINES;\r\n }\r\n\r\n return geometry;\r\n};\r\n\r\n/**\r\n * Creates a new {@link Geometry} with LINES representing the provided\r\n * attribute (attributeName) for the provided geometry. This is used to\r\n * visualize vector attributes like normals, tangents, and bitangents.\r\n *\r\n * @param {Geometry} geometry The Geometry instance with the attribute.\r\n * @param {String} [attributeName='normal'] The name of the attribute.\r\n * @param {Number} [length=10000.0] The length of each line segment in meters. This can be negative to point the vector in the opposite direction.\r\n * @returns {Geometry} A new Geometry instance with line segments for the vector.\r\n *\r\n * @exception {DeveloperError} geometry.attributes must have an attribute with the same name as the attributeName parameter.\r\n *\r\n * @example\r\n * var geometry = Cesium.GeometryPipeline.createLineSegmentsForVectors(instance.geometry, 'bitangent', 100000.0);\r\n */\r\nGeometryPipeline.createLineSegmentsForVectors = function (\r\n geometry,\r\n attributeName,\r\n length\r\n) {\r\n attributeName = defaultValue(attributeName, \"normal\");\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n if (!defined(geometry.attributes.position)) {\r\n throw new DeveloperError(\"geometry.attributes.position is required.\");\r\n }\r\n if (!defined(geometry.attributes[attributeName])) {\r\n throw new DeveloperError(\r\n \"geometry.attributes must have an attribute with the same name as the attributeName parameter, \" +\r\n attributeName +\r\n \".\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n length = defaultValue(length, 10000.0);\r\n\r\n var positions = geometry.attributes.position.values;\r\n var vectors = geometry.attributes[attributeName].values;\r\n var positionsLength = positions.length;\r\n\r\n var newPositions = new Float64Array(2 * positionsLength);\r\n\r\n var j = 0;\r\n for (var i = 0; i < positionsLength; i += 3) {\r\n newPositions[j++] = positions[i];\r\n newPositions[j++] = positions[i + 1];\r\n newPositions[j++] = positions[i + 2];\r\n\r\n newPositions[j++] = positions[i] + vectors[i] * length;\r\n newPositions[j++] = positions[i + 1] + vectors[i + 1] * length;\r\n newPositions[j++] = positions[i + 2] + vectors[i + 2] * length;\r\n }\r\n\r\n var newBoundingSphere;\r\n var bs = geometry.boundingSphere;\r\n if (defined(bs)) {\r\n newBoundingSphere = new BoundingSphere(bs.center, bs.radius + length);\r\n }\r\n\r\n return new Geometry({\r\n attributes: {\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: newPositions,\r\n }),\r\n },\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: newBoundingSphere,\r\n });\r\n};\r\n\r\n/**\r\n * Creates an object that maps attribute names to unique locations (indices)\r\n * for matching vertex attributes and shader programs.\r\n *\r\n * @param {Geometry} geometry The geometry, which is not modified, to create the object for.\r\n * @returns {Object} An object with attribute name / index pairs.\r\n *\r\n * @example\r\n * var attributeLocations = Cesium.GeometryPipeline.createAttributeLocations(geometry);\r\n * // Example output\r\n * // {\r\n * // 'position' : 0,\r\n * // 'normal' : 1\r\n * // }\r\n */\r\nGeometryPipeline.createAttributeLocations = function (geometry) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n //>>includeEnd('debug')\r\n\r\n // There can be a WebGL performance hit when attribute 0 is disabled, so\r\n // assign attribute locations to well-known attributes.\r\n var semantics = [\r\n \"position\",\r\n \"positionHigh\",\r\n \"positionLow\",\r\n\r\n // From VertexFormat.position - after 2D projection and high-precision encoding\r\n \"position3DHigh\",\r\n \"position3DLow\",\r\n \"position2DHigh\",\r\n \"position2DLow\",\r\n\r\n // From Primitive\r\n \"pickColor\",\r\n\r\n // From VertexFormat\r\n \"normal\",\r\n \"st\",\r\n \"tangent\",\r\n \"bitangent\",\r\n\r\n // For shadow volumes\r\n \"extrudeDirection\",\r\n\r\n // From compressing texture coordinates and normals\r\n \"compressedAttributes\",\r\n ];\r\n\r\n var attributes = geometry.attributes;\r\n var indices = {};\r\n var j = 0;\r\n var i;\r\n var len = semantics.length;\r\n\r\n // Attribute locations for well-known attributes\r\n for (i = 0; i < len; ++i) {\r\n var semantic = semantics[i];\r\n\r\n if (defined(attributes[semantic])) {\r\n indices[semantic] = j++;\r\n }\r\n }\r\n\r\n // Locations for custom attributes\r\n for (var name in attributes) {\r\n if (attributes.hasOwnProperty(name) && !defined(indices[name])) {\r\n indices[name] = j++;\r\n }\r\n }\r\n\r\n return indices;\r\n};\r\n\r\n/**\r\n * Reorders a geometry's attributes and indices to achieve better performance from the GPU's pre-vertex-shader cache.\r\n *\r\n * @param {Geometry} geometry The geometry to modify.\r\n * @returns {Geometry} The modified geometry argument, with its attributes and indices reordered for the GPU's pre-vertex-shader cache.\r\n *\r\n * @exception {DeveloperError} Each attribute array in geometry.attributes must have the same number of attributes.\r\n *\r\n *\r\n * @example\r\n * geometry = Cesium.GeometryPipeline.reorderForPreVertexCache(geometry);\r\n *\r\n * @see GeometryPipeline.reorderForPostVertexCache\r\n */\r\nGeometryPipeline.reorderForPreVertexCache = function (geometry) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var numVertices = Geometry.computeNumberOfVertices(geometry);\r\n\r\n var indices = geometry.indices;\r\n if (defined(indices)) {\r\n var indexCrossReferenceOldToNew = new Int32Array(numVertices);\r\n for (var i = 0; i < numVertices; i++) {\r\n indexCrossReferenceOldToNew[i] = -1;\r\n }\r\n\r\n // Construct cross reference and reorder indices\r\n var indicesIn = indices;\r\n var numIndices = indicesIn.length;\r\n var indicesOut = IndexDatatype.createTypedArray(numVertices, numIndices);\r\n\r\n var intoIndicesIn = 0;\r\n var intoIndicesOut = 0;\r\n var nextIndex = 0;\r\n var tempIndex;\r\n while (intoIndicesIn < numIndices) {\r\n tempIndex = indexCrossReferenceOldToNew[indicesIn[intoIndicesIn]];\r\n if (tempIndex !== -1) {\r\n indicesOut[intoIndicesOut] = tempIndex;\r\n } else {\r\n tempIndex = indicesIn[intoIndicesIn];\r\n indexCrossReferenceOldToNew[tempIndex] = nextIndex;\r\n\r\n indicesOut[intoIndicesOut] = nextIndex;\r\n ++nextIndex;\r\n }\r\n ++intoIndicesIn;\r\n ++intoIndicesOut;\r\n }\r\n geometry.indices = indicesOut;\r\n\r\n // Reorder attributes\r\n var attributes = geometry.attributes;\r\n for (var property in attributes) {\r\n if (\r\n attributes.hasOwnProperty(property) &&\r\n defined(attributes[property]) &&\r\n defined(attributes[property].values)\r\n ) {\r\n var attribute = attributes[property];\r\n var elementsIn = attribute.values;\r\n var intoElementsIn = 0;\r\n var numComponents = attribute.componentsPerAttribute;\r\n var elementsOut = ComponentDatatype.createTypedArray(\r\n attribute.componentDatatype,\r\n nextIndex * numComponents\r\n );\r\n while (intoElementsIn < numVertices) {\r\n var temp = indexCrossReferenceOldToNew[intoElementsIn];\r\n if (temp !== -1) {\r\n for (var j = 0; j < numComponents; j++) {\r\n elementsOut[numComponents * temp + j] =\r\n elementsIn[numComponents * intoElementsIn + j];\r\n }\r\n }\r\n ++intoElementsIn;\r\n }\r\n attribute.values = elementsOut;\r\n }\r\n }\r\n }\r\n\r\n return geometry;\r\n};\r\n\r\n/**\r\n * Reorders a geometry's indices to achieve better performance from the GPU's\r\n * post vertex-shader cache by using the Tipsify algorithm. If the geometry primitiveType\r\n * is not TRIANGLES or the geometry does not have an indices, this function has no effect.\r\n *\r\n * @param {Geometry} geometry The geometry to modify.\r\n * @param {Number} [cacheCapacity=24] The number of vertices that can be held in the GPU's vertex cache.\r\n * @returns {Geometry} The modified geometry argument, with its indices reordered for the post-vertex-shader cache.\r\n *\r\n * @exception {DeveloperError} cacheCapacity must be greater than two.\r\n *\r\n *\r\n * @example\r\n * geometry = Cesium.GeometryPipeline.reorderForPostVertexCache(geometry);\r\n *\r\n * @see GeometryPipeline.reorderForPreVertexCache\r\n * @see {@link http://gfx.cs.princ0eton.edu/pubs/Sander_2007_%3ETR/tipsy.pdf|Fast Triangle Reordering for Vertex Locality and Reduced Overdraw}\r\n * by Sander, Nehab, and Barczak\r\n */\r\nGeometryPipeline.reorderForPostVertexCache = function (\r\n geometry,\r\n cacheCapacity\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = geometry.indices;\r\n if (geometry.primitiveType === PrimitiveType.TRIANGLES && defined(indices)) {\r\n var numIndices = indices.length;\r\n var maximumIndex = 0;\r\n for (var j = 0; j < numIndices; j++) {\r\n if (indices[j] > maximumIndex) {\r\n maximumIndex = indices[j];\r\n }\r\n }\r\n geometry.indices = Tipsify.tipsify({\r\n indices: indices,\r\n maximumIndex: maximumIndex,\r\n cacheSize: cacheCapacity,\r\n });\r\n }\r\n\r\n return geometry;\r\n};\r\n\r\nfunction copyAttributesDescriptions(attributes) {\r\n var newAttributes = {};\r\n\r\n for (var attribute in attributes) {\r\n if (\r\n attributes.hasOwnProperty(attribute) &&\r\n defined(attributes[attribute]) &&\r\n defined(attributes[attribute].values)\r\n ) {\r\n var attr = attributes[attribute];\r\n newAttributes[attribute] = new GeometryAttribute({\r\n componentDatatype: attr.componentDatatype,\r\n componentsPerAttribute: attr.componentsPerAttribute,\r\n normalize: attr.normalize,\r\n values: [],\r\n });\r\n }\r\n }\r\n\r\n return newAttributes;\r\n}\r\n\r\nfunction copyVertex(destinationAttributes, sourceAttributes, index) {\r\n for (var attribute in sourceAttributes) {\r\n if (\r\n sourceAttributes.hasOwnProperty(attribute) &&\r\n defined(sourceAttributes[attribute]) &&\r\n defined(sourceAttributes[attribute].values)\r\n ) {\r\n var attr = sourceAttributes[attribute];\r\n\r\n for (var k = 0; k < attr.componentsPerAttribute; ++k) {\r\n destinationAttributes[attribute].values.push(\r\n attr.values[index * attr.componentsPerAttribute + k]\r\n );\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Splits a geometry into multiple geometries, if necessary, to ensure that indices in the\r\n * indices fit into unsigned shorts. This is used to meet the WebGL requirements\r\n * when unsigned int indices are not supported.\r\n *

\r\n * If the geometry does not have any indices, this function has no effect.\r\n *

\r\n *\r\n * @param {Geometry} geometry The geometry to be split into multiple geometries.\r\n * @returns {Geometry[]} An array of geometries, each with indices that fit into unsigned shorts.\r\n *\r\n * @exception {DeveloperError} geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS\r\n * @exception {DeveloperError} All geometry attribute lists must have the same number of attributes.\r\n *\r\n * @example\r\n * var geometries = Cesium.GeometryPipeline.fitToUnsignedShortIndices(geometry);\r\n */\r\nGeometryPipeline.fitToUnsignedShortIndices = function (geometry) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n if (\r\n defined(geometry.indices) &&\r\n geometry.primitiveType !== PrimitiveType.TRIANGLES &&\r\n geometry.primitiveType !== PrimitiveType.LINES &&\r\n geometry.primitiveType !== PrimitiveType.POINTS\r\n ) {\r\n throw new DeveloperError(\r\n \"geometry.primitiveType must equal to PrimitiveType.TRIANGLES, PrimitiveType.LINES, or PrimitiveType.POINTS.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var geometries = [];\r\n\r\n // If there's an index list and more than 64K attributes, it is possible that\r\n // some indices are outside the range of unsigned short [0, 64K - 1]\r\n var numberOfVertices = Geometry.computeNumberOfVertices(geometry);\r\n if (\r\n defined(geometry.indices) &&\r\n numberOfVertices >= CesiumMath.SIXTY_FOUR_KILOBYTES\r\n ) {\r\n var oldToNewIndex = [];\r\n var newIndices = [];\r\n var currentIndex = 0;\r\n var newAttributes = copyAttributesDescriptions(geometry.attributes);\r\n\r\n var originalIndices = geometry.indices;\r\n var numberOfIndices = originalIndices.length;\r\n\r\n var indicesPerPrimitive;\r\n\r\n if (geometry.primitiveType === PrimitiveType.TRIANGLES) {\r\n indicesPerPrimitive = 3;\r\n } else if (geometry.primitiveType === PrimitiveType.LINES) {\r\n indicesPerPrimitive = 2;\r\n } else if (geometry.primitiveType === PrimitiveType.POINTS) {\r\n indicesPerPrimitive = 1;\r\n }\r\n\r\n for (var j = 0; j < numberOfIndices; j += indicesPerPrimitive) {\r\n for (var k = 0; k < indicesPerPrimitive; ++k) {\r\n var x = originalIndices[j + k];\r\n var i = oldToNewIndex[x];\r\n if (!defined(i)) {\r\n i = currentIndex++;\r\n oldToNewIndex[x] = i;\r\n copyVertex(newAttributes, geometry.attributes, x);\r\n }\r\n newIndices.push(i);\r\n }\r\n\r\n if (\r\n currentIndex + indicesPerPrimitive >=\r\n CesiumMath.SIXTY_FOUR_KILOBYTES\r\n ) {\r\n geometries.push(\r\n new Geometry({\r\n attributes: newAttributes,\r\n indices: newIndices,\r\n primitiveType: geometry.primitiveType,\r\n boundingSphere: geometry.boundingSphere,\r\n boundingSphereCV: geometry.boundingSphereCV,\r\n })\r\n );\r\n\r\n // Reset for next vertex-array\r\n oldToNewIndex = [];\r\n newIndices = [];\r\n currentIndex = 0;\r\n newAttributes = copyAttributesDescriptions(geometry.attributes);\r\n }\r\n }\r\n\r\n if (newIndices.length !== 0) {\r\n geometries.push(\r\n new Geometry({\r\n attributes: newAttributes,\r\n indices: newIndices,\r\n primitiveType: geometry.primitiveType,\r\n boundingSphere: geometry.boundingSphere,\r\n boundingSphereCV: geometry.boundingSphereCV,\r\n })\r\n );\r\n }\r\n } else {\r\n // No need to split into multiple geometries\r\n geometries.push(geometry);\r\n }\r\n\r\n return geometries;\r\n};\r\n\r\nvar scratchProjectTo2DCartesian3 = new Cartesian3();\r\nvar scratchProjectTo2DCartographic = new Cartographic();\r\n\r\n/**\r\n * Projects a geometry's 3D position attribute to 2D, replacing the position\r\n * attribute with separate position3D and position2D attributes.\r\n *

\r\n * If the geometry does not have a position, this function has no effect.\r\n *

\r\n *\r\n * @param {Geometry} geometry The geometry to modify.\r\n * @param {String} attributeName The name of the attribute.\r\n * @param {String} attributeName3D The name of the attribute in 3D.\r\n * @param {String} attributeName2D The name of the attribute in 2D.\r\n * @param {Object} [projection=new GeographicProjection()] The projection to use.\r\n * @returns {Geometry} The modified geometry argument with position3D and position2D attributes.\r\n *\r\n * @exception {DeveloperError} geometry must have attribute matching the attributeName argument.\r\n * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.DOUBLE.\r\n * @exception {DeveloperError} Could not project a point to 2D.\r\n *\r\n * @example\r\n * geometry = Cesium.GeometryPipeline.projectTo2D(geometry, 'position', 'position3D', 'position2D');\r\n */\r\nGeometryPipeline.projectTo2D = function (\r\n geometry,\r\n attributeName,\r\n attributeName3D,\r\n attributeName2D,\r\n projection\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n if (!defined(attributeName)) {\r\n throw new DeveloperError(\"attributeName is required.\");\r\n }\r\n if (!defined(attributeName3D)) {\r\n throw new DeveloperError(\"attributeName3D is required.\");\r\n }\r\n if (!defined(attributeName2D)) {\r\n throw new DeveloperError(\"attributeName2D is required.\");\r\n }\r\n if (!defined(geometry.attributes[attributeName])) {\r\n throw new DeveloperError(\r\n \"geometry must have attribute matching the attributeName argument: \" +\r\n attributeName +\r\n \".\"\r\n );\r\n }\r\n if (\r\n geometry.attributes[attributeName].componentDatatype !==\r\n ComponentDatatype.DOUBLE\r\n ) {\r\n throw new DeveloperError(\r\n \"The attribute componentDatatype must be ComponentDatatype.DOUBLE.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var attribute = geometry.attributes[attributeName];\r\n projection = defined(projection) ? projection : new GeographicProjection();\r\n var ellipsoid = projection.ellipsoid;\r\n\r\n // Project original values to 2D.\r\n var values3D = attribute.values;\r\n var projectedValues = new Float64Array(values3D.length);\r\n var index = 0;\r\n\r\n for (var i = 0; i < values3D.length; i += 3) {\r\n var value = Cartesian3.fromArray(values3D, i, scratchProjectTo2DCartesian3);\r\n\r\n var lonLat = ellipsoid.cartesianToCartographic(\r\n value,\r\n scratchProjectTo2DCartographic\r\n );\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(lonLat)) {\r\n throw new DeveloperError(\r\n \"Could not project point (\" +\r\n value.x +\r\n \", \" +\r\n value.y +\r\n \", \" +\r\n value.z +\r\n \") to 2D.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var projectedLonLat = projection.project(\r\n lonLat,\r\n scratchProjectTo2DCartesian3\r\n );\r\n\r\n projectedValues[index++] = projectedLonLat.x;\r\n projectedValues[index++] = projectedLonLat.y;\r\n projectedValues[index++] = projectedLonLat.z;\r\n }\r\n\r\n // Rename original cartesians to WGS84 cartesians.\r\n geometry.attributes[attributeName3D] = attribute;\r\n\r\n // Replace original cartesians with 2D projected cartesians\r\n geometry.attributes[attributeName2D] = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: projectedValues,\r\n });\r\n delete geometry.attributes[attributeName];\r\n\r\n return geometry;\r\n};\r\n\r\nvar encodedResult = {\r\n high: 0.0,\r\n low: 0.0,\r\n};\r\n\r\n/**\r\n * Encodes floating-point geometry attribute values as two separate attributes to improve\r\n * rendering precision.\r\n *

\r\n * This is commonly used to create high-precision position vertex attributes.\r\n *

\r\n *\r\n * @param {Geometry} geometry The geometry to modify.\r\n * @param {String} attributeName The name of the attribute.\r\n * @param {String} attributeHighName The name of the attribute for the encoded high bits.\r\n * @param {String} attributeLowName The name of the attribute for the encoded low bits.\r\n * @returns {Geometry} The modified geometry argument, with its encoded attribute.\r\n *\r\n * @exception {DeveloperError} geometry must have attribute matching the attributeName argument.\r\n * @exception {DeveloperError} The attribute componentDatatype must be ComponentDatatype.DOUBLE.\r\n *\r\n * @example\r\n * geometry = Cesium.GeometryPipeline.encodeAttribute(geometry, 'position3D', 'position3DHigh', 'position3DLow');\r\n */\r\nGeometryPipeline.encodeAttribute = function (\r\n geometry,\r\n attributeName,\r\n attributeHighName,\r\n attributeLowName\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n if (!defined(attributeName)) {\r\n throw new DeveloperError(\"attributeName is required.\");\r\n }\r\n if (!defined(attributeHighName)) {\r\n throw new DeveloperError(\"attributeHighName is required.\");\r\n }\r\n if (!defined(attributeLowName)) {\r\n throw new DeveloperError(\"attributeLowName is required.\");\r\n }\r\n if (!defined(geometry.attributes[attributeName])) {\r\n throw new DeveloperError(\r\n \"geometry must have attribute matching the attributeName argument: \" +\r\n attributeName +\r\n \".\"\r\n );\r\n }\r\n if (\r\n geometry.attributes[attributeName].componentDatatype !==\r\n ComponentDatatype.DOUBLE\r\n ) {\r\n throw new DeveloperError(\r\n \"The attribute componentDatatype must be ComponentDatatype.DOUBLE.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var attribute = geometry.attributes[attributeName];\r\n var values = attribute.values;\r\n var length = values.length;\r\n var highValues = new Float32Array(length);\r\n var lowValues = new Float32Array(length);\r\n\r\n for (var i = 0; i < length; ++i) {\r\n EncodedCartesian3.encode(values[i], encodedResult);\r\n highValues[i] = encodedResult.high;\r\n lowValues[i] = encodedResult.low;\r\n }\r\n\r\n var componentsPerAttribute = attribute.componentsPerAttribute;\r\n\r\n geometry.attributes[attributeHighName] = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: componentsPerAttribute,\r\n values: highValues,\r\n });\r\n geometry.attributes[attributeLowName] = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: componentsPerAttribute,\r\n values: lowValues,\r\n });\r\n delete geometry.attributes[attributeName];\r\n\r\n return geometry;\r\n};\r\n\r\nvar scratchCartesian3 = new Cartesian3();\r\n\r\nfunction transformPoint(matrix, attribute) {\r\n if (defined(attribute)) {\r\n var values = attribute.values;\r\n var length = values.length;\r\n for (var i = 0; i < length; i += 3) {\r\n Cartesian3.unpack(values, i, scratchCartesian3);\r\n Matrix4.multiplyByPoint(matrix, scratchCartesian3, scratchCartesian3);\r\n Cartesian3.pack(scratchCartesian3, values, i);\r\n }\r\n }\r\n}\r\n\r\nfunction transformVector(matrix, attribute) {\r\n if (defined(attribute)) {\r\n var values = attribute.values;\r\n var length = values.length;\r\n for (var i = 0; i < length; i += 3) {\r\n Cartesian3.unpack(values, i, scratchCartesian3);\r\n Matrix3.multiplyByVector(matrix, scratchCartesian3, scratchCartesian3);\r\n scratchCartesian3 = Cartesian3.normalize(\r\n scratchCartesian3,\r\n scratchCartesian3\r\n );\r\n Cartesian3.pack(scratchCartesian3, values, i);\r\n }\r\n }\r\n}\r\n\r\nvar inverseTranspose = new Matrix4();\r\nvar normalMatrix = new Matrix3();\r\n\r\n/**\r\n * Transforms a geometry instance to world coordinates. This changes\r\n * the instance's modelMatrix to {@link Matrix4.IDENTITY} and transforms the\r\n * following attributes if they are present: position, normal,\r\n * tangent, and bitangent.\r\n *\r\n * @param {GeometryInstance} instance The geometry instance to modify.\r\n * @returns {GeometryInstance} The modified instance argument, with its attributes transforms to world coordinates.\r\n *\r\n * @example\r\n * Cesium.GeometryPipeline.transformToWorldCoordinates(instance);\r\n */\r\nGeometryPipeline.transformToWorldCoordinates = function (instance) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(instance)) {\r\n throw new DeveloperError(\"instance is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var modelMatrix = instance.modelMatrix;\r\n\r\n if (Matrix4.equals(modelMatrix, Matrix4.IDENTITY)) {\r\n // Already in world coordinates\r\n return instance;\r\n }\r\n\r\n var attributes = instance.geometry.attributes;\r\n\r\n // Transform attributes in known vertex formats\r\n transformPoint(modelMatrix, attributes.position);\r\n transformPoint(modelMatrix, attributes.prevPosition);\r\n transformPoint(modelMatrix, attributes.nextPosition);\r\n\r\n if (\r\n defined(attributes.normal) ||\r\n defined(attributes.tangent) ||\r\n defined(attributes.bitangent)\r\n ) {\r\n Matrix4.inverse(modelMatrix, inverseTranspose);\r\n Matrix4.transpose(inverseTranspose, inverseTranspose);\r\n Matrix4.getMatrix3(inverseTranspose, normalMatrix);\r\n\r\n transformVector(normalMatrix, attributes.normal);\r\n transformVector(normalMatrix, attributes.tangent);\r\n transformVector(normalMatrix, attributes.bitangent);\r\n }\r\n\r\n var boundingSphere = instance.geometry.boundingSphere;\r\n if (defined(boundingSphere)) {\r\n instance.geometry.boundingSphere = BoundingSphere.transform(\r\n boundingSphere,\r\n modelMatrix,\r\n boundingSphere\r\n );\r\n }\r\n\r\n instance.modelMatrix = Matrix4.clone(Matrix4.IDENTITY);\r\n\r\n return instance;\r\n};\r\n\r\nfunction findAttributesInAllGeometries(instances, propertyName) {\r\n var length = instances.length;\r\n\r\n var attributesInAllGeometries = {};\r\n\r\n var attributes0 = instances[0][propertyName].attributes;\r\n var name;\r\n\r\n for (name in attributes0) {\r\n if (\r\n attributes0.hasOwnProperty(name) &&\r\n defined(attributes0[name]) &&\r\n defined(attributes0[name].values)\r\n ) {\r\n var attribute = attributes0[name];\r\n var numberOfComponents = attribute.values.length;\r\n var inAllGeometries = true;\r\n\r\n // Does this same attribute exist in all geometries?\r\n for (var i = 1; i < length; ++i) {\r\n var otherAttribute = instances[i][propertyName].attributes[name];\r\n\r\n if (\r\n !defined(otherAttribute) ||\r\n attribute.componentDatatype !== otherAttribute.componentDatatype ||\r\n attribute.componentsPerAttribute !==\r\n otherAttribute.componentsPerAttribute ||\r\n attribute.normalize !== otherAttribute.normalize\r\n ) {\r\n inAllGeometries = false;\r\n break;\r\n }\r\n\r\n numberOfComponents += otherAttribute.values.length;\r\n }\r\n\r\n if (inAllGeometries) {\r\n attributesInAllGeometries[name] = new GeometryAttribute({\r\n componentDatatype: attribute.componentDatatype,\r\n componentsPerAttribute: attribute.componentsPerAttribute,\r\n normalize: attribute.normalize,\r\n values: ComponentDatatype.createTypedArray(\r\n attribute.componentDatatype,\r\n numberOfComponents\r\n ),\r\n });\r\n }\r\n }\r\n }\r\n\r\n return attributesInAllGeometries;\r\n}\r\n\r\nvar tempScratch = new Cartesian3();\r\n\r\nfunction combineGeometries(instances, propertyName) {\r\n var length = instances.length;\r\n\r\n var name;\r\n var i;\r\n var j;\r\n var k;\r\n\r\n var m = instances[0].modelMatrix;\r\n var haveIndices = defined(instances[0][propertyName].indices);\r\n var primitiveType = instances[0][propertyName].primitiveType;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n for (i = 1; i < length; ++i) {\r\n if (!Matrix4.equals(instances[i].modelMatrix, m)) {\r\n throw new DeveloperError(\"All instances must have the same modelMatrix.\");\r\n }\r\n if (defined(instances[i][propertyName].indices) !== haveIndices) {\r\n throw new DeveloperError(\r\n \"All instance geometries must have an indices or not have one.\"\r\n );\r\n }\r\n if (instances[i][propertyName].primitiveType !== primitiveType) {\r\n throw new DeveloperError(\r\n \"All instance geometries must have the same primitiveType.\"\r\n );\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Find subset of attributes in all geometries\r\n var attributes = findAttributesInAllGeometries(instances, propertyName);\r\n var values;\r\n var sourceValues;\r\n var sourceValuesLength;\r\n\r\n // Combine attributes from each geometry into a single typed array\r\n for (name in attributes) {\r\n if (attributes.hasOwnProperty(name)) {\r\n values = attributes[name].values;\r\n\r\n k = 0;\r\n for (i = 0; i < length; ++i) {\r\n sourceValues = instances[i][propertyName].attributes[name].values;\r\n sourceValuesLength = sourceValues.length;\r\n\r\n for (j = 0; j < sourceValuesLength; ++j) {\r\n values[k++] = sourceValues[j];\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Combine index lists\r\n var indices;\r\n\r\n if (haveIndices) {\r\n var numberOfIndices = 0;\r\n for (i = 0; i < length; ++i) {\r\n numberOfIndices += instances[i][propertyName].indices.length;\r\n }\r\n\r\n var numberOfVertices = Geometry.computeNumberOfVertices(\r\n new Geometry({\r\n attributes: attributes,\r\n primitiveType: PrimitiveType.POINTS,\r\n })\r\n );\r\n var destIndices = IndexDatatype.createTypedArray(\r\n numberOfVertices,\r\n numberOfIndices\r\n );\r\n\r\n var destOffset = 0;\r\n var offset = 0;\r\n\r\n for (i = 0; i < length; ++i) {\r\n var sourceIndices = instances[i][propertyName].indices;\r\n var sourceIndicesLen = sourceIndices.length;\r\n\r\n for (k = 0; k < sourceIndicesLen; ++k) {\r\n destIndices[destOffset++] = offset + sourceIndices[k];\r\n }\r\n\r\n offset += Geometry.computeNumberOfVertices(instances[i][propertyName]);\r\n }\r\n\r\n indices = destIndices;\r\n }\r\n\r\n // Create bounding sphere that includes all instances\r\n var center = new Cartesian3();\r\n var radius = 0.0;\r\n var bs;\r\n\r\n for (i = 0; i < length; ++i) {\r\n bs = instances[i][propertyName].boundingSphere;\r\n if (!defined(bs)) {\r\n // If any geometries have an undefined bounding sphere, then so does the combined geometry\r\n center = undefined;\r\n break;\r\n }\r\n\r\n Cartesian3.add(bs.center, center, center);\r\n }\r\n\r\n if (defined(center)) {\r\n Cartesian3.divideByScalar(center, length, center);\r\n\r\n for (i = 0; i < length; ++i) {\r\n bs = instances[i][propertyName].boundingSphere;\r\n var tempRadius =\r\n Cartesian3.magnitude(\r\n Cartesian3.subtract(bs.center, center, tempScratch)\r\n ) + bs.radius;\r\n\r\n if (tempRadius > radius) {\r\n radius = tempRadius;\r\n }\r\n }\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: primitiveType,\r\n boundingSphere: defined(center)\r\n ? new BoundingSphere(center, radius)\r\n : undefined,\r\n });\r\n}\r\n\r\n/**\r\n * Combines geometry from several {@link GeometryInstance} objects into one geometry.\r\n * This concatenates the attributes, concatenates and adjusts the indices, and creates\r\n * a bounding sphere encompassing all instances.\r\n *

\r\n * If the instances do not have the same attributes, a subset of attributes common\r\n * to all instances is used, and the others are ignored.\r\n *

\r\n *

\r\n * This is used by {@link Primitive} to efficiently render a large amount of static data.\r\n *

\r\n *\r\n * @private\r\n *\r\n * @param {GeometryInstance[]} [instances] The array of {@link GeometryInstance} objects whose geometry will be combined.\r\n * @returns {Geometry} A single geometry created from the provided geometry instances.\r\n *\r\n * @exception {DeveloperError} All instances must have the same modelMatrix.\r\n * @exception {DeveloperError} All instance geometries must have an indices or not have one.\r\n * @exception {DeveloperError} All instance geometries must have the same primitiveType.\r\n *\r\n *\r\n * @example\r\n * for (var i = 0; i < instances.length; ++i) {\r\n * Cesium.GeometryPipeline.transformToWorldCoordinates(instances[i]);\r\n * }\r\n * var geometries = Cesium.GeometryPipeline.combineInstances(instances);\r\n *\r\n * @see GeometryPipeline.transformToWorldCoordinates\r\n */\r\nGeometryPipeline.combineInstances = function (instances) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(instances) || instances.length < 1) {\r\n throw new DeveloperError(\r\n \"instances is required and must have length greater than zero.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var instanceGeometry = [];\r\n var instanceSplitGeometry = [];\r\n var length = instances.length;\r\n for (var i = 0; i < length; ++i) {\r\n var instance = instances[i];\r\n\r\n if (defined(instance.geometry)) {\r\n instanceGeometry.push(instance);\r\n } else if (\r\n defined(instance.westHemisphereGeometry) &&\r\n defined(instance.eastHemisphereGeometry)\r\n ) {\r\n instanceSplitGeometry.push(instance);\r\n }\r\n }\r\n\r\n var geometries = [];\r\n if (instanceGeometry.length > 0) {\r\n geometries.push(combineGeometries(instanceGeometry, \"geometry\"));\r\n }\r\n\r\n if (instanceSplitGeometry.length > 0) {\r\n geometries.push(\r\n combineGeometries(instanceSplitGeometry, \"westHemisphereGeometry\")\r\n );\r\n geometries.push(\r\n combineGeometries(instanceSplitGeometry, \"eastHemisphereGeometry\")\r\n );\r\n }\r\n\r\n return geometries;\r\n};\r\n\r\nvar normal = new Cartesian3();\r\nvar v0 = new Cartesian3();\r\nvar v1 = new Cartesian3();\r\nvar v2 = new Cartesian3();\r\n\r\n/**\r\n * Computes per-vertex normals for a geometry containing TRIANGLES by averaging the normals of\r\n * all triangles incident to the vertex. The result is a new normal attribute added to the geometry.\r\n * This assumes a counter-clockwise winding order.\r\n *\r\n * @param {Geometry} geometry The geometry to modify.\r\n * @returns {Geometry} The modified geometry argument with the computed normal attribute.\r\n *\r\n * @exception {DeveloperError} geometry.indices length must be greater than 0 and be a multiple of 3.\r\n * @exception {DeveloperError} geometry.primitiveType must be {@link PrimitiveType.TRIANGLES}.\r\n *\r\n * @example\r\n * Cesium.GeometryPipeline.computeNormal(geometry);\r\n */\r\nGeometryPipeline.computeNormal = function (geometry) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n if (\r\n !defined(geometry.attributes.position) ||\r\n !defined(geometry.attributes.position.values)\r\n ) {\r\n throw new DeveloperError(\r\n \"geometry.attributes.position.values is required.\"\r\n );\r\n }\r\n if (!defined(geometry.indices)) {\r\n throw new DeveloperError(\"geometry.indices is required.\");\r\n }\r\n if (geometry.indices.length < 2 || geometry.indices.length % 3 !== 0) {\r\n throw new DeveloperError(\r\n \"geometry.indices length must be greater than 0 and be a multiple of 3.\"\r\n );\r\n }\r\n if (geometry.primitiveType !== PrimitiveType.TRIANGLES) {\r\n throw new DeveloperError(\r\n \"geometry.primitiveType must be PrimitiveType.TRIANGLES.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = geometry.indices;\r\n var attributes = geometry.attributes;\r\n var vertices = attributes.position.values;\r\n var numVertices = attributes.position.values.length / 3;\r\n var numIndices = indices.length;\r\n var normalsPerVertex = new Array(numVertices);\r\n var normalsPerTriangle = new Array(numIndices / 3);\r\n var normalIndices = new Array(numIndices);\r\n var i;\r\n for (i = 0; i < numVertices; i++) {\r\n normalsPerVertex[i] = {\r\n indexOffset: 0,\r\n count: 0,\r\n currentCount: 0,\r\n };\r\n }\r\n\r\n var j = 0;\r\n for (i = 0; i < numIndices; i += 3) {\r\n var i0 = indices[i];\r\n var i1 = indices[i + 1];\r\n var i2 = indices[i + 2];\r\n var i03 = i0 * 3;\r\n var i13 = i1 * 3;\r\n var i23 = i2 * 3;\r\n\r\n v0.x = vertices[i03];\r\n v0.y = vertices[i03 + 1];\r\n v0.z = vertices[i03 + 2];\r\n v1.x = vertices[i13];\r\n v1.y = vertices[i13 + 1];\r\n v1.z = vertices[i13 + 2];\r\n v2.x = vertices[i23];\r\n v2.y = vertices[i23 + 1];\r\n v2.z = vertices[i23 + 2];\r\n\r\n normalsPerVertex[i0].count++;\r\n normalsPerVertex[i1].count++;\r\n normalsPerVertex[i2].count++;\r\n\r\n Cartesian3.subtract(v1, v0, v1);\r\n Cartesian3.subtract(v2, v0, v2);\r\n normalsPerTriangle[j] = Cartesian3.cross(v1, v2, new Cartesian3());\r\n j++;\r\n }\r\n\r\n var indexOffset = 0;\r\n for (i = 0; i < numVertices; i++) {\r\n normalsPerVertex[i].indexOffset += indexOffset;\r\n indexOffset += normalsPerVertex[i].count;\r\n }\r\n\r\n j = 0;\r\n var vertexNormalData;\r\n for (i = 0; i < numIndices; i += 3) {\r\n vertexNormalData = normalsPerVertex[indices[i]];\r\n var index = vertexNormalData.indexOffset + vertexNormalData.currentCount;\r\n normalIndices[index] = j;\r\n vertexNormalData.currentCount++;\r\n\r\n vertexNormalData = normalsPerVertex[indices[i + 1]];\r\n index = vertexNormalData.indexOffset + vertexNormalData.currentCount;\r\n normalIndices[index] = j;\r\n vertexNormalData.currentCount++;\r\n\r\n vertexNormalData = normalsPerVertex[indices[i + 2]];\r\n index = vertexNormalData.indexOffset + vertexNormalData.currentCount;\r\n normalIndices[index] = j;\r\n vertexNormalData.currentCount++;\r\n\r\n j++;\r\n }\r\n\r\n var normalValues = new Float32Array(numVertices * 3);\r\n for (i = 0; i < numVertices; i++) {\r\n var i3 = i * 3;\r\n vertexNormalData = normalsPerVertex[i];\r\n Cartesian3.clone(Cartesian3.ZERO, normal);\r\n if (vertexNormalData.count > 0) {\r\n for (j = 0; j < vertexNormalData.count; j++) {\r\n Cartesian3.add(\r\n normal,\r\n normalsPerTriangle[normalIndices[vertexNormalData.indexOffset + j]],\r\n normal\r\n );\r\n }\r\n\r\n // We can run into an issue where a vertex is used with 2 primitives that have opposite winding order.\r\n if (\r\n Cartesian3.equalsEpsilon(Cartesian3.ZERO, normal, CesiumMath.EPSILON10)\r\n ) {\r\n Cartesian3.clone(\r\n normalsPerTriangle[normalIndices[vertexNormalData.indexOffset]],\r\n normal\r\n );\r\n }\r\n }\r\n\r\n // We end up with a zero vector probably because of a degenerate triangle\r\n if (\r\n Cartesian3.equalsEpsilon(Cartesian3.ZERO, normal, CesiumMath.EPSILON10)\r\n ) {\r\n // Default to (0,0,1)\r\n normal.z = 1.0;\r\n }\r\n\r\n Cartesian3.normalize(normal, normal);\r\n normalValues[i3] = normal.x;\r\n normalValues[i3 + 1] = normal.y;\r\n normalValues[i3 + 2] = normal.z;\r\n }\r\n\r\n geometry.attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normalValues,\r\n });\r\n\r\n return geometry;\r\n};\r\n\r\nvar normalScratch = new Cartesian3();\r\nvar normalScale = new Cartesian3();\r\nvar tScratch = new Cartesian3();\r\n\r\n/**\r\n * Computes per-vertex tangents and bitangents for a geometry containing TRIANGLES.\r\n * The result is new tangent and bitangent attributes added to the geometry.\r\n * This assumes a counter-clockwise winding order.\r\n *

\r\n * Based on Computing Tangent Space Basis Vectors\r\n * for an Arbitrary Mesh by Eric Lengyel.\r\n *

\r\n *\r\n * @param {Geometry} geometry The geometry to modify.\r\n * @returns {Geometry} The modified geometry argument with the computed tangent and bitangent attributes.\r\n *\r\n * @exception {DeveloperError} geometry.indices length must be greater than 0 and be a multiple of 3.\r\n * @exception {DeveloperError} geometry.primitiveType must be {@link PrimitiveType.TRIANGLES}.\r\n *\r\n * @example\r\n * Cesium.GeometryPipeline.computeTangentAndBiTangent(geometry);\r\n */\r\nGeometryPipeline.computeTangentAndBitangent = function (geometry) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var attributes = geometry.attributes;\r\n var indices = geometry.indices;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(attributes.position) || !defined(attributes.position.values)) {\r\n throw new DeveloperError(\r\n \"geometry.attributes.position.values is required.\"\r\n );\r\n }\r\n if (!defined(attributes.normal) || !defined(attributes.normal.values)) {\r\n throw new DeveloperError(\"geometry.attributes.normal.values is required.\");\r\n }\r\n if (!defined(attributes.st) || !defined(attributes.st.values)) {\r\n throw new DeveloperError(\"geometry.attributes.st.values is required.\");\r\n }\r\n if (!defined(indices)) {\r\n throw new DeveloperError(\"geometry.indices is required.\");\r\n }\r\n if (indices.length < 2 || indices.length % 3 !== 0) {\r\n throw new DeveloperError(\r\n \"geometry.indices length must be greater than 0 and be a multiple of 3.\"\r\n );\r\n }\r\n if (geometry.primitiveType !== PrimitiveType.TRIANGLES) {\r\n throw new DeveloperError(\r\n \"geometry.primitiveType must be PrimitiveType.TRIANGLES.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var vertices = geometry.attributes.position.values;\r\n var normals = geometry.attributes.normal.values;\r\n var st = geometry.attributes.st.values;\r\n\r\n var numVertices = geometry.attributes.position.values.length / 3;\r\n var numIndices = indices.length;\r\n var tan1 = new Array(numVertices * 3);\r\n\r\n var i;\r\n for (i = 0; i < tan1.length; i++) {\r\n tan1[i] = 0;\r\n }\r\n\r\n var i03;\r\n var i13;\r\n var i23;\r\n for (i = 0; i < numIndices; i += 3) {\r\n var i0 = indices[i];\r\n var i1 = indices[i + 1];\r\n var i2 = indices[i + 2];\r\n i03 = i0 * 3;\r\n i13 = i1 * 3;\r\n i23 = i2 * 3;\r\n var i02 = i0 * 2;\r\n var i12 = i1 * 2;\r\n var i22 = i2 * 2;\r\n\r\n var ux = vertices[i03];\r\n var uy = vertices[i03 + 1];\r\n var uz = vertices[i03 + 2];\r\n\r\n var wx = st[i02];\r\n var wy = st[i02 + 1];\r\n var t1 = st[i12 + 1] - wy;\r\n var t2 = st[i22 + 1] - wy;\r\n\r\n var r = 1.0 / ((st[i12] - wx) * t2 - (st[i22] - wx) * t1);\r\n var sdirx = (t2 * (vertices[i13] - ux) - t1 * (vertices[i23] - ux)) * r;\r\n var sdiry =\r\n (t2 * (vertices[i13 + 1] - uy) - t1 * (vertices[i23 + 1] - uy)) * r;\r\n var sdirz =\r\n (t2 * (vertices[i13 + 2] - uz) - t1 * (vertices[i23 + 2] - uz)) * r;\r\n\r\n tan1[i03] += sdirx;\r\n tan1[i03 + 1] += sdiry;\r\n tan1[i03 + 2] += sdirz;\r\n\r\n tan1[i13] += sdirx;\r\n tan1[i13 + 1] += sdiry;\r\n tan1[i13 + 2] += sdirz;\r\n\r\n tan1[i23] += sdirx;\r\n tan1[i23 + 1] += sdiry;\r\n tan1[i23 + 2] += sdirz;\r\n }\r\n\r\n var tangentValues = new Float32Array(numVertices * 3);\r\n var bitangentValues = new Float32Array(numVertices * 3);\r\n\r\n for (i = 0; i < numVertices; i++) {\r\n i03 = i * 3;\r\n i13 = i03 + 1;\r\n i23 = i03 + 2;\r\n\r\n var n = Cartesian3.fromArray(normals, i03, normalScratch);\r\n var t = Cartesian3.fromArray(tan1, i03, tScratch);\r\n var scalar = Cartesian3.dot(n, t);\r\n Cartesian3.multiplyByScalar(n, scalar, normalScale);\r\n Cartesian3.normalize(Cartesian3.subtract(t, normalScale, t), t);\r\n\r\n tangentValues[i03] = t.x;\r\n tangentValues[i13] = t.y;\r\n tangentValues[i23] = t.z;\r\n\r\n Cartesian3.normalize(Cartesian3.cross(n, t, t), t);\r\n\r\n bitangentValues[i03] = t.x;\r\n bitangentValues[i13] = t.y;\r\n bitangentValues[i23] = t.z;\r\n }\r\n\r\n geometry.attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangentValues,\r\n });\r\n\r\n geometry.attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangentValues,\r\n });\r\n\r\n return geometry;\r\n};\r\n\r\nvar scratchCartesian2 = new Cartesian2();\r\nvar toEncode1 = new Cartesian3();\r\nvar toEncode2 = new Cartesian3();\r\nvar toEncode3 = new Cartesian3();\r\nvar encodeResult2 = new Cartesian2();\r\n/**\r\n * Compresses and packs geometry normal attribute values to save memory.\r\n *\r\n * @param {Geometry} geometry The geometry to modify.\r\n * @returns {Geometry} The modified geometry argument, with its normals compressed and packed.\r\n *\r\n * @example\r\n * geometry = Cesium.GeometryPipeline.compressVertices(geometry);\r\n */\r\nGeometryPipeline.compressVertices = function (geometry) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry)) {\r\n throw new DeveloperError(\"geometry is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var extrudeAttribute = geometry.attributes.extrudeDirection;\r\n var i;\r\n var numVertices;\r\n if (defined(extrudeAttribute)) {\r\n //only shadow volumes use extrudeDirection, and shadow volumes use vertexFormat: POSITION_ONLY so we don't need to check other attributes\r\n var extrudeDirections = extrudeAttribute.values;\r\n numVertices = extrudeDirections.length / 3.0;\r\n var compressedDirections = new Float32Array(numVertices * 2);\r\n\r\n var i2 = 0;\r\n for (i = 0; i < numVertices; ++i) {\r\n Cartesian3.fromArray(extrudeDirections, i * 3.0, toEncode1);\r\n if (Cartesian3.equals(toEncode1, Cartesian3.ZERO)) {\r\n i2 += 2;\r\n continue;\r\n }\r\n encodeResult2 = AttributeCompression.octEncodeInRange(\r\n toEncode1,\r\n 65535,\r\n encodeResult2\r\n );\r\n compressedDirections[i2++] = encodeResult2.x;\r\n compressedDirections[i2++] = encodeResult2.y;\r\n }\r\n\r\n geometry.attributes.compressedAttributes = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: compressedDirections,\r\n });\r\n delete geometry.attributes.extrudeDirection;\r\n return geometry;\r\n }\r\n\r\n var normalAttribute = geometry.attributes.normal;\r\n var stAttribute = geometry.attributes.st;\r\n\r\n var hasNormal = defined(normalAttribute);\r\n var hasSt = defined(stAttribute);\r\n if (!hasNormal && !hasSt) {\r\n return geometry;\r\n }\r\n\r\n var tangentAttribute = geometry.attributes.tangent;\r\n var bitangentAttribute = geometry.attributes.bitangent;\r\n\r\n var hasTangent = defined(tangentAttribute);\r\n var hasBitangent = defined(bitangentAttribute);\r\n\r\n var normals;\r\n var st;\r\n var tangents;\r\n var bitangents;\r\n\r\n if (hasNormal) {\r\n normals = normalAttribute.values;\r\n }\r\n if (hasSt) {\r\n st = stAttribute.values;\r\n }\r\n if (hasTangent) {\r\n tangents = tangentAttribute.values;\r\n }\r\n if (hasBitangent) {\r\n bitangents = bitangentAttribute.values;\r\n }\r\n\r\n var length = hasNormal ? normals.length : st.length;\r\n var numComponents = hasNormal ? 3.0 : 2.0;\r\n numVertices = length / numComponents;\r\n\r\n var compressedLength = numVertices;\r\n var numCompressedComponents = hasSt && hasNormal ? 2.0 : 1.0;\r\n numCompressedComponents += hasTangent || hasBitangent ? 1.0 : 0.0;\r\n compressedLength *= numCompressedComponents;\r\n\r\n var compressedAttributes = new Float32Array(compressedLength);\r\n\r\n var normalIndex = 0;\r\n for (i = 0; i < numVertices; ++i) {\r\n if (hasSt) {\r\n Cartesian2.fromArray(st, i * 2.0, scratchCartesian2);\r\n compressedAttributes[\r\n normalIndex++\r\n ] = AttributeCompression.compressTextureCoordinates(scratchCartesian2);\r\n }\r\n\r\n var index = i * 3.0;\r\n if (hasNormal && defined(tangents) && defined(bitangents)) {\r\n Cartesian3.fromArray(normals, index, toEncode1);\r\n Cartesian3.fromArray(tangents, index, toEncode2);\r\n Cartesian3.fromArray(bitangents, index, toEncode3);\r\n\r\n AttributeCompression.octPack(\r\n toEncode1,\r\n toEncode2,\r\n toEncode3,\r\n scratchCartesian2\r\n );\r\n compressedAttributes[normalIndex++] = scratchCartesian2.x;\r\n compressedAttributes[normalIndex++] = scratchCartesian2.y;\r\n } else {\r\n if (hasNormal) {\r\n Cartesian3.fromArray(normals, index, toEncode1);\r\n compressedAttributes[\r\n normalIndex++\r\n ] = AttributeCompression.octEncodeFloat(toEncode1);\r\n }\r\n\r\n if (hasTangent) {\r\n Cartesian3.fromArray(tangents, index, toEncode1);\r\n compressedAttributes[\r\n normalIndex++\r\n ] = AttributeCompression.octEncodeFloat(toEncode1);\r\n }\r\n\r\n if (hasBitangent) {\r\n Cartesian3.fromArray(bitangents, index, toEncode1);\r\n compressedAttributes[\r\n normalIndex++\r\n ] = AttributeCompression.octEncodeFloat(toEncode1);\r\n }\r\n }\r\n }\r\n\r\n geometry.attributes.compressedAttributes = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: numCompressedComponents,\r\n values: compressedAttributes,\r\n });\r\n\r\n if (hasNormal) {\r\n delete geometry.attributes.normal;\r\n }\r\n if (hasSt) {\r\n delete geometry.attributes.st;\r\n }\r\n if (hasBitangent) {\r\n delete geometry.attributes.bitangent;\r\n }\r\n if (hasTangent) {\r\n delete geometry.attributes.tangent;\r\n }\r\n\r\n return geometry;\r\n};\r\n\r\nfunction indexTriangles(geometry) {\r\n if (defined(geometry.indices)) {\r\n return geometry;\r\n }\r\n var numberOfVertices = Geometry.computeNumberOfVertices(geometry);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numberOfVertices < 3) {\r\n throw new DeveloperError(\"The number of vertices must be at least three.\");\r\n }\r\n if (numberOfVertices % 3 !== 0) {\r\n throw new DeveloperError(\r\n \"The number of vertices must be a multiple of three.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = IndexDatatype.createTypedArray(\r\n numberOfVertices,\r\n numberOfVertices\r\n );\r\n for (var i = 0; i < numberOfVertices; ++i) {\r\n indices[i] = i;\r\n }\r\n\r\n geometry.indices = indices;\r\n return geometry;\r\n}\r\n\r\nfunction indexTriangleFan(geometry) {\r\n var numberOfVertices = Geometry.computeNumberOfVertices(geometry);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numberOfVertices < 3) {\r\n throw new DeveloperError(\"The number of vertices must be at least three.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = IndexDatatype.createTypedArray(\r\n numberOfVertices,\r\n (numberOfVertices - 2) * 3\r\n );\r\n indices[0] = 1;\r\n indices[1] = 0;\r\n indices[2] = 2;\r\n\r\n var indicesIndex = 3;\r\n for (var i = 3; i < numberOfVertices; ++i) {\r\n indices[indicesIndex++] = i - 1;\r\n indices[indicesIndex++] = 0;\r\n indices[indicesIndex++] = i;\r\n }\r\n\r\n geometry.indices = indices;\r\n geometry.primitiveType = PrimitiveType.TRIANGLES;\r\n return geometry;\r\n}\r\n\r\nfunction indexTriangleStrip(geometry) {\r\n var numberOfVertices = Geometry.computeNumberOfVertices(geometry);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numberOfVertices < 3) {\r\n throw new DeveloperError(\"The number of vertices must be at least 3.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = IndexDatatype.createTypedArray(\r\n numberOfVertices,\r\n (numberOfVertices - 2) * 3\r\n );\r\n indices[0] = 0;\r\n indices[1] = 1;\r\n indices[2] = 2;\r\n\r\n if (numberOfVertices > 3) {\r\n indices[3] = 0;\r\n indices[4] = 2;\r\n indices[5] = 3;\r\n }\r\n\r\n var indicesIndex = 6;\r\n for (var i = 3; i < numberOfVertices - 1; i += 2) {\r\n indices[indicesIndex++] = i;\r\n indices[indicesIndex++] = i - 1;\r\n indices[indicesIndex++] = i + 1;\r\n\r\n if (i + 2 < numberOfVertices) {\r\n indices[indicesIndex++] = i;\r\n indices[indicesIndex++] = i + 1;\r\n indices[indicesIndex++] = i + 2;\r\n }\r\n }\r\n\r\n geometry.indices = indices;\r\n geometry.primitiveType = PrimitiveType.TRIANGLES;\r\n return geometry;\r\n}\r\n\r\nfunction indexLines(geometry) {\r\n if (defined(geometry.indices)) {\r\n return geometry;\r\n }\r\n var numberOfVertices = Geometry.computeNumberOfVertices(geometry);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numberOfVertices < 2) {\r\n throw new DeveloperError(\"The number of vertices must be at least two.\");\r\n }\r\n if (numberOfVertices % 2 !== 0) {\r\n throw new DeveloperError(\"The number of vertices must be a multiple of 2.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = IndexDatatype.createTypedArray(\r\n numberOfVertices,\r\n numberOfVertices\r\n );\r\n for (var i = 0; i < numberOfVertices; ++i) {\r\n indices[i] = i;\r\n }\r\n\r\n geometry.indices = indices;\r\n return geometry;\r\n}\r\n\r\nfunction indexLineStrip(geometry) {\r\n var numberOfVertices = Geometry.computeNumberOfVertices(geometry);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numberOfVertices < 2) {\r\n throw new DeveloperError(\"The number of vertices must be at least two.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = IndexDatatype.createTypedArray(\r\n numberOfVertices,\r\n (numberOfVertices - 1) * 2\r\n );\r\n indices[0] = 0;\r\n indices[1] = 1;\r\n var indicesIndex = 2;\r\n for (var i = 2; i < numberOfVertices; ++i) {\r\n indices[indicesIndex++] = i - 1;\r\n indices[indicesIndex++] = i;\r\n }\r\n\r\n geometry.indices = indices;\r\n geometry.primitiveType = PrimitiveType.LINES;\r\n return geometry;\r\n}\r\n\r\nfunction indexLineLoop(geometry) {\r\n var numberOfVertices = Geometry.computeNumberOfVertices(geometry);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (numberOfVertices < 2) {\r\n throw new DeveloperError(\"The number of vertices must be at least two.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indices = IndexDatatype.createTypedArray(\r\n numberOfVertices,\r\n numberOfVertices * 2\r\n );\r\n\r\n indices[0] = 0;\r\n indices[1] = 1;\r\n\r\n var indicesIndex = 2;\r\n for (var i = 2; i < numberOfVertices; ++i) {\r\n indices[indicesIndex++] = i - 1;\r\n indices[indicesIndex++] = i;\r\n }\r\n\r\n indices[indicesIndex++] = numberOfVertices - 1;\r\n indices[indicesIndex] = 0;\r\n\r\n geometry.indices = indices;\r\n geometry.primitiveType = PrimitiveType.LINES;\r\n return geometry;\r\n}\r\n\r\nfunction indexPrimitive(geometry) {\r\n switch (geometry.primitiveType) {\r\n case PrimitiveType.TRIANGLE_FAN:\r\n return indexTriangleFan(geometry);\r\n case PrimitiveType.TRIANGLE_STRIP:\r\n return indexTriangleStrip(geometry);\r\n case PrimitiveType.TRIANGLES:\r\n return indexTriangles(geometry);\r\n case PrimitiveType.LINE_STRIP:\r\n return indexLineStrip(geometry);\r\n case PrimitiveType.LINE_LOOP:\r\n return indexLineLoop(geometry);\r\n case PrimitiveType.LINES:\r\n return indexLines(geometry);\r\n }\r\n\r\n return geometry;\r\n}\r\n\r\nfunction offsetPointFromXZPlane(p, isBehind) {\r\n if (Math.abs(p.y) < CesiumMath.EPSILON6) {\r\n if (isBehind) {\r\n p.y = -CesiumMath.EPSILON6;\r\n } else {\r\n p.y = CesiumMath.EPSILON6;\r\n }\r\n }\r\n}\r\n\r\nfunction offsetTriangleFromXZPlane(p0, p1, p2) {\r\n if (p0.y !== 0.0 && p1.y !== 0.0 && p2.y !== 0.0) {\r\n offsetPointFromXZPlane(p0, p0.y < 0.0);\r\n offsetPointFromXZPlane(p1, p1.y < 0.0);\r\n offsetPointFromXZPlane(p2, p2.y < 0.0);\r\n return;\r\n }\r\n\r\n var p0y = Math.abs(p0.y);\r\n var p1y = Math.abs(p1.y);\r\n var p2y = Math.abs(p2.y);\r\n\r\n var sign;\r\n if (p0y > p1y) {\r\n if (p0y > p2y) {\r\n sign = CesiumMath.sign(p0.y);\r\n } else {\r\n sign = CesiumMath.sign(p2.y);\r\n }\r\n } else if (p1y > p2y) {\r\n sign = CesiumMath.sign(p1.y);\r\n } else {\r\n sign = CesiumMath.sign(p2.y);\r\n }\r\n\r\n var isBehind = sign < 0.0;\r\n offsetPointFromXZPlane(p0, isBehind);\r\n offsetPointFromXZPlane(p1, isBehind);\r\n offsetPointFromXZPlane(p2, isBehind);\r\n}\r\n\r\nvar c3 = new Cartesian3();\r\nfunction getXZIntersectionOffsetPoints(p, p1, u1, v1) {\r\n Cartesian3.add(\r\n p,\r\n Cartesian3.multiplyByScalar(\r\n Cartesian3.subtract(p1, p, c3),\r\n p.y / (p.y - p1.y),\r\n c3\r\n ),\r\n u1\r\n );\r\n Cartesian3.clone(u1, v1);\r\n offsetPointFromXZPlane(u1, true);\r\n offsetPointFromXZPlane(v1, false);\r\n}\r\n\r\nvar u1 = new Cartesian3();\r\nvar u2 = new Cartesian3();\r\nvar q1 = new Cartesian3();\r\nvar q2 = new Cartesian3();\r\n\r\nvar splitTriangleResult = {\r\n positions: new Array(7),\r\n indices: new Array(3 * 3),\r\n};\r\n\r\nfunction splitTriangle(p0, p1, p2) {\r\n // In WGS84 coordinates, for a triangle approximately on the\r\n // ellipsoid to cross the IDL, first it needs to be on the\r\n // negative side of the plane x = 0.\r\n if (p0.x >= 0.0 || p1.x >= 0.0 || p2.x >= 0.0) {\r\n return undefined;\r\n }\r\n\r\n offsetTriangleFromXZPlane(p0, p1, p2);\r\n\r\n var p0Behind = p0.y < 0.0;\r\n var p1Behind = p1.y < 0.0;\r\n var p2Behind = p2.y < 0.0;\r\n\r\n var numBehind = 0;\r\n numBehind += p0Behind ? 1 : 0;\r\n numBehind += p1Behind ? 1 : 0;\r\n numBehind += p2Behind ? 1 : 0;\r\n\r\n var indices = splitTriangleResult.indices;\r\n\r\n if (numBehind === 1) {\r\n indices[1] = 3;\r\n indices[2] = 4;\r\n indices[5] = 6;\r\n indices[7] = 6;\r\n indices[8] = 5;\r\n\r\n if (p0Behind) {\r\n getXZIntersectionOffsetPoints(p0, p1, u1, q1);\r\n getXZIntersectionOffsetPoints(p0, p2, u2, q2);\r\n\r\n indices[0] = 0;\r\n indices[3] = 1;\r\n indices[4] = 2;\r\n indices[6] = 1;\r\n } else if (p1Behind) {\r\n getXZIntersectionOffsetPoints(p1, p2, u1, q1);\r\n getXZIntersectionOffsetPoints(p1, p0, u2, q2);\r\n\r\n indices[0] = 1;\r\n indices[3] = 2;\r\n indices[4] = 0;\r\n indices[6] = 2;\r\n } else if (p2Behind) {\r\n getXZIntersectionOffsetPoints(p2, p0, u1, q1);\r\n getXZIntersectionOffsetPoints(p2, p1, u2, q2);\r\n\r\n indices[0] = 2;\r\n indices[3] = 0;\r\n indices[4] = 1;\r\n indices[6] = 0;\r\n }\r\n } else if (numBehind === 2) {\r\n indices[2] = 4;\r\n indices[4] = 4;\r\n indices[5] = 3;\r\n indices[7] = 5;\r\n indices[8] = 6;\r\n\r\n if (!p0Behind) {\r\n getXZIntersectionOffsetPoints(p0, p1, u1, q1);\r\n getXZIntersectionOffsetPoints(p0, p2, u2, q2);\r\n\r\n indices[0] = 1;\r\n indices[1] = 2;\r\n indices[3] = 1;\r\n indices[6] = 0;\r\n } else if (!p1Behind) {\r\n getXZIntersectionOffsetPoints(p1, p2, u1, q1);\r\n getXZIntersectionOffsetPoints(p1, p0, u2, q2);\r\n\r\n indices[0] = 2;\r\n indices[1] = 0;\r\n indices[3] = 2;\r\n indices[6] = 1;\r\n } else if (!p2Behind) {\r\n getXZIntersectionOffsetPoints(p2, p0, u1, q1);\r\n getXZIntersectionOffsetPoints(p2, p1, u2, q2);\r\n\r\n indices[0] = 0;\r\n indices[1] = 1;\r\n indices[3] = 0;\r\n indices[6] = 2;\r\n }\r\n }\r\n\r\n var positions = splitTriangleResult.positions;\r\n positions[0] = p0;\r\n positions[1] = p1;\r\n positions[2] = p2;\r\n positions.length = 3;\r\n\r\n if (numBehind === 1 || numBehind === 2) {\r\n positions[3] = u1;\r\n positions[4] = u2;\r\n positions[5] = q1;\r\n positions[6] = q2;\r\n positions.length = 7;\r\n }\r\n\r\n return splitTriangleResult;\r\n}\r\n\r\nfunction updateGeometryAfterSplit(geometry, computeBoundingSphere) {\r\n var attributes = geometry.attributes;\r\n\r\n if (attributes.position.values.length === 0) {\r\n return undefined;\r\n }\r\n\r\n for (var property in attributes) {\r\n if (\r\n attributes.hasOwnProperty(property) &&\r\n defined(attributes[property]) &&\r\n defined(attributes[property].values)\r\n ) {\r\n var attribute = attributes[property];\r\n attribute.values = ComponentDatatype.createTypedArray(\r\n attribute.componentDatatype,\r\n attribute.values\r\n );\r\n }\r\n }\r\n\r\n var numberOfVertices = Geometry.computeNumberOfVertices(geometry);\r\n geometry.indices = IndexDatatype.createTypedArray(\r\n numberOfVertices,\r\n geometry.indices\r\n );\r\n\r\n if (computeBoundingSphere) {\r\n geometry.boundingSphere = BoundingSphere.fromVertices(\r\n attributes.position.values\r\n );\r\n }\r\n\r\n return geometry;\r\n}\r\n\r\nfunction copyGeometryForSplit(geometry) {\r\n var attributes = geometry.attributes;\r\n var copiedAttributes = {};\r\n\r\n for (var property in attributes) {\r\n if (\r\n attributes.hasOwnProperty(property) &&\r\n defined(attributes[property]) &&\r\n defined(attributes[property].values)\r\n ) {\r\n var attribute = attributes[property];\r\n copiedAttributes[property] = new GeometryAttribute({\r\n componentDatatype: attribute.componentDatatype,\r\n componentsPerAttribute: attribute.componentsPerAttribute,\r\n normalize: attribute.normalize,\r\n values: [],\r\n });\r\n }\r\n }\r\n\r\n return new Geometry({\r\n attributes: copiedAttributes,\r\n indices: [],\r\n primitiveType: geometry.primitiveType,\r\n });\r\n}\r\n\r\nfunction updateInstanceAfterSplit(instance, westGeometry, eastGeometry) {\r\n var computeBoundingSphere = defined(instance.geometry.boundingSphere);\r\n\r\n westGeometry = updateGeometryAfterSplit(westGeometry, computeBoundingSphere);\r\n eastGeometry = updateGeometryAfterSplit(eastGeometry, computeBoundingSphere);\r\n\r\n if (defined(eastGeometry) && !defined(westGeometry)) {\r\n instance.geometry = eastGeometry;\r\n } else if (!defined(eastGeometry) && defined(westGeometry)) {\r\n instance.geometry = westGeometry;\r\n } else {\r\n instance.westHemisphereGeometry = westGeometry;\r\n instance.eastHemisphereGeometry = eastGeometry;\r\n instance.geometry = undefined;\r\n }\r\n}\r\n\r\nfunction generateBarycentricInterpolateFunction(\r\n CartesianType,\r\n numberOfComponents\r\n) {\r\n var v0Scratch = new CartesianType();\r\n var v1Scratch = new CartesianType();\r\n var v2Scratch = new CartesianType();\r\n\r\n return function (\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n sourceValues,\r\n currentValues,\r\n insertedIndex,\r\n normalize\r\n ) {\r\n var v0 = CartesianType.fromArray(\r\n sourceValues,\r\n i0 * numberOfComponents,\r\n v0Scratch\r\n );\r\n var v1 = CartesianType.fromArray(\r\n sourceValues,\r\n i1 * numberOfComponents,\r\n v1Scratch\r\n );\r\n var v2 = CartesianType.fromArray(\r\n sourceValues,\r\n i2 * numberOfComponents,\r\n v2Scratch\r\n );\r\n\r\n CartesianType.multiplyByScalar(v0, coords.x, v0);\r\n CartesianType.multiplyByScalar(v1, coords.y, v1);\r\n CartesianType.multiplyByScalar(v2, coords.z, v2);\r\n\r\n var value = CartesianType.add(v0, v1, v0);\r\n CartesianType.add(value, v2, value);\r\n\r\n if (normalize) {\r\n CartesianType.normalize(value, value);\r\n }\r\n\r\n CartesianType.pack(\r\n value,\r\n currentValues,\r\n insertedIndex * numberOfComponents\r\n );\r\n };\r\n}\r\n\r\nvar interpolateAndPackCartesian4 = generateBarycentricInterpolateFunction(\r\n Cartesian4,\r\n 4\r\n);\r\nvar interpolateAndPackCartesian3 = generateBarycentricInterpolateFunction(\r\n Cartesian3,\r\n 3\r\n);\r\nvar interpolateAndPackCartesian2 = generateBarycentricInterpolateFunction(\r\n Cartesian2,\r\n 2\r\n);\r\nvar interpolateAndPackBoolean = function (\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n sourceValues,\r\n currentValues,\r\n insertedIndex\r\n) {\r\n var v1 = sourceValues[i0] * coords.x;\r\n var v2 = sourceValues[i1] * coords.y;\r\n var v3 = sourceValues[i2] * coords.z;\r\n currentValues[insertedIndex] = v1 + v2 + v3 > CesiumMath.EPSILON6 ? 1 : 0;\r\n};\r\n\r\nvar p0Scratch = new Cartesian3();\r\nvar p1Scratch = new Cartesian3();\r\nvar p2Scratch = new Cartesian3();\r\nvar barycentricScratch = new Cartesian3();\r\n\r\nfunction computeTriangleAttributes(\r\n i0,\r\n i1,\r\n i2,\r\n point,\r\n positions,\r\n normals,\r\n tangents,\r\n bitangents,\r\n texCoords,\r\n extrudeDirections,\r\n applyOffset,\r\n currentAttributes,\r\n customAttributeNames,\r\n customAttributesLength,\r\n allAttributes,\r\n insertedIndex\r\n) {\r\n if (\r\n !defined(normals) &&\r\n !defined(tangents) &&\r\n !defined(bitangents) &&\r\n !defined(texCoords) &&\r\n !defined(extrudeDirections) &&\r\n customAttributesLength === 0\r\n ) {\r\n return;\r\n }\r\n\r\n var p0 = Cartesian3.fromArray(positions, i0 * 3, p0Scratch);\r\n var p1 = Cartesian3.fromArray(positions, i1 * 3, p1Scratch);\r\n var p2 = Cartesian3.fromArray(positions, i2 * 3, p2Scratch);\r\n var coords = barycentricCoordinates(point, p0, p1, p2, barycentricScratch);\r\n\r\n if (defined(normals)) {\r\n interpolateAndPackCartesian3(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n normals,\r\n currentAttributes.normal.values,\r\n insertedIndex,\r\n true\r\n );\r\n }\r\n\r\n if (defined(extrudeDirections)) {\r\n var d0 = Cartesian3.fromArray(extrudeDirections, i0 * 3, p0Scratch);\r\n var d1 = Cartesian3.fromArray(extrudeDirections, i1 * 3, p1Scratch);\r\n var d2 = Cartesian3.fromArray(extrudeDirections, i2 * 3, p2Scratch);\r\n\r\n Cartesian3.multiplyByScalar(d0, coords.x, d0);\r\n Cartesian3.multiplyByScalar(d1, coords.y, d1);\r\n Cartesian3.multiplyByScalar(d2, coords.z, d2);\r\n\r\n var direction;\r\n if (\r\n !Cartesian3.equals(d0, Cartesian3.ZERO) ||\r\n !Cartesian3.equals(d1, Cartesian3.ZERO) ||\r\n !Cartesian3.equals(d2, Cartesian3.ZERO)\r\n ) {\r\n direction = Cartesian3.add(d0, d1, d0);\r\n Cartesian3.add(direction, d2, direction);\r\n Cartesian3.normalize(direction, direction);\r\n } else {\r\n direction = p0Scratch;\r\n direction.x = 0;\r\n direction.y = 0;\r\n direction.z = 0;\r\n }\r\n Cartesian3.pack(\r\n direction,\r\n currentAttributes.extrudeDirection.values,\r\n insertedIndex * 3\r\n );\r\n }\r\n\r\n if (defined(applyOffset)) {\r\n interpolateAndPackBoolean(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n applyOffset,\r\n currentAttributes.applyOffset.values,\r\n insertedIndex\r\n );\r\n }\r\n\r\n if (defined(tangents)) {\r\n interpolateAndPackCartesian3(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n tangents,\r\n currentAttributes.tangent.values,\r\n insertedIndex,\r\n true\r\n );\r\n }\r\n\r\n if (defined(bitangents)) {\r\n interpolateAndPackCartesian3(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n bitangents,\r\n currentAttributes.bitangent.values,\r\n insertedIndex,\r\n true\r\n );\r\n }\r\n\r\n if (defined(texCoords)) {\r\n interpolateAndPackCartesian2(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n texCoords,\r\n currentAttributes.st.values,\r\n insertedIndex\r\n );\r\n }\r\n\r\n if (customAttributesLength > 0) {\r\n for (var i = 0; i < customAttributesLength; i++) {\r\n var attributeName = customAttributeNames[i];\r\n genericInterpolate(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n insertedIndex,\r\n allAttributes[attributeName],\r\n currentAttributes[attributeName]\r\n );\r\n }\r\n }\r\n}\r\n\r\nfunction genericInterpolate(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n insertedIndex,\r\n sourceAttribute,\r\n currentAttribute\r\n) {\r\n var componentsPerAttribute = sourceAttribute.componentsPerAttribute;\r\n var sourceValues = sourceAttribute.values;\r\n var currentValues = currentAttribute.values;\r\n switch (componentsPerAttribute) {\r\n case 4:\r\n interpolateAndPackCartesian4(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n sourceValues,\r\n currentValues,\r\n insertedIndex,\r\n false\r\n );\r\n break;\r\n case 3:\r\n interpolateAndPackCartesian3(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n sourceValues,\r\n currentValues,\r\n insertedIndex,\r\n false\r\n );\r\n break;\r\n case 2:\r\n interpolateAndPackCartesian2(\r\n i0,\r\n i1,\r\n i2,\r\n coords,\r\n sourceValues,\r\n currentValues,\r\n insertedIndex,\r\n false\r\n );\r\n break;\r\n default:\r\n currentValues[insertedIndex] =\r\n sourceValues[i0] * coords.x +\r\n sourceValues[i1] * coords.y +\r\n sourceValues[i2] * coords.z;\r\n }\r\n}\r\n\r\nfunction insertSplitPoint(\r\n currentAttributes,\r\n currentIndices,\r\n currentIndexMap,\r\n indices,\r\n currentIndex,\r\n point\r\n) {\r\n var insertIndex = currentAttributes.position.values.length / 3;\r\n\r\n if (currentIndex !== -1) {\r\n var prevIndex = indices[currentIndex];\r\n var newIndex = currentIndexMap[prevIndex];\r\n\r\n if (newIndex === -1) {\r\n currentIndexMap[prevIndex] = insertIndex;\r\n currentAttributes.position.values.push(point.x, point.y, point.z);\r\n currentIndices.push(insertIndex);\r\n return insertIndex;\r\n }\r\n\r\n currentIndices.push(newIndex);\r\n return newIndex;\r\n }\r\n\r\n currentAttributes.position.values.push(point.x, point.y, point.z);\r\n currentIndices.push(insertIndex);\r\n return insertIndex;\r\n}\r\n\r\nvar NAMED_ATTRIBUTES = {\r\n position: true,\r\n normal: true,\r\n bitangent: true,\r\n tangent: true,\r\n st: true,\r\n extrudeDirection: true,\r\n applyOffset: true,\r\n};\r\nfunction splitLongitudeTriangles(instance) {\r\n var geometry = instance.geometry;\r\n var attributes = geometry.attributes;\r\n var positions = attributes.position.values;\r\n var normals = defined(attributes.normal)\r\n ? attributes.normal.values\r\n : undefined;\r\n var bitangents = defined(attributes.bitangent)\r\n ? attributes.bitangent.values\r\n : undefined;\r\n var tangents = defined(attributes.tangent)\r\n ? attributes.tangent.values\r\n : undefined;\r\n var texCoords = defined(attributes.st) ? attributes.st.values : undefined;\r\n var extrudeDirections = defined(attributes.extrudeDirection)\r\n ? attributes.extrudeDirection.values\r\n : undefined;\r\n var applyOffset = defined(attributes.applyOffset)\r\n ? attributes.applyOffset.values\r\n : undefined;\r\n var indices = geometry.indices;\r\n\r\n var customAttributeNames = [];\r\n for (var attributeName in attributes) {\r\n if (\r\n attributes.hasOwnProperty(attributeName) &&\r\n !NAMED_ATTRIBUTES[attributeName] &&\r\n defined(attributes[attributeName])\r\n ) {\r\n customAttributeNames.push(attributeName);\r\n }\r\n }\r\n var customAttributesLength = customAttributeNames.length;\r\n\r\n var eastGeometry = copyGeometryForSplit(geometry);\r\n var westGeometry = copyGeometryForSplit(geometry);\r\n\r\n var currentAttributes;\r\n var currentIndices;\r\n var currentIndexMap;\r\n var insertedIndex;\r\n var i;\r\n\r\n var westGeometryIndexMap = [];\r\n westGeometryIndexMap.length = positions.length / 3;\r\n\r\n var eastGeometryIndexMap = [];\r\n eastGeometryIndexMap.length = positions.length / 3;\r\n\r\n for (i = 0; i < westGeometryIndexMap.length; ++i) {\r\n westGeometryIndexMap[i] = -1;\r\n eastGeometryIndexMap[i] = -1;\r\n }\r\n\r\n var len = indices.length;\r\n for (i = 0; i < len; i += 3) {\r\n var i0 = indices[i];\r\n var i1 = indices[i + 1];\r\n var i2 = indices[i + 2];\r\n\r\n var p0 = Cartesian3.fromArray(positions, i0 * 3);\r\n var p1 = Cartesian3.fromArray(positions, i1 * 3);\r\n var p2 = Cartesian3.fromArray(positions, i2 * 3);\r\n\r\n var result = splitTriangle(p0, p1, p2);\r\n if (defined(result) && result.positions.length > 3) {\r\n var resultPositions = result.positions;\r\n var resultIndices = result.indices;\r\n var resultLength = resultIndices.length;\r\n\r\n for (var j = 0; j < resultLength; ++j) {\r\n var resultIndex = resultIndices[j];\r\n var point = resultPositions[resultIndex];\r\n\r\n if (point.y < 0.0) {\r\n currentAttributes = westGeometry.attributes;\r\n currentIndices = westGeometry.indices;\r\n currentIndexMap = westGeometryIndexMap;\r\n } else {\r\n currentAttributes = eastGeometry.attributes;\r\n currentIndices = eastGeometry.indices;\r\n currentIndexMap = eastGeometryIndexMap;\r\n }\r\n\r\n insertedIndex = insertSplitPoint(\r\n currentAttributes,\r\n currentIndices,\r\n currentIndexMap,\r\n indices,\r\n resultIndex < 3 ? i + resultIndex : -1,\r\n point\r\n );\r\n computeTriangleAttributes(\r\n i0,\r\n i1,\r\n i2,\r\n point,\r\n positions,\r\n normals,\r\n tangents,\r\n bitangents,\r\n texCoords,\r\n extrudeDirections,\r\n applyOffset,\r\n currentAttributes,\r\n customAttributeNames,\r\n customAttributesLength,\r\n attributes,\r\n insertedIndex\r\n );\r\n }\r\n } else {\r\n if (defined(result)) {\r\n p0 = result.positions[0];\r\n p1 = result.positions[1];\r\n p2 = result.positions[2];\r\n }\r\n\r\n if (p0.y < 0.0) {\r\n currentAttributes = westGeometry.attributes;\r\n currentIndices = westGeometry.indices;\r\n currentIndexMap = westGeometryIndexMap;\r\n } else {\r\n currentAttributes = eastGeometry.attributes;\r\n currentIndices = eastGeometry.indices;\r\n currentIndexMap = eastGeometryIndexMap;\r\n }\r\n\r\n insertedIndex = insertSplitPoint(\r\n currentAttributes,\r\n currentIndices,\r\n currentIndexMap,\r\n indices,\r\n i,\r\n p0\r\n );\r\n computeTriangleAttributes(\r\n i0,\r\n i1,\r\n i2,\r\n p0,\r\n positions,\r\n normals,\r\n tangents,\r\n bitangents,\r\n texCoords,\r\n extrudeDirections,\r\n applyOffset,\r\n currentAttributes,\r\n customAttributeNames,\r\n customAttributesLength,\r\n attributes,\r\n insertedIndex\r\n );\r\n\r\n insertedIndex = insertSplitPoint(\r\n currentAttributes,\r\n currentIndices,\r\n currentIndexMap,\r\n indices,\r\n i + 1,\r\n p1\r\n );\r\n computeTriangleAttributes(\r\n i0,\r\n i1,\r\n i2,\r\n p1,\r\n positions,\r\n normals,\r\n tangents,\r\n bitangents,\r\n texCoords,\r\n extrudeDirections,\r\n applyOffset,\r\n currentAttributes,\r\n customAttributeNames,\r\n customAttributesLength,\r\n attributes,\r\n insertedIndex\r\n );\r\n\r\n insertedIndex = insertSplitPoint(\r\n currentAttributes,\r\n currentIndices,\r\n currentIndexMap,\r\n indices,\r\n i + 2,\r\n p2\r\n );\r\n computeTriangleAttributes(\r\n i0,\r\n i1,\r\n i2,\r\n p2,\r\n positions,\r\n normals,\r\n tangents,\r\n bitangents,\r\n texCoords,\r\n extrudeDirections,\r\n applyOffset,\r\n currentAttributes,\r\n customAttributeNames,\r\n customAttributesLength,\r\n attributes,\r\n insertedIndex\r\n );\r\n }\r\n }\r\n\r\n updateInstanceAfterSplit(instance, westGeometry, eastGeometry);\r\n}\r\n\r\nvar xzPlane = Plane.fromPointNormal(Cartesian3.ZERO, Cartesian3.UNIT_Y);\r\n\r\nvar offsetScratch = new Cartesian3();\r\nvar offsetPointScratch = new Cartesian3();\r\n\r\nfunction computeLineAttributes(\r\n i0,\r\n i1,\r\n point,\r\n positions,\r\n insertIndex,\r\n currentAttributes,\r\n applyOffset\r\n) {\r\n if (!defined(applyOffset)) {\r\n return;\r\n }\r\n\r\n var p0 = Cartesian3.fromArray(positions, i0 * 3, p0Scratch);\r\n if (Cartesian3.equalsEpsilon(p0, point, CesiumMath.EPSILON10)) {\r\n currentAttributes.applyOffset.values[insertIndex] = applyOffset[i0];\r\n } else {\r\n currentAttributes.applyOffset.values[insertIndex] = applyOffset[i1];\r\n }\r\n}\r\n\r\nfunction splitLongitudeLines(instance) {\r\n var geometry = instance.geometry;\r\n var attributes = geometry.attributes;\r\n var positions = attributes.position.values;\r\n var applyOffset = defined(attributes.applyOffset)\r\n ? attributes.applyOffset.values\r\n : undefined;\r\n var indices = geometry.indices;\r\n\r\n var eastGeometry = copyGeometryForSplit(geometry);\r\n var westGeometry = copyGeometryForSplit(geometry);\r\n\r\n var i;\r\n var length = indices.length;\r\n\r\n var westGeometryIndexMap = [];\r\n westGeometryIndexMap.length = positions.length / 3;\r\n\r\n var eastGeometryIndexMap = [];\r\n eastGeometryIndexMap.length = positions.length / 3;\r\n\r\n for (i = 0; i < westGeometryIndexMap.length; ++i) {\r\n westGeometryIndexMap[i] = -1;\r\n eastGeometryIndexMap[i] = -1;\r\n }\r\n\r\n for (i = 0; i < length; i += 2) {\r\n var i0 = indices[i];\r\n var i1 = indices[i + 1];\r\n\r\n var p0 = Cartesian3.fromArray(positions, i0 * 3, p0Scratch);\r\n var p1 = Cartesian3.fromArray(positions, i1 * 3, p1Scratch);\r\n var insertIndex;\r\n\r\n if (Math.abs(p0.y) < CesiumMath.EPSILON6) {\r\n if (p0.y < 0.0) {\r\n p0.y = -CesiumMath.EPSILON6;\r\n } else {\r\n p0.y = CesiumMath.EPSILON6;\r\n }\r\n }\r\n\r\n if (Math.abs(p1.y) < CesiumMath.EPSILON6) {\r\n if (p1.y < 0.0) {\r\n p1.y = -CesiumMath.EPSILON6;\r\n } else {\r\n p1.y = CesiumMath.EPSILON6;\r\n }\r\n }\r\n\r\n var p0Attributes = eastGeometry.attributes;\r\n var p0Indices = eastGeometry.indices;\r\n var p0IndexMap = eastGeometryIndexMap;\r\n var p1Attributes = westGeometry.attributes;\r\n var p1Indices = westGeometry.indices;\r\n var p1IndexMap = westGeometryIndexMap;\r\n\r\n var intersection = IntersectionTests.lineSegmentPlane(\r\n p0,\r\n p1,\r\n xzPlane,\r\n p2Scratch\r\n );\r\n if (defined(intersection)) {\r\n // move point on the xz-plane slightly away from the plane\r\n var offset = Cartesian3.multiplyByScalar(\r\n Cartesian3.UNIT_Y,\r\n 5.0 * CesiumMath.EPSILON9,\r\n offsetScratch\r\n );\r\n if (p0.y < 0.0) {\r\n Cartesian3.negate(offset, offset);\r\n\r\n p0Attributes = westGeometry.attributes;\r\n p0Indices = westGeometry.indices;\r\n p0IndexMap = westGeometryIndexMap;\r\n p1Attributes = eastGeometry.attributes;\r\n p1Indices = eastGeometry.indices;\r\n p1IndexMap = eastGeometryIndexMap;\r\n }\r\n\r\n var offsetPoint = Cartesian3.add(\r\n intersection,\r\n offset,\r\n offsetPointScratch\r\n );\r\n\r\n insertIndex = insertSplitPoint(\r\n p0Attributes,\r\n p0Indices,\r\n p0IndexMap,\r\n indices,\r\n i,\r\n p0\r\n );\r\n computeLineAttributes(\r\n i0,\r\n i1,\r\n p0,\r\n positions,\r\n insertIndex,\r\n p0Attributes,\r\n applyOffset\r\n );\r\n\r\n insertIndex = insertSplitPoint(\r\n p0Attributes,\r\n p0Indices,\r\n p0IndexMap,\r\n indices,\r\n -1,\r\n offsetPoint\r\n );\r\n computeLineAttributes(\r\n i0,\r\n i1,\r\n offsetPoint,\r\n positions,\r\n insertIndex,\r\n p0Attributes,\r\n applyOffset\r\n );\r\n\r\n Cartesian3.negate(offset, offset);\r\n Cartesian3.add(intersection, offset, offsetPoint);\r\n insertIndex = insertSplitPoint(\r\n p1Attributes,\r\n p1Indices,\r\n p1IndexMap,\r\n indices,\r\n -1,\r\n offsetPoint\r\n );\r\n computeLineAttributes(\r\n i0,\r\n i1,\r\n offsetPoint,\r\n positions,\r\n insertIndex,\r\n p1Attributes,\r\n applyOffset\r\n );\r\n\r\n insertIndex = insertSplitPoint(\r\n p1Attributes,\r\n p1Indices,\r\n p1IndexMap,\r\n indices,\r\n i + 1,\r\n p1\r\n );\r\n computeLineAttributes(\r\n i0,\r\n i1,\r\n p1,\r\n positions,\r\n insertIndex,\r\n p1Attributes,\r\n applyOffset\r\n );\r\n } else {\r\n var currentAttributes;\r\n var currentIndices;\r\n var currentIndexMap;\r\n\r\n if (p0.y < 0.0) {\r\n currentAttributes = westGeometry.attributes;\r\n currentIndices = westGeometry.indices;\r\n currentIndexMap = westGeometryIndexMap;\r\n } else {\r\n currentAttributes = eastGeometry.attributes;\r\n currentIndices = eastGeometry.indices;\r\n currentIndexMap = eastGeometryIndexMap;\r\n }\r\n\r\n insertIndex = insertSplitPoint(\r\n currentAttributes,\r\n currentIndices,\r\n currentIndexMap,\r\n indices,\r\n i,\r\n p0\r\n );\r\n computeLineAttributes(\r\n i0,\r\n i1,\r\n p0,\r\n positions,\r\n insertIndex,\r\n currentAttributes,\r\n applyOffset\r\n );\r\n\r\n insertIndex = insertSplitPoint(\r\n currentAttributes,\r\n currentIndices,\r\n currentIndexMap,\r\n indices,\r\n i + 1,\r\n p1\r\n );\r\n computeLineAttributes(\r\n i0,\r\n i1,\r\n p1,\r\n positions,\r\n insertIndex,\r\n currentAttributes,\r\n applyOffset\r\n );\r\n }\r\n }\r\n\r\n updateInstanceAfterSplit(instance, westGeometry, eastGeometry);\r\n}\r\n\r\nvar cartesian2Scratch0 = new Cartesian2();\r\nvar cartesian2Scratch1 = new Cartesian2();\r\n\r\nvar cartesian3Scratch0 = new Cartesian3();\r\nvar cartesian3Scratch2 = new Cartesian3();\r\nvar cartesian3Scratch3 = new Cartesian3();\r\nvar cartesian3Scratch4 = new Cartesian3();\r\nvar cartesian3Scratch5 = new Cartesian3();\r\nvar cartesian3Scratch6 = new Cartesian3();\r\n\r\nvar cartesian4Scratch0 = new Cartesian4();\r\n\r\nfunction updateAdjacencyAfterSplit(geometry) {\r\n var attributes = geometry.attributes;\r\n var positions = attributes.position.values;\r\n var prevPositions = attributes.prevPosition.values;\r\n var nextPositions = attributes.nextPosition.values;\r\n\r\n var length = positions.length;\r\n for (var j = 0; j < length; j += 3) {\r\n var position = Cartesian3.unpack(positions, j, cartesian3Scratch0);\r\n if (position.x > 0.0) {\r\n continue;\r\n }\r\n\r\n var prevPosition = Cartesian3.unpack(prevPositions, j, cartesian3Scratch2);\r\n if (\r\n (position.y < 0.0 && prevPosition.y > 0.0) ||\r\n (position.y > 0.0 && prevPosition.y < 0.0)\r\n ) {\r\n if (j - 3 > 0) {\r\n prevPositions[j] = positions[j - 3];\r\n prevPositions[j + 1] = positions[j - 2];\r\n prevPositions[j + 2] = positions[j - 1];\r\n } else {\r\n Cartesian3.pack(position, prevPositions, j);\r\n }\r\n }\r\n\r\n var nextPosition = Cartesian3.unpack(nextPositions, j, cartesian3Scratch3);\r\n if (\r\n (position.y < 0.0 && nextPosition.y > 0.0) ||\r\n (position.y > 0.0 && nextPosition.y < 0.0)\r\n ) {\r\n if (j + 3 < length) {\r\n nextPositions[j] = positions[j + 3];\r\n nextPositions[j + 1] = positions[j + 4];\r\n nextPositions[j + 2] = positions[j + 5];\r\n } else {\r\n Cartesian3.pack(position, nextPositions, j);\r\n }\r\n }\r\n }\r\n}\r\n\r\nvar offsetScalar = 5.0 * CesiumMath.EPSILON9;\r\nvar coplanarOffset = CesiumMath.EPSILON6;\r\n\r\nfunction splitLongitudePolyline(instance) {\r\n var geometry = instance.geometry;\r\n var attributes = geometry.attributes;\r\n var positions = attributes.position.values;\r\n var prevPositions = attributes.prevPosition.values;\r\n var nextPositions = attributes.nextPosition.values;\r\n var expandAndWidths = attributes.expandAndWidth.values;\r\n\r\n var texCoords = defined(attributes.st) ? attributes.st.values : undefined;\r\n var colors = defined(attributes.color) ? attributes.color.values : undefined;\r\n\r\n var eastGeometry = copyGeometryForSplit(geometry);\r\n var westGeometry = copyGeometryForSplit(geometry);\r\n\r\n var i;\r\n var j;\r\n var index;\r\n\r\n var intersectionFound = false;\r\n\r\n var length = positions.length / 3;\r\n for (i = 0; i < length; i += 4) {\r\n var i0 = i;\r\n var i2 = i + 2;\r\n\r\n var p0 = Cartesian3.fromArray(positions, i0 * 3, cartesian3Scratch0);\r\n var p2 = Cartesian3.fromArray(positions, i2 * 3, cartesian3Scratch2);\r\n\r\n // Offset points that are close to the 180 longitude and change the previous/next point\r\n // to be the same offset point so it can be projected to 2D. There is special handling in the\r\n // shader for when position == prevPosition || position == nextPosition.\r\n if (Math.abs(p0.y) < coplanarOffset) {\r\n p0.y = coplanarOffset * (p2.y < 0.0 ? -1.0 : 1.0);\r\n positions[i * 3 + 1] = p0.y;\r\n positions[(i + 1) * 3 + 1] = p0.y;\r\n\r\n for (j = i0 * 3; j < i0 * 3 + 4 * 3; j += 3) {\r\n prevPositions[j] = positions[i * 3];\r\n prevPositions[j + 1] = positions[i * 3 + 1];\r\n prevPositions[j + 2] = positions[i * 3 + 2];\r\n }\r\n }\r\n\r\n // Do the same but for when the line crosses 180 longitude in the opposite direction.\r\n if (Math.abs(p2.y) < coplanarOffset) {\r\n p2.y = coplanarOffset * (p0.y < 0.0 ? -1.0 : 1.0);\r\n positions[(i + 2) * 3 + 1] = p2.y;\r\n positions[(i + 3) * 3 + 1] = p2.y;\r\n\r\n for (j = i0 * 3; j < i0 * 3 + 4 * 3; j += 3) {\r\n nextPositions[j] = positions[(i + 2) * 3];\r\n nextPositions[j + 1] = positions[(i + 2) * 3 + 1];\r\n nextPositions[j + 2] = positions[(i + 2) * 3 + 2];\r\n }\r\n }\r\n\r\n var p0Attributes = eastGeometry.attributes;\r\n var p0Indices = eastGeometry.indices;\r\n var p2Attributes = westGeometry.attributes;\r\n var p2Indices = westGeometry.indices;\r\n\r\n var intersection = IntersectionTests.lineSegmentPlane(\r\n p0,\r\n p2,\r\n xzPlane,\r\n cartesian3Scratch4\r\n );\r\n if (defined(intersection)) {\r\n intersectionFound = true;\r\n\r\n // move point on the xz-plane slightly away from the plane\r\n var offset = Cartesian3.multiplyByScalar(\r\n Cartesian3.UNIT_Y,\r\n offsetScalar,\r\n cartesian3Scratch5\r\n );\r\n if (p0.y < 0.0) {\r\n Cartesian3.negate(offset, offset);\r\n p0Attributes = westGeometry.attributes;\r\n p0Indices = westGeometry.indices;\r\n p2Attributes = eastGeometry.attributes;\r\n p2Indices = eastGeometry.indices;\r\n }\r\n\r\n var offsetPoint = Cartesian3.add(\r\n intersection,\r\n offset,\r\n cartesian3Scratch6\r\n );\r\n p0Attributes.position.values.push(p0.x, p0.y, p0.z, p0.x, p0.y, p0.z);\r\n p0Attributes.position.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p0Attributes.position.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n\r\n p0Attributes.prevPosition.values.push(\r\n prevPositions[i0 * 3],\r\n prevPositions[i0 * 3 + 1],\r\n prevPositions[i0 * 3 + 2]\r\n );\r\n p0Attributes.prevPosition.values.push(\r\n prevPositions[i0 * 3 + 3],\r\n prevPositions[i0 * 3 + 4],\r\n prevPositions[i0 * 3 + 5]\r\n );\r\n p0Attributes.prevPosition.values.push(p0.x, p0.y, p0.z, p0.x, p0.y, p0.z);\r\n\r\n p0Attributes.nextPosition.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p0Attributes.nextPosition.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p0Attributes.nextPosition.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p0Attributes.nextPosition.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n\r\n Cartesian3.negate(offset, offset);\r\n Cartesian3.add(intersection, offset, offsetPoint);\r\n p2Attributes.position.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p2Attributes.position.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p2Attributes.position.values.push(p2.x, p2.y, p2.z, p2.x, p2.y, p2.z);\r\n\r\n p2Attributes.prevPosition.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p2Attributes.prevPosition.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p2Attributes.prevPosition.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n p2Attributes.prevPosition.values.push(\r\n offsetPoint.x,\r\n offsetPoint.y,\r\n offsetPoint.z\r\n );\r\n\r\n p2Attributes.nextPosition.values.push(p2.x, p2.y, p2.z, p2.x, p2.y, p2.z);\r\n p2Attributes.nextPosition.values.push(\r\n nextPositions[i2 * 3],\r\n nextPositions[i2 * 3 + 1],\r\n nextPositions[i2 * 3 + 2]\r\n );\r\n p2Attributes.nextPosition.values.push(\r\n nextPositions[i2 * 3 + 3],\r\n nextPositions[i2 * 3 + 4],\r\n nextPositions[i2 * 3 + 5]\r\n );\r\n\r\n var ew0 = Cartesian2.fromArray(\r\n expandAndWidths,\r\n i0 * 2,\r\n cartesian2Scratch0\r\n );\r\n var width = Math.abs(ew0.y);\r\n\r\n p0Attributes.expandAndWidth.values.push(-1, width, 1, width);\r\n p0Attributes.expandAndWidth.values.push(-1, -width, 1, -width);\r\n p2Attributes.expandAndWidth.values.push(-1, width, 1, width);\r\n p2Attributes.expandAndWidth.values.push(-1, -width, 1, -width);\r\n\r\n var t = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(intersection, p0, cartesian3Scratch3)\r\n );\r\n t /= Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(p2, p0, cartesian3Scratch3)\r\n );\r\n\r\n if (defined(colors)) {\r\n var c0 = Cartesian4.fromArray(colors, i0 * 4, cartesian4Scratch0);\r\n var c2 = Cartesian4.fromArray(colors, i2 * 4, cartesian4Scratch0);\r\n\r\n var r = CesiumMath.lerp(c0.x, c2.x, t);\r\n var g = CesiumMath.lerp(c0.y, c2.y, t);\r\n var b = CesiumMath.lerp(c0.z, c2.z, t);\r\n var a = CesiumMath.lerp(c0.w, c2.w, t);\r\n\r\n for (j = i0 * 4; j < i0 * 4 + 2 * 4; ++j) {\r\n p0Attributes.color.values.push(colors[j]);\r\n }\r\n p0Attributes.color.values.push(r, g, b, a);\r\n p0Attributes.color.values.push(r, g, b, a);\r\n p2Attributes.color.values.push(r, g, b, a);\r\n p2Attributes.color.values.push(r, g, b, a);\r\n for (j = i2 * 4; j < i2 * 4 + 2 * 4; ++j) {\r\n p2Attributes.color.values.push(colors[j]);\r\n }\r\n }\r\n\r\n if (defined(texCoords)) {\r\n var s0 = Cartesian2.fromArray(texCoords, i0 * 2, cartesian2Scratch0);\r\n var s3 = Cartesian2.fromArray(\r\n texCoords,\r\n (i + 3) * 2,\r\n cartesian2Scratch1\r\n );\r\n\r\n var sx = CesiumMath.lerp(s0.x, s3.x, t);\r\n\r\n for (j = i0 * 2; j < i0 * 2 + 2 * 2; ++j) {\r\n p0Attributes.st.values.push(texCoords[j]);\r\n }\r\n p0Attributes.st.values.push(sx, s0.y);\r\n p0Attributes.st.values.push(sx, s3.y);\r\n p2Attributes.st.values.push(sx, s0.y);\r\n p2Attributes.st.values.push(sx, s3.y);\r\n for (j = i2 * 2; j < i2 * 2 + 2 * 2; ++j) {\r\n p2Attributes.st.values.push(texCoords[j]);\r\n }\r\n }\r\n\r\n index = p0Attributes.position.values.length / 3 - 4;\r\n p0Indices.push(index, index + 2, index + 1);\r\n p0Indices.push(index + 1, index + 2, index + 3);\r\n\r\n index = p2Attributes.position.values.length / 3 - 4;\r\n p2Indices.push(index, index + 2, index + 1);\r\n p2Indices.push(index + 1, index + 2, index + 3);\r\n } else {\r\n var currentAttributes;\r\n var currentIndices;\r\n\r\n if (p0.y < 0.0) {\r\n currentAttributes = westGeometry.attributes;\r\n currentIndices = westGeometry.indices;\r\n } else {\r\n currentAttributes = eastGeometry.attributes;\r\n currentIndices = eastGeometry.indices;\r\n }\r\n\r\n currentAttributes.position.values.push(p0.x, p0.y, p0.z);\r\n currentAttributes.position.values.push(p0.x, p0.y, p0.z);\r\n currentAttributes.position.values.push(p2.x, p2.y, p2.z);\r\n currentAttributes.position.values.push(p2.x, p2.y, p2.z);\r\n\r\n for (j = i * 3; j < i * 3 + 4 * 3; ++j) {\r\n currentAttributes.prevPosition.values.push(prevPositions[j]);\r\n currentAttributes.nextPosition.values.push(nextPositions[j]);\r\n }\r\n\r\n for (j = i * 2; j < i * 2 + 4 * 2; ++j) {\r\n currentAttributes.expandAndWidth.values.push(expandAndWidths[j]);\r\n if (defined(texCoords)) {\r\n currentAttributes.st.values.push(texCoords[j]);\r\n }\r\n }\r\n\r\n if (defined(colors)) {\r\n for (j = i * 4; j < i * 4 + 4 * 4; ++j) {\r\n currentAttributes.color.values.push(colors[j]);\r\n }\r\n }\r\n\r\n index = currentAttributes.position.values.length / 3 - 4;\r\n currentIndices.push(index, index + 2, index + 1);\r\n currentIndices.push(index + 1, index + 2, index + 3);\r\n }\r\n }\r\n\r\n if (intersectionFound) {\r\n updateAdjacencyAfterSplit(westGeometry);\r\n updateAdjacencyAfterSplit(eastGeometry);\r\n }\r\n\r\n updateInstanceAfterSplit(instance, westGeometry, eastGeometry);\r\n}\r\n\r\n/**\r\n * Splits the instances's geometry, by introducing new vertices and indices,that\r\n * intersect the International Date Line and Prime Meridian so that no primitives cross longitude\r\n * -180/180 degrees. This is not required for 3D drawing, but is required for\r\n * correcting drawing in 2D and Columbus view.\r\n *\r\n * @private\r\n *\r\n * @param {GeometryInstance} instance The instance to modify.\r\n * @returns {GeometryInstance} The modified instance argument, with it's geometry split at the International Date Line.\r\n *\r\n * @example\r\n * instance = Cesium.GeometryPipeline.splitLongitude(instance);\r\n */\r\nGeometryPipeline.splitLongitude = function (instance) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(instance)) {\r\n throw new DeveloperError(\"instance is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var geometry = instance.geometry;\r\n var boundingSphere = geometry.boundingSphere;\r\n if (defined(boundingSphere)) {\r\n var minX = boundingSphere.center.x - boundingSphere.radius;\r\n if (\r\n minX > 0 ||\r\n BoundingSphere.intersectPlane(boundingSphere, Plane.ORIGIN_ZX_PLANE) !==\r\n Intersect.INTERSECTING\r\n ) {\r\n return instance;\r\n }\r\n }\r\n\r\n if (geometry.geometryType !== GeometryType.NONE) {\r\n switch (geometry.geometryType) {\r\n case GeometryType.POLYLINES:\r\n splitLongitudePolyline(instance);\r\n break;\r\n case GeometryType.TRIANGLES:\r\n splitLongitudeTriangles(instance);\r\n break;\r\n case GeometryType.LINES:\r\n splitLongitudeLines(instance);\r\n break;\r\n }\r\n } else {\r\n indexPrimitive(geometry);\r\n if (geometry.primitiveType === PrimitiveType.TRIANGLES) {\r\n splitLongitudeTriangles(instance);\r\n } else if (geometry.primitiveType === PrimitiveType.LINES) {\r\n splitLongitudeLines(instance);\r\n }\r\n }\r\n\r\n return instance;\r\n};\r\nexport default GeometryPipeline;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport EllipseGeometryLibrary from \"./EllipseGeometryLibrary.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport GeographicProjection from \"./GeographicProjection.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryInstance from \"./GeometryInstance.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport GeometryPipeline from \"./GeometryPipeline.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar scratchCartesian1 = new Cartesian3();\r\nvar scratchCartesian2 = new Cartesian3();\r\nvar scratchCartesian3 = new Cartesian3();\r\nvar scratchCartesian4 = new Cartesian3();\r\nvar texCoordScratch = new Cartesian2();\r\nvar textureMatrixScratch = new Matrix3();\r\nvar tangentMatrixScratch = new Matrix3();\r\nvar quaternionScratch = new Quaternion();\r\n\r\nvar scratchNormal = new Cartesian3();\r\nvar scratchTangent = new Cartesian3();\r\nvar scratchBitangent = new Cartesian3();\r\n\r\nvar scratchCartographic = new Cartographic();\r\nvar projectedCenterScratch = new Cartesian3();\r\n\r\nvar scratchMinTexCoord = new Cartesian2();\r\nvar scratchMaxTexCoord = new Cartesian2();\r\n\r\nfunction computeTopBottomAttributes(positions, options, extrude) {\r\n var vertexFormat = options.vertexFormat;\r\n var center = options.center;\r\n var semiMajorAxis = options.semiMajorAxis;\r\n var semiMinorAxis = options.semiMinorAxis;\r\n var ellipsoid = options.ellipsoid;\r\n var stRotation = options.stRotation;\r\n var size = extrude ? (positions.length / 3) * 2 : positions.length / 3;\r\n var shadowVolume = options.shadowVolume;\r\n\r\n var textureCoordinates = vertexFormat.st\r\n ? new Float32Array(size * 2)\r\n : undefined;\r\n var normals = vertexFormat.normal ? new Float32Array(size * 3) : undefined;\r\n var tangents = vertexFormat.tangent ? new Float32Array(size * 3) : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(size * 3)\r\n : undefined;\r\n\r\n var extrudeNormals = shadowVolume ? new Float32Array(size * 3) : undefined;\r\n\r\n var textureCoordIndex = 0;\r\n\r\n // Raise positions to a height above the ellipsoid and compute the\r\n // texture coordinates, normals, tangents, and bitangents.\r\n var normal = scratchNormal;\r\n var tangent = scratchTangent;\r\n var bitangent = scratchBitangent;\r\n\r\n var projection = new GeographicProjection(ellipsoid);\r\n var projectedCenter = projection.project(\r\n ellipsoid.cartesianToCartographic(center, scratchCartographic),\r\n projectedCenterScratch\r\n );\r\n\r\n var geodeticNormal = ellipsoid.scaleToGeodeticSurface(\r\n center,\r\n scratchCartesian1\r\n );\r\n ellipsoid.geodeticSurfaceNormal(geodeticNormal, geodeticNormal);\r\n\r\n var textureMatrix = textureMatrixScratch;\r\n var tangentMatrix = tangentMatrixScratch;\r\n if (stRotation !== 0) {\r\n var rotation = Quaternion.fromAxisAngle(\r\n geodeticNormal,\r\n stRotation,\r\n quaternionScratch\r\n );\r\n textureMatrix = Matrix3.fromQuaternion(rotation, textureMatrix);\r\n\r\n rotation = Quaternion.fromAxisAngle(\r\n geodeticNormal,\r\n -stRotation,\r\n quaternionScratch\r\n );\r\n tangentMatrix = Matrix3.fromQuaternion(rotation, tangentMatrix);\r\n } else {\r\n textureMatrix = Matrix3.clone(Matrix3.IDENTITY, textureMatrix);\r\n tangentMatrix = Matrix3.clone(Matrix3.IDENTITY, tangentMatrix);\r\n }\r\n\r\n var minTexCoord = Cartesian2.fromElements(\r\n Number.POSITIVE_INFINITY,\r\n Number.POSITIVE_INFINITY,\r\n scratchMinTexCoord\r\n );\r\n var maxTexCoord = Cartesian2.fromElements(\r\n Number.NEGATIVE_INFINITY,\r\n Number.NEGATIVE_INFINITY,\r\n scratchMaxTexCoord\r\n );\r\n\r\n var length = positions.length;\r\n var bottomOffset = extrude ? length : 0;\r\n var stOffset = (bottomOffset / 3) * 2;\r\n for (var i = 0; i < length; i += 3) {\r\n var i1 = i + 1;\r\n var i2 = i + 2;\r\n var position = Cartesian3.fromArray(positions, i, scratchCartesian1);\r\n\r\n if (vertexFormat.st) {\r\n var rotatedPoint = Matrix3.multiplyByVector(\r\n textureMatrix,\r\n position,\r\n scratchCartesian2\r\n );\r\n var projectedPoint = projection.project(\r\n ellipsoid.cartesianToCartographic(rotatedPoint, scratchCartographic),\r\n scratchCartesian3\r\n );\r\n Cartesian3.subtract(projectedPoint, projectedCenter, projectedPoint);\r\n\r\n texCoordScratch.x =\r\n (projectedPoint.x + semiMajorAxis) / (2.0 * semiMajorAxis);\r\n texCoordScratch.y =\r\n (projectedPoint.y + semiMinorAxis) / (2.0 * semiMinorAxis);\r\n\r\n minTexCoord.x = Math.min(texCoordScratch.x, minTexCoord.x);\r\n minTexCoord.y = Math.min(texCoordScratch.y, minTexCoord.y);\r\n maxTexCoord.x = Math.max(texCoordScratch.x, maxTexCoord.x);\r\n maxTexCoord.y = Math.max(texCoordScratch.y, maxTexCoord.y);\r\n\r\n if (extrude) {\r\n textureCoordinates[textureCoordIndex + stOffset] = texCoordScratch.x;\r\n textureCoordinates[textureCoordIndex + 1 + stOffset] =\r\n texCoordScratch.y;\r\n }\r\n\r\n textureCoordinates[textureCoordIndex++] = texCoordScratch.x;\r\n textureCoordinates[textureCoordIndex++] = texCoordScratch.y;\r\n }\r\n\r\n if (\r\n vertexFormat.normal ||\r\n vertexFormat.tangent ||\r\n vertexFormat.bitangent ||\r\n shadowVolume\r\n ) {\r\n normal = ellipsoid.geodeticSurfaceNormal(position, normal);\r\n\r\n if (shadowVolume) {\r\n extrudeNormals[i + bottomOffset] = -normal.x;\r\n extrudeNormals[i1 + bottomOffset] = -normal.y;\r\n extrudeNormals[i2 + bottomOffset] = -normal.z;\r\n }\r\n\r\n if (\r\n vertexFormat.normal ||\r\n vertexFormat.tangent ||\r\n vertexFormat.bitangent\r\n ) {\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n tangent = Cartesian3.normalize(\r\n Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent),\r\n tangent\r\n );\r\n Matrix3.multiplyByVector(tangentMatrix, tangent, tangent);\r\n }\r\n if (vertexFormat.normal) {\r\n normals[i] = normal.x;\r\n normals[i1] = normal.y;\r\n normals[i2] = normal.z;\r\n if (extrude) {\r\n normals[i + bottomOffset] = -normal.x;\r\n normals[i1 + bottomOffset] = -normal.y;\r\n normals[i2 + bottomOffset] = -normal.z;\r\n }\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n tangents[i] = tangent.x;\r\n tangents[i1] = tangent.y;\r\n tangents[i2] = tangent.z;\r\n if (extrude) {\r\n tangents[i + bottomOffset] = -tangent.x;\r\n tangents[i1 + bottomOffset] = -tangent.y;\r\n tangents[i2 + bottomOffset] = -tangent.z;\r\n }\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n bitangent = Cartesian3.normalize(\r\n Cartesian3.cross(normal, tangent, bitangent),\r\n bitangent\r\n );\r\n bitangents[i] = bitangent.x;\r\n bitangents[i1] = bitangent.y;\r\n bitangents[i2] = bitangent.z;\r\n if (extrude) {\r\n bitangents[i + bottomOffset] = bitangent.x;\r\n bitangents[i1 + bottomOffset] = bitangent.y;\r\n bitangents[i2 + bottomOffset] = bitangent.z;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (vertexFormat.st) {\r\n length = textureCoordinates.length;\r\n for (var k = 0; k < length; k += 2) {\r\n textureCoordinates[k] =\r\n (textureCoordinates[k] - minTexCoord.x) /\r\n (maxTexCoord.x - minTexCoord.x);\r\n textureCoordinates[k + 1] =\r\n (textureCoordinates[k + 1] - minTexCoord.y) /\r\n (maxTexCoord.y - minTexCoord.y);\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n\r\n if (vertexFormat.position) {\r\n var finalPositions = EllipseGeometryLibrary.raisePositionsToHeight(\r\n positions,\r\n options,\r\n extrude\r\n );\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: finalPositions,\r\n });\r\n }\r\n\r\n if (vertexFormat.st) {\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: textureCoordinates,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n\r\n if (shadowVolume) {\r\n attributes.extrudeDirection = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: extrudeNormals,\r\n });\r\n }\r\n\r\n if (extrude && defined(options.offsetAttribute)) {\r\n var offsetAttribute = new Uint8Array(size);\r\n if (options.offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);\r\n } else {\r\n var offsetValue =\r\n options.offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n offsetAttribute = arrayFill(offsetAttribute, offsetValue);\r\n }\r\n\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: offsetAttribute,\r\n });\r\n }\r\n\r\n return attributes;\r\n}\r\n\r\nfunction topIndices(numPts) {\r\n // numTriangles in half = 3 + 8 + 12 + ... = -1 + 4 + (4 + 4) + (4 + 4 + 4) + ... = -1 + 4 * (1 + 2 + 3 + ...)\r\n // = -1 + 4 * ((n * ( n + 1)) / 2)\r\n // total triangles = 2 * numTrangles in half\r\n // indices = total triangles * 3;\r\n // Substitute numPts for n above\r\n\r\n var indices = new Array(12 * (numPts * (numPts + 1)) - 6);\r\n var indicesIndex = 0;\r\n var prevIndex;\r\n var numInterior;\r\n var positionIndex;\r\n var i;\r\n var j;\r\n // Indices triangles to the 'right' of the north vector\r\n\r\n prevIndex = 0;\r\n positionIndex = 1;\r\n for (i = 0; i < 3; i++) {\r\n indices[indicesIndex++] = positionIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n indices[indicesIndex++] = positionIndex;\r\n }\r\n\r\n for (i = 2; i < numPts + 1; ++i) {\r\n positionIndex = i * (i + 1) - 1;\r\n prevIndex = (i - 1) * i - 1;\r\n\r\n indices[indicesIndex++] = positionIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n indices[indicesIndex++] = positionIndex;\r\n\r\n numInterior = 2 * i;\r\n for (j = 0; j < numInterior - 1; ++j) {\r\n indices[indicesIndex++] = positionIndex;\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n\r\n indices[indicesIndex++] = positionIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n indices[indicesIndex++] = positionIndex;\r\n }\r\n\r\n indices[indicesIndex++] = positionIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n indices[indicesIndex++] = positionIndex;\r\n }\r\n\r\n // Indices for center column of triangles\r\n numInterior = numPts * 2;\r\n ++positionIndex;\r\n ++prevIndex;\r\n for (i = 0; i < numInterior - 1; ++i) {\r\n indices[indicesIndex++] = positionIndex;\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n\r\n indices[indicesIndex++] = positionIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n indices[indicesIndex++] = positionIndex;\r\n }\r\n\r\n indices[indicesIndex++] = positionIndex;\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n\r\n indices[indicesIndex++] = positionIndex++;\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n\r\n // Reverse the process creating indices to the 'left' of the north vector\r\n ++prevIndex;\r\n for (i = numPts - 1; i > 1; --i) {\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n indices[indicesIndex++] = positionIndex;\r\n\r\n numInterior = 2 * i;\r\n for (j = 0; j < numInterior - 1; ++j) {\r\n indices[indicesIndex++] = positionIndex;\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n\r\n indices[indicesIndex++] = positionIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n indices[indicesIndex++] = positionIndex;\r\n }\r\n\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = positionIndex++;\r\n }\r\n\r\n for (i = 0; i < 3; i++) {\r\n indices[indicesIndex++] = prevIndex++;\r\n indices[indicesIndex++] = prevIndex;\r\n indices[indicesIndex++] = positionIndex;\r\n }\r\n return indices;\r\n}\r\n\r\nvar boundingSphereCenter = new Cartesian3();\r\n\r\nfunction computeEllipse(options) {\r\n var center = options.center;\r\n boundingSphereCenter = Cartesian3.multiplyByScalar(\r\n options.ellipsoid.geodeticSurfaceNormal(center, boundingSphereCenter),\r\n options.height,\r\n boundingSphereCenter\r\n );\r\n boundingSphereCenter = Cartesian3.add(\r\n center,\r\n boundingSphereCenter,\r\n boundingSphereCenter\r\n );\r\n var boundingSphere = new BoundingSphere(\r\n boundingSphereCenter,\r\n options.semiMajorAxis\r\n );\r\n var cep = EllipseGeometryLibrary.computeEllipsePositions(\r\n options,\r\n true,\r\n false\r\n );\r\n var positions = cep.positions;\r\n var numPts = cep.numPts;\r\n var attributes = computeTopBottomAttributes(positions, options, false);\r\n var indices = topIndices(numPts);\r\n indices = IndexDatatype.createTypedArray(positions.length / 3, indices);\r\n return {\r\n boundingSphere: boundingSphere,\r\n attributes: attributes,\r\n indices: indices,\r\n };\r\n}\r\n\r\nfunction computeWallAttributes(positions, options) {\r\n var vertexFormat = options.vertexFormat;\r\n var center = options.center;\r\n var semiMajorAxis = options.semiMajorAxis;\r\n var semiMinorAxis = options.semiMinorAxis;\r\n var ellipsoid = options.ellipsoid;\r\n var height = options.height;\r\n var extrudedHeight = options.extrudedHeight;\r\n var stRotation = options.stRotation;\r\n var size = (positions.length / 3) * 2;\r\n\r\n var finalPositions = new Float64Array(size * 3);\r\n var textureCoordinates = vertexFormat.st\r\n ? new Float32Array(size * 2)\r\n : undefined;\r\n var normals = vertexFormat.normal ? new Float32Array(size * 3) : undefined;\r\n var tangents = vertexFormat.tangent ? new Float32Array(size * 3) : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(size * 3)\r\n : undefined;\r\n\r\n var shadowVolume = options.shadowVolume;\r\n var extrudeNormals = shadowVolume ? new Float32Array(size * 3) : undefined;\r\n\r\n var textureCoordIndex = 0;\r\n\r\n // Raise positions to a height above the ellipsoid and compute the\r\n // texture coordinates, normals, tangents, and bitangents.\r\n var normal = scratchNormal;\r\n var tangent = scratchTangent;\r\n var bitangent = scratchBitangent;\r\n\r\n var projection = new GeographicProjection(ellipsoid);\r\n var projectedCenter = projection.project(\r\n ellipsoid.cartesianToCartographic(center, scratchCartographic),\r\n projectedCenterScratch\r\n );\r\n\r\n var geodeticNormal = ellipsoid.scaleToGeodeticSurface(\r\n center,\r\n scratchCartesian1\r\n );\r\n ellipsoid.geodeticSurfaceNormal(geodeticNormal, geodeticNormal);\r\n var rotation = Quaternion.fromAxisAngle(\r\n geodeticNormal,\r\n stRotation,\r\n quaternionScratch\r\n );\r\n var textureMatrix = Matrix3.fromQuaternion(rotation, textureMatrixScratch);\r\n\r\n var minTexCoord = Cartesian2.fromElements(\r\n Number.POSITIVE_INFINITY,\r\n Number.POSITIVE_INFINITY,\r\n scratchMinTexCoord\r\n );\r\n var maxTexCoord = Cartesian2.fromElements(\r\n Number.NEGATIVE_INFINITY,\r\n Number.NEGATIVE_INFINITY,\r\n scratchMaxTexCoord\r\n );\r\n\r\n var length = positions.length;\r\n var stOffset = (length / 3) * 2;\r\n for (var i = 0; i < length; i += 3) {\r\n var i1 = i + 1;\r\n var i2 = i + 2;\r\n var position = Cartesian3.fromArray(positions, i, scratchCartesian1);\r\n var extrudedPosition;\r\n\r\n if (vertexFormat.st) {\r\n var rotatedPoint = Matrix3.multiplyByVector(\r\n textureMatrix,\r\n position,\r\n scratchCartesian2\r\n );\r\n var projectedPoint = projection.project(\r\n ellipsoid.cartesianToCartographic(rotatedPoint, scratchCartographic),\r\n scratchCartesian3\r\n );\r\n Cartesian3.subtract(projectedPoint, projectedCenter, projectedPoint);\r\n\r\n texCoordScratch.x =\r\n (projectedPoint.x + semiMajorAxis) / (2.0 * semiMajorAxis);\r\n texCoordScratch.y =\r\n (projectedPoint.y + semiMinorAxis) / (2.0 * semiMinorAxis);\r\n\r\n minTexCoord.x = Math.min(texCoordScratch.x, minTexCoord.x);\r\n minTexCoord.y = Math.min(texCoordScratch.y, minTexCoord.y);\r\n maxTexCoord.x = Math.max(texCoordScratch.x, maxTexCoord.x);\r\n maxTexCoord.y = Math.max(texCoordScratch.y, maxTexCoord.y);\r\n\r\n textureCoordinates[textureCoordIndex + stOffset] = texCoordScratch.x;\r\n textureCoordinates[textureCoordIndex + 1 + stOffset] = texCoordScratch.y;\r\n\r\n textureCoordinates[textureCoordIndex++] = texCoordScratch.x;\r\n textureCoordinates[textureCoordIndex++] = texCoordScratch.y;\r\n }\r\n\r\n position = ellipsoid.scaleToGeodeticSurface(position, position);\r\n extrudedPosition = Cartesian3.clone(position, scratchCartesian2);\r\n normal = ellipsoid.geodeticSurfaceNormal(position, normal);\r\n\r\n if (shadowVolume) {\r\n extrudeNormals[i + length] = -normal.x;\r\n extrudeNormals[i1 + length] = -normal.y;\r\n extrudeNormals[i2 + length] = -normal.z;\r\n }\r\n\r\n var scaledNormal = Cartesian3.multiplyByScalar(\r\n normal,\r\n height,\r\n scratchCartesian4\r\n );\r\n position = Cartesian3.add(position, scaledNormal, position);\r\n scaledNormal = Cartesian3.multiplyByScalar(\r\n normal,\r\n extrudedHeight,\r\n scaledNormal\r\n );\r\n extrudedPosition = Cartesian3.add(\r\n extrudedPosition,\r\n scaledNormal,\r\n extrudedPosition\r\n );\r\n\r\n if (vertexFormat.position) {\r\n finalPositions[i + length] = extrudedPosition.x;\r\n finalPositions[i1 + length] = extrudedPosition.y;\r\n finalPositions[i2 + length] = extrudedPosition.z;\r\n\r\n finalPositions[i] = position.x;\r\n finalPositions[i1] = position.y;\r\n finalPositions[i2] = position.z;\r\n }\r\n\r\n if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {\r\n bitangent = Cartesian3.clone(normal, bitangent);\r\n var next = Cartesian3.fromArray(\r\n positions,\r\n (i + 3) % length,\r\n scratchCartesian4\r\n );\r\n Cartesian3.subtract(next, position, next);\r\n var bottom = Cartesian3.subtract(\r\n extrudedPosition,\r\n position,\r\n scratchCartesian3\r\n );\r\n\r\n normal = Cartesian3.normalize(\r\n Cartesian3.cross(bottom, next, normal),\r\n normal\r\n );\r\n\r\n if (vertexFormat.normal) {\r\n normals[i] = normal.x;\r\n normals[i1] = normal.y;\r\n normals[i2] = normal.z;\r\n\r\n normals[i + length] = normal.x;\r\n normals[i1 + length] = normal.y;\r\n normals[i2 + length] = normal.z;\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n tangent = Cartesian3.normalize(\r\n Cartesian3.cross(bitangent, normal, tangent),\r\n tangent\r\n );\r\n tangents[i] = tangent.x;\r\n tangents[i1] = tangent.y;\r\n tangents[i2] = tangent.z;\r\n\r\n tangents[i + length] = tangent.x;\r\n tangents[i + 1 + length] = tangent.y;\r\n tangents[i + 2 + length] = tangent.z;\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n bitangents[i] = bitangent.x;\r\n bitangents[i1] = bitangent.y;\r\n bitangents[i2] = bitangent.z;\r\n\r\n bitangents[i + length] = bitangent.x;\r\n bitangents[i1 + length] = bitangent.y;\r\n bitangents[i2 + length] = bitangent.z;\r\n }\r\n }\r\n }\r\n\r\n if (vertexFormat.st) {\r\n length = textureCoordinates.length;\r\n for (var k = 0; k < length; k += 2) {\r\n textureCoordinates[k] =\r\n (textureCoordinates[k] - minTexCoord.x) /\r\n (maxTexCoord.x - minTexCoord.x);\r\n textureCoordinates[k + 1] =\r\n (textureCoordinates[k + 1] - minTexCoord.y) /\r\n (maxTexCoord.y - minTexCoord.y);\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n\r\n if (vertexFormat.position) {\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: finalPositions,\r\n });\r\n }\r\n\r\n if (vertexFormat.st) {\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: textureCoordinates,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n\r\n if (shadowVolume) {\r\n attributes.extrudeDirection = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: extrudeNormals,\r\n });\r\n }\r\n\r\n if (defined(options.offsetAttribute)) {\r\n var offsetAttribute = new Uint8Array(size);\r\n if (options.offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);\r\n } else {\r\n var offsetValue =\r\n options.offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n offsetAttribute = arrayFill(offsetAttribute, offsetValue);\r\n }\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: offsetAttribute,\r\n });\r\n }\r\n\r\n return attributes;\r\n}\r\n\r\nfunction computeWallIndices(positions) {\r\n var length = positions.length / 3;\r\n var indices = IndexDatatype.createTypedArray(length, length * 6);\r\n var index = 0;\r\n for (var i = 0; i < length; i++) {\r\n var UL = i;\r\n var LL = i + length;\r\n var UR = (UL + 1) % length;\r\n var LR = UR + length;\r\n indices[index++] = UL;\r\n indices[index++] = LL;\r\n indices[index++] = UR;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n }\r\n\r\n return indices;\r\n}\r\n\r\nvar topBoundingSphere = new BoundingSphere();\r\nvar bottomBoundingSphere = new BoundingSphere();\r\n\r\nfunction computeExtrudedEllipse(options) {\r\n var center = options.center;\r\n var ellipsoid = options.ellipsoid;\r\n var semiMajorAxis = options.semiMajorAxis;\r\n var scaledNormal = Cartesian3.multiplyByScalar(\r\n ellipsoid.geodeticSurfaceNormal(center, scratchCartesian1),\r\n options.height,\r\n scratchCartesian1\r\n );\r\n topBoundingSphere.center = Cartesian3.add(\r\n center,\r\n scaledNormal,\r\n topBoundingSphere.center\r\n );\r\n topBoundingSphere.radius = semiMajorAxis;\r\n\r\n scaledNormal = Cartesian3.multiplyByScalar(\r\n ellipsoid.geodeticSurfaceNormal(center, scaledNormal),\r\n options.extrudedHeight,\r\n scaledNormal\r\n );\r\n bottomBoundingSphere.center = Cartesian3.add(\r\n center,\r\n scaledNormal,\r\n bottomBoundingSphere.center\r\n );\r\n bottomBoundingSphere.radius = semiMajorAxis;\r\n\r\n var cep = EllipseGeometryLibrary.computeEllipsePositions(options, true, true);\r\n var positions = cep.positions;\r\n var numPts = cep.numPts;\r\n var outerPositions = cep.outerPositions;\r\n var boundingSphere = BoundingSphere.union(\r\n topBoundingSphere,\r\n bottomBoundingSphere\r\n );\r\n var topBottomAttributes = computeTopBottomAttributes(\r\n positions,\r\n options,\r\n true\r\n );\r\n var indices = topIndices(numPts);\r\n var length = indices.length;\r\n indices.length = length * 2;\r\n var posLength = positions.length / 3;\r\n for (var i = 0; i < length; i += 3) {\r\n indices[i + length] = indices[i + 2] + posLength;\r\n indices[i + 1 + length] = indices[i + 1] + posLength;\r\n indices[i + 2 + length] = indices[i] + posLength;\r\n }\r\n\r\n var topBottomIndices = IndexDatatype.createTypedArray(\r\n (posLength * 2) / 3,\r\n indices\r\n );\r\n\r\n var topBottomGeo = new Geometry({\r\n attributes: topBottomAttributes,\r\n indices: topBottomIndices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n\r\n var wallAttributes = computeWallAttributes(outerPositions, options);\r\n indices = computeWallIndices(outerPositions);\r\n var wallIndices = IndexDatatype.createTypedArray(\r\n (outerPositions.length * 2) / 3,\r\n indices\r\n );\r\n\r\n var wallGeo = new Geometry({\r\n attributes: wallAttributes,\r\n indices: wallIndices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n\r\n var geo = GeometryPipeline.combineInstances([\r\n new GeometryInstance({\r\n geometry: topBottomGeo,\r\n }),\r\n new GeometryInstance({\r\n geometry: wallGeo,\r\n }),\r\n ]);\r\n\r\n return {\r\n boundingSphere: boundingSphere,\r\n attributes: geo[0].attributes,\r\n indices: geo[0].indices,\r\n };\r\n}\r\n\r\nfunction computeRectangle(\r\n center,\r\n semiMajorAxis,\r\n semiMinorAxis,\r\n rotation,\r\n granularity,\r\n ellipsoid,\r\n result\r\n) {\r\n var cep = EllipseGeometryLibrary.computeEllipsePositions(\r\n {\r\n center: center,\r\n semiMajorAxis: semiMajorAxis,\r\n semiMinorAxis: semiMinorAxis,\r\n rotation: rotation,\r\n granularity: granularity,\r\n },\r\n false,\r\n true\r\n );\r\n var positionsFlat = cep.outerPositions;\r\n var positionsCount = positionsFlat.length / 3;\r\n var positions = new Array(positionsCount);\r\n for (var i = 0; i < positionsCount; ++i) {\r\n positions[i] = Cartesian3.fromArray(positionsFlat, i * 3);\r\n }\r\n var rectangle = Rectangle.fromCartesianArray(positions, ellipsoid, result);\r\n // Rectangle width goes beyond 180 degrees when the ellipse crosses a pole.\r\n // When this happens, make the rectangle into a \"circle\" around the pole\r\n if (rectangle.width > CesiumMath.PI) {\r\n rectangle.north =\r\n rectangle.north > 0.0\r\n ? CesiumMath.PI_OVER_TWO - CesiumMath.EPSILON7\r\n : rectangle.north;\r\n rectangle.south =\r\n rectangle.south < 0.0\r\n ? CesiumMath.EPSILON7 - CesiumMath.PI_OVER_TWO\r\n : rectangle.south;\r\n rectangle.east = CesiumMath.PI;\r\n rectangle.west = -CesiumMath.PI;\r\n }\r\n return rectangle;\r\n}\r\n\r\n/**\r\n * A description of an ellipse on an ellipsoid. Ellipse geometry can be rendered with both {@link Primitive} and {@link GroundPrimitive}.\r\n *\r\n * @alias EllipseGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.center The ellipse's center point in the fixed frame.\r\n * @param {Number} options.semiMajorAxis The length of the ellipse's semi-major axis in meters.\r\n * @param {Number} options.semiMinorAxis The length of the ellipse's semi-minor axis in meters.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on.\r\n * @param {Number} [options.height=0.0] The distance in meters between the ellipse and the ellipsoid surface.\r\n * @param {Number} [options.extrudedHeight] The distance in meters between the ellipse's extruded face and the ellipsoid surface.\r\n * @param {Number} [options.rotation=0.0] The angle of rotation counter-clockwise from north.\r\n * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates counter-clockwise from north.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The angular distance between points on the ellipse in radians.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n *\r\n * @exception {DeveloperError} semiMajorAxis and semiMinorAxis must be greater than zero.\r\n * @exception {DeveloperError} semiMajorAxis must be greater than or equal to the semiMinorAxis.\r\n * @exception {DeveloperError} granularity must be greater than zero.\r\n *\r\n *\r\n * @example\r\n * // Create an ellipse.\r\n * var ellipse = new Cesium.EllipseGeometry({\r\n * center : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),\r\n * semiMajorAxis : 500000.0,\r\n * semiMinorAxis : 300000.0,\r\n * rotation : Cesium.Math.toRadians(60.0)\r\n * });\r\n * var geometry = Cesium.EllipseGeometry.createGeometry(ellipse);\r\n *\r\n * @see EllipseGeometry.createGeometry\r\n */\r\nfunction EllipseGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var center = options.center;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var semiMajorAxis = options.semiMajorAxis;\r\n var semiMinorAxis = options.semiMinorAxis;\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.center\", center);\r\n Check.typeOf.number(\"options.semiMajorAxis\", semiMajorAxis);\r\n Check.typeOf.number(\"options.semiMinorAxis\", semiMinorAxis);\r\n if (semiMajorAxis < semiMinorAxis) {\r\n throw new DeveloperError(\r\n \"semiMajorAxis must be greater than or equal to the semiMinorAxis.\"\r\n );\r\n }\r\n if (granularity <= 0.0) {\r\n throw new DeveloperError(\"granularity must be greater than zero.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var height = defaultValue(options.height, 0.0);\r\n var extrudedHeight = defaultValue(options.extrudedHeight, height);\r\n\r\n this._center = Cartesian3.clone(center);\r\n this._semiMajorAxis = semiMajorAxis;\r\n this._semiMinorAxis = semiMinorAxis;\r\n this._ellipsoid = Ellipsoid.clone(ellipsoid);\r\n this._rotation = defaultValue(options.rotation, 0.0);\r\n this._stRotation = defaultValue(options.stRotation, 0.0);\r\n this._height = Math.max(extrudedHeight, height);\r\n this._granularity = granularity;\r\n this._vertexFormat = VertexFormat.clone(vertexFormat);\r\n this._extrudedHeight = Math.min(extrudedHeight, height);\r\n this._shadowVolume = defaultValue(options.shadowVolume, false);\r\n this._workerName = \"createEllipseGeometry\";\r\n this._offsetAttribute = options.offsetAttribute;\r\n\r\n this._rectangle = undefined;\r\n this._textureCoordinateRotationPoints = undefined;\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nEllipseGeometry.packedLength =\r\n Cartesian3.packedLength +\r\n Ellipsoid.packedLength +\r\n VertexFormat.packedLength +\r\n 9;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {EllipseGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nEllipseGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Cartesian3.pack(value._center, array, startingIndex);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._semiMajorAxis;\r\n array[startingIndex++] = value._semiMinorAxis;\r\n array[startingIndex++] = value._rotation;\r\n array[startingIndex++] = value._stRotation;\r\n array[startingIndex++] = value._height;\r\n array[startingIndex++] = value._granularity;\r\n array[startingIndex++] = value._extrudedHeight;\r\n array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchCenter = new Cartesian3();\r\nvar scratchEllipsoid = new Ellipsoid();\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n center: scratchCenter,\r\n ellipsoid: scratchEllipsoid,\r\n vertexFormat: scratchVertexFormat,\r\n semiMajorAxis: undefined,\r\n semiMinorAxis: undefined,\r\n rotation: undefined,\r\n stRotation: undefined,\r\n height: undefined,\r\n granularity: undefined,\r\n extrudedHeight: undefined,\r\n shadowVolume: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {EllipseGeometry} [result] The object into which to store the result.\r\n * @returns {EllipseGeometry} The modified result parameter or a new EllipseGeometry instance if one was not provided.\r\n */\r\nEllipseGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var center = Cartesian3.unpack(array, startingIndex, scratchCenter);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var semiMajorAxis = array[startingIndex++];\r\n var semiMinorAxis = array[startingIndex++];\r\n var rotation = array[startingIndex++];\r\n var stRotation = array[startingIndex++];\r\n var height = array[startingIndex++];\r\n var granularity = array[startingIndex++];\r\n var extrudedHeight = array[startingIndex++];\r\n var shadowVolume = array[startingIndex++] === 1.0;\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.height = height;\r\n scratchOptions.extrudedHeight = extrudedHeight;\r\n scratchOptions.granularity = granularity;\r\n scratchOptions.stRotation = stRotation;\r\n scratchOptions.rotation = rotation;\r\n scratchOptions.semiMajorAxis = semiMajorAxis;\r\n scratchOptions.semiMinorAxis = semiMinorAxis;\r\n scratchOptions.shadowVolume = shadowVolume;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return new EllipseGeometry(scratchOptions);\r\n }\r\n\r\n result._center = Cartesian3.clone(center, result._center);\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._semiMajorAxis = semiMajorAxis;\r\n result._semiMinorAxis = semiMinorAxis;\r\n result._rotation = rotation;\r\n result._stRotation = stRotation;\r\n result._height = height;\r\n result._granularity = granularity;\r\n result._extrudedHeight = extrudedHeight;\r\n result._shadowVolume = shadowVolume;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the bounding rectangle based on the provided options\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.center The ellipse's center point in the fixed frame.\r\n * @param {Number} options.semiMajorAxis The length of the ellipse's semi-major axis in meters.\r\n * @param {Number} options.semiMinorAxis The length of the ellipse's semi-minor axis in meters.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on.\r\n * @param {Number} [options.rotation=0.0] The angle of rotation counter-clockwise from north.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The angular distance between points on the ellipse in radians.\r\n * @param {Rectangle} [result] An object in which to store the result\r\n *\r\n * @returns {Rectangle} The result rectangle\r\n */\r\nEllipseGeometry.computeRectangle = function (options, result) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var center = options.center;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var semiMajorAxis = options.semiMajorAxis;\r\n var semiMinorAxis = options.semiMinorAxis;\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var rotation = defaultValue(options.rotation, 0.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.center\", center);\r\n Check.typeOf.number(\"options.semiMajorAxis\", semiMajorAxis);\r\n Check.typeOf.number(\"options.semiMinorAxis\", semiMinorAxis);\r\n if (semiMajorAxis < semiMinorAxis) {\r\n throw new DeveloperError(\r\n \"semiMajorAxis must be greater than or equal to the semiMinorAxis.\"\r\n );\r\n }\r\n if (granularity <= 0.0) {\r\n throw new DeveloperError(\"granularity must be greater than zero.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return computeRectangle(\r\n center,\r\n semiMajorAxis,\r\n semiMinorAxis,\r\n rotation,\r\n granularity,\r\n ellipsoid,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a ellipse on an ellipsoid, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {EllipseGeometry} ellipseGeometry A description of the ellipse.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nEllipseGeometry.createGeometry = function (ellipseGeometry) {\r\n if (\r\n ellipseGeometry._semiMajorAxis <= 0.0 ||\r\n ellipseGeometry._semiMinorAxis <= 0.0\r\n ) {\r\n return;\r\n }\r\n\r\n var height = ellipseGeometry._height;\r\n var extrudedHeight = ellipseGeometry._extrudedHeight;\r\n var extrude = !CesiumMath.equalsEpsilon(\r\n height,\r\n extrudedHeight,\r\n 0,\r\n CesiumMath.EPSILON2\r\n );\r\n\r\n ellipseGeometry._center = ellipseGeometry._ellipsoid.scaleToGeodeticSurface(\r\n ellipseGeometry._center,\r\n ellipseGeometry._center\r\n );\r\n var options = {\r\n center: ellipseGeometry._center,\r\n semiMajorAxis: ellipseGeometry._semiMajorAxis,\r\n semiMinorAxis: ellipseGeometry._semiMinorAxis,\r\n ellipsoid: ellipseGeometry._ellipsoid,\r\n rotation: ellipseGeometry._rotation,\r\n height: height,\r\n granularity: ellipseGeometry._granularity,\r\n vertexFormat: ellipseGeometry._vertexFormat,\r\n stRotation: ellipseGeometry._stRotation,\r\n };\r\n var geometry;\r\n if (extrude) {\r\n options.extrudedHeight = extrudedHeight;\r\n options.shadowVolume = ellipseGeometry._shadowVolume;\r\n options.offsetAttribute = ellipseGeometry._offsetAttribute;\r\n geometry = computeExtrudedEllipse(options);\r\n } else {\r\n geometry = computeEllipse(options);\r\n\r\n if (defined(ellipseGeometry._offsetAttribute)) {\r\n var length = geometry.attributes.position.values.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n ellipseGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n geometry.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n }\r\n\r\n return new Geometry({\r\n attributes: geometry.attributes,\r\n indices: geometry.indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: geometry.boundingSphere,\r\n offsetAttribute: ellipseGeometry._offsetAttribute,\r\n });\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nEllipseGeometry.createShadowVolume = function (\r\n ellipseGeometry,\r\n minHeightFunc,\r\n maxHeightFunc\r\n) {\r\n var granularity = ellipseGeometry._granularity;\r\n var ellipsoid = ellipseGeometry._ellipsoid;\r\n\r\n var minHeight = minHeightFunc(granularity, ellipsoid);\r\n var maxHeight = maxHeightFunc(granularity, ellipsoid);\r\n\r\n return new EllipseGeometry({\r\n center: ellipseGeometry._center,\r\n semiMajorAxis: ellipseGeometry._semiMajorAxis,\r\n semiMinorAxis: ellipseGeometry._semiMinorAxis,\r\n ellipsoid: ellipsoid,\r\n rotation: ellipseGeometry._rotation,\r\n stRotation: ellipseGeometry._stRotation,\r\n granularity: granularity,\r\n extrudedHeight: minHeight,\r\n height: maxHeight,\r\n vertexFormat: VertexFormat.POSITION_ONLY,\r\n shadowVolume: true,\r\n });\r\n};\r\n\r\nfunction textureCoordinateRotationPoints(ellipseGeometry) {\r\n var stRotation = -ellipseGeometry._stRotation;\r\n if (stRotation === 0.0) {\r\n return [0, 0, 0, 1, 1, 0];\r\n }\r\n\r\n var cep = EllipseGeometryLibrary.computeEllipsePositions(\r\n {\r\n center: ellipseGeometry._center,\r\n semiMajorAxis: ellipseGeometry._semiMajorAxis,\r\n semiMinorAxis: ellipseGeometry._semiMinorAxis,\r\n rotation: ellipseGeometry._rotation,\r\n granularity: ellipseGeometry._granularity,\r\n },\r\n false,\r\n true\r\n );\r\n var positionsFlat = cep.outerPositions;\r\n var positionsCount = positionsFlat.length / 3;\r\n var positions = new Array(positionsCount);\r\n for (var i = 0; i < positionsCount; ++i) {\r\n positions[i] = Cartesian3.fromArray(positionsFlat, i * 3);\r\n }\r\n\r\n var ellipsoid = ellipseGeometry._ellipsoid;\r\n var boundingRectangle = ellipseGeometry.rectangle;\r\n return Geometry._textureCoordinateRotationPoints(\r\n positions,\r\n stRotation,\r\n ellipsoid,\r\n boundingRectangle\r\n );\r\n}\r\n\r\nObject.defineProperties(EllipseGeometry.prototype, {\r\n /**\r\n * @private\r\n */\r\n rectangle: {\r\n get: function () {\r\n if (!defined(this._rectangle)) {\r\n this._rectangle = computeRectangle(\r\n this._center,\r\n this._semiMajorAxis,\r\n this._semiMinorAxis,\r\n this._rotation,\r\n this._granularity,\r\n this._ellipsoid\r\n );\r\n }\r\n return this._rectangle;\r\n },\r\n },\r\n /**\r\n * For remapping texture coordinates when rendering EllipseGeometries as GroundPrimitives.\r\n * @private\r\n */\r\n textureCoordinateRotationPoints: {\r\n get: function () {\r\n if (!defined(this._textureCoordinateRotationPoints)) {\r\n this._textureCoordinateRotationPoints = textureCoordinateRotationPoints(\r\n this\r\n );\r\n }\r\n return this._textureCoordinateRotationPoints;\r\n },\r\n },\r\n});\r\nexport default EllipseGeometry;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport EllipseGeometry from \"./EllipseGeometry.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\n/**\r\n * A description of a circle on the ellipsoid. Circle geometry can be rendered with both {@link Primitive} and {@link GroundPrimitive}.\r\n *\r\n * @alias CircleGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.center The circle's center point in the fixed frame.\r\n * @param {Number} options.radius The radius in meters.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the circle will be on.\r\n * @param {Number} [options.height=0.0] The distance in meters between the circle and the ellipsoid surface.\r\n * @param {Number} [options.granularity=0.02] The angular distance between points on the circle in radians.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {Number} [options.extrudedHeight=0.0] The distance in meters between the circle's extruded face and the ellipsoid surface.\r\n * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.\r\n *\r\n * @exception {DeveloperError} radius must be greater than zero.\r\n * @exception {DeveloperError} granularity must be greater than zero.\r\n *\r\n * @see CircleGeometry.createGeometry\r\n * @see Packable\r\n *\r\n * @example\r\n * // Create a circle.\r\n * var circle = new Cesium.CircleGeometry({\r\n * center : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),\r\n * radius : 100000.0\r\n * });\r\n * var geometry = Cesium.CircleGeometry.createGeometry(circle);\r\n */\r\nfunction CircleGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var radius = options.radius;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"radius\", radius);\r\n //>>includeEnd('debug');\r\n\r\n var ellipseGeometryOptions = {\r\n center: options.center,\r\n semiMajorAxis: radius,\r\n semiMinorAxis: radius,\r\n ellipsoid: options.ellipsoid,\r\n height: options.height,\r\n extrudedHeight: options.extrudedHeight,\r\n granularity: options.granularity,\r\n vertexFormat: options.vertexFormat,\r\n stRotation: options.stRotation,\r\n shadowVolume: options.shadowVolume,\r\n };\r\n this._ellipseGeometry = new EllipseGeometry(ellipseGeometryOptions);\r\n this._workerName = \"createCircleGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nCircleGeometry.packedLength = EllipseGeometry.packedLength;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {CircleGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCircleGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n //>>includeEnd('debug');\r\n return EllipseGeometry.pack(value._ellipseGeometry, array, startingIndex);\r\n};\r\n\r\nvar scratchEllipseGeometry = new EllipseGeometry({\r\n center: new Cartesian3(),\r\n semiMajorAxis: 1.0,\r\n semiMinorAxis: 1.0,\r\n});\r\nvar scratchOptions = {\r\n center: new Cartesian3(),\r\n radius: undefined,\r\n ellipsoid: Ellipsoid.clone(Ellipsoid.UNIT_SPHERE),\r\n height: undefined,\r\n extrudedHeight: undefined,\r\n granularity: undefined,\r\n vertexFormat: new VertexFormat(),\r\n stRotation: undefined,\r\n semiMajorAxis: undefined,\r\n semiMinorAxis: undefined,\r\n shadowVolume: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {CircleGeometry} [result] The object into which to store the result.\r\n * @returns {CircleGeometry} The modified result parameter or a new CircleGeometry instance if one was not provided.\r\n */\r\nCircleGeometry.unpack = function (array, startingIndex, result) {\r\n var ellipseGeometry = EllipseGeometry.unpack(\r\n array,\r\n startingIndex,\r\n scratchEllipseGeometry\r\n );\r\n scratchOptions.center = Cartesian3.clone(\r\n ellipseGeometry._center,\r\n scratchOptions.center\r\n );\r\n scratchOptions.ellipsoid = Ellipsoid.clone(\r\n ellipseGeometry._ellipsoid,\r\n scratchOptions.ellipsoid\r\n );\r\n scratchOptions.height = ellipseGeometry._height;\r\n scratchOptions.extrudedHeight = ellipseGeometry._extrudedHeight;\r\n scratchOptions.granularity = ellipseGeometry._granularity;\r\n scratchOptions.vertexFormat = VertexFormat.clone(\r\n ellipseGeometry._vertexFormat,\r\n scratchOptions.vertexFormat\r\n );\r\n scratchOptions.stRotation = ellipseGeometry._stRotation;\r\n scratchOptions.shadowVolume = ellipseGeometry._shadowVolume;\r\n\r\n if (!defined(result)) {\r\n scratchOptions.radius = ellipseGeometry._semiMajorAxis;\r\n return new CircleGeometry(scratchOptions);\r\n }\r\n\r\n scratchOptions.semiMajorAxis = ellipseGeometry._semiMajorAxis;\r\n scratchOptions.semiMinorAxis = ellipseGeometry._semiMinorAxis;\r\n result._ellipseGeometry = new EllipseGeometry(scratchOptions);\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a circle on an ellipsoid, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {CircleGeometry} circleGeometry A description of the circle.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nCircleGeometry.createGeometry = function (circleGeometry) {\r\n return EllipseGeometry.createGeometry(circleGeometry._ellipseGeometry);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCircleGeometry.createShadowVolume = function (\r\n circleGeometry,\r\n minHeightFunc,\r\n maxHeightFunc\r\n) {\r\n var granularity = circleGeometry._ellipseGeometry._granularity;\r\n var ellipsoid = circleGeometry._ellipseGeometry._ellipsoid;\r\n\r\n var minHeight = minHeightFunc(granularity, ellipsoid);\r\n var maxHeight = maxHeightFunc(granularity, ellipsoid);\r\n\r\n return new CircleGeometry({\r\n center: circleGeometry._ellipseGeometry._center,\r\n radius: circleGeometry._ellipseGeometry._semiMajorAxis,\r\n ellipsoid: ellipsoid,\r\n stRotation: circleGeometry._ellipseGeometry._stRotation,\r\n granularity: granularity,\r\n extrudedHeight: minHeight,\r\n height: maxHeight,\r\n vertexFormat: VertexFormat.POSITION_ONLY,\r\n shadowVolume: true,\r\n });\r\n};\r\n\r\nObject.defineProperties(CircleGeometry.prototype, {\r\n /**\r\n * @private\r\n */\r\n rectangle: {\r\n get: function () {\r\n return this._ellipseGeometry.rectangle;\r\n },\r\n },\r\n /**\r\n * For remapping texture coordinates when rendering CircleGeometries as GroundPrimitives.\r\n * @private\r\n */\r\n textureCoordinateRotationPoints: {\r\n get: function () {\r\n return this._ellipseGeometry.textureCoordinateRotationPoints;\r\n },\r\n },\r\n});\r\nexport default CircleGeometry;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport EllipseGeometryLibrary from \"./EllipseGeometryLibrary.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\n\r\nvar scratchCartesian1 = new Cartesian3();\r\nvar boundingSphereCenter = new Cartesian3();\r\n\r\nfunction computeEllipse(options) {\r\n var center = options.center;\r\n boundingSphereCenter = Cartesian3.multiplyByScalar(\r\n options.ellipsoid.geodeticSurfaceNormal(center, boundingSphereCenter),\r\n options.height,\r\n boundingSphereCenter\r\n );\r\n boundingSphereCenter = Cartesian3.add(\r\n center,\r\n boundingSphereCenter,\r\n boundingSphereCenter\r\n );\r\n var boundingSphere = new BoundingSphere(\r\n boundingSphereCenter,\r\n options.semiMajorAxis\r\n );\r\n var positions = EllipseGeometryLibrary.computeEllipsePositions(\r\n options,\r\n false,\r\n true\r\n ).outerPositions;\r\n\r\n var attributes = new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: EllipseGeometryLibrary.raisePositionsToHeight(\r\n positions,\r\n options,\r\n false\r\n ),\r\n }),\r\n });\r\n\r\n var length = positions.length / 3;\r\n var indices = IndexDatatype.createTypedArray(length, length * 2);\r\n var index = 0;\r\n for (var i = 0; i < length; ++i) {\r\n indices[index++] = i;\r\n indices[index++] = (i + 1) % length;\r\n }\r\n\r\n return {\r\n boundingSphere: boundingSphere,\r\n attributes: attributes,\r\n indices: indices,\r\n };\r\n}\r\n\r\nvar topBoundingSphere = new BoundingSphere();\r\nvar bottomBoundingSphere = new BoundingSphere();\r\nfunction computeExtrudedEllipse(options) {\r\n var center = options.center;\r\n var ellipsoid = options.ellipsoid;\r\n var semiMajorAxis = options.semiMajorAxis;\r\n var scaledNormal = Cartesian3.multiplyByScalar(\r\n ellipsoid.geodeticSurfaceNormal(center, scratchCartesian1),\r\n options.height,\r\n scratchCartesian1\r\n );\r\n topBoundingSphere.center = Cartesian3.add(\r\n center,\r\n scaledNormal,\r\n topBoundingSphere.center\r\n );\r\n topBoundingSphere.radius = semiMajorAxis;\r\n\r\n scaledNormal = Cartesian3.multiplyByScalar(\r\n ellipsoid.geodeticSurfaceNormal(center, scaledNormal),\r\n options.extrudedHeight,\r\n scaledNormal\r\n );\r\n bottomBoundingSphere.center = Cartesian3.add(\r\n center,\r\n scaledNormal,\r\n bottomBoundingSphere.center\r\n );\r\n bottomBoundingSphere.radius = semiMajorAxis;\r\n\r\n var positions = EllipseGeometryLibrary.computeEllipsePositions(\r\n options,\r\n false,\r\n true\r\n ).outerPositions;\r\n var attributes = new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: EllipseGeometryLibrary.raisePositionsToHeight(\r\n positions,\r\n options,\r\n true\r\n ),\r\n }),\r\n });\r\n\r\n positions = attributes.position.values;\r\n var boundingSphere = BoundingSphere.union(\r\n topBoundingSphere,\r\n bottomBoundingSphere\r\n );\r\n var length = positions.length / 3;\r\n\r\n if (defined(options.offsetAttribute)) {\r\n var applyOffset = new Uint8Array(length);\r\n if (options.offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n applyOffset = arrayFill(applyOffset, 1, 0, length / 2);\r\n } else {\r\n var offsetValue =\r\n options.offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n applyOffset = arrayFill(applyOffset, offsetValue);\r\n }\r\n\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n var numberOfVerticalLines = defaultValue(options.numberOfVerticalLines, 16);\r\n numberOfVerticalLines = CesiumMath.clamp(\r\n numberOfVerticalLines,\r\n 0,\r\n length / 2\r\n );\r\n\r\n var indices = IndexDatatype.createTypedArray(\r\n length,\r\n length * 2 + numberOfVerticalLines * 2\r\n );\r\n\r\n length /= 2;\r\n var index = 0;\r\n var i;\r\n for (i = 0; i < length; ++i) {\r\n indices[index++] = i;\r\n indices[index++] = (i + 1) % length;\r\n indices[index++] = i + length;\r\n indices[index++] = ((i + 1) % length) + length;\r\n }\r\n\r\n var numSide;\r\n if (numberOfVerticalLines > 0) {\r\n var numSideLines = Math.min(numberOfVerticalLines, length);\r\n numSide = Math.round(length / numSideLines);\r\n\r\n var maxI = Math.min(numSide * numberOfVerticalLines, length);\r\n for (i = 0; i < maxI; i += numSide) {\r\n indices[index++] = i;\r\n indices[index++] = i + length;\r\n }\r\n }\r\n\r\n return {\r\n boundingSphere: boundingSphere,\r\n attributes: attributes,\r\n indices: indices,\r\n };\r\n}\r\n\r\n/**\r\n * A description of the outline of an ellipse on an ellipsoid.\r\n *\r\n * @alias EllipseOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.center The ellipse's center point in the fixed frame.\r\n * @param {Number} options.semiMajorAxis The length of the ellipse's semi-major axis in meters.\r\n * @param {Number} options.semiMinorAxis The length of the ellipse's semi-minor axis in meters.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the ellipse will be on.\r\n * @param {Number} [options.height=0.0] The distance in meters between the ellipse and the ellipsoid surface.\r\n * @param {Number} [options.extrudedHeight] The distance in meters between the ellipse's extruded face and the ellipsoid surface.\r\n * @param {Number} [options.rotation=0.0] The angle from north (counter-clockwise) in radians.\r\n * @param {Number} [options.granularity=0.02] The angular distance between points on the ellipse in radians.\r\n * @param {Number} [options.numberOfVerticalLines=16] Number of lines to draw between the top and bottom surface of an extruded ellipse.\r\n *\r\n * @exception {DeveloperError} semiMajorAxis and semiMinorAxis must be greater than zero.\r\n * @exception {DeveloperError} semiMajorAxis must be greater than or equal to the semiMinorAxis.\r\n * @exception {DeveloperError} granularity must be greater than zero.\r\n *\r\n * @see EllipseOutlineGeometry.createGeometry\r\n *\r\n * @example\r\n * var ellipse = new Cesium.EllipseOutlineGeometry({\r\n * center : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),\r\n * semiMajorAxis : 500000.0,\r\n * semiMinorAxis : 300000.0,\r\n * rotation : Cesium.Math.toRadians(60.0)\r\n * });\r\n * var geometry = Cesium.EllipseOutlineGeometry.createGeometry(ellipse);\r\n */\r\nfunction EllipseOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var center = options.center;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var semiMajorAxis = options.semiMajorAxis;\r\n var semiMinorAxis = options.semiMinorAxis;\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(center)) {\r\n throw new DeveloperError(\"center is required.\");\r\n }\r\n if (!defined(semiMajorAxis)) {\r\n throw new DeveloperError(\"semiMajorAxis is required.\");\r\n }\r\n if (!defined(semiMinorAxis)) {\r\n throw new DeveloperError(\"semiMinorAxis is required.\");\r\n }\r\n if (semiMajorAxis < semiMinorAxis) {\r\n throw new DeveloperError(\r\n \"semiMajorAxis must be greater than or equal to the semiMinorAxis.\"\r\n );\r\n }\r\n if (granularity <= 0.0) {\r\n throw new DeveloperError(\"granularity must be greater than zero.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var height = defaultValue(options.height, 0.0);\r\n var extrudedHeight = defaultValue(options.extrudedHeight, height);\r\n\r\n this._center = Cartesian3.clone(center);\r\n this._semiMajorAxis = semiMajorAxis;\r\n this._semiMinorAxis = semiMinorAxis;\r\n this._ellipsoid = Ellipsoid.clone(ellipsoid);\r\n this._rotation = defaultValue(options.rotation, 0.0);\r\n this._height = Math.max(extrudedHeight, height);\r\n this._granularity = granularity;\r\n this._extrudedHeight = Math.min(extrudedHeight, height);\r\n this._numberOfVerticalLines = Math.max(\r\n defaultValue(options.numberOfVerticalLines, 16),\r\n 0\r\n );\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createEllipseOutlineGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nEllipseOutlineGeometry.packedLength =\r\n Cartesian3.packedLength + Ellipsoid.packedLength + 8;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {EllipseOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nEllipseOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Cartesian3.pack(value._center, array, startingIndex);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n array[startingIndex++] = value._semiMajorAxis;\r\n array[startingIndex++] = value._semiMinorAxis;\r\n array[startingIndex++] = value._rotation;\r\n array[startingIndex++] = value._height;\r\n array[startingIndex++] = value._granularity;\r\n array[startingIndex++] = value._extrudedHeight;\r\n array[startingIndex++] = value._numberOfVerticalLines;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchCenter = new Cartesian3();\r\nvar scratchEllipsoid = new Ellipsoid();\r\nvar scratchOptions = {\r\n center: scratchCenter,\r\n ellipsoid: scratchEllipsoid,\r\n semiMajorAxis: undefined,\r\n semiMinorAxis: undefined,\r\n rotation: undefined,\r\n height: undefined,\r\n granularity: undefined,\r\n extrudedHeight: undefined,\r\n numberOfVerticalLines: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {EllipseOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {EllipseOutlineGeometry} The modified result parameter or a new EllipseOutlineGeometry instance if one was not provided.\r\n */\r\nEllipseOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var center = Cartesian3.unpack(array, startingIndex, scratchCenter);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var semiMajorAxis = array[startingIndex++];\r\n var semiMinorAxis = array[startingIndex++];\r\n var rotation = array[startingIndex++];\r\n var height = array[startingIndex++];\r\n var granularity = array[startingIndex++];\r\n var extrudedHeight = array[startingIndex++];\r\n var numberOfVerticalLines = array[startingIndex++];\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.height = height;\r\n scratchOptions.extrudedHeight = extrudedHeight;\r\n scratchOptions.granularity = granularity;\r\n scratchOptions.rotation = rotation;\r\n scratchOptions.semiMajorAxis = semiMajorAxis;\r\n scratchOptions.semiMinorAxis = semiMinorAxis;\r\n scratchOptions.numberOfVerticalLines = numberOfVerticalLines;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return new EllipseOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._center = Cartesian3.clone(center, result._center);\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._semiMajorAxis = semiMajorAxis;\r\n result._semiMinorAxis = semiMinorAxis;\r\n result._rotation = rotation;\r\n result._height = height;\r\n result._granularity = granularity;\r\n result._extrudedHeight = extrudedHeight;\r\n result._numberOfVerticalLines = numberOfVerticalLines;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an outline of an ellipse on an ellipsoid, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {EllipseOutlineGeometry} ellipseGeometry A description of the ellipse.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nEllipseOutlineGeometry.createGeometry = function (ellipseGeometry) {\r\n if (\r\n ellipseGeometry._semiMajorAxis <= 0.0 ||\r\n ellipseGeometry._semiMinorAxis <= 0.0\r\n ) {\r\n return;\r\n }\r\n\r\n var height = ellipseGeometry._height;\r\n var extrudedHeight = ellipseGeometry._extrudedHeight;\r\n var extrude = !CesiumMath.equalsEpsilon(\r\n height,\r\n extrudedHeight,\r\n 0,\r\n CesiumMath.EPSILON2\r\n );\r\n\r\n ellipseGeometry._center = ellipseGeometry._ellipsoid.scaleToGeodeticSurface(\r\n ellipseGeometry._center,\r\n ellipseGeometry._center\r\n );\r\n var options = {\r\n center: ellipseGeometry._center,\r\n semiMajorAxis: ellipseGeometry._semiMajorAxis,\r\n semiMinorAxis: ellipseGeometry._semiMinorAxis,\r\n ellipsoid: ellipseGeometry._ellipsoid,\r\n rotation: ellipseGeometry._rotation,\r\n height: height,\r\n granularity: ellipseGeometry._granularity,\r\n numberOfVerticalLines: ellipseGeometry._numberOfVerticalLines,\r\n };\r\n var geometry;\r\n if (extrude) {\r\n options.extrudedHeight = extrudedHeight;\r\n options.offsetAttribute = ellipseGeometry._offsetAttribute;\r\n geometry = computeExtrudedEllipse(options);\r\n } else {\r\n geometry = computeEllipse(options);\r\n\r\n if (defined(ellipseGeometry._offsetAttribute)) {\r\n var length = geometry.attributes.position.values.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n ellipseGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n geometry.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n }\r\n\r\n return new Geometry({\r\n attributes: geometry.attributes,\r\n indices: geometry.indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: geometry.boundingSphere,\r\n offsetAttribute: ellipseGeometry._offsetAttribute,\r\n });\r\n};\r\nexport default EllipseOutlineGeometry;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport EllipseOutlineGeometry from \"./EllipseOutlineGeometry.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\n\r\n/**\r\n * A description of the outline of a circle on the ellipsoid.\r\n *\r\n * @alias CircleOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3} options.center The circle's center point in the fixed frame.\r\n * @param {Number} options.radius The radius in meters.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid the circle will be on.\r\n * @param {Number} [options.height=0.0] The distance in meters between the circle and the ellipsoid surface.\r\n * @param {Number} [options.granularity=0.02] The angular distance between points on the circle in radians.\r\n * @param {Number} [options.extrudedHeight=0.0] The distance in meters between the circle's extruded face and the ellipsoid surface.\r\n * @param {Number} [options.numberOfVerticalLines=16] Number of lines to draw between the top and bottom of an extruded circle.\r\n *\r\n * @exception {DeveloperError} radius must be greater than zero.\r\n * @exception {DeveloperError} granularity must be greater than zero.\r\n *\r\n * @see CircleOutlineGeometry.createGeometry\r\n * @see Packable\r\n *\r\n * @example\r\n * // Create a circle.\r\n * var circle = new Cesium.CircleOutlineGeometry({\r\n * center : Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),\r\n * radius : 100000.0\r\n * });\r\n * var geometry = Cesium.CircleOutlineGeometry.createGeometry(circle);\r\n */\r\nfunction CircleOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var radius = options.radius;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"radius\", radius);\r\n //>>includeEnd('debug');\r\n\r\n var ellipseGeometryOptions = {\r\n center: options.center,\r\n semiMajorAxis: radius,\r\n semiMinorAxis: radius,\r\n ellipsoid: options.ellipsoid,\r\n height: options.height,\r\n extrudedHeight: options.extrudedHeight,\r\n granularity: options.granularity,\r\n numberOfVerticalLines: options.numberOfVerticalLines,\r\n };\r\n this._ellipseGeometry = new EllipseOutlineGeometry(ellipseGeometryOptions);\r\n this._workerName = \"createCircleOutlineGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nCircleOutlineGeometry.packedLength = EllipseOutlineGeometry.packedLength;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {CircleOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCircleOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n //>>includeEnd('debug');\r\n return EllipseOutlineGeometry.pack(\r\n value._ellipseGeometry,\r\n array,\r\n startingIndex\r\n );\r\n};\r\n\r\nvar scratchEllipseGeometry = new EllipseOutlineGeometry({\r\n center: new Cartesian3(),\r\n semiMajorAxis: 1.0,\r\n semiMinorAxis: 1.0,\r\n});\r\nvar scratchOptions = {\r\n center: new Cartesian3(),\r\n radius: undefined,\r\n ellipsoid: Ellipsoid.clone(Ellipsoid.UNIT_SPHERE),\r\n height: undefined,\r\n extrudedHeight: undefined,\r\n granularity: undefined,\r\n numberOfVerticalLines: undefined,\r\n semiMajorAxis: undefined,\r\n semiMinorAxis: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {CircleOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {CircleOutlineGeometry} The modified result parameter or a new CircleOutlineGeometry instance if one was not provided.\r\n */\r\nCircleOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n var ellipseGeometry = EllipseOutlineGeometry.unpack(\r\n array,\r\n startingIndex,\r\n scratchEllipseGeometry\r\n );\r\n scratchOptions.center = Cartesian3.clone(\r\n ellipseGeometry._center,\r\n scratchOptions.center\r\n );\r\n scratchOptions.ellipsoid = Ellipsoid.clone(\r\n ellipseGeometry._ellipsoid,\r\n scratchOptions.ellipsoid\r\n );\r\n scratchOptions.height = ellipseGeometry._height;\r\n scratchOptions.extrudedHeight = ellipseGeometry._extrudedHeight;\r\n scratchOptions.granularity = ellipseGeometry._granularity;\r\n scratchOptions.numberOfVerticalLines = ellipseGeometry._numberOfVerticalLines;\r\n\r\n if (!defined(result)) {\r\n scratchOptions.radius = ellipseGeometry._semiMajorAxis;\r\n return new CircleOutlineGeometry(scratchOptions);\r\n }\r\n\r\n scratchOptions.semiMajorAxis = ellipseGeometry._semiMajorAxis;\r\n scratchOptions.semiMinorAxis = ellipseGeometry._semiMinorAxis;\r\n result._ellipseGeometry = new EllipseOutlineGeometry(scratchOptions);\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an outline of a circle on an ellipsoid, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {CircleOutlineGeometry} circleGeometry A description of the circle.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nCircleOutlineGeometry.createGeometry = function (circleGeometry) {\r\n return EllipseOutlineGeometry.createGeometry(circleGeometry._ellipseGeometry);\r\n};\r\nexport default CircleOutlineGeometry;\r\n","/**\r\n * Constants used by {@link Clock#tick} to determine behavior\r\n * when {@link Clock#startTime} or {@link Clock#stopTime} is reached.\r\n *\r\n * @enum {Number}\r\n *\r\n * @see Clock\r\n * @see ClockStep\r\n */\r\nvar ClockRange = {\r\n /**\r\n * {@link Clock#tick} will always advances the clock in its current direction.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n UNBOUNDED: 0,\r\n\r\n /**\r\n * When {@link Clock#startTime} or {@link Clock#stopTime} is reached,\r\n * {@link Clock#tick} will not advance {@link Clock#currentTime} any further.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CLAMPED: 1,\r\n\r\n /**\r\n * When {@link Clock#stopTime} is reached, {@link Clock#tick} will advance\r\n * {@link Clock#currentTime} to the opposite end of the interval. When\r\n * time is moving backwards, {@link Clock#tick} will not advance past\r\n * {@link Clock#startTime}\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LOOP_STOP: 2,\r\n};\r\nexport default Object.freeze(ClockRange);\r\n","/**\r\n * Constants to determine how much time advances with each call\r\n * to {@link Clock#tick}.\r\n *\r\n * @enum {Number}\r\n *\r\n * @see Clock\r\n * @see ClockRange\r\n */\r\nvar ClockStep = {\r\n /**\r\n * {@link Clock#tick} advances the current time by a fixed step,\r\n * which is the number of seconds specified by {@link Clock#multiplier}.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n TICK_DEPENDENT: 0,\r\n\r\n /**\r\n * {@link Clock#tick} advances the current time by the amount of system\r\n * time elapsed since the previous call multiplied by {@link Clock#multiplier}.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SYSTEM_CLOCK_MULTIPLIER: 1,\r\n\r\n /**\r\n * {@link Clock#tick} sets the clock to the current system time;\r\n * ignoring all other settings.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SYSTEM_CLOCK: 2,\r\n};\r\nexport default Object.freeze(ClockStep);\r\n","/**\r\n * Gets a timestamp that can be used in measuring the time between events. Timestamps\r\n * are expressed in milliseconds, but it is not specified what the milliseconds are\r\n * measured from. This function uses performance.now() if it is available, or Date.now()\r\n * otherwise.\r\n *\r\n * @function getTimestamp\r\n *\r\n * @returns {Number} The timestamp in milliseconds since some unspecified reference time.\r\n */\r\nvar getTimestamp;\r\n\r\nif (\r\n typeof performance !== \"undefined\" &&\r\n typeof performance.now === \"function\" &&\r\n isFinite(performance.now())\r\n) {\r\n getTimestamp = function () {\r\n return performance.now();\r\n };\r\n} else {\r\n getTimestamp = function () {\r\n return Date.now();\r\n };\r\n}\r\nexport default getTimestamp;\r\n","import ClockRange from \"./ClockRange.js\";\r\nimport ClockStep from \"./ClockStep.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Event from \"./Event.js\";\r\nimport getTimestamp from \"./getTimestamp.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\n\r\n/**\r\n * A simple clock for keeping track of simulated time.\r\n *\r\n * @alias Clock\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {JulianDate} [options.startTime] The start time of the clock.\r\n * @param {JulianDate} [options.stopTime] The stop time of the clock.\r\n * @param {JulianDate} [options.currentTime] The current time.\r\n * @param {Number} [options.multiplier=1.0] Determines how much time advances when {@link Clock#tick} is called, negative values allow for advancing backwards.\r\n * @param {ClockStep} [options.clockStep=ClockStep.SYSTEM_CLOCK_MULTIPLIER] Determines if calls to {@link Clock#tick} are frame dependent or system clock dependent.\r\n * @param {ClockRange} [options.clockRange=ClockRange.UNBOUNDED] Determines how the clock should behave when {@link Clock#startTime} or {@link Clock#stopTime} is reached.\r\n * @param {Boolean} [options.canAnimate=true] Indicates whether {@link Clock#tick} can advance time. This could be false if data is being buffered, for example. The clock will only tick when both {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.\r\n * @param {Boolean} [options.shouldAnimate=false] Indicates whether {@link Clock#tick} should attempt to advance time. The clock will only tick when both {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.\r\n *\r\n * @exception {DeveloperError} startTime must come before stopTime.\r\n *\r\n *\r\n * @example\r\n * // Create a clock that loops on Christmas day 2013 and runs in real-time.\r\n * var clock = new Cesium.Clock({\r\n * startTime : Cesium.JulianDate.fromIso8601(\"2013-12-25\"),\r\n * currentTime : Cesium.JulianDate.fromIso8601(\"2013-12-25\"),\r\n * stopTime : Cesium.JulianDate.fromIso8601(\"2013-12-26\"),\r\n * clockRange : Cesium.ClockRange.LOOP_STOP,\r\n * clockStep : Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER\r\n * });\r\n *\r\n * @see ClockStep\r\n * @see ClockRange\r\n * @see JulianDate\r\n */\r\nfunction Clock(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var currentTime = options.currentTime;\r\n var startTime = options.startTime;\r\n var stopTime = options.stopTime;\r\n\r\n if (!defined(currentTime)) {\r\n // if not specified, current time is the start time,\r\n // or if that is not specified, 1 day before the stop time,\r\n // or if that is not specified, then now.\r\n if (defined(startTime)) {\r\n currentTime = JulianDate.clone(startTime);\r\n } else if (defined(stopTime)) {\r\n currentTime = JulianDate.addDays(stopTime, -1.0, new JulianDate());\r\n } else {\r\n currentTime = JulianDate.now();\r\n }\r\n } else {\r\n currentTime = JulianDate.clone(currentTime);\r\n }\r\n\r\n if (!defined(startTime)) {\r\n // if not specified, start time is the current time\r\n // (as determined above)\r\n startTime = JulianDate.clone(currentTime);\r\n } else {\r\n startTime = JulianDate.clone(startTime);\r\n }\r\n\r\n if (!defined(stopTime)) {\r\n // if not specified, stop time is 1 day after the start time\r\n // (as determined above)\r\n stopTime = JulianDate.addDays(startTime, 1.0, new JulianDate());\r\n } else {\r\n stopTime = JulianDate.clone(stopTime);\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (JulianDate.greaterThan(startTime, stopTime)) {\r\n throw new DeveloperError(\"startTime must come before stopTime.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * The start time of the clock.\r\n * @type {JulianDate}\r\n */\r\n this.startTime = startTime;\r\n\r\n /**\r\n * The stop time of the clock.\r\n * @type {JulianDate}\r\n */\r\n this.stopTime = stopTime;\r\n\r\n /**\r\n * Determines how the clock should behave when\r\n * {@link Clock#startTime} or {@link Clock#stopTime}\r\n * is reached.\r\n * @type {ClockRange}\r\n * @default {@link ClockRange.UNBOUNDED}\r\n */\r\n this.clockRange = defaultValue(options.clockRange, ClockRange.UNBOUNDED);\r\n\r\n /**\r\n * Indicates whether {@link Clock#tick} can advance time. This could be false if data is being buffered,\r\n * for example. The clock will only advance time when both\r\n * {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.canAnimate = defaultValue(options.canAnimate, true);\r\n\r\n /**\r\n * An {@link Event} that is fired whenever {@link Clock#tick} is called.\r\n * @type {Event}\r\n */\r\n this.onTick = new Event();\r\n /**\r\n * An {@link Event} that is fired whenever {@link Clock#stopTime} is reached.\r\n * @type {Event}\r\n */\r\n this.onStop = new Event();\r\n\r\n this._currentTime = undefined;\r\n this._multiplier = undefined;\r\n this._clockStep = undefined;\r\n this._shouldAnimate = undefined;\r\n this._lastSystemTime = getTimestamp();\r\n\r\n // set values using the property setters to\r\n // make values consistent.\r\n\r\n this.currentTime = currentTime;\r\n this.multiplier = defaultValue(options.multiplier, 1.0);\r\n this.shouldAnimate = defaultValue(options.shouldAnimate, false);\r\n this.clockStep = defaultValue(\r\n options.clockStep,\r\n ClockStep.SYSTEM_CLOCK_MULTIPLIER\r\n );\r\n}\r\n\r\nObject.defineProperties(Clock.prototype, {\r\n /**\r\n * The current time.\r\n * Changing this property will change\r\n * {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to\r\n * {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.\r\n * @memberof Clock.prototype\r\n * @type {JulianDate}\r\n */\r\n currentTime: {\r\n get: function () {\r\n return this._currentTime;\r\n },\r\n set: function (value) {\r\n if (JulianDate.equals(this._currentTime, value)) {\r\n return;\r\n }\r\n\r\n if (this._clockStep === ClockStep.SYSTEM_CLOCK) {\r\n this._clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER;\r\n }\r\n\r\n this._currentTime = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets how much time advances when {@link Clock#tick} is called. Negative values allow for advancing backwards.\r\n * If {@link Clock#clockStep} is set to {@link ClockStep.TICK_DEPENDENT}, this is the number of seconds to advance.\r\n * If {@link Clock#clockStep} is set to {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}, this value is multiplied by the\r\n * elapsed system time since the last call to {@link Clock#tick}.\r\n * Changing this property will change\r\n * {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to\r\n * {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.\r\n * @memberof Clock.prototype\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n multiplier: {\r\n get: function () {\r\n return this._multiplier;\r\n },\r\n set: function (value) {\r\n if (this._multiplier === value) {\r\n return;\r\n }\r\n\r\n if (this._clockStep === ClockStep.SYSTEM_CLOCK) {\r\n this._clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER;\r\n }\r\n\r\n this._multiplier = value;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if calls to {@link Clock#tick} are frame dependent or system clock dependent.\r\n * Changing this property to {@link ClockStep.SYSTEM_CLOCK} will set\r\n * {@link Clock#multiplier} to 1.0, {@link Clock#shouldAnimate} to true, and\r\n * {@link Clock#currentTime} to the current system clock time.\r\n * @memberof Clock.prototype\r\n * @type ClockStep\r\n * @default {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}\r\n */\r\n clockStep: {\r\n get: function () {\r\n return this._clockStep;\r\n },\r\n set: function (value) {\r\n if (value === ClockStep.SYSTEM_CLOCK) {\r\n this._multiplier = 1.0;\r\n this._shouldAnimate = true;\r\n this._currentTime = JulianDate.now();\r\n }\r\n\r\n this._clockStep = value;\r\n },\r\n },\r\n\r\n /**\r\n * Indicates whether {@link Clock#tick} should attempt to advance time.\r\n * The clock will only advance time when both\r\n * {@link Clock#canAnimate} and {@link Clock#shouldAnimate} are true.\r\n * Changing this property will change\r\n * {@link Clock#clockStep} from {@link ClockStep.SYSTEM_CLOCK} to\r\n * {@link ClockStep.SYSTEM_CLOCK_MULTIPLIER}.\r\n * @memberof Clock.prototype\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n shouldAnimate: {\r\n get: function () {\r\n return this._shouldAnimate;\r\n },\r\n set: function (value) {\r\n if (this._shouldAnimate === value) {\r\n return;\r\n }\r\n\r\n if (this._clockStep === ClockStep.SYSTEM_CLOCK) {\r\n this._clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER;\r\n }\r\n\r\n this._shouldAnimate = value;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Advances the clock from the current time based on the current configuration options.\r\n * tick should be called every frame, regardless of whether animation is taking place\r\n * or not. To control animation, use the {@link Clock#shouldAnimate} property.\r\n *\r\n * @returns {JulianDate} The new value of the {@link Clock#currentTime} property.\r\n */\r\nClock.prototype.tick = function () {\r\n var currentSystemTime = getTimestamp();\r\n var currentTime = JulianDate.clone(this._currentTime);\r\n\r\n if (this.canAnimate && this._shouldAnimate) {\r\n var clockStep = this._clockStep;\r\n if (clockStep === ClockStep.SYSTEM_CLOCK) {\r\n currentTime = JulianDate.now(currentTime);\r\n } else {\r\n var multiplier = this._multiplier;\r\n\r\n if (clockStep === ClockStep.TICK_DEPENDENT) {\r\n currentTime = JulianDate.addSeconds(\r\n currentTime,\r\n multiplier,\r\n currentTime\r\n );\r\n } else {\r\n var milliseconds = currentSystemTime - this._lastSystemTime;\r\n currentTime = JulianDate.addSeconds(\r\n currentTime,\r\n multiplier * (milliseconds / 1000.0),\r\n currentTime\r\n );\r\n }\r\n\r\n var clockRange = this.clockRange;\r\n var startTime = this.startTime;\r\n var stopTime = this.stopTime;\r\n\r\n if (clockRange === ClockRange.CLAMPED) {\r\n if (JulianDate.lessThan(currentTime, startTime)) {\r\n currentTime = JulianDate.clone(startTime, currentTime);\r\n } else if (JulianDate.greaterThan(currentTime, stopTime)) {\r\n currentTime = JulianDate.clone(stopTime, currentTime);\r\n this.onStop.raiseEvent(this);\r\n }\r\n } else if (clockRange === ClockRange.LOOP_STOP) {\r\n if (JulianDate.lessThan(currentTime, startTime)) {\r\n currentTime = JulianDate.clone(startTime, currentTime);\r\n }\r\n while (JulianDate.greaterThan(currentTime, stopTime)) {\r\n currentTime = JulianDate.addSeconds(\r\n startTime,\r\n JulianDate.secondsDifference(currentTime, stopTime),\r\n currentTime\r\n );\r\n this.onStop.raiseEvent(this);\r\n }\r\n }\r\n }\r\n }\r\n\r\n this._currentTime = currentTime;\r\n this._lastSystemTime = currentSystemTime;\r\n this.onTick.raiseEvent(this);\r\n return currentTime;\r\n};\r\nexport default Clock;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport FeatureDetection from \"./FeatureDetection.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nfunction hue2rgb(m1, m2, h) {\r\n if (h < 0) {\r\n h += 1;\r\n }\r\n if (h > 1) {\r\n h -= 1;\r\n }\r\n if (h * 6 < 1) {\r\n return m1 + (m2 - m1) * 6 * h;\r\n }\r\n if (h * 2 < 1) {\r\n return m2;\r\n }\r\n if (h * 3 < 2) {\r\n return m1 + (m2 - m1) * (2 / 3 - h) * 6;\r\n }\r\n return m1;\r\n}\r\n\r\n/**\r\n * A color, specified using red, green, blue, and alpha values,\r\n * which range from 0 (no intensity) to 1.0 (full intensity).\r\n * @param {Number} [red=1.0] The red component.\r\n * @param {Number} [green=1.0] The green component.\r\n * @param {Number} [blue=1.0] The blue component.\r\n * @param {Number} [alpha=1.0] The alpha component.\r\n *\r\n * @constructor\r\n * @alias Color\r\n *\r\n * @see Packable\r\n */\r\nfunction Color(red, green, blue, alpha) {\r\n /**\r\n * The red component.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.red = defaultValue(red, 1.0);\r\n /**\r\n * The green component.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.green = defaultValue(green, 1.0);\r\n /**\r\n * The blue component.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.blue = defaultValue(blue, 1.0);\r\n /**\r\n * The alpha component.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.alpha = defaultValue(alpha, 1.0);\r\n}\r\n\r\n/**\r\n * Creates a Color instance from a {@link Cartesian4}. x, y, z,\r\n * and w map to red, green, blue, and alpha, respectively.\r\n *\r\n * @param {Cartesian4} cartesian The source cartesian.\r\n * @param {Color} [result] The object onto which to store the result.\r\n * @returns {Color} The modified result parameter or a new Color instance if one was not provided.\r\n */\r\nColor.fromCartesian4 = function (cartesian, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian\", cartesian);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Color(cartesian.x, cartesian.y, cartesian.z, cartesian.w);\r\n }\r\n\r\n result.red = cartesian.x;\r\n result.green = cartesian.y;\r\n result.blue = cartesian.z;\r\n result.alpha = cartesian.w;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new Color specified using red, green, blue, and alpha values\r\n * that are in the range of 0 to 255, converting them internally to a range of 0.0 to 1.0.\r\n *\r\n * @param {Number} [red=255] The red component.\r\n * @param {Number} [green=255] The green component.\r\n * @param {Number} [blue=255] The blue component.\r\n * @param {Number} [alpha=255] The alpha component.\r\n * @param {Color} [result] The object onto which to store the result.\r\n * @returns {Color} The modified result parameter or a new Color instance if one was not provided.\r\n */\r\nColor.fromBytes = function (red, green, blue, alpha, result) {\r\n red = Color.byteToFloat(defaultValue(red, 255.0));\r\n green = Color.byteToFloat(defaultValue(green, 255.0));\r\n blue = Color.byteToFloat(defaultValue(blue, 255.0));\r\n alpha = Color.byteToFloat(defaultValue(alpha, 255.0));\r\n\r\n if (!defined(result)) {\r\n return new Color(red, green, blue, alpha);\r\n }\r\n\r\n result.red = red;\r\n result.green = green;\r\n result.blue = blue;\r\n result.alpha = alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new Color that has the same red, green, and blue components\r\n * of the specified color, but with the specified alpha value.\r\n *\r\n * @param {Color} color The base color\r\n * @param {Number} alpha The new alpha component.\r\n * @param {Color} [result] The object onto which to store the result.\r\n * @returns {Color} The modified result parameter or a new Color instance if one was not provided.\r\n *\r\n * @example var translucentRed = Cesium.Color.fromAlpha(Cesium.Color.RED, 0.9);\r\n */\r\nColor.fromAlpha = function (color, alpha, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"color\", color);\r\n Check.typeOf.number(\"alpha\", alpha);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Color(color.red, color.green, color.blue, alpha);\r\n }\r\n\r\n result.red = color.red;\r\n result.green = color.green;\r\n result.blue = color.blue;\r\n result.alpha = alpha;\r\n return result;\r\n};\r\n\r\nvar scratchArrayBuffer;\r\nvar scratchUint32Array;\r\nvar scratchUint8Array;\r\nif (FeatureDetection.supportsTypedArrays()) {\r\n scratchArrayBuffer = new ArrayBuffer(4);\r\n scratchUint32Array = new Uint32Array(scratchArrayBuffer);\r\n scratchUint8Array = new Uint8Array(scratchArrayBuffer);\r\n}\r\n\r\n/**\r\n * Creates a new Color from a single numeric unsigned 32-bit RGBA value, using the endianness\r\n * of the system.\r\n *\r\n * @param {Number} rgba A single numeric unsigned 32-bit RGBA value.\r\n * @param {Color} [result] The object to store the result in, if undefined a new instance will be created.\r\n * @returns {Color} The color object.\r\n *\r\n * @example\r\n * var color = Cesium.Color.fromRgba(0x67ADDFFF);\r\n *\r\n * @see Color#toRgba\r\n */\r\nColor.fromRgba = function (rgba, result) {\r\n // scratchUint32Array and scratchUint8Array share an underlying array buffer\r\n scratchUint32Array[0] = rgba;\r\n return Color.fromBytes(\r\n scratchUint8Array[0],\r\n scratchUint8Array[1],\r\n scratchUint8Array[2],\r\n scratchUint8Array[3],\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Creates a Color instance from hue, saturation, and lightness.\r\n *\r\n * @param {Number} [hue=0] The hue angle 0...1\r\n * @param {Number} [saturation=0] The saturation value 0...1\r\n * @param {Number} [lightness=0] The lightness value 0...1\r\n * @param {Number} [alpha=1.0] The alpha component 0...1\r\n * @param {Color} [result] The object to store the result in, if undefined a new instance will be created.\r\n * @returns {Color} The color object.\r\n *\r\n * @see {@link http://www.w3.org/TR/css3-color/#hsl-color|CSS color values}\r\n */\r\nColor.fromHsl = function (hue, saturation, lightness, alpha, result) {\r\n hue = defaultValue(hue, 0.0) % 1.0;\r\n saturation = defaultValue(saturation, 0.0);\r\n lightness = defaultValue(lightness, 0.0);\r\n alpha = defaultValue(alpha, 1.0);\r\n\r\n var red = lightness;\r\n var green = lightness;\r\n var blue = lightness;\r\n\r\n if (saturation !== 0) {\r\n var m2;\r\n if (lightness < 0.5) {\r\n m2 = lightness * (1 + saturation);\r\n } else {\r\n m2 = lightness + saturation - lightness * saturation;\r\n }\r\n\r\n var m1 = 2.0 * lightness - m2;\r\n red = hue2rgb(m1, m2, hue + 1 / 3);\r\n green = hue2rgb(m1, m2, hue);\r\n blue = hue2rgb(m1, m2, hue - 1 / 3);\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Color(red, green, blue, alpha);\r\n }\r\n\r\n result.red = red;\r\n result.green = green;\r\n result.blue = blue;\r\n result.alpha = alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a random color using the provided options. For reproducible random colors, you should\r\n * call {@link CesiumMath#setRandomNumberSeed} once at the beginning of your application.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Number} [options.red] If specified, the red component to use instead of a randomized value.\r\n * @param {Number} [options.minimumRed=0.0] The maximum red value to generate if none was specified.\r\n * @param {Number} [options.maximumRed=1.0] The minimum red value to generate if none was specified.\r\n * @param {Number} [options.green] If specified, the green component to use instead of a randomized value.\r\n * @param {Number} [options.minimumGreen=0.0] The maximum green value to generate if none was specified.\r\n * @param {Number} [options.maximumGreen=1.0] The minimum green value to generate if none was specified.\r\n * @param {Number} [options.blue] If specified, the blue component to use instead of a randomized value.\r\n * @param {Number} [options.minimumBlue=0.0] The maximum blue value to generate if none was specified.\r\n * @param {Number} [options.maximumBlue=1.0] The minimum blue value to generate if none was specified.\r\n * @param {Number} [options.alpha] If specified, the alpha component to use instead of a randomized value.\r\n * @param {Number} [options.minimumAlpha=0.0] The maximum alpha value to generate if none was specified.\r\n * @param {Number} [options.maximumAlpha=1.0] The minimum alpha value to generate if none was specified.\r\n * @param {Color} [result] The object to store the result in, if undefined a new instance will be created.\r\n * @returns {Color} The modified result parameter or a new instance if result was undefined.\r\n *\r\n * @exception {DeveloperError} minimumRed must be less than or equal to maximumRed.\r\n * @exception {DeveloperError} minimumGreen must be less than or equal to maximumGreen.\r\n * @exception {DeveloperError} minimumBlue must be less than or equal to maximumBlue.\r\n * @exception {DeveloperError} minimumAlpha must be less than or equal to maximumAlpha.\r\n *\r\n * @example\r\n * //Create a completely random color\r\n * var color = Cesium.Color.fromRandom();\r\n *\r\n * //Create a random shade of yellow.\r\n * var color = Cesium.Color.fromRandom({\r\n * red : 1.0,\r\n * green : 1.0,\r\n * alpha : 1.0\r\n * });\r\n *\r\n * //Create a random bright color.\r\n * var color = Cesium.Color.fromRandom({\r\n * minimumRed : 0.75,\r\n * minimumGreen : 0.75,\r\n * minimumBlue : 0.75,\r\n * alpha : 1.0\r\n * });\r\n */\r\nColor.fromRandom = function (options, result) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var red = options.red;\r\n if (!defined(red)) {\r\n var minimumRed = defaultValue(options.minimumRed, 0);\r\n var maximumRed = defaultValue(options.maximumRed, 1.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.lessThanOrEquals(\"minimumRed\", minimumRed, maximumRed);\r\n //>>includeEnd('debug');\r\n\r\n red =\r\n minimumRed + CesiumMath.nextRandomNumber() * (maximumRed - minimumRed);\r\n }\r\n\r\n var green = options.green;\r\n if (!defined(green)) {\r\n var minimumGreen = defaultValue(options.minimumGreen, 0);\r\n var maximumGreen = defaultValue(options.maximumGreen, 1.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"minimumGreen\",\r\n minimumGreen,\r\n maximumGreen\r\n );\r\n //>>includeEnd('debug');\r\n green =\r\n minimumGreen +\r\n CesiumMath.nextRandomNumber() * (maximumGreen - minimumGreen);\r\n }\r\n\r\n var blue = options.blue;\r\n if (!defined(blue)) {\r\n var minimumBlue = defaultValue(options.minimumBlue, 0);\r\n var maximumBlue = defaultValue(options.maximumBlue, 1.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"minimumBlue\",\r\n minimumBlue,\r\n maximumBlue\r\n );\r\n //>>includeEnd('debug');\r\n\r\n blue =\r\n minimumBlue + CesiumMath.nextRandomNumber() * (maximumBlue - minimumBlue);\r\n }\r\n\r\n var alpha = options.alpha;\r\n if (!defined(alpha)) {\r\n var minimumAlpha = defaultValue(options.minimumAlpha, 0);\r\n var maximumAlpha = defaultValue(options.maximumAlpha, 1.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"minumumAlpha\",\r\n minimumAlpha,\r\n maximumAlpha\r\n );\r\n //>>includeEnd('debug');\r\n\r\n alpha =\r\n minimumAlpha +\r\n CesiumMath.nextRandomNumber() * (maximumAlpha - minimumAlpha);\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Color(red, green, blue, alpha);\r\n }\r\n\r\n result.red = red;\r\n result.green = green;\r\n result.blue = blue;\r\n result.alpha = alpha;\r\n return result;\r\n};\r\n\r\n//#rgba\r\nvar rgbaMatcher = /^#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])?$/i;\r\n//#rrggbbaa\r\nvar rrggbbaaMatcher = /^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})?$/i;\r\n//rgb(), rgba(), or rgb%()\r\nvar rgbParenthesesMatcher = /^rgba?\\(\\s*([0-9.]+%?)\\s*,\\s*([0-9.]+%?)\\s*,\\s*([0-9.]+%?)(?:\\s*,\\s*([0-9.]+))?\\s*\\)$/i;\r\n//hsl() or hsla()\r\nvar hslParenthesesMatcher = /^hsla?\\(\\s*([0-9.]+)\\s*,\\s*([0-9.]+%)\\s*,\\s*([0-9.]+%)(?:\\s*,\\s*([0-9.]+))?\\s*\\)$/i;\r\n\r\n/**\r\n * Creates a Color instance from a CSS color value.\r\n *\r\n * @param {String} color The CSS color value in #rgb, #rgba, #rrggbb, #rrggbbaa, rgb(), rgba(), hsl(), or hsla() format.\r\n * @param {Color} [result] The object to store the result in, if undefined a new instance will be created.\r\n * @returns {Color} The color object, or undefined if the string was not a valid CSS color.\r\n *\r\n *\r\n * @example\r\n * var cesiumBlue = Cesium.Color.fromCssColorString('#67ADDF');\r\n * var green = Cesium.Color.fromCssColorString('green');\r\n *\r\n * @see {@link http://www.w3.org/TR/css3-color|CSS color values}\r\n */\r\nColor.fromCssColorString = function (color, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"color\", color);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Color();\r\n }\r\n\r\n // Remove all whitespaces from the color string\r\n color = color.replace(/\\s/g, \"\");\r\n\r\n var namedColor = Color[color.toUpperCase()];\r\n if (defined(namedColor)) {\r\n Color.clone(namedColor, result);\r\n return result;\r\n }\r\n\r\n var matches = rgbaMatcher.exec(color);\r\n if (matches !== null) {\r\n result.red = parseInt(matches[1], 16) / 15;\r\n result.green = parseInt(matches[2], 16) / 15.0;\r\n result.blue = parseInt(matches[3], 16) / 15.0;\r\n result.alpha = parseInt(defaultValue(matches[4], \"f\"), 16) / 15.0;\r\n return result;\r\n }\r\n\r\n matches = rrggbbaaMatcher.exec(color);\r\n if (matches !== null) {\r\n result.red = parseInt(matches[1], 16) / 255.0;\r\n result.green = parseInt(matches[2], 16) / 255.0;\r\n result.blue = parseInt(matches[3], 16) / 255.0;\r\n result.alpha = parseInt(defaultValue(matches[4], \"ff\"), 16) / 255.0;\r\n return result;\r\n }\r\n\r\n matches = rgbParenthesesMatcher.exec(color);\r\n if (matches !== null) {\r\n result.red =\r\n parseFloat(matches[1]) / (\"%\" === matches[1].substr(-1) ? 100.0 : 255.0);\r\n result.green =\r\n parseFloat(matches[2]) / (\"%\" === matches[2].substr(-1) ? 100.0 : 255.0);\r\n result.blue =\r\n parseFloat(matches[3]) / (\"%\" === matches[3].substr(-1) ? 100.0 : 255.0);\r\n result.alpha = parseFloat(defaultValue(matches[4], \"1.0\"));\r\n return result;\r\n }\r\n\r\n matches = hslParenthesesMatcher.exec(color);\r\n if (matches !== null) {\r\n return Color.fromHsl(\r\n parseFloat(matches[1]) / 360.0,\r\n parseFloat(matches[2]) / 100.0,\r\n parseFloat(matches[3]) / 100.0,\r\n parseFloat(defaultValue(matches[4], \"1.0\")),\r\n result\r\n );\r\n }\r\n\r\n result = undefined;\r\n return result;\r\n};\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nColor.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Color} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nColor.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n array[startingIndex++] = value.red;\r\n array[startingIndex++] = value.green;\r\n array[startingIndex++] = value.blue;\r\n array[startingIndex] = value.alpha;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Color} [result] The object into which to store the result.\r\n * @returns {Color} The modified result parameter or a new Color instance if one was not provided.\r\n */\r\nColor.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n if (!defined(result)) {\r\n result = new Color();\r\n }\r\n result.red = array[startingIndex++];\r\n result.green = array[startingIndex++];\r\n result.blue = array[startingIndex++];\r\n result.alpha = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Converts a 'byte' color component in the range of 0 to 255 into\r\n * a 'float' color component in the range of 0 to 1.0.\r\n *\r\n * @param {Number} number The number to be converted.\r\n * @returns {Number} The converted number.\r\n */\r\nColor.byteToFloat = function (number) {\r\n return number / 255.0;\r\n};\r\n\r\n/**\r\n * Converts a 'float' color component in the range of 0 to 1.0 into\r\n * a 'byte' color component in the range of 0 to 255.\r\n *\r\n * @param {Number} number The number to be converted.\r\n * @returns {Number} The converted number.\r\n */\r\nColor.floatToByte = function (number) {\r\n return number === 1.0 ? 255.0 : (number * 256.0) | 0;\r\n};\r\n\r\n/**\r\n * Duplicates a Color.\r\n *\r\n * @param {Color} color The Color to duplicate.\r\n * @param {Color} [result] The object to store the result in, if undefined a new instance will be created.\r\n * @returns {Color} The modified result parameter or a new instance if result was undefined. (Returns undefined if color is undefined)\r\n */\r\nColor.clone = function (color, result) {\r\n if (!defined(color)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new Color(color.red, color.green, color.blue, color.alpha);\r\n }\r\n result.red = color.red;\r\n result.green = color.green;\r\n result.blue = color.blue;\r\n result.alpha = color.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns true if the first Color equals the second color.\r\n *\r\n * @param {Color} left The first Color to compare for equality.\r\n * @param {Color} right The second Color to compare for equality.\r\n * @returns {Boolean} true if the Colors are equal; otherwise, false.\r\n */\r\nColor.equals = function (left, right) {\r\n return (\r\n left === right || //\r\n (defined(left) && //\r\n defined(right) && //\r\n left.red === right.red && //\r\n left.green === right.green && //\r\n left.blue === right.blue && //\r\n left.alpha === right.alpha)\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nColor.equalsArray = function (color, array, offset) {\r\n return (\r\n color.red === array[offset] &&\r\n color.green === array[offset + 1] &&\r\n color.blue === array[offset + 2] &&\r\n color.alpha === array[offset + 3]\r\n );\r\n};\r\n\r\n/**\r\n * Returns a duplicate of a Color instance.\r\n *\r\n * @param {Color} [result] The object to store the result in, if undefined a new instance will be created.\r\n * @returns {Color} The modified result parameter or a new instance if result was undefined.\r\n */\r\nColor.prototype.clone = function (result) {\r\n return Color.clone(this, result);\r\n};\r\n\r\n/**\r\n * Returns true if this Color equals other.\r\n *\r\n * @param {Color} other The Color to compare for equality.\r\n * @returns {Boolean} true if the Colors are equal; otherwise, false.\r\n */\r\nColor.prototype.equals = function (other) {\r\n return Color.equals(this, other);\r\n};\r\n\r\n/**\r\n * Returns true if this Color equals other componentwise within the specified epsilon.\r\n *\r\n * @param {Color} other The Color to compare for equality.\r\n * @param {Number} [epsilon=0.0] The epsilon to use for equality testing.\r\n * @returns {Boolean} true if the Colors are equal within the specified epsilon; otherwise, false.\r\n */\r\nColor.prototype.equalsEpsilon = function (other, epsilon) {\r\n return (\r\n this === other || //\r\n (defined(other) && //\r\n Math.abs(this.red - other.red) <= epsilon && //\r\n Math.abs(this.green - other.green) <= epsilon && //\r\n Math.abs(this.blue - other.blue) <= epsilon && //\r\n Math.abs(this.alpha - other.alpha) <= epsilon)\r\n );\r\n};\r\n\r\n/**\r\n * Creates a string representing this Color in the format '(red, green, blue, alpha)'.\r\n *\r\n * @returns {String} A string representing this Color in the format '(red, green, blue, alpha)'.\r\n */\r\nColor.prototype.toString = function () {\r\n return (\r\n \"(\" +\r\n this.red +\r\n \", \" +\r\n this.green +\r\n \", \" +\r\n this.blue +\r\n \", \" +\r\n this.alpha +\r\n \")\"\r\n );\r\n};\r\n\r\n/**\r\n * Creates a string containing the CSS color value for this color.\r\n *\r\n * @returns {String} The CSS equivalent of this color.\r\n *\r\n * @see {@link http://www.w3.org/TR/css3-color/#rgba-color|CSS RGB or RGBA color values}\r\n */\r\nColor.prototype.toCssColorString = function () {\r\n var red = Color.floatToByte(this.red);\r\n var green = Color.floatToByte(this.green);\r\n var blue = Color.floatToByte(this.blue);\r\n if (this.alpha === 1) {\r\n return \"rgb(\" + red + \",\" + green + \",\" + blue + \")\";\r\n }\r\n return \"rgba(\" + red + \",\" + green + \",\" + blue + \",\" + this.alpha + \")\";\r\n};\r\n\r\n/**\r\n * Creates a string containing CSS hex string color value for this color.\r\n *\r\n * @returns {String} The CSS hex string equivalent of this color.\r\n */\r\nColor.prototype.toCssHexString = function () {\r\n var r = Color.floatToByte(this.red).toString(16);\r\n if (r.length < 2) {\r\n r = \"0\" + r;\r\n }\r\n var g = Color.floatToByte(this.green).toString(16);\r\n if (g.length < 2) {\r\n g = \"0\" + g;\r\n }\r\n var b = Color.floatToByte(this.blue).toString(16);\r\n if (b.length < 2) {\r\n b = \"0\" + b;\r\n }\r\n if (this.alpha < 1) {\r\n var hexAlpha = Color.floatToByte(this.alpha).toString(16);\r\n if (hexAlpha.length < 2) {\r\n hexAlpha = \"0\" + hexAlpha;\r\n }\r\n return \"#\" + r + g + b + hexAlpha;\r\n }\r\n return \"#\" + r + g + b;\r\n};\r\n\r\n/**\r\n * Converts this color to an array of red, green, blue, and alpha values\r\n * that are in the range of 0 to 255.\r\n *\r\n * @param {Number[]} [result] The array to store the result in, if undefined a new instance will be created.\r\n * @returns {Number[]} The modified result parameter or a new instance if result was undefined.\r\n */\r\nColor.prototype.toBytes = function (result) {\r\n var red = Color.floatToByte(this.red);\r\n var green = Color.floatToByte(this.green);\r\n var blue = Color.floatToByte(this.blue);\r\n var alpha = Color.floatToByte(this.alpha);\r\n\r\n if (!defined(result)) {\r\n return [red, green, blue, alpha];\r\n }\r\n result[0] = red;\r\n result[1] = green;\r\n result[2] = blue;\r\n result[3] = alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Converts this color to a single numeric unsigned 32-bit RGBA value, using the endianness\r\n * of the system.\r\n *\r\n * @returns {Number} A single numeric unsigned 32-bit RGBA value.\r\n *\r\n *\r\n * @example\r\n * var rgba = Cesium.Color.BLUE.toRgba();\r\n *\r\n * @see Color.fromRgba\r\n */\r\nColor.prototype.toRgba = function () {\r\n // scratchUint32Array and scratchUint8Array share an underlying array buffer\r\n scratchUint8Array[0] = Color.floatToByte(this.red);\r\n scratchUint8Array[1] = Color.floatToByte(this.green);\r\n scratchUint8Array[2] = Color.floatToByte(this.blue);\r\n scratchUint8Array[3] = Color.floatToByte(this.alpha);\r\n return scratchUint32Array[0];\r\n};\r\n\r\n/**\r\n * Brightens this color by the provided magnitude.\r\n *\r\n * @param {Number} magnitude A positive number indicating the amount to brighten.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n *\r\n * @example\r\n * var brightBlue = Cesium.Color.BLUE.brighten(0.5, new Cesium.Color());\r\n */\r\nColor.prototype.brighten = function (magnitude, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"magnitude\", magnitude);\r\n Check.typeOf.number.greaterThanOrEquals(\"magnitude\", magnitude, 0.0);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n magnitude = 1.0 - magnitude;\r\n result.red = 1.0 - (1.0 - this.red) * magnitude;\r\n result.green = 1.0 - (1.0 - this.green) * magnitude;\r\n result.blue = 1.0 - (1.0 - this.blue) * magnitude;\r\n result.alpha = this.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Darkens this color by the provided magnitude.\r\n *\r\n * @param {Number} magnitude A positive number indicating the amount to darken.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n *\r\n * @example\r\n * var darkBlue = Cesium.Color.BLUE.darken(0.5, new Cesium.Color());\r\n */\r\nColor.prototype.darken = function (magnitude, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"magnitude\", magnitude);\r\n Check.typeOf.number.greaterThanOrEquals(\"magnitude\", magnitude, 0.0);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n magnitude = 1.0 - magnitude;\r\n result.red = this.red * magnitude;\r\n result.green = this.green * magnitude;\r\n result.blue = this.blue * magnitude;\r\n result.alpha = this.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new Color that has the same red, green, and blue components\r\n * as this Color, but with the specified alpha value.\r\n *\r\n * @param {Number} alpha The new alpha component.\r\n * @param {Color} [result] The object onto which to store the result.\r\n * @returns {Color} The modified result parameter or a new Color instance if one was not provided.\r\n *\r\n * @example var translucentRed = Cesium.Color.RED.withAlpha(0.9);\r\n */\r\nColor.prototype.withAlpha = function (alpha, result) {\r\n return Color.fromAlpha(this, alpha, result);\r\n};\r\n\r\n/**\r\n * Computes the componentwise sum of two Colors.\r\n *\r\n * @param {Color} left The first Color.\r\n * @param {Color} right The second Color.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n */\r\nColor.add = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.red = left.red + right.red;\r\n result.green = left.green + right.green;\r\n result.blue = left.blue + right.blue;\r\n result.alpha = left.alpha + right.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise difference of two Colors.\r\n *\r\n * @param {Color} left The first Color.\r\n * @param {Color} right The second Color.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n */\r\nColor.subtract = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.red = left.red - right.red;\r\n result.green = left.green - right.green;\r\n result.blue = left.blue - right.blue;\r\n result.alpha = left.alpha - right.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise product of two Colors.\r\n *\r\n * @param {Color} left The first Color.\r\n * @param {Color} right The second Color.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n */\r\nColor.multiply = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.red = left.red * right.red;\r\n result.green = left.green * right.green;\r\n result.blue = left.blue * right.blue;\r\n result.alpha = left.alpha * right.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise quotient of two Colors.\r\n *\r\n * @param {Color} left The first Color.\r\n * @param {Color} right The second Color.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n */\r\nColor.divide = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.red = left.red / right.red;\r\n result.green = left.green / right.green;\r\n result.blue = left.blue / right.blue;\r\n result.alpha = left.alpha / right.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the componentwise modulus of two Colors.\r\n *\r\n * @param {Color} left The first Color.\r\n * @param {Color} right The second Color.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n */\r\nColor.mod = function (left, right, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n Check.typeOf.object(\"right\", right);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.red = left.red % right.red;\r\n result.green = left.green % right.green;\r\n result.blue = left.blue % right.blue;\r\n result.alpha = left.alpha % right.alpha;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the linear interpolation or extrapolation at t between the provided colors.\r\n *\r\n * @param {Color} start The color corresponding to t at 0.0.\r\n * @param {Color} end The color corresponding to t at 1.0.\r\n * @param {Number} t The point along t at which to interpolate.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n */\r\nColor.lerp = function (start, end, t, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"start\", start);\r\n Check.typeOf.object(\"end\", end);\r\n Check.typeOf.number(\"t\", t);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.red = CesiumMath.lerp(start.red, end.red, t);\r\n result.green = CesiumMath.lerp(start.green, end.green, t);\r\n result.blue = CesiumMath.lerp(start.blue, end.blue, t);\r\n result.alpha = CesiumMath.lerp(start.alpha, end.alpha, t);\r\n return result;\r\n};\r\n\r\n/**\r\n * Multiplies the provided Color componentwise by the provided scalar.\r\n *\r\n * @param {Color} color The Color to be scaled.\r\n * @param {Number} scalar The scalar to multiply with.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n */\r\nColor.multiplyByScalar = function (color, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"color\", color);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.red = color.red * scalar;\r\n result.green = color.green * scalar;\r\n result.blue = color.blue * scalar;\r\n result.alpha = color.alpha * scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * Divides the provided Color componentwise by the provided scalar.\r\n *\r\n * @param {Color} color The Color to be divided.\r\n * @param {Number} scalar The scalar to divide with.\r\n * @param {Color} result The object onto which to store the result.\r\n * @returns {Color} The modified result parameter.\r\n */\r\nColor.divideByScalar = function (color, scalar, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"color\", color);\r\n Check.typeOf.number(\"scalar\", scalar);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n result.red = color.red / scalar;\r\n result.green = color.green / scalar;\r\n result.blue = color.blue / scalar;\r\n result.alpha = color.alpha / scalar;\r\n return result;\r\n};\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F0F8FF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.ALICEBLUE = Object.freeze(Color.fromCssColorString(\"#F0F8FF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FAEBD7\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.ANTIQUEWHITE = Object.freeze(Color.fromCssColorString(\"#FAEBD7\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #00FFFF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.AQUA = Object.freeze(Color.fromCssColorString(\"#00FFFF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #7FFFD4\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.AQUAMARINE = Object.freeze(Color.fromCssColorString(\"#7FFFD4\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F0FFFF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.AZURE = Object.freeze(Color.fromCssColorString(\"#F0FFFF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F5F5DC\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.BEIGE = Object.freeze(Color.fromCssColorString(\"#F5F5DC\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFE4C4\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.BISQUE = Object.freeze(Color.fromCssColorString(\"#FFE4C4\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #000000\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.BLACK = Object.freeze(Color.fromCssColorString(\"#000000\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFEBCD\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.BLANCHEDALMOND = Object.freeze(Color.fromCssColorString(\"#FFEBCD\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #0000FF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.BLUE = Object.freeze(Color.fromCssColorString(\"#0000FF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #8A2BE2\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.BLUEVIOLET = Object.freeze(Color.fromCssColorString(\"#8A2BE2\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #A52A2A\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.BROWN = Object.freeze(Color.fromCssColorString(\"#A52A2A\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #DEB887\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.BURLYWOOD = Object.freeze(Color.fromCssColorString(\"#DEB887\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #5F9EA0\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.CADETBLUE = Object.freeze(Color.fromCssColorString(\"#5F9EA0\"));\r\n/**\r\n * An immutable Color instance initialized to CSS color #7FFF00\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.CHARTREUSE = Object.freeze(Color.fromCssColorString(\"#7FFF00\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #D2691E\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.CHOCOLATE = Object.freeze(Color.fromCssColorString(\"#D2691E\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF7F50\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.CORAL = Object.freeze(Color.fromCssColorString(\"#FF7F50\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #6495ED\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.CORNFLOWERBLUE = Object.freeze(Color.fromCssColorString(\"#6495ED\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFF8DC\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.CORNSILK = Object.freeze(Color.fromCssColorString(\"#FFF8DC\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #DC143C\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.CRIMSON = Object.freeze(Color.fromCssColorString(\"#DC143C\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #00FFFF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.CYAN = Object.freeze(Color.fromCssColorString(\"#00FFFF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #00008B\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKBLUE = Object.freeze(Color.fromCssColorString(\"#00008B\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #008B8B\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKCYAN = Object.freeze(Color.fromCssColorString(\"#008B8B\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #B8860B\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKGOLDENROD = Object.freeze(Color.fromCssColorString(\"#B8860B\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #A9A9A9\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKGRAY = Object.freeze(Color.fromCssColorString(\"#A9A9A9\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #006400\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKGREEN = Object.freeze(Color.fromCssColorString(\"#006400\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #A9A9A9\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKGREY = Color.DARKGRAY;\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #BDB76B\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKKHAKI = Object.freeze(Color.fromCssColorString(\"#BDB76B\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #8B008B\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKMAGENTA = Object.freeze(Color.fromCssColorString(\"#8B008B\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #556B2F\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKOLIVEGREEN = Object.freeze(Color.fromCssColorString(\"#556B2F\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF8C00\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKORANGE = Object.freeze(Color.fromCssColorString(\"#FF8C00\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #9932CC\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKORCHID = Object.freeze(Color.fromCssColorString(\"#9932CC\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #8B0000\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKRED = Object.freeze(Color.fromCssColorString(\"#8B0000\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #E9967A\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKSALMON = Object.freeze(Color.fromCssColorString(\"#E9967A\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #8FBC8F\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKSEAGREEN = Object.freeze(Color.fromCssColorString(\"#8FBC8F\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #483D8B\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKSLATEBLUE = Object.freeze(Color.fromCssColorString(\"#483D8B\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #2F4F4F\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKSLATEGRAY = Object.freeze(Color.fromCssColorString(\"#2F4F4F\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #2F4F4F\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKSLATEGREY = Color.DARKSLATEGRAY;\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #00CED1\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKTURQUOISE = Object.freeze(Color.fromCssColorString(\"#00CED1\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #9400D3\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DARKVIOLET = Object.freeze(Color.fromCssColorString(\"#9400D3\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF1493\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DEEPPINK = Object.freeze(Color.fromCssColorString(\"#FF1493\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #00BFFF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DEEPSKYBLUE = Object.freeze(Color.fromCssColorString(\"#00BFFF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #696969\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DIMGRAY = Object.freeze(Color.fromCssColorString(\"#696969\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #696969\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DIMGREY = Color.DIMGRAY;\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #1E90FF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.DODGERBLUE = Object.freeze(Color.fromCssColorString(\"#1E90FF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #B22222\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.FIREBRICK = Object.freeze(Color.fromCssColorString(\"#B22222\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFFAF0\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.FLORALWHITE = Object.freeze(Color.fromCssColorString(\"#FFFAF0\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #228B22\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.FORESTGREEN = Object.freeze(Color.fromCssColorString(\"#228B22\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF00FF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.FUCHSIA = Object.freeze(Color.fromCssColorString(\"#FF00FF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #DCDCDC\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.GAINSBORO = Object.freeze(Color.fromCssColorString(\"#DCDCDC\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F8F8FF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.GHOSTWHITE = Object.freeze(Color.fromCssColorString(\"#F8F8FF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFD700\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.GOLD = Object.freeze(Color.fromCssColorString(\"#FFD700\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #DAA520\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.GOLDENROD = Object.freeze(Color.fromCssColorString(\"#DAA520\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #808080\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.GRAY = Object.freeze(Color.fromCssColorString(\"#808080\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #008000\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.GREEN = Object.freeze(Color.fromCssColorString(\"#008000\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #ADFF2F\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.GREENYELLOW = Object.freeze(Color.fromCssColorString(\"#ADFF2F\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #808080\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.GREY = Color.GRAY;\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F0FFF0\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.HONEYDEW = Object.freeze(Color.fromCssColorString(\"#F0FFF0\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF69B4\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.HOTPINK = Object.freeze(Color.fromCssColorString(\"#FF69B4\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #CD5C5C\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.INDIANRED = Object.freeze(Color.fromCssColorString(\"#CD5C5C\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #4B0082\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.INDIGO = Object.freeze(Color.fromCssColorString(\"#4B0082\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFFFF0\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.IVORY = Object.freeze(Color.fromCssColorString(\"#FFFFF0\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F0E68C\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.KHAKI = Object.freeze(Color.fromCssColorString(\"#F0E68C\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #E6E6FA\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LAVENDER = Object.freeze(Color.fromCssColorString(\"#E6E6FA\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFF0F5\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LAVENDAR_BLUSH = Object.freeze(Color.fromCssColorString(\"#FFF0F5\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #7CFC00\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LAWNGREEN = Object.freeze(Color.fromCssColorString(\"#7CFC00\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFFACD\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LEMONCHIFFON = Object.freeze(Color.fromCssColorString(\"#FFFACD\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #ADD8E6\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTBLUE = Object.freeze(Color.fromCssColorString(\"#ADD8E6\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F08080\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTCORAL = Object.freeze(Color.fromCssColorString(\"#F08080\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #E0FFFF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTCYAN = Object.freeze(Color.fromCssColorString(\"#E0FFFF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FAFAD2\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTGOLDENRODYELLOW = Object.freeze(Color.fromCssColorString(\"#FAFAD2\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #D3D3D3\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTGRAY = Object.freeze(Color.fromCssColorString(\"#D3D3D3\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #90EE90\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTGREEN = Object.freeze(Color.fromCssColorString(\"#90EE90\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #D3D3D3\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTGREY = Color.LIGHTGRAY;\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFB6C1\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTPINK = Object.freeze(Color.fromCssColorString(\"#FFB6C1\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #20B2AA\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTSEAGREEN = Object.freeze(Color.fromCssColorString(\"#20B2AA\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #87CEFA\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTSKYBLUE = Object.freeze(Color.fromCssColorString(\"#87CEFA\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #778899\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTSLATEGRAY = Object.freeze(Color.fromCssColorString(\"#778899\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #778899\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTSLATEGREY = Color.LIGHTSLATEGRAY;\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #B0C4DE\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTSTEELBLUE = Object.freeze(Color.fromCssColorString(\"#B0C4DE\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFFFE0\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIGHTYELLOW = Object.freeze(Color.fromCssColorString(\"#FFFFE0\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #00FF00\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIME = Object.freeze(Color.fromCssColorString(\"#00FF00\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #32CD32\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LIMEGREEN = Object.freeze(Color.fromCssColorString(\"#32CD32\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FAF0E6\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.LINEN = Object.freeze(Color.fromCssColorString(\"#FAF0E6\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF00FF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MAGENTA = Object.freeze(Color.fromCssColorString(\"#FF00FF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #800000\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MAROON = Object.freeze(Color.fromCssColorString(\"#800000\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #66CDAA\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMAQUAMARINE = Object.freeze(Color.fromCssColorString(\"#66CDAA\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #0000CD\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMBLUE = Object.freeze(Color.fromCssColorString(\"#0000CD\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #BA55D3\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMORCHID = Object.freeze(Color.fromCssColorString(\"#BA55D3\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #9370DB\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMPURPLE = Object.freeze(Color.fromCssColorString(\"#9370DB\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #3CB371\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMSEAGREEN = Object.freeze(Color.fromCssColorString(\"#3CB371\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #7B68EE\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMSLATEBLUE = Object.freeze(Color.fromCssColorString(\"#7B68EE\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #00FA9A\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMSPRINGGREEN = Object.freeze(Color.fromCssColorString(\"#00FA9A\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #48D1CC\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMTURQUOISE = Object.freeze(Color.fromCssColorString(\"#48D1CC\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #C71585\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MEDIUMVIOLETRED = Object.freeze(Color.fromCssColorString(\"#C71585\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #191970\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MIDNIGHTBLUE = Object.freeze(Color.fromCssColorString(\"#191970\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F5FFFA\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MINTCREAM = Object.freeze(Color.fromCssColorString(\"#F5FFFA\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFE4E1\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MISTYROSE = Object.freeze(Color.fromCssColorString(\"#FFE4E1\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFE4B5\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.MOCCASIN = Object.freeze(Color.fromCssColorString(\"#FFE4B5\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFDEAD\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.NAVAJOWHITE = Object.freeze(Color.fromCssColorString(\"#FFDEAD\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #000080\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.NAVY = Object.freeze(Color.fromCssColorString(\"#000080\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FDF5E6\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.OLDLACE = Object.freeze(Color.fromCssColorString(\"#FDF5E6\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #808000\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.OLIVE = Object.freeze(Color.fromCssColorString(\"#808000\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #6B8E23\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.OLIVEDRAB = Object.freeze(Color.fromCssColorString(\"#6B8E23\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFA500\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.ORANGE = Object.freeze(Color.fromCssColorString(\"#FFA500\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF4500\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.ORANGERED = Object.freeze(Color.fromCssColorString(\"#FF4500\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #DA70D6\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.ORCHID = Object.freeze(Color.fromCssColorString(\"#DA70D6\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #EEE8AA\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PALEGOLDENROD = Object.freeze(Color.fromCssColorString(\"#EEE8AA\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #98FB98\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PALEGREEN = Object.freeze(Color.fromCssColorString(\"#98FB98\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #AFEEEE\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PALETURQUOISE = Object.freeze(Color.fromCssColorString(\"#AFEEEE\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #DB7093\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PALEVIOLETRED = Object.freeze(Color.fromCssColorString(\"#DB7093\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFEFD5\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PAPAYAWHIP = Object.freeze(Color.fromCssColorString(\"#FFEFD5\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFDAB9\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PEACHPUFF = Object.freeze(Color.fromCssColorString(\"#FFDAB9\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #CD853F\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PERU = Object.freeze(Color.fromCssColorString(\"#CD853F\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFC0CB\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PINK = Object.freeze(Color.fromCssColorString(\"#FFC0CB\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #DDA0DD\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PLUM = Object.freeze(Color.fromCssColorString(\"#DDA0DD\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #B0E0E6\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.POWDERBLUE = Object.freeze(Color.fromCssColorString(\"#B0E0E6\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #800080\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.PURPLE = Object.freeze(Color.fromCssColorString(\"#800080\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF0000\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.RED = Object.freeze(Color.fromCssColorString(\"#FF0000\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #BC8F8F\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.ROSYBROWN = Object.freeze(Color.fromCssColorString(\"#BC8F8F\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #4169E1\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.ROYALBLUE = Object.freeze(Color.fromCssColorString(\"#4169E1\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #8B4513\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SADDLEBROWN = Object.freeze(Color.fromCssColorString(\"#8B4513\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FA8072\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SALMON = Object.freeze(Color.fromCssColorString(\"#FA8072\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F4A460\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SANDYBROWN = Object.freeze(Color.fromCssColorString(\"#F4A460\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #2E8B57\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SEAGREEN = Object.freeze(Color.fromCssColorString(\"#2E8B57\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFF5EE\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SEASHELL = Object.freeze(Color.fromCssColorString(\"#FFF5EE\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #A0522D\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SIENNA = Object.freeze(Color.fromCssColorString(\"#A0522D\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #C0C0C0\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SILVER = Object.freeze(Color.fromCssColorString(\"#C0C0C0\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #87CEEB\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SKYBLUE = Object.freeze(Color.fromCssColorString(\"#87CEEB\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #6A5ACD\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SLATEBLUE = Object.freeze(Color.fromCssColorString(\"#6A5ACD\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #708090\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SLATEGRAY = Object.freeze(Color.fromCssColorString(\"#708090\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #708090\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SLATEGREY = Color.SLATEGRAY;\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFFAFA\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SNOW = Object.freeze(Color.fromCssColorString(\"#FFFAFA\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #00FF7F\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.SPRINGGREEN = Object.freeze(Color.fromCssColorString(\"#00FF7F\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #4682B4\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.STEELBLUE = Object.freeze(Color.fromCssColorString(\"#4682B4\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #D2B48C\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.TAN = Object.freeze(Color.fromCssColorString(\"#D2B48C\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #008080\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.TEAL = Object.freeze(Color.fromCssColorString(\"#008080\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #D8BFD8\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.THISTLE = Object.freeze(Color.fromCssColorString(\"#D8BFD8\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FF6347\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.TOMATO = Object.freeze(Color.fromCssColorString(\"#FF6347\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #40E0D0\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.TURQUOISE = Object.freeze(Color.fromCssColorString(\"#40E0D0\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #EE82EE\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.VIOLET = Object.freeze(Color.fromCssColorString(\"#EE82EE\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F5DEB3\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.WHEAT = Object.freeze(Color.fromCssColorString(\"#F5DEB3\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFFFFF\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.WHITE = Object.freeze(Color.fromCssColorString(\"#FFFFFF\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #F5F5F5\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.WHITESMOKE = Object.freeze(Color.fromCssColorString(\"#F5F5F5\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #FFFF00\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.YELLOW = Object.freeze(Color.fromCssColorString(\"#FFFF00\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS color #9ACD32\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.YELLOWGREEN = Object.freeze(Color.fromCssColorString(\"#9ACD32\"));\r\n\r\n/**\r\n * An immutable Color instance initialized to CSS transparent.\r\n * \r\n *\r\n * @constant\r\n * @type {Color}\r\n */\r\nColor.TRANSPARENT = Object.freeze(new Color(0, 0, 0, 0));\r\nexport default Color;\r\n","import Color from \"./Color.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Value and type information for per-instance geometry color.\r\n *\r\n * @alias ColorGeometryInstanceAttribute\r\n * @constructor\r\n *\r\n * @param {Number} [red=1.0] The red component.\r\n * @param {Number} [green=1.0] The green component.\r\n * @param {Number} [blue=1.0] The blue component.\r\n * @param {Number} [alpha=1.0] The alpha component.\r\n *\r\n *\r\n * @example\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : Cesium.BoxGeometry.fromDimensions({\r\n * dimensions : new Cesium.Cartesian3(1000000.0, 1000000.0, 500000.0)\r\n * }),\r\n * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(\r\n * Cesium.Cartesian3.fromDegrees(0.0, 0.0)), new Cesium.Cartesian3(0.0, 0.0, 1000000.0), new Cesium.Matrix4()),\r\n * id : 'box',\r\n * attributes : {\r\n * color : new Cesium.ColorGeometryInstanceAttribute(red, green, blue, alpha)\r\n * }\r\n * });\r\n *\r\n * @see GeometryInstance\r\n * @see GeometryInstanceAttribute\r\n */\r\nfunction ColorGeometryInstanceAttribute(red, green, blue, alpha) {\r\n red = defaultValue(red, 1.0);\r\n green = defaultValue(green, 1.0);\r\n blue = defaultValue(blue, 1.0);\r\n alpha = defaultValue(alpha, 1.0);\r\n\r\n /**\r\n * The values for the attributes stored in a typed array.\r\n *\r\n * @type Uint8Array\r\n *\r\n * @default [255, 255, 255, 255]\r\n */\r\n this.value = new Uint8Array([\r\n Color.floatToByte(red),\r\n Color.floatToByte(green),\r\n Color.floatToByte(blue),\r\n Color.floatToByte(alpha),\r\n ]);\r\n}\r\n\r\nObject.defineProperties(ColorGeometryInstanceAttribute.prototype, {\r\n /**\r\n * The datatype of each component in the attribute, e.g., individual elements in\r\n * {@link ColorGeometryInstanceAttribute#value}.\r\n *\r\n * @memberof ColorGeometryInstanceAttribute.prototype\r\n *\r\n * @type {ComponentDatatype}\r\n * @readonly\r\n *\r\n * @default {@link ComponentDatatype.UNSIGNED_BYTE}\r\n */\r\n componentDatatype: {\r\n get: function () {\r\n return ComponentDatatype.UNSIGNED_BYTE;\r\n },\r\n },\r\n\r\n /**\r\n * The number of components in the attributes, i.e., {@link ColorGeometryInstanceAttribute#value}.\r\n *\r\n * @memberof ColorGeometryInstanceAttribute.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n *\r\n * @default 4\r\n */\r\n componentsPerAttribute: {\r\n get: function () {\r\n return 4;\r\n },\r\n },\r\n\r\n /**\r\n * When true and componentDatatype is an integer format,\r\n * indicate that the components should be mapped to the range [0, 1] (unsigned)\r\n * or [-1, 1] (signed) when they are accessed as floating-point for rendering.\r\n *\r\n * @memberof ColorGeometryInstanceAttribute.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n normalize: {\r\n get: function () {\r\n return true;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates a new {@link ColorGeometryInstanceAttribute} instance given the provided {@link Color}.\r\n *\r\n * @param {Color} color The color.\r\n * @returns {ColorGeometryInstanceAttribute} The new {@link ColorGeometryInstanceAttribute} instance.\r\n *\r\n * @example\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : geometry,\r\n * attributes : {\r\n * color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.CORNFLOWERBLUE),\r\n * }\r\n * });\r\n */\r\nColorGeometryInstanceAttribute.fromColor = function (color) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(color)) {\r\n throw new DeveloperError(\"color is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return new ColorGeometryInstanceAttribute(\r\n color.red,\r\n color.green,\r\n color.blue,\r\n color.alpha\r\n );\r\n};\r\n\r\n/**\r\n * Converts a color to a typed array that can be used to assign a color attribute.\r\n *\r\n * @param {Color} color The color.\r\n * @param {Uint8Array} [result] The array to store the result in, if undefined a new instance will be created.\r\n *\r\n * @returns {Uint8Array} The modified result parameter or a new instance if result was undefined.\r\n *\r\n * @example\r\n * var attributes = primitive.getGeometryInstanceAttributes('an id');\r\n * attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA, attributes.color);\r\n */\r\nColorGeometryInstanceAttribute.toValue = function (color, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(color)) {\r\n throw new DeveloperError(\"color is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Uint8Array(color.toBytes());\r\n }\r\n return color.toBytes(result);\r\n};\r\n\r\n/**\r\n * Compares the provided ColorGeometryInstanceAttributes and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {ColorGeometryInstanceAttribute} [left] The first ColorGeometryInstanceAttribute.\r\n * @param {ColorGeometryInstanceAttribute} [right] The second ColorGeometryInstanceAttribute.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nColorGeometryInstanceAttribute.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.value[0] === right.value[0] &&\r\n left.value[1] === right.value[1] &&\r\n left.value[2] === right.value[2] &&\r\n left.value[3] === right.value[3])\r\n );\r\n};\r\nexport default ColorGeometryInstanceAttribute;\r\n","import defined from \"./defined.js\";\r\n\r\n/**\r\n * Describes a compressed texture and contains a compressed texture buffer.\r\n * @alias CompressedTextureBuffer\r\n * @constructor\r\n *\r\n * @param {PixelFormat} internalFormat The pixel format of the compressed texture.\r\n * @param {Number} width The width of the texture.\r\n * @param {Number} height The height of the texture.\r\n * @param {Uint8Array} buffer The compressed texture buffer.\r\n */\r\nfunction CompressedTextureBuffer(internalFormat, width, height, buffer) {\r\n this._format = internalFormat;\r\n this._width = width;\r\n this._height = height;\r\n this._buffer = buffer;\r\n}\r\n\r\nObject.defineProperties(CompressedTextureBuffer.prototype, {\r\n /**\r\n * The format of the compressed texture.\r\n * @type PixelFormat\r\n * @readonly\r\n * @memberof CompressedTextureBuffer.prototype\r\n */\r\n internalFormat: {\r\n get: function () {\r\n return this._format;\r\n },\r\n },\r\n /**\r\n * The width of the texture.\r\n * @type Number\r\n * @readonly\r\n * @memberof CompressedTextureBuffer.prototype\r\n */\r\n width: {\r\n get: function () {\r\n return this._width;\r\n },\r\n },\r\n /**\r\n * The height of the texture.\r\n * @type Number\r\n * @readonly\r\n * @memberof CompressedTextureBuffer.prototype\r\n */\r\n height: {\r\n get: function () {\r\n return this._height;\r\n },\r\n },\r\n /**\r\n * The compressed texture buffer.\r\n * @type Uint8Array\r\n * @readonly\r\n * @memberof CompressedTextureBuffer.prototype\r\n */\r\n bufferView: {\r\n get: function () {\r\n return this._buffer;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates a shallow clone of a compressed texture buffer.\r\n *\r\n * @param {CompressedTextureBuffer} object The compressed texture buffer to be cloned.\r\n * @return {CompressedTextureBuffer} A shallow clone of the compressed texture buffer.\r\n */\r\nCompressedTextureBuffer.clone = function (object) {\r\n if (!defined(object)) {\r\n return undefined;\r\n }\r\n\r\n return new CompressedTextureBuffer(\r\n object._format,\r\n object._width,\r\n object._height,\r\n object._buffer\r\n );\r\n};\r\n\r\n/**\r\n * Creates a shallow clone of this compressed texture buffer.\r\n *\r\n * @return {CompressedTextureBuffer} A shallow clone of the compressed texture buffer.\r\n */\r\nCompressedTextureBuffer.prototype.clone = function () {\r\n return CompressedTextureBuffer.clone(this);\r\n};\r\nexport default CompressedTextureBuffer;\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport OrientedBoundingBox from \"./OrientedBoundingBox.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar CoplanarPolygonGeometryLibrary = {};\r\n\r\nvar scratchIntersectionPoint = new Cartesian3();\r\nvar scratchXAxis = new Cartesian3();\r\nvar scratchYAxis = new Cartesian3();\r\nvar scratchZAxis = new Cartesian3();\r\nvar obbScratch = new OrientedBoundingBox();\r\n\r\nCoplanarPolygonGeometryLibrary.validOutline = function (positions) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"positions\", positions);\r\n //>>includeEnd('debug');\r\n\r\n var orientedBoundingBox = OrientedBoundingBox.fromPoints(\r\n positions,\r\n obbScratch\r\n );\r\n var halfAxes = orientedBoundingBox.halfAxes;\r\n var xAxis = Matrix3.getColumn(halfAxes, 0, scratchXAxis);\r\n var yAxis = Matrix3.getColumn(halfAxes, 1, scratchYAxis);\r\n var zAxis = Matrix3.getColumn(halfAxes, 2, scratchZAxis);\r\n\r\n var xMag = Cartesian3.magnitude(xAxis);\r\n var yMag = Cartesian3.magnitude(yAxis);\r\n var zMag = Cartesian3.magnitude(zAxis);\r\n\r\n // If all the points are on a line return undefined because we can't draw a polygon\r\n return !(\r\n (xMag === 0 && (yMag === 0 || zMag === 0)) ||\r\n (yMag === 0 && zMag === 0)\r\n );\r\n};\r\n\r\n// call after removeDuplicates\r\nCoplanarPolygonGeometryLibrary.computeProjectTo2DArguments = function (\r\n positions,\r\n centerResult,\r\n planeAxis1Result,\r\n planeAxis2Result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"positions\", positions);\r\n Check.defined(\"centerResult\", centerResult);\r\n Check.defined(\"planeAxis1Result\", planeAxis1Result);\r\n Check.defined(\"planeAxis2Result\", planeAxis2Result);\r\n //>>includeEnd('debug');\r\n\r\n var orientedBoundingBox = OrientedBoundingBox.fromPoints(\r\n positions,\r\n obbScratch\r\n );\r\n var halfAxes = orientedBoundingBox.halfAxes;\r\n var xAxis = Matrix3.getColumn(halfAxes, 0, scratchXAxis);\r\n var yAxis = Matrix3.getColumn(halfAxes, 1, scratchYAxis);\r\n var zAxis = Matrix3.getColumn(halfAxes, 2, scratchZAxis);\r\n\r\n var xMag = Cartesian3.magnitude(xAxis);\r\n var yMag = Cartesian3.magnitude(yAxis);\r\n var zMag = Cartesian3.magnitude(zAxis);\r\n var min = Math.min(xMag, yMag, zMag);\r\n\r\n // If all the points are on a line return undefined because we can't draw a polygon\r\n if (\r\n (xMag === 0 && (yMag === 0 || zMag === 0)) ||\r\n (yMag === 0 && zMag === 0)\r\n ) {\r\n return false;\r\n }\r\n\r\n var planeAxis1;\r\n var planeAxis2;\r\n\r\n if (min === yMag || min === zMag) {\r\n planeAxis1 = xAxis;\r\n }\r\n if (min === xMag) {\r\n planeAxis1 = yAxis;\r\n } else if (min === zMag) {\r\n planeAxis2 = yAxis;\r\n }\r\n if (min === xMag || min === yMag) {\r\n planeAxis2 = zAxis;\r\n }\r\n\r\n Cartesian3.normalize(planeAxis1, planeAxis1Result);\r\n Cartesian3.normalize(planeAxis2, planeAxis2Result);\r\n Cartesian3.clone(orientedBoundingBox.center, centerResult);\r\n return true;\r\n};\r\n\r\nfunction projectTo2D(position, center, axis1, axis2, result) {\r\n var v = Cartesian3.subtract(position, center, scratchIntersectionPoint);\r\n var x = Cartesian3.dot(axis1, v);\r\n var y = Cartesian3.dot(axis2, v);\r\n\r\n return Cartesian2.fromElements(x, y, result);\r\n}\r\n\r\nCoplanarPolygonGeometryLibrary.createProjectPointsTo2DFunction = function (\r\n center,\r\n axis1,\r\n axis2\r\n) {\r\n return function (positions) {\r\n var positionResults = new Array(positions.length);\r\n for (var i = 0; i < positions.length; i++) {\r\n positionResults[i] = projectTo2D(positions[i], center, axis1, axis2);\r\n }\r\n\r\n return positionResults;\r\n };\r\n};\r\n\r\nCoplanarPolygonGeometryLibrary.createProjectPointTo2DFunction = function (\r\n center,\r\n axis1,\r\n axis2\r\n) {\r\n return function (position, result) {\r\n return projectTo2D(position, center, axis1, axis2, result);\r\n };\r\n};\r\nexport default CoplanarPolygonGeometryLibrary;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nfunction calculateM(ellipticity, major, latitude) {\r\n if (ellipticity === 0.0) {\r\n // sphere\r\n return major * latitude;\r\n }\r\n\r\n var e2 = ellipticity * ellipticity;\r\n var e4 = e2 * e2;\r\n var e6 = e4 * e2;\r\n var e8 = e6 * e2;\r\n var e10 = e8 * e2;\r\n var e12 = e10 * e2;\r\n var phi = latitude;\r\n var sin2Phi = Math.sin(2 * phi);\r\n var sin4Phi = Math.sin(4 * phi);\r\n var sin6Phi = Math.sin(6 * phi);\r\n var sin8Phi = Math.sin(8 * phi);\r\n var sin10Phi = Math.sin(10 * phi);\r\n var sin12Phi = Math.sin(12 * phi);\r\n\r\n return (\r\n major *\r\n ((1 -\r\n e2 / 4 -\r\n (3 * e4) / 64 -\r\n (5 * e6) / 256 -\r\n (175 * e8) / 16384 -\r\n (441 * e10) / 65536 -\r\n (4851 * e12) / 1048576) *\r\n phi -\r\n ((3 * e2) / 8 +\r\n (3 * e4) / 32 +\r\n (45 * e6) / 1024 +\r\n (105 * e8) / 4096 +\r\n (2205 * e10) / 131072 +\r\n (6237 * e12) / 524288) *\r\n sin2Phi +\r\n ((15 * e4) / 256 +\r\n (45 * e6) / 1024 +\r\n (525 * e8) / 16384 +\r\n (1575 * e10) / 65536 +\r\n (155925 * e12) / 8388608) *\r\n sin4Phi -\r\n ((35 * e6) / 3072 +\r\n (175 * e8) / 12288 +\r\n (3675 * e10) / 262144 +\r\n (13475 * e12) / 1048576) *\r\n sin6Phi +\r\n ((315 * e8) / 131072 + (2205 * e10) / 524288 + (43659 * e12) / 8388608) *\r\n sin8Phi -\r\n ((693 * e10) / 1310720 + (6237 * e12) / 5242880) * sin10Phi +\r\n ((1001 * e12) / 8388608) * sin12Phi)\r\n );\r\n}\r\n\r\nfunction calculateInverseM(M, ellipticity, major) {\r\n var d = M / major;\r\n\r\n if (ellipticity === 0.0) {\r\n // sphere\r\n return d;\r\n }\r\n\r\n var d2 = d * d;\r\n var d3 = d2 * d;\r\n var d4 = d3 * d;\r\n var e = ellipticity;\r\n var e2 = e * e;\r\n var e4 = e2 * e2;\r\n var e6 = e4 * e2;\r\n var e8 = e6 * e2;\r\n var e10 = e8 * e2;\r\n var e12 = e10 * e2;\r\n var sin2D = Math.sin(2 * d);\r\n var cos2D = Math.cos(2 * d);\r\n var sin4D = Math.sin(4 * d);\r\n var cos4D = Math.cos(4 * d);\r\n var sin6D = Math.sin(6 * d);\r\n var cos6D = Math.cos(6 * d);\r\n var sin8D = Math.sin(8 * d);\r\n var cos8D = Math.cos(8 * d);\r\n var sin10D = Math.sin(10 * d);\r\n var cos10D = Math.cos(10 * d);\r\n var sin12D = Math.sin(12 * d);\r\n\r\n return (\r\n d +\r\n (d * e2) / 4 +\r\n (7 * d * e4) / 64 +\r\n (15 * d * e6) / 256 +\r\n (579 * d * e8) / 16384 +\r\n (1515 * d * e10) / 65536 +\r\n (16837 * d * e12) / 1048576 +\r\n ((3 * d * e4) / 16 +\r\n (45 * d * e6) / 256 -\r\n (d * (32 * d2 - 561) * e8) / 4096 -\r\n (d * (232 * d2 - 1677) * e10) / 16384 +\r\n (d * (399985 - 90560 * d2 + 512 * d4) * e12) / 5242880) *\r\n cos2D +\r\n ((21 * d * e6) / 256 +\r\n (483 * d * e8) / 4096 -\r\n (d * (224 * d2 - 1969) * e10) / 16384 -\r\n (d * (33152 * d2 - 112599) * e12) / 1048576) *\r\n cos4D +\r\n ((151 * d * e8) / 4096 +\r\n (4681 * d * e10) / 65536 +\r\n (1479 * d * e12) / 16384 -\r\n (453 * d3 * e12) / 32768) *\r\n cos6D +\r\n ((1097 * d * e10) / 65536 + (42783 * d * e12) / 1048576) * cos8D +\r\n ((8011 * d * e12) / 1048576) * cos10D +\r\n ((3 * e2) / 8 +\r\n (3 * e4) / 16 +\r\n (213 * e6) / 2048 -\r\n (3 * d2 * e6) / 64 +\r\n (255 * e8) / 4096 -\r\n (33 * d2 * e8) / 512 +\r\n (20861 * e10) / 524288 -\r\n (33 * d2 * e10) / 512 +\r\n (d4 * e10) / 1024 +\r\n (28273 * e12) / 1048576 -\r\n (471 * d2 * e12) / 8192 +\r\n (9 * d4 * e12) / 4096) *\r\n sin2D +\r\n ((21 * e4) / 256 +\r\n (21 * e6) / 256 +\r\n (533 * e8) / 8192 -\r\n (21 * d2 * e8) / 512 +\r\n (197 * e10) / 4096 -\r\n (315 * d2 * e10) / 4096 +\r\n (584039 * e12) / 16777216 -\r\n (12517 * d2 * e12) / 131072 +\r\n (7 * d4 * e12) / 2048) *\r\n sin4D +\r\n ((151 * e6) / 6144 +\r\n (151 * e8) / 4096 +\r\n (5019 * e10) / 131072 -\r\n (453 * d2 * e10) / 16384 +\r\n (26965 * e12) / 786432 -\r\n (8607 * d2 * e12) / 131072) *\r\n sin6D +\r\n ((1097 * e8) / 131072 +\r\n (1097 * e10) / 65536 +\r\n (225797 * e12) / 10485760 -\r\n (1097 * d2 * e12) / 65536) *\r\n sin8D +\r\n ((8011 * e10) / 2621440 + (8011 * e12) / 1048576) * sin10D +\r\n ((293393 * e12) / 251658240) * sin12D\r\n );\r\n}\r\n\r\nfunction calculateSigma(ellipticity, latitude) {\r\n if (ellipticity === 0.0) {\r\n // sphere\r\n return Math.log(Math.tan(0.5 * (CesiumMath.PI_OVER_TWO + latitude)));\r\n }\r\n\r\n var eSinL = ellipticity * Math.sin(latitude);\r\n return (\r\n Math.log(Math.tan(0.5 * (CesiumMath.PI_OVER_TWO + latitude))) -\r\n (ellipticity / 2.0) * Math.log((1 + eSinL) / (1 - eSinL))\r\n );\r\n}\r\n\r\nfunction calculateHeading(\r\n ellipsoidRhumbLine,\r\n firstLongitude,\r\n firstLatitude,\r\n secondLongitude,\r\n secondLatitude\r\n) {\r\n var sigma1 = calculateSigma(ellipsoidRhumbLine._ellipticity, firstLatitude);\r\n var sigma2 = calculateSigma(ellipsoidRhumbLine._ellipticity, secondLatitude);\r\n return Math.atan2(\r\n CesiumMath.negativePiToPi(secondLongitude - firstLongitude),\r\n sigma2 - sigma1\r\n );\r\n}\r\n\r\nfunction calculateArcLength(\r\n ellipsoidRhumbLine,\r\n major,\r\n minor,\r\n firstLongitude,\r\n firstLatitude,\r\n secondLongitude,\r\n secondLatitude\r\n) {\r\n var heading = ellipsoidRhumbLine._heading;\r\n var deltaLongitude = secondLongitude - firstLongitude;\r\n\r\n var distance = 0.0;\r\n\r\n //Check to see if the rhumb line has constant latitude\r\n //This equation will diverge if heading gets close to 90 degrees\r\n if (\r\n CesiumMath.equalsEpsilon(\r\n Math.abs(heading),\r\n CesiumMath.PI_OVER_TWO,\r\n CesiumMath.EPSILON8\r\n )\r\n ) {\r\n //If heading is close to 90 degrees\r\n if (major === minor) {\r\n distance =\r\n major *\r\n Math.cos(firstLatitude) *\r\n CesiumMath.negativePiToPi(deltaLongitude);\r\n } else {\r\n var sinPhi = Math.sin(firstLatitude);\r\n distance =\r\n (major *\r\n Math.cos(firstLatitude) *\r\n CesiumMath.negativePiToPi(deltaLongitude)) /\r\n Math.sqrt(1 - ellipsoidRhumbLine._ellipticitySquared * sinPhi * sinPhi);\r\n }\r\n } else {\r\n var M1 = calculateM(ellipsoidRhumbLine._ellipticity, major, firstLatitude);\r\n var M2 = calculateM(ellipsoidRhumbLine._ellipticity, major, secondLatitude);\r\n\r\n distance = (M2 - M1) / Math.cos(heading);\r\n }\r\n return Math.abs(distance);\r\n}\r\n\r\nvar scratchCart1 = new Cartesian3();\r\nvar scratchCart2 = new Cartesian3();\r\n\r\nfunction computeProperties(ellipsoidRhumbLine, start, end, ellipsoid) {\r\n var firstCartesian = Cartesian3.normalize(\r\n ellipsoid.cartographicToCartesian(start, scratchCart2),\r\n scratchCart1\r\n );\r\n var lastCartesian = Cartesian3.normalize(\r\n ellipsoid.cartographicToCartesian(end, scratchCart2),\r\n scratchCart2\r\n );\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"value\",\r\n Math.abs(\r\n Math.abs(Cartesian3.angleBetween(firstCartesian, lastCartesian)) - Math.PI\r\n ),\r\n 0.0125\r\n );\r\n //>>includeEnd('debug');\r\n\r\n var major = ellipsoid.maximumRadius;\r\n var minor = ellipsoid.minimumRadius;\r\n var majorSquared = major * major;\r\n var minorSquared = minor * minor;\r\n ellipsoidRhumbLine._ellipticitySquared =\r\n (majorSquared - minorSquared) / majorSquared;\r\n ellipsoidRhumbLine._ellipticity = Math.sqrt(\r\n ellipsoidRhumbLine._ellipticitySquared\r\n );\r\n\r\n ellipsoidRhumbLine._start = Cartographic.clone(\r\n start,\r\n ellipsoidRhumbLine._start\r\n );\r\n ellipsoidRhumbLine._start.height = 0;\r\n\r\n ellipsoidRhumbLine._end = Cartographic.clone(end, ellipsoidRhumbLine._end);\r\n ellipsoidRhumbLine._end.height = 0;\r\n\r\n ellipsoidRhumbLine._heading = calculateHeading(\r\n ellipsoidRhumbLine,\r\n start.longitude,\r\n start.latitude,\r\n end.longitude,\r\n end.latitude\r\n );\r\n ellipsoidRhumbLine._distance = calculateArcLength(\r\n ellipsoidRhumbLine,\r\n ellipsoid.maximumRadius,\r\n ellipsoid.minimumRadius,\r\n start.longitude,\r\n start.latitude,\r\n end.longitude,\r\n end.latitude\r\n );\r\n}\r\n\r\nfunction interpolateUsingSurfaceDistance(\r\n start,\r\n heading,\r\n distance,\r\n major,\r\n ellipticity,\r\n result\r\n) {\r\n if (distance === 0.0) {\r\n return Cartographic.clone(start, result);\r\n }\r\n\r\n var ellipticitySquared = ellipticity * ellipticity;\r\n\r\n var longitude;\r\n var latitude;\r\n var deltaLongitude;\r\n\r\n //Check to see if the rhumb line has constant latitude\r\n //This won't converge if heading is close to 90 degrees\r\n if (\r\n Math.abs(CesiumMath.PI_OVER_TWO - Math.abs(heading)) > CesiumMath.EPSILON8\r\n ) {\r\n //Calculate latitude of the second point\r\n var M1 = calculateM(ellipticity, major, start.latitude);\r\n var deltaM = distance * Math.cos(heading);\r\n var M2 = M1 + deltaM;\r\n latitude = calculateInverseM(M2, ellipticity, major);\r\n\r\n //Now find the longitude of the second point\r\n var sigma1 = calculateSigma(ellipticity, start.latitude);\r\n var sigma2 = calculateSigma(ellipticity, latitude);\r\n deltaLongitude = Math.tan(heading) * (sigma2 - sigma1);\r\n longitude = CesiumMath.negativePiToPi(start.longitude + deltaLongitude);\r\n } else {\r\n //If heading is close to 90 degrees\r\n latitude = start.latitude;\r\n var localRad;\r\n\r\n if (ellipticity === 0.0) {\r\n // sphere\r\n localRad = major * Math.cos(start.latitude);\r\n } else {\r\n var sinPhi = Math.sin(start.latitude);\r\n localRad =\r\n (major * Math.cos(start.latitude)) /\r\n Math.sqrt(1 - ellipticitySquared * sinPhi * sinPhi);\r\n }\r\n\r\n deltaLongitude = distance / localRad;\r\n if (heading > 0.0) {\r\n longitude = CesiumMath.negativePiToPi(start.longitude + deltaLongitude);\r\n } else {\r\n longitude = CesiumMath.negativePiToPi(start.longitude - deltaLongitude);\r\n }\r\n }\r\n\r\n if (defined(result)) {\r\n result.longitude = longitude;\r\n result.latitude = latitude;\r\n result.height = 0;\r\n\r\n return result;\r\n }\r\n\r\n return new Cartographic(longitude, latitude, 0);\r\n}\r\n\r\n/**\r\n * Initializes a rhumb line on the ellipsoid connecting the two provided planetodetic points.\r\n *\r\n * @alias EllipsoidRhumbLine\r\n * @constructor\r\n *\r\n * @param {Cartographic} [start] The initial planetodetic point on the path.\r\n * @param {Cartographic} [end] The final planetodetic point on the path.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the rhumb line lies.\r\n *\r\n * @exception {DeveloperError} angle between start and end must be at least 0.0125 radians.\r\n */\r\nfunction EllipsoidRhumbLine(start, end, ellipsoid) {\r\n var e = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n this._ellipsoid = e;\r\n this._start = new Cartographic();\r\n this._end = new Cartographic();\r\n\r\n this._heading = undefined;\r\n this._distance = undefined;\r\n this._ellipticity = undefined;\r\n this._ellipticitySquared = undefined;\r\n\r\n if (defined(start) && defined(end)) {\r\n computeProperties(this, start, end, e);\r\n }\r\n}\r\n\r\nObject.defineProperties(EllipsoidRhumbLine.prototype, {\r\n /**\r\n * Gets the ellipsoid.\r\n * @memberof EllipsoidRhumbLine.prototype\r\n * @type {Ellipsoid}\r\n * @readonly\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the surface distance between the start and end point\r\n * @memberof EllipsoidRhumbLine.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n surfaceDistance: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"distance\", this._distance);\r\n //>>includeEnd('debug');\r\n\r\n return this._distance;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the initial planetodetic point on the path.\r\n * @memberof EllipsoidRhumbLine.prototype\r\n * @type {Cartographic}\r\n * @readonly\r\n */\r\n start: {\r\n get: function () {\r\n return this._start;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the final planetodetic point on the path.\r\n * @memberof EllipsoidRhumbLine.prototype\r\n * @type {Cartographic}\r\n * @readonly\r\n */\r\n end: {\r\n get: function () {\r\n return this._end;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the heading from the start point to the end point.\r\n * @memberof EllipsoidRhumbLine.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n heading: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"distance\", this._distance);\r\n //>>includeEnd('debug');\r\n\r\n return this._heading;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Create a rhumb line using an initial position with a heading and distance.\r\n *\r\n * @param {Cartographic} start The initial planetodetic point on the path.\r\n * @param {Number} heading The heading in radians.\r\n * @param {Number} distance The rhumb line distance between the start and end point.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the rhumb line lies.\r\n * @param {EllipsoidRhumbLine} [result] The object in which to store the result.\r\n * @returns {EllipsoidRhumbLine} The EllipsoidRhumbLine object.\r\n */\r\nEllipsoidRhumbLine.fromStartHeadingDistance = function (\r\n start,\r\n heading,\r\n distance,\r\n ellipsoid,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"start\", start);\r\n Check.defined(\"heading\", heading);\r\n Check.defined(\"distance\", distance);\r\n Check.typeOf.number.greaterThan(\"distance\", distance, 0.0);\r\n //>>includeEnd('debug');\r\n\r\n var e = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n var major = e.maximumRadius;\r\n var minor = e.minimumRadius;\r\n var majorSquared = major * major;\r\n var minorSquared = minor * minor;\r\n var ellipticity = Math.sqrt((majorSquared - minorSquared) / majorSquared);\r\n\r\n heading = CesiumMath.negativePiToPi(heading);\r\n var end = interpolateUsingSurfaceDistance(\r\n start,\r\n heading,\r\n distance,\r\n e.maximumRadius,\r\n ellipticity\r\n );\r\n\r\n if (\r\n !defined(result) ||\r\n (defined(ellipsoid) && !ellipsoid.equals(result.ellipsoid))\r\n ) {\r\n return new EllipsoidRhumbLine(start, end, e);\r\n }\r\n\r\n result.setEndPoints(start, end);\r\n return result;\r\n};\r\n\r\n/**\r\n * Sets the start and end points of the rhumb line.\r\n *\r\n * @param {Cartographic} start The initial planetodetic point on the path.\r\n * @param {Cartographic} end The final planetodetic point on the path.\r\n */\r\nEllipsoidRhumbLine.prototype.setEndPoints = function (start, end) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"start\", start);\r\n Check.defined(\"end\", end);\r\n //>>includeEnd('debug');\r\n\r\n computeProperties(this, start, end, this._ellipsoid);\r\n};\r\n\r\n/**\r\n * Provides the location of a point at the indicated portion along the rhumb line.\r\n *\r\n * @param {Number} fraction The portion of the distance between the initial and final points.\r\n * @param {Cartographic} [result] The object in which to store the result.\r\n * @returns {Cartographic} The location of the point along the rhumb line.\r\n */\r\nEllipsoidRhumbLine.prototype.interpolateUsingFraction = function (\r\n fraction,\r\n result\r\n) {\r\n return this.interpolateUsingSurfaceDistance(\r\n fraction * this._distance,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Provides the location of a point at the indicated distance along the rhumb line.\r\n *\r\n * @param {Number} distance The distance from the inital point to the point of interest along the rhumbLine.\r\n * @param {Cartographic} [result] The object in which to store the result.\r\n * @returns {Cartographic} The location of the point along the rhumb line.\r\n *\r\n * @exception {DeveloperError} start and end must be set before calling function interpolateUsingSurfaceDistance\r\n */\r\nEllipsoidRhumbLine.prototype.interpolateUsingSurfaceDistance = function (\r\n distance,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"distance\", distance);\r\n if (!defined(this._distance) || this._distance === 0.0) {\r\n throw new DeveloperError(\r\n \"EllipsoidRhumbLine must have distinct start and end set.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return interpolateUsingSurfaceDistance(\r\n this._start,\r\n this._heading,\r\n distance,\r\n this._ellipsoid.maximumRadius,\r\n this._ellipticity,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Provides the location of a point at the indicated longitude along the rhumb line.\r\n * If the longitude is outside the range of start and end points, the first intersection with the longitude from the start point in the direction of the heading is returned. This follows the spiral property of a rhumb line.\r\n *\r\n * @param {Number} intersectionLongitude The longitude, in radians, at which to find the intersection point from the starting point using the heading.\r\n * @param {Cartographic} [result] The object in which to store the result.\r\n * @returns {Cartographic} The location of the intersection point along the rhumb line, undefined if there is no intersection or infinite intersections.\r\n *\r\n * @exception {DeveloperError} start and end must be set before calling function findIntersectionWithLongitude.\r\n */\r\nEllipsoidRhumbLine.prototype.findIntersectionWithLongitude = function (\r\n intersectionLongitude,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"intersectionLongitude\", intersectionLongitude);\r\n if (!defined(this._distance) || this._distance === 0.0) {\r\n throw new DeveloperError(\r\n \"EllipsoidRhumbLine must have distinct start and end set.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var ellipticity = this._ellipticity;\r\n var heading = this._heading;\r\n var absHeading = Math.abs(heading);\r\n var start = this._start;\r\n\r\n intersectionLongitude = CesiumMath.negativePiToPi(intersectionLongitude);\r\n\r\n if (\r\n CesiumMath.equalsEpsilon(\r\n Math.abs(intersectionLongitude),\r\n Math.PI,\r\n CesiumMath.EPSILON14\r\n )\r\n ) {\r\n intersectionLongitude = CesiumMath.sign(start.longitude) * Math.PI;\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new Cartographic();\r\n }\r\n\r\n // If heading is -PI/2 or PI/2, this is an E-W rhumb line\r\n // If heading is 0 or PI, this is an N-S rhumb line\r\n if (Math.abs(CesiumMath.PI_OVER_TWO - absHeading) <= CesiumMath.EPSILON8) {\r\n result.longitude = intersectionLongitude;\r\n result.latitude = start.latitude;\r\n result.height = 0;\r\n return result;\r\n } else if (\r\n CesiumMath.equalsEpsilon(\r\n Math.abs(CesiumMath.PI_OVER_TWO - absHeading),\r\n CesiumMath.PI_OVER_TWO,\r\n CesiumMath.EPSILON8\r\n )\r\n ) {\r\n if (\r\n CesiumMath.equalsEpsilon(\r\n intersectionLongitude,\r\n start.longitude,\r\n CesiumMath.EPSILON12\r\n )\r\n ) {\r\n return undefined;\r\n }\r\n\r\n result.longitude = intersectionLongitude;\r\n result.latitude =\r\n CesiumMath.PI_OVER_TWO *\r\n CesiumMath.sign(CesiumMath.PI_OVER_TWO - heading);\r\n result.height = 0;\r\n return result;\r\n }\r\n\r\n // Use iterative solver from Equation 9 from http://edwilliams.org/ellipsoid/ellipsoid.pdf\r\n var phi1 = start.latitude;\r\n var eSinPhi1 = ellipticity * Math.sin(phi1);\r\n var leftComponent =\r\n Math.tan(0.5 * (CesiumMath.PI_OVER_TWO + phi1)) *\r\n Math.exp((intersectionLongitude - start.longitude) / Math.tan(heading));\r\n var denominator = (1 + eSinPhi1) / (1 - eSinPhi1);\r\n\r\n var newPhi = start.latitude;\r\n var phi;\r\n do {\r\n phi = newPhi;\r\n var eSinPhi = ellipticity * Math.sin(phi);\r\n var numerator = (1 + eSinPhi) / (1 - eSinPhi);\r\n newPhi =\r\n 2 *\r\n Math.atan(\r\n leftComponent * Math.pow(numerator / denominator, ellipticity / 2)\r\n ) -\r\n CesiumMath.PI_OVER_TWO;\r\n } while (!CesiumMath.equalsEpsilon(newPhi, phi, CesiumMath.EPSILON12));\r\n\r\n result.longitude = intersectionLongitude;\r\n result.latitude = newPhi;\r\n result.height = 0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Provides the location of a point at the indicated latitude along the rhumb line.\r\n * If the latitude is outside the range of start and end points, the first intersection with the latitude from that start point in the direction of the heading is returned. This follows the spiral property of a rhumb line.\r\n *\r\n * @param {Number} intersectionLatitude The latitude, in radians, at which to find the intersection point from the starting point using the heading.\r\n * @param {Cartographic} [result] The object in which to store the result.\r\n * @returns {Cartographic} The location of the intersection point along the rhumb line, undefined if there is no intersection or infinite intersections.\r\n *\r\n * @exception {DeveloperError} start and end must be set before calling function findIntersectionWithLongitude.\r\n */\r\nEllipsoidRhumbLine.prototype.findIntersectionWithLatitude = function (\r\n intersectionLatitude,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"intersectionLatitude\", intersectionLatitude);\r\n if (!defined(this._distance) || this._distance === 0.0) {\r\n throw new DeveloperError(\r\n \"EllipsoidRhumbLine must have distinct start and end set.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var ellipticity = this._ellipticity;\r\n var heading = this._heading;\r\n var start = this._start;\r\n\r\n // If start and end have same latitude, return undefined since it's either no intersection or infinite intersections\r\n if (\r\n CesiumMath.equalsEpsilon(\r\n Math.abs(heading),\r\n CesiumMath.PI_OVER_TWO,\r\n CesiumMath.EPSILON8\r\n )\r\n ) {\r\n return;\r\n }\r\n\r\n // Can be solved using the same equations from interpolateUsingSurfaceDistance\r\n var sigma1 = calculateSigma(ellipticity, start.latitude);\r\n var sigma2 = calculateSigma(ellipticity, intersectionLatitude);\r\n var deltaLongitude = Math.tan(heading) * (sigma2 - sigma1);\r\n var longitude = CesiumMath.negativePiToPi(start.longitude + deltaLongitude);\r\n\r\n if (defined(result)) {\r\n result.longitude = longitude;\r\n result.latitude = intersectionLatitude;\r\n result.height = 0;\r\n\r\n return result;\r\n }\r\n\r\n return new Cartographic(longitude, intersectionLatitude, 0);\r\n};\r\nexport default EllipsoidRhumbLine;\r\n","function earcut(data, holeIndices, dim) {\r\n\r\n dim = dim || 2;\r\n\r\n var hasHoles = holeIndices && holeIndices.length,\r\n outerLen = hasHoles ? holeIndices[0] * dim : data.length,\r\n outerNode = linkedList(data, 0, outerLen, dim, true),\r\n triangles = [];\r\n\r\n if (!outerNode || outerNode.next === outerNode.prev) return triangles;\r\n\r\n var minX, minY, maxX, maxY, x, y, invSize;\r\n\r\n if (hasHoles) outerNode = eliminateHoles(data, holeIndices, outerNode, dim);\r\n\r\n // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox\r\n if (data.length > 80 * dim) {\r\n minX = maxX = data[0];\r\n minY = maxY = data[1];\r\n\r\n for (var i = dim; i < outerLen; i += dim) {\r\n x = data[i];\r\n y = data[i + 1];\r\n if (x < minX) minX = x;\r\n if (y < minY) minY = y;\r\n if (x > maxX) maxX = x;\r\n if (y > maxY) maxY = y;\r\n }\r\n\r\n // minX, minY and invSize are later used to transform coords into integers for z-order calculation\r\n invSize = Math.max(maxX - minX, maxY - minY);\r\n invSize = invSize !== 0 ? 1 / invSize : 0;\r\n }\r\n\r\n earcutLinked(outerNode, triangles, dim, minX, minY, invSize);\r\n\r\n return triangles;\r\n}\r\n\r\n// create a circular doubly linked list from polygon points in the specified winding order\r\nfunction linkedList(data, start, end, dim, clockwise) {\r\n var i, last;\r\n\r\n if (clockwise === (signedArea(data, start, end, dim) > 0)) {\r\n for (i = start; i < end; i += dim) last = insertNode(i, data[i], data[i + 1], last);\r\n } else {\r\n for (i = end - dim; i >= start; i -= dim) last = insertNode(i, data[i], data[i + 1], last);\r\n }\r\n\r\n if (last && equals(last, last.next)) {\r\n removeNode(last);\r\n last = last.next;\r\n }\r\n\r\n return last;\r\n}\r\n\r\n// eliminate colinear or duplicate points\r\nfunction filterPoints(start, end) {\r\n if (!start) return start;\r\n if (!end) end = start;\r\n\r\n var p = start,\r\n again;\r\n do {\r\n again = false;\r\n\r\n if (!p.steiner && (equals(p, p.next) || area(p.prev, p, p.next) === 0)) {\r\n removeNode(p);\r\n p = end = p.prev;\r\n if (p === p.next) break;\r\n again = true;\r\n\r\n } else {\r\n p = p.next;\r\n }\r\n } while (again || p !== end);\r\n\r\n return end;\r\n}\r\n\r\n// main ear slicing loop which triangulates a polygon (given as a linked list)\r\nfunction earcutLinked(ear, triangles, dim, minX, minY, invSize, pass) {\r\n if (!ear) return;\r\n\r\n // interlink polygon nodes in z-order\r\n if (!pass && invSize) indexCurve(ear, minX, minY, invSize);\r\n\r\n var stop = ear,\r\n prev, next;\r\n\r\n // iterate through ears, slicing them one by one\r\n while (ear.prev !== ear.next) {\r\n prev = ear.prev;\r\n next = ear.next;\r\n\r\n if (invSize ? isEarHashed(ear, minX, minY, invSize) : isEar(ear)) {\r\n // cut off the triangle\r\n triangles.push(prev.i / dim);\r\n triangles.push(ear.i / dim);\r\n triangles.push(next.i / dim);\r\n\r\n removeNode(ear);\r\n\r\n // skipping the next vertex leads to less sliver triangles\r\n ear = next.next;\r\n stop = next.next;\r\n\r\n continue;\r\n }\r\n\r\n ear = next;\r\n\r\n // if we looped through the whole remaining polygon and can't find any more ears\r\n if (ear === stop) {\r\n // try filtering points and slicing again\r\n if (!pass) {\r\n earcutLinked(filterPoints(ear), triangles, dim, minX, minY, invSize, 1);\r\n\r\n // if this didn't work, try curing all small self-intersections locally\r\n } else if (pass === 1) {\r\n ear = cureLocalIntersections(filterPoints(ear), triangles, dim);\r\n earcutLinked(ear, triangles, dim, minX, minY, invSize, 2);\r\n\r\n // as a last resort, try splitting the remaining polygon into two\r\n } else if (pass === 2) {\r\n splitEarcut(ear, triangles, dim, minX, minY, invSize);\r\n }\r\n\r\n break;\r\n }\r\n }\r\n}\r\n\r\n// check whether a polygon node forms a valid ear with adjacent nodes\r\nfunction isEar(ear) {\r\n var a = ear.prev,\r\n b = ear,\r\n c = ear.next;\r\n\r\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\r\n\r\n // now make sure we don't have other points inside the potential ear\r\n var p = ear.next.next;\r\n\r\n while (p !== ear.prev) {\r\n if (pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&\r\n area(p.prev, p, p.next) >= 0) return false;\r\n p = p.next;\r\n }\r\n\r\n return true;\r\n}\r\n\r\nfunction isEarHashed(ear, minX, minY, invSize) {\r\n var a = ear.prev,\r\n b = ear,\r\n c = ear.next;\r\n\r\n if (area(a, b, c) >= 0) return false; // reflex, can't be an ear\r\n\r\n // triangle bbox; min & max are calculated like this for speed\r\n var minTX = a.x < b.x ? (a.x < c.x ? a.x : c.x) : (b.x < c.x ? b.x : c.x),\r\n minTY = a.y < b.y ? (a.y < c.y ? a.y : c.y) : (b.y < c.y ? b.y : c.y),\r\n maxTX = a.x > b.x ? (a.x > c.x ? a.x : c.x) : (b.x > c.x ? b.x : c.x),\r\n maxTY = a.y > b.y ? (a.y > c.y ? a.y : c.y) : (b.y > c.y ? b.y : c.y);\r\n\r\n // z-order range for the current triangle bbox;\r\n var minZ = zOrder(minTX, minTY, minX, minY, invSize),\r\n maxZ = zOrder(maxTX, maxTY, minX, minY, invSize);\r\n\r\n var p = ear.prevZ,\r\n n = ear.nextZ;\r\n\r\n // look for points inside the triangle in both directions\r\n while (p && p.z >= minZ && n && n.z <= maxZ) {\r\n if (p !== ear.prev && p !== ear.next &&\r\n pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&\r\n area(p.prev, p, p.next) >= 0) return false;\r\n p = p.prevZ;\r\n\r\n if (n !== ear.prev && n !== ear.next &&\r\n pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) &&\r\n area(n.prev, n, n.next) >= 0) return false;\r\n n = n.nextZ;\r\n }\r\n\r\n // look for remaining points in decreasing z-order\r\n while (p && p.z >= minZ) {\r\n if (p !== ear.prev && p !== ear.next &&\r\n pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y) &&\r\n area(p.prev, p, p.next) >= 0) return false;\r\n p = p.prevZ;\r\n }\r\n\r\n // look for remaining points in increasing z-order\r\n while (n && n.z <= maxZ) {\r\n if (n !== ear.prev && n !== ear.next &&\r\n pointInTriangle(a.x, a.y, b.x, b.y, c.x, c.y, n.x, n.y) &&\r\n area(n.prev, n, n.next) >= 0) return false;\r\n n = n.nextZ;\r\n }\r\n\r\n return true;\r\n}\r\n\r\n// go through all polygon nodes and cure small local self-intersections\r\nfunction cureLocalIntersections(start, triangles, dim) {\r\n var p = start;\r\n do {\r\n var a = p.prev,\r\n b = p.next.next;\r\n\r\n if (!equals(a, b) && intersects(a, p, p.next, b) && locallyInside(a, b) && locallyInside(b, a)) {\r\n\r\n triangles.push(a.i / dim);\r\n triangles.push(p.i / dim);\r\n triangles.push(b.i / dim);\r\n\r\n // remove two nodes involved\r\n removeNode(p);\r\n removeNode(p.next);\r\n\r\n p = start = b;\r\n }\r\n p = p.next;\r\n } while (p !== start);\r\n\r\n return filterPoints(p);\r\n}\r\n\r\n// try splitting polygon into two and triangulate them independently\r\nfunction splitEarcut(start, triangles, dim, minX, minY, invSize) {\r\n // look for a valid diagonal that divides the polygon into two\r\n var a = start;\r\n do {\r\n var b = a.next.next;\r\n while (b !== a.prev) {\r\n if (a.i !== b.i && isValidDiagonal(a, b)) {\r\n // split the polygon in two by the diagonal\r\n var c = splitPolygon(a, b);\r\n\r\n // filter colinear points around the cuts\r\n a = filterPoints(a, a.next);\r\n c = filterPoints(c, c.next);\r\n\r\n // run earcut on each half\r\n earcutLinked(a, triangles, dim, minX, minY, invSize);\r\n earcutLinked(c, triangles, dim, minX, minY, invSize);\r\n return;\r\n }\r\n b = b.next;\r\n }\r\n a = a.next;\r\n } while (a !== start);\r\n}\r\n\r\n// link every hole into the outer loop, producing a single-ring polygon without holes\r\nfunction eliminateHoles(data, holeIndices, outerNode, dim) {\r\n var queue = [],\r\n i, len, start, end, list;\r\n\r\n for (i = 0, len = holeIndices.length; i < len; i++) {\r\n start = holeIndices[i] * dim;\r\n end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\r\n list = linkedList(data, start, end, dim, false);\r\n if (list === list.next) list.steiner = true;\r\n queue.push(getLeftmost(list));\r\n }\r\n\r\n queue.sort(compareX);\r\n\r\n // process holes from left to right\r\n for (i = 0; i < queue.length; i++) {\r\n eliminateHole(queue[i], outerNode);\r\n outerNode = filterPoints(outerNode, outerNode.next);\r\n }\r\n\r\n return outerNode;\r\n}\r\n\r\nfunction compareX(a, b) {\r\n return a.x - b.x;\r\n}\r\n\r\n// find a bridge between vertices that connects hole with an outer ring and and link it\r\nfunction eliminateHole(hole, outerNode) {\r\n outerNode = findHoleBridge(hole, outerNode);\r\n if (outerNode) {\r\n var b = splitPolygon(outerNode, hole);\r\n filterPoints(b, b.next);\r\n }\r\n}\r\n\r\n// David Eberly's algorithm for finding a bridge between hole and outer polygon\r\nfunction findHoleBridge(hole, outerNode) {\r\n var p = outerNode,\r\n hx = hole.x,\r\n hy = hole.y,\r\n qx = -Infinity,\r\n m;\r\n\r\n // find a segment intersected by a ray from the hole's leftmost point to the left;\r\n // segment's endpoint with lesser x will be potential connection point\r\n do {\r\n if (hy <= p.y && hy >= p.next.y && p.next.y !== p.y) {\r\n var x = p.x + (hy - p.y) * (p.next.x - p.x) / (p.next.y - p.y);\r\n if (x <= hx && x > qx) {\r\n qx = x;\r\n if (x === hx) {\r\n if (hy === p.y) return p;\r\n if (hy === p.next.y) return p.next;\r\n }\r\n m = p.x < p.next.x ? p : p.next;\r\n }\r\n }\r\n p = p.next;\r\n } while (p !== outerNode);\r\n\r\n if (!m) return null;\r\n\r\n if (hx === qx) return m; // hole touches outer segment; pick leftmost endpoint\r\n\r\n // look for points inside the triangle of hole point, segment intersection and endpoint;\r\n // if there are no points found, we have a valid connection;\r\n // otherwise choose the point of the minimum angle with the ray as connection point\r\n\r\n var stop = m,\r\n mx = m.x,\r\n my = m.y,\r\n tanMin = Infinity,\r\n tan;\r\n\r\n p = m;\r\n\r\n do {\r\n if (hx >= p.x && p.x >= mx && hx !== p.x &&\r\n pointInTriangle(hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y)) {\r\n\r\n tan = Math.abs(hy - p.y) / (hx - p.x); // tangential\r\n\r\n if (locallyInside(p, hole) &&\r\n (tan < tanMin || (tan === tanMin && (p.x > m.x || (p.x === m.x && sectorContainsSector(m, p)))))) {\r\n m = p;\r\n tanMin = tan;\r\n }\r\n }\r\n\r\n p = p.next;\r\n } while (p !== stop);\r\n\r\n return m;\r\n}\r\n\r\n// whether sector in vertex m contains sector in vertex p in the same coordinates\r\nfunction sectorContainsSector(m, p) {\r\n return area(m.prev, m, p.prev) < 0 && area(p.next, m, m.next) < 0;\r\n}\r\n\r\n// interlink polygon nodes in z-order\r\nfunction indexCurve(start, minX, minY, invSize) {\r\n var p = start;\r\n do {\r\n if (p.z === null) p.z = zOrder(p.x, p.y, minX, minY, invSize);\r\n p.prevZ = p.prev;\r\n p.nextZ = p.next;\r\n p = p.next;\r\n } while (p !== start);\r\n\r\n p.prevZ.nextZ = null;\r\n p.prevZ = null;\r\n\r\n sortLinked(p);\r\n}\r\n\r\n// Simon Tatham's linked list merge sort algorithm\r\n// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html\r\nfunction sortLinked(list) {\r\n var i, p, q, e, tail, numMerges, pSize, qSize,\r\n inSize = 1;\r\n\r\n do {\r\n p = list;\r\n list = null;\r\n tail = null;\r\n numMerges = 0;\r\n\r\n while (p) {\r\n numMerges++;\r\n q = p;\r\n pSize = 0;\r\n for (i = 0; i < inSize; i++) {\r\n pSize++;\r\n q = q.nextZ;\r\n if (!q) break;\r\n }\r\n qSize = inSize;\r\n\r\n while (pSize > 0 || (qSize > 0 && q)) {\r\n\r\n if (pSize !== 0 && (qSize === 0 || !q || p.z <= q.z)) {\r\n e = p;\r\n p = p.nextZ;\r\n pSize--;\r\n } else {\r\n e = q;\r\n q = q.nextZ;\r\n qSize--;\r\n }\r\n\r\n if (tail) tail.nextZ = e;\r\n else list = e;\r\n\r\n e.prevZ = tail;\r\n tail = e;\r\n }\r\n\r\n p = q;\r\n }\r\n\r\n tail.nextZ = null;\r\n inSize *= 2;\r\n\r\n } while (numMerges > 1);\r\n\r\n return list;\r\n}\r\n\r\n// z-order of a point given coords and inverse of the longer side of data bbox\r\nfunction zOrder(x, y, minX, minY, invSize) {\r\n // coords are transformed into non-negative 15-bit integer range\r\n x = 32767 * (x - minX) * invSize;\r\n y = 32767 * (y - minY) * invSize;\r\n\r\n x = (x | (x << 8)) & 0x00FF00FF;\r\n x = (x | (x << 4)) & 0x0F0F0F0F;\r\n x = (x | (x << 2)) & 0x33333333;\r\n x = (x | (x << 1)) & 0x55555555;\r\n\r\n y = (y | (y << 8)) & 0x00FF00FF;\r\n y = (y | (y << 4)) & 0x0F0F0F0F;\r\n y = (y | (y << 2)) & 0x33333333;\r\n y = (y | (y << 1)) & 0x55555555;\r\n\r\n return x | (y << 1);\r\n}\r\n\r\n// find the leftmost node of a polygon ring\r\nfunction getLeftmost(start) {\r\n var p = start,\r\n leftmost = start;\r\n do {\r\n if (p.x < leftmost.x || (p.x === leftmost.x && p.y < leftmost.y)) leftmost = p;\r\n p = p.next;\r\n } while (p !== start);\r\n\r\n return leftmost;\r\n}\r\n\r\n// check if a point lies within a convex triangle\r\nfunction pointInTriangle(ax, ay, bx, by, cx, cy, px, py) {\r\n return (cx - px) * (ay - py) - (ax - px) * (cy - py) >= 0 &&\r\n (ax - px) * (by - py) - (bx - px) * (ay - py) >= 0 &&\r\n (bx - px) * (cy - py) - (cx - px) * (by - py) >= 0;\r\n}\r\n\r\n// check if a diagonal between two polygon nodes is valid (lies in polygon interior)\r\nfunction isValidDiagonal(a, b) {\r\n return a.next.i !== b.i && a.prev.i !== b.i && !intersectsPolygon(a, b) && // dones't intersect other edges\r\n (locallyInside(a, b) && locallyInside(b, a) && middleInside(a, b) && // locally visible\r\n (area(a.prev, a, b.prev) || area(a, b.prev, b)) || // does not create opposite-facing sectors\r\n equals(a, b) && area(a.prev, a, a.next) > 0 && area(b.prev, b, b.next) > 0); // special zero-length case\r\n}\r\n\r\n// signed area of a triangle\r\nfunction area(p, q, r) {\r\n return (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);\r\n}\r\n\r\n// check if two points are equal\r\nfunction equals(p1, p2) {\r\n return p1.x === p2.x && p1.y === p2.y;\r\n}\r\n\r\n// check if two segments intersect\r\nfunction intersects(p1, q1, p2, q2) {\r\n var o1 = sign(area(p1, q1, p2));\r\n var o2 = sign(area(p1, q1, q2));\r\n var o3 = sign(area(p2, q2, p1));\r\n var o4 = sign(area(p2, q2, q1));\r\n\r\n if (o1 !== o2 && o3 !== o4) return true; // general case\r\n\r\n if (o1 === 0 && onSegment(p1, p2, q1)) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1\r\n if (o2 === 0 && onSegment(p1, q2, q1)) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1\r\n if (o3 === 0 && onSegment(p2, p1, q2)) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2\r\n if (o4 === 0 && onSegment(p2, q1, q2)) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2\r\n\r\n return false;\r\n}\r\n\r\n// for collinear points p, q, r, check if point q lies on segment pr\r\nfunction onSegment(p, q, r) {\r\n return q.x <= Math.max(p.x, r.x) && q.x >= Math.min(p.x, r.x) && q.y <= Math.max(p.y, r.y) && q.y >= Math.min(p.y, r.y);\r\n}\r\n\r\nfunction sign(num) {\r\n return num > 0 ? 1 : num < 0 ? -1 : 0;\r\n}\r\n\r\n// check if a polygon diagonal intersects any polygon segments\r\nfunction intersectsPolygon(a, b) {\r\n var p = a;\r\n do {\r\n if (p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i &&\r\n intersects(p, p.next, a, b)) return true;\r\n p = p.next;\r\n } while (p !== a);\r\n\r\n return false;\r\n}\r\n\r\n// check if a polygon diagonal is locally inside the polygon\r\nfunction locallyInside(a, b) {\r\n return area(a.prev, a, a.next) < 0 ?\r\n area(a, b, a.next) >= 0 && area(a, a.prev, b) >= 0 :\r\n area(a, b, a.prev) < 0 || area(a, a.next, b) < 0;\r\n}\r\n\r\n// check if the middle point of a polygon diagonal is inside the polygon\r\nfunction middleInside(a, b) {\r\n var p = a,\r\n inside = false,\r\n px = (a.x + b.x) / 2,\r\n py = (a.y + b.y) / 2;\r\n do {\r\n if (((p.y > py) !== (p.next.y > py)) && p.next.y !== p.y &&\r\n (px < (p.next.x - p.x) * (py - p.y) / (p.next.y - p.y) + p.x))\r\n inside = !inside;\r\n p = p.next;\r\n } while (p !== a);\r\n\r\n return inside;\r\n}\r\n\r\n// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two;\r\n// if one belongs to the outer ring and another to a hole, it merges it into a single ring\r\nfunction splitPolygon(a, b) {\r\n var a2 = new Node(a.i, a.x, a.y),\r\n b2 = new Node(b.i, b.x, b.y),\r\n an = a.next,\r\n bp = b.prev;\r\n\r\n a.next = b;\r\n b.prev = a;\r\n\r\n a2.next = an;\r\n an.prev = a2;\r\n\r\n b2.next = a2;\r\n a2.prev = b2;\r\n\r\n bp.next = b2;\r\n b2.prev = bp;\r\n\r\n return b2;\r\n}\r\n\r\n// create a node and optionally link it with previous one (in a circular doubly linked list)\r\nfunction insertNode(i, x, y, last) {\r\n var p = new Node(i, x, y);\r\n\r\n if (!last) {\r\n p.prev = p;\r\n p.next = p;\r\n\r\n } else {\r\n p.next = last.next;\r\n p.prev = last;\r\n last.next.prev = p;\r\n last.next = p;\r\n }\r\n return p;\r\n}\r\n\r\nfunction removeNode(p) {\r\n p.next.prev = p.prev;\r\n p.prev.next = p.next;\r\n\r\n if (p.prevZ) p.prevZ.nextZ = p.nextZ;\r\n if (p.nextZ) p.nextZ.prevZ = p.prevZ;\r\n}\r\n\r\nfunction Node(i, x, y) {\r\n // vertex index in coordinates array\r\n this.i = i;\r\n\r\n // vertex coordinates\r\n this.x = x;\r\n this.y = y;\r\n\r\n // previous and next vertex nodes in a polygon ring\r\n this.prev = null;\r\n this.next = null;\r\n\r\n // z-order curve value\r\n this.z = null;\r\n\r\n // previous and next nodes in z-order\r\n this.prevZ = null;\r\n this.nextZ = null;\r\n\r\n // indicates whether this is a steiner point\r\n this.steiner = false;\r\n}\r\n\r\n// return a percentage difference between the polygon area and its triangulation area;\r\n// used to verify correctness of triangulation\r\nearcut.deviation = function (data, holeIndices, dim, triangles) {\r\n var hasHoles = holeIndices && holeIndices.length;\r\n var outerLen = hasHoles ? holeIndices[0] * dim : data.length;\r\n\r\n var polygonArea = Math.abs(signedArea(data, 0, outerLen, dim));\r\n if (hasHoles) {\r\n for (var i = 0, len = holeIndices.length; i < len; i++) {\r\n var start = holeIndices[i] * dim;\r\n var end = i < len - 1 ? holeIndices[i + 1] * dim : data.length;\r\n polygonArea -= Math.abs(signedArea(data, start, end, dim));\r\n }\r\n }\r\n\r\n var trianglesArea = 0;\r\n for (i = 0; i < triangles.length; i += 3) {\r\n var a = triangles[i] * dim;\r\n var b = triangles[i + 1] * dim;\r\n var c = triangles[i + 2] * dim;\r\n trianglesArea += Math.abs(\r\n (data[a] - data[c]) * (data[b + 1] - data[a + 1]) -\r\n (data[a] - data[b]) * (data[c + 1] - data[a + 1]));\r\n }\r\n\r\n return polygonArea === 0 && trianglesArea === 0 ? 0 :\r\n Math.abs((trianglesArea - polygonArea) / polygonArea);\r\n};\r\n\r\nfunction signedArea(data, start, end, dim) {\r\n var sum = 0;\r\n for (var i = start, j = end - dim; i < end; i += dim) {\r\n sum += (data[j] - data[i]) * (data[i + 1] + data[j + 1]);\r\n j = i;\r\n }\r\n return sum;\r\n}\r\n\r\n// turn a polygon in a multi-dimensional array form (e.g. as in GeoJSON) into a form Earcut accepts\r\nearcut.flatten = function (data) {\r\n var dim = data[0][0].length,\r\n result = {vertices: [], holes: [], dimensions: dim},\r\n holeIndex = 0;\r\n\r\n for (var i = 0; i < data.length; i++) {\r\n for (var j = 0; j < data[i].length; j++) {\r\n for (var d = 0; d < dim; d++) result.vertices.push(data[i][j][d]);\r\n }\r\n if (i > 0) {\r\n holeIndex += data[i - 1].length;\r\n result.holes.push(holeIndex);\r\n }\r\n }\r\n return result;\r\n};\r\n\r\nexport default earcut;\r\n","import WebGLConstants from \"./WebGLConstants.js\";\r\n\r\n/**\r\n * Winding order defines the order of vertices for a triangle to be considered front-facing.\r\n *\r\n * @enum {Number}\r\n */\r\nvar WindingOrder = {\r\n /**\r\n * Vertices are in clockwise order.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CLOCKWISE: WebGLConstants.CW,\r\n\r\n /**\r\n * Vertices are in counter-clockwise order.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n COUNTER_CLOCKWISE: WebGLConstants.CCW,\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nWindingOrder.validate = function (windingOrder) {\r\n return (\r\n windingOrder === WindingOrder.CLOCKWISE ||\r\n windingOrder === WindingOrder.COUNTER_CLOCKWISE\r\n );\r\n};\r\n\r\nexport default Object.freeze(WindingOrder);\r\n","import earcut from \"../ThirdParty/earcut-2.2.1.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport EllipsoidRhumbLine from \"./EllipsoidRhumbLine.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport WindingOrder from \"./WindingOrder.js\";\r\n\r\nvar scaleToGeodeticHeightN = new Cartesian3();\r\nvar scaleToGeodeticHeightP = new Cartesian3();\r\n\r\n/**\r\n * @private\r\n */\r\nvar PolygonPipeline = {};\r\n\r\n/**\r\n * @exception {DeveloperError} At least three positions are required.\r\n */\r\nPolygonPipeline.computeArea2D = function (positions) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"positions\", positions);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"positions.length\",\r\n positions.length,\r\n 3\r\n );\r\n //>>includeEnd('debug');\r\n\r\n var length = positions.length;\r\n var area = 0.0;\r\n\r\n for (var i0 = length - 1, i1 = 0; i1 < length; i0 = i1++) {\r\n var v0 = positions[i0];\r\n var v1 = positions[i1];\r\n\r\n area += v0.x * v1.y - v1.x * v0.y;\r\n }\r\n\r\n return area * 0.5;\r\n};\r\n\r\n/**\r\n * @returns {WindingOrder} The winding order.\r\n *\r\n * @exception {DeveloperError} At least three positions are required.\r\n */\r\nPolygonPipeline.computeWindingOrder2D = function (positions) {\r\n var area = PolygonPipeline.computeArea2D(positions);\r\n return area > 0.0 ? WindingOrder.COUNTER_CLOCKWISE : WindingOrder.CLOCKWISE;\r\n};\r\n\r\n/**\r\n * Triangulate a polygon.\r\n *\r\n * @param {Cartesian2[]} positions Cartesian2 array containing the vertices of the polygon\r\n * @param {Number[]} [holes] An array of the staring indices of the holes.\r\n * @returns {Number[]} Index array representing triangles that fill the polygon\r\n */\r\nPolygonPipeline.triangulate = function (positions, holes) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"positions\", positions);\r\n //>>includeEnd('debug');\r\n\r\n var flattenedPositions = Cartesian2.packArray(positions);\r\n return earcut(flattenedPositions, holes, 2);\r\n};\r\n\r\nvar subdivisionV0Scratch = new Cartesian3();\r\nvar subdivisionV1Scratch = new Cartesian3();\r\nvar subdivisionV2Scratch = new Cartesian3();\r\nvar subdivisionS0Scratch = new Cartesian3();\r\nvar subdivisionS1Scratch = new Cartesian3();\r\nvar subdivisionS2Scratch = new Cartesian3();\r\nvar subdivisionMidScratch = new Cartesian3();\r\n\r\n/**\r\n * Subdivides positions and raises points to the surface of the ellipsoid.\r\n *\r\n * @param {Ellipsoid} ellipsoid The ellipsoid the polygon in on.\r\n * @param {Cartesian3[]} positions An array of {@link Cartesian3} positions of the polygon.\r\n * @param {Number[]} indices An array of indices that determines the triangles in the polygon.\r\n * @param {Number} [granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n *\r\n * @exception {DeveloperError} At least three indices are required.\r\n * @exception {DeveloperError} The number of indices must be divisable by three.\r\n * @exception {DeveloperError} Granularity must be greater than zero.\r\n */\r\nPolygonPipeline.computeSubdivision = function (\r\n ellipsoid,\r\n positions,\r\n indices,\r\n granularity\r\n) {\r\n granularity = defaultValue(granularity, CesiumMath.RADIANS_PER_DEGREE);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"ellipsoid\", ellipsoid);\r\n Check.defined(\"positions\", positions);\r\n Check.defined(\"indices\", indices);\r\n Check.typeOf.number.greaterThanOrEquals(\"indices.length\", indices.length, 3);\r\n Check.typeOf.number.equals(\"indices.length % 3\", \"0\", indices.length % 3, 0);\r\n Check.typeOf.number.greaterThan(\"granularity\", granularity, 0.0);\r\n //>>includeEnd('debug');\r\n\r\n // triangles that need (or might need) to be subdivided.\r\n var triangles = indices.slice(0);\r\n\r\n // New positions due to edge splits are appended to the positions list.\r\n var i;\r\n var length = positions.length;\r\n var subdividedPositions = new Array(length * 3);\r\n var q = 0;\r\n for (i = 0; i < length; i++) {\r\n var item = positions[i];\r\n subdividedPositions[q++] = item.x;\r\n subdividedPositions[q++] = item.y;\r\n subdividedPositions[q++] = item.z;\r\n }\r\n\r\n var subdividedIndices = [];\r\n\r\n // Used to make sure shared edges are not split more than once.\r\n var edges = {};\r\n\r\n var radius = ellipsoid.maximumRadius;\r\n var minDistance = CesiumMath.chordLength(granularity, radius);\r\n var minDistanceSqrd = minDistance * minDistance;\r\n\r\n while (triangles.length > 0) {\r\n var i2 = triangles.pop();\r\n var i1 = triangles.pop();\r\n var i0 = triangles.pop();\r\n\r\n var v0 = Cartesian3.fromArray(\r\n subdividedPositions,\r\n i0 * 3,\r\n subdivisionV0Scratch\r\n );\r\n var v1 = Cartesian3.fromArray(\r\n subdividedPositions,\r\n i1 * 3,\r\n subdivisionV1Scratch\r\n );\r\n var v2 = Cartesian3.fromArray(\r\n subdividedPositions,\r\n i2 * 3,\r\n subdivisionV2Scratch\r\n );\r\n\r\n var s0 = Cartesian3.multiplyByScalar(\r\n Cartesian3.normalize(v0, subdivisionS0Scratch),\r\n radius,\r\n subdivisionS0Scratch\r\n );\r\n var s1 = Cartesian3.multiplyByScalar(\r\n Cartesian3.normalize(v1, subdivisionS1Scratch),\r\n radius,\r\n subdivisionS1Scratch\r\n );\r\n var s2 = Cartesian3.multiplyByScalar(\r\n Cartesian3.normalize(v2, subdivisionS2Scratch),\r\n radius,\r\n subdivisionS2Scratch\r\n );\r\n\r\n var g0 = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(s0, s1, subdivisionMidScratch)\r\n );\r\n var g1 = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(s1, s2, subdivisionMidScratch)\r\n );\r\n var g2 = Cartesian3.magnitudeSquared(\r\n Cartesian3.subtract(s2, s0, subdivisionMidScratch)\r\n );\r\n\r\n var max = Math.max(g0, g1, g2);\r\n var edge;\r\n var mid;\r\n\r\n // if the max length squared of a triangle edge is greater than the chord length of squared\r\n // of the granularity, subdivide the triangle\r\n if (max > minDistanceSqrd) {\r\n if (g0 === max) {\r\n edge = Math.min(i0, i1) + \" \" + Math.max(i0, i1);\r\n\r\n i = edges[edge];\r\n if (!defined(i)) {\r\n mid = Cartesian3.add(v0, v1, subdivisionMidScratch);\r\n Cartesian3.multiplyByScalar(mid, 0.5, mid);\r\n subdividedPositions.push(mid.x, mid.y, mid.z);\r\n i = subdividedPositions.length / 3 - 1;\r\n edges[edge] = i;\r\n }\r\n\r\n triangles.push(i0, i, i2);\r\n triangles.push(i, i1, i2);\r\n } else if (g1 === max) {\r\n edge = Math.min(i1, i2) + \" \" + Math.max(i1, i2);\r\n\r\n i = edges[edge];\r\n if (!defined(i)) {\r\n mid = Cartesian3.add(v1, v2, subdivisionMidScratch);\r\n Cartesian3.multiplyByScalar(mid, 0.5, mid);\r\n subdividedPositions.push(mid.x, mid.y, mid.z);\r\n i = subdividedPositions.length / 3 - 1;\r\n edges[edge] = i;\r\n }\r\n\r\n triangles.push(i1, i, i0);\r\n triangles.push(i, i2, i0);\r\n } else if (g2 === max) {\r\n edge = Math.min(i2, i0) + \" \" + Math.max(i2, i0);\r\n\r\n i = edges[edge];\r\n if (!defined(i)) {\r\n mid = Cartesian3.add(v2, v0, subdivisionMidScratch);\r\n Cartesian3.multiplyByScalar(mid, 0.5, mid);\r\n subdividedPositions.push(mid.x, mid.y, mid.z);\r\n i = subdividedPositions.length / 3 - 1;\r\n edges[edge] = i;\r\n }\r\n\r\n triangles.push(i2, i, i1);\r\n triangles.push(i, i0, i1);\r\n }\r\n } else {\r\n subdividedIndices.push(i0);\r\n subdividedIndices.push(i1);\r\n subdividedIndices.push(i2);\r\n }\r\n }\r\n\r\n return new Geometry({\r\n attributes: {\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: subdividedPositions,\r\n }),\r\n },\r\n indices: subdividedIndices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n};\r\n\r\nvar subdivisionC0Scratch = new Cartographic();\r\nvar subdivisionC1Scratch = new Cartographic();\r\nvar subdivisionC2Scratch = new Cartographic();\r\nvar subdivisionCartographicScratch = new Cartographic();\r\n\r\n/**\r\n * Subdivides positions on rhumb lines and raises points to the surface of the ellipsoid.\r\n *\r\n * @param {Ellipsoid} ellipsoid The ellipsoid the polygon in on.\r\n * @param {Cartesian3[]} positions An array of {@link Cartesian3} positions of the polygon.\r\n * @param {Number[]} indices An array of indices that determines the triangles in the polygon.\r\n * @param {Number} [granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n *\r\n * @exception {DeveloperError} At least three indices are required.\r\n * @exception {DeveloperError} The number of indices must be divisable by three.\r\n * @exception {DeveloperError} Granularity must be greater than zero.\r\n */\r\nPolygonPipeline.computeRhumbLineSubdivision = function (\r\n ellipsoid,\r\n positions,\r\n indices,\r\n granularity\r\n) {\r\n granularity = defaultValue(granularity, CesiumMath.RADIANS_PER_DEGREE);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"ellipsoid\", ellipsoid);\r\n Check.defined(\"positions\", positions);\r\n Check.defined(\"indices\", indices);\r\n Check.typeOf.number.greaterThanOrEquals(\"indices.length\", indices.length, 3);\r\n Check.typeOf.number.equals(\"indices.length % 3\", \"0\", indices.length % 3, 0);\r\n Check.typeOf.number.greaterThan(\"granularity\", granularity, 0.0);\r\n //>>includeEnd('debug');\r\n\r\n // triangles that need (or might need) to be subdivided.\r\n var triangles = indices.slice(0);\r\n\r\n // New positions due to edge splits are appended to the positions list.\r\n var i;\r\n var length = positions.length;\r\n var subdividedPositions = new Array(length * 3);\r\n var q = 0;\r\n for (i = 0; i < length; i++) {\r\n var item = positions[i];\r\n subdividedPositions[q++] = item.x;\r\n subdividedPositions[q++] = item.y;\r\n subdividedPositions[q++] = item.z;\r\n }\r\n\r\n var subdividedIndices = [];\r\n\r\n // Used to make sure shared edges are not split more than once.\r\n var edges = {};\r\n\r\n var radius = ellipsoid.maximumRadius;\r\n var minDistance = CesiumMath.chordLength(granularity, radius);\r\n\r\n var rhumb0 = new EllipsoidRhumbLine(undefined, undefined, ellipsoid);\r\n var rhumb1 = new EllipsoidRhumbLine(undefined, undefined, ellipsoid);\r\n var rhumb2 = new EllipsoidRhumbLine(undefined, undefined, ellipsoid);\r\n\r\n while (triangles.length > 0) {\r\n var i2 = triangles.pop();\r\n var i1 = triangles.pop();\r\n var i0 = triangles.pop();\r\n\r\n var v0 = Cartesian3.fromArray(\r\n subdividedPositions,\r\n i0 * 3,\r\n subdivisionV0Scratch\r\n );\r\n var v1 = Cartesian3.fromArray(\r\n subdividedPositions,\r\n i1 * 3,\r\n subdivisionV1Scratch\r\n );\r\n var v2 = Cartesian3.fromArray(\r\n subdividedPositions,\r\n i2 * 3,\r\n subdivisionV2Scratch\r\n );\r\n\r\n var c0 = ellipsoid.cartesianToCartographic(v0, subdivisionC0Scratch);\r\n var c1 = ellipsoid.cartesianToCartographic(v1, subdivisionC1Scratch);\r\n var c2 = ellipsoid.cartesianToCartographic(v2, subdivisionC2Scratch);\r\n\r\n rhumb0.setEndPoints(c0, c1);\r\n var g0 = rhumb0.surfaceDistance;\r\n rhumb1.setEndPoints(c1, c2);\r\n var g1 = rhumb1.surfaceDistance;\r\n rhumb2.setEndPoints(c2, c0);\r\n var g2 = rhumb2.surfaceDistance;\r\n\r\n var max = Math.max(g0, g1, g2);\r\n var edge;\r\n var mid;\r\n var midHeight;\r\n var midCartesian3;\r\n\r\n // if the max length squared of a triangle edge is greater than granularity, subdivide the triangle\r\n if (max > minDistance) {\r\n if (g0 === max) {\r\n edge = Math.min(i0, i1) + \" \" + Math.max(i0, i1);\r\n\r\n i = edges[edge];\r\n if (!defined(i)) {\r\n mid = rhumb0.interpolateUsingFraction(\r\n 0.5,\r\n subdivisionCartographicScratch\r\n );\r\n midHeight = (c0.height + c1.height) * 0.5;\r\n midCartesian3 = Cartesian3.fromRadians(\r\n mid.longitude,\r\n mid.latitude,\r\n midHeight,\r\n ellipsoid,\r\n subdivisionMidScratch\r\n );\r\n subdividedPositions.push(\r\n midCartesian3.x,\r\n midCartesian3.y,\r\n midCartesian3.z\r\n );\r\n i = subdividedPositions.length / 3 - 1;\r\n edges[edge] = i;\r\n }\r\n\r\n triangles.push(i0, i, i2);\r\n triangles.push(i, i1, i2);\r\n } else if (g1 === max) {\r\n edge = Math.min(i1, i2) + \" \" + Math.max(i1, i2);\r\n\r\n i = edges[edge];\r\n if (!defined(i)) {\r\n mid = rhumb1.interpolateUsingFraction(\r\n 0.5,\r\n subdivisionCartographicScratch\r\n );\r\n midHeight = (c1.height + c2.height) * 0.5;\r\n midCartesian3 = Cartesian3.fromRadians(\r\n mid.longitude,\r\n mid.latitude,\r\n midHeight,\r\n ellipsoid,\r\n subdivisionMidScratch\r\n );\r\n subdividedPositions.push(\r\n midCartesian3.x,\r\n midCartesian3.y,\r\n midCartesian3.z\r\n );\r\n i = subdividedPositions.length / 3 - 1;\r\n edges[edge] = i;\r\n }\r\n\r\n triangles.push(i1, i, i0);\r\n triangles.push(i, i2, i0);\r\n } else if (g2 === max) {\r\n edge = Math.min(i2, i0) + \" \" + Math.max(i2, i0);\r\n\r\n i = edges[edge];\r\n if (!defined(i)) {\r\n mid = rhumb2.interpolateUsingFraction(\r\n 0.5,\r\n subdivisionCartographicScratch\r\n );\r\n midHeight = (c2.height + c0.height) * 0.5;\r\n midCartesian3 = Cartesian3.fromRadians(\r\n mid.longitude,\r\n mid.latitude,\r\n midHeight,\r\n ellipsoid,\r\n subdivisionMidScratch\r\n );\r\n subdividedPositions.push(\r\n midCartesian3.x,\r\n midCartesian3.y,\r\n midCartesian3.z\r\n );\r\n i = subdividedPositions.length / 3 - 1;\r\n edges[edge] = i;\r\n }\r\n\r\n triangles.push(i2, i, i1);\r\n triangles.push(i, i0, i1);\r\n }\r\n } else {\r\n subdividedIndices.push(i0);\r\n subdividedIndices.push(i1);\r\n subdividedIndices.push(i2);\r\n }\r\n }\r\n\r\n return new Geometry({\r\n attributes: {\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: subdividedPositions,\r\n }),\r\n },\r\n indices: subdividedIndices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n};\r\n\r\n/**\r\n * Scales each position of a geometry's position attribute to a height, in place.\r\n *\r\n * @param {Number[]} positions The array of numbers representing the positions to be scaled\r\n * @param {Number} [height=0.0] The desired height to add to the positions\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the positions lie.\r\n * @param {Boolean} [scaleToSurface=true] true if the positions need to be scaled to the surface before the height is added.\r\n * @returns {Number[]} The input array of positions, scaled to height\r\n */\r\nPolygonPipeline.scaleToGeodeticHeight = function (\r\n positions,\r\n height,\r\n ellipsoid,\r\n scaleToSurface\r\n) {\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n\r\n var n = scaleToGeodeticHeightN;\r\n var p = scaleToGeodeticHeightP;\r\n\r\n height = defaultValue(height, 0.0);\r\n scaleToSurface = defaultValue(scaleToSurface, true);\r\n\r\n if (defined(positions)) {\r\n var length = positions.length;\r\n\r\n for (var i = 0; i < length; i += 3) {\r\n Cartesian3.fromArray(positions, i, p);\r\n\r\n if (scaleToSurface) {\r\n p = ellipsoid.scaleToGeodeticSurface(p, p);\r\n }\r\n\r\n if (height !== 0) {\r\n n = ellipsoid.geodeticSurfaceNormal(p, n);\r\n\r\n Cartesian3.multiplyByScalar(n, height, n);\r\n Cartesian3.add(p, n, p);\r\n }\r\n\r\n positions[i] = p.x;\r\n positions[i + 1] = p.y;\r\n positions[i + 2] = p.z;\r\n }\r\n }\r\n\r\n return positions;\r\n};\r\nexport default PolygonPipeline;\r\n","/**\r\n * A queue that can enqueue items at the end, and dequeue items from the front.\r\n *\r\n * @alias Queue\r\n * @constructor\r\n */\r\nfunction Queue() {\r\n this._array = [];\r\n this._offset = 0;\r\n this._length = 0;\r\n}\r\n\r\nObject.defineProperties(Queue.prototype, {\r\n /**\r\n * The length of the queue.\r\n *\r\n * @memberof Queue.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._length;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Enqueues the specified item.\r\n *\r\n * @param {*} item The item to enqueue.\r\n */\r\nQueue.prototype.enqueue = function (item) {\r\n this._array.push(item);\r\n this._length++;\r\n};\r\n\r\n/**\r\n * Dequeues an item. Returns undefined if the queue is empty.\r\n *\r\n * @returns {*} The the dequeued item.\r\n */\r\nQueue.prototype.dequeue = function () {\r\n if (this._length === 0) {\r\n return undefined;\r\n }\r\n\r\n var array = this._array;\r\n var offset = this._offset;\r\n var item = array[offset];\r\n array[offset] = undefined;\r\n\r\n offset++;\r\n if (offset > 10 && offset * 2 > array.length) {\r\n //compact array\r\n this._array = array.slice(offset);\r\n offset = 0;\r\n }\r\n\r\n this._offset = offset;\r\n this._length--;\r\n\r\n return item;\r\n};\r\n\r\n/**\r\n * Returns the item at the front of the queue. Returns undefined if the queue is empty.\r\n *\r\n * @returns {*} The item at the front of the queue.\r\n */\r\nQueue.prototype.peek = function () {\r\n if (this._length === 0) {\r\n return undefined;\r\n }\r\n\r\n return this._array[this._offset];\r\n};\r\n\r\n/**\r\n * Check whether this queue contains the specified item.\r\n *\r\n * @param {*} item The item to search for.\r\n */\r\nQueue.prototype.contains = function (item) {\r\n return this._array.indexOf(item) !== -1;\r\n};\r\n\r\n/**\r\n * Remove all items from the queue.\r\n */\r\nQueue.prototype.clear = function () {\r\n this._array.length = this._offset = this._length = 0;\r\n};\r\n\r\n/**\r\n * Sort the items in the queue in-place.\r\n *\r\n * @param {Queue.Comparator} compareFunction A function that defines the sort order.\r\n */\r\nQueue.prototype.sort = function (compareFunction) {\r\n if (this._offset > 0) {\r\n //compact array\r\n this._array = this._array.slice(this._offset);\r\n this._offset = 0;\r\n }\r\n\r\n this._array.sort(compareFunction);\r\n};\r\n\r\n/**\r\n * A function used to compare two items while sorting a queue.\r\n * @callback Queue.Comparator\r\n *\r\n * @param {*} a An item in the array.\r\n * @param {*} b An item in the array.\r\n * @returns {Number} Returns a negative value if a is less than b,\r\n * a positive value if a is greater than b, or\r\n * 0 if a is equal to b.\r\n *\r\n * @example\r\n * function compareNumbers(a, b) {\r\n * return a - b;\r\n * }\r\n */\r\nexport default Queue;\r\n","import ArcType from \"./ArcType.js\";\r\nimport arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport EllipsoidRhumbLine from \"./EllipsoidRhumbLine.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryPipeline from \"./GeometryPipeline.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport Queue from \"./Queue.js\";\r\nimport WindingOrder from \"./WindingOrder.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar PolygonGeometryLibrary = {};\r\n\r\nPolygonGeometryLibrary.computeHierarchyPackedLength = function (\r\n polygonHierarchy\r\n) {\r\n var numComponents = 0;\r\n var stack = [polygonHierarchy];\r\n while (stack.length > 0) {\r\n var hierarchy = stack.pop();\r\n if (!defined(hierarchy)) {\r\n continue;\r\n }\r\n\r\n numComponents += 2;\r\n\r\n var positions = hierarchy.positions;\r\n var holes = hierarchy.holes;\r\n\r\n if (defined(positions)) {\r\n numComponents += positions.length * Cartesian3.packedLength;\r\n }\r\n\r\n if (defined(holes)) {\r\n var length = holes.length;\r\n for (var i = 0; i < length; ++i) {\r\n stack.push(holes[i]);\r\n }\r\n }\r\n }\r\n\r\n return numComponents;\r\n};\r\n\r\nPolygonGeometryLibrary.packPolygonHierarchy = function (\r\n polygonHierarchy,\r\n array,\r\n startingIndex\r\n) {\r\n var stack = [polygonHierarchy];\r\n while (stack.length > 0) {\r\n var hierarchy = stack.pop();\r\n if (!defined(hierarchy)) {\r\n continue;\r\n }\r\n\r\n var positions = hierarchy.positions;\r\n var holes = hierarchy.holes;\r\n\r\n array[startingIndex++] = defined(positions) ? positions.length : 0;\r\n array[startingIndex++] = defined(holes) ? holes.length : 0;\r\n\r\n if (defined(positions)) {\r\n var positionsLength = positions.length;\r\n for (var i = 0; i < positionsLength; ++i, startingIndex += 3) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n }\r\n\r\n if (defined(holes)) {\r\n var holesLength = holes.length;\r\n for (var j = 0; j < holesLength; ++j) {\r\n stack.push(holes[j]);\r\n }\r\n }\r\n }\r\n\r\n return startingIndex;\r\n};\r\n\r\nPolygonGeometryLibrary.unpackPolygonHierarchy = function (\r\n array,\r\n startingIndex\r\n) {\r\n var positionsLength = array[startingIndex++];\r\n var holesLength = array[startingIndex++];\r\n\r\n var positions = new Array(positionsLength);\r\n var holes = holesLength > 0 ? new Array(holesLength) : undefined;\r\n\r\n for (\r\n var i = 0;\r\n i < positionsLength;\r\n ++i, startingIndex += Cartesian3.packedLength\r\n ) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n for (var j = 0; j < holesLength; ++j) {\r\n holes[j] = PolygonGeometryLibrary.unpackPolygonHierarchy(\r\n array,\r\n startingIndex\r\n );\r\n startingIndex = holes[j].startingIndex;\r\n delete holes[j].startingIndex;\r\n }\r\n\r\n return {\r\n positions: positions,\r\n holes: holes,\r\n startingIndex: startingIndex,\r\n };\r\n};\r\n\r\nvar distanceScratch = new Cartesian3();\r\nfunction getPointAtDistance(p0, p1, distance, length) {\r\n Cartesian3.subtract(p1, p0, distanceScratch);\r\n Cartesian3.multiplyByScalar(\r\n distanceScratch,\r\n distance / length,\r\n distanceScratch\r\n );\r\n Cartesian3.add(p0, distanceScratch, distanceScratch);\r\n return [distanceScratch.x, distanceScratch.y, distanceScratch.z];\r\n}\r\n\r\nPolygonGeometryLibrary.subdivideLineCount = function (p0, p1, minDistance) {\r\n var distance = Cartesian3.distance(p0, p1);\r\n var n = distance / minDistance;\r\n var countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));\r\n return Math.pow(2, countDivide);\r\n};\r\n\r\nvar scratchCartographic0 = new Cartographic();\r\nvar scratchCartographic1 = new Cartographic();\r\nvar scratchCartographic2 = new Cartographic();\r\nvar scratchCartesian0 = new Cartesian3();\r\nPolygonGeometryLibrary.subdivideRhumbLineCount = function (\r\n ellipsoid,\r\n p0,\r\n p1,\r\n minDistance\r\n) {\r\n var c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);\r\n var c1 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);\r\n var rhumb = new EllipsoidRhumbLine(c0, c1, ellipsoid);\r\n var n = rhumb.surfaceDistance / minDistance;\r\n var countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));\r\n return Math.pow(2, countDivide);\r\n};\r\n\r\nPolygonGeometryLibrary.subdivideLine = function (p0, p1, minDistance, result) {\r\n var numVertices = PolygonGeometryLibrary.subdivideLineCount(\r\n p0,\r\n p1,\r\n minDistance\r\n );\r\n var length = Cartesian3.distance(p0, p1);\r\n var distanceBetweenVertices = length / numVertices;\r\n\r\n if (!defined(result)) {\r\n result = [];\r\n }\r\n\r\n var positions = result;\r\n positions.length = numVertices * 3;\r\n\r\n var index = 0;\r\n for (var i = 0; i < numVertices; i++) {\r\n var p = getPointAtDistance(p0, p1, i * distanceBetweenVertices, length);\r\n positions[index++] = p[0];\r\n positions[index++] = p[1];\r\n positions[index++] = p[2];\r\n }\r\n\r\n return positions;\r\n};\r\n\r\nPolygonGeometryLibrary.subdivideRhumbLine = function (\r\n ellipsoid,\r\n p0,\r\n p1,\r\n minDistance,\r\n result\r\n) {\r\n var c0 = ellipsoid.cartesianToCartographic(p0, scratchCartographic0);\r\n var c1 = ellipsoid.cartesianToCartographic(p1, scratchCartographic1);\r\n var rhumb = new EllipsoidRhumbLine(c0, c1, ellipsoid);\r\n\r\n var n = rhumb.surfaceDistance / minDistance;\r\n var countDivide = Math.max(0, Math.ceil(CesiumMath.log2(n)));\r\n var numVertices = Math.pow(2, countDivide);\r\n var distanceBetweenVertices = rhumb.surfaceDistance / numVertices;\r\n\r\n if (!defined(result)) {\r\n result = [];\r\n }\r\n\r\n var positions = result;\r\n positions.length = numVertices * 3;\r\n\r\n var index = 0;\r\n for (var i = 0; i < numVertices; i++) {\r\n var c = rhumb.interpolateUsingSurfaceDistance(\r\n i * distanceBetweenVertices,\r\n scratchCartographic2\r\n );\r\n var p = ellipsoid.cartographicToCartesian(c, scratchCartesian0);\r\n positions[index++] = p.x;\r\n positions[index++] = p.y;\r\n positions[index++] = p.z;\r\n }\r\n\r\n return positions;\r\n};\r\n\r\nvar scaleToGeodeticHeightN1 = new Cartesian3();\r\nvar scaleToGeodeticHeightN2 = new Cartesian3();\r\nvar scaleToGeodeticHeightP1 = new Cartesian3();\r\nvar scaleToGeodeticHeightP2 = new Cartesian3();\r\n\r\nPolygonGeometryLibrary.scaleToGeodeticHeightExtruded = function (\r\n geometry,\r\n maxHeight,\r\n minHeight,\r\n ellipsoid,\r\n perPositionHeight\r\n) {\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n\r\n var n1 = scaleToGeodeticHeightN1;\r\n var n2 = scaleToGeodeticHeightN2;\r\n var p = scaleToGeodeticHeightP1;\r\n var p2 = scaleToGeodeticHeightP2;\r\n\r\n if (\r\n defined(geometry) &&\r\n defined(geometry.attributes) &&\r\n defined(geometry.attributes.position)\r\n ) {\r\n var positions = geometry.attributes.position.values;\r\n var length = positions.length / 2;\r\n\r\n for (var i = 0; i < length; i += 3) {\r\n Cartesian3.fromArray(positions, i, p);\r\n\r\n ellipsoid.geodeticSurfaceNormal(p, n1);\r\n p2 = ellipsoid.scaleToGeodeticSurface(p, p2);\r\n n2 = Cartesian3.multiplyByScalar(n1, minHeight, n2);\r\n n2 = Cartesian3.add(p2, n2, n2);\r\n positions[i + length] = n2.x;\r\n positions[i + 1 + length] = n2.y;\r\n positions[i + 2 + length] = n2.z;\r\n\r\n if (perPositionHeight) {\r\n p2 = Cartesian3.clone(p, p2);\r\n }\r\n n2 = Cartesian3.multiplyByScalar(n1, maxHeight, n2);\r\n n2 = Cartesian3.add(p2, n2, n2);\r\n positions[i] = n2.x;\r\n positions[i + 1] = n2.y;\r\n positions[i + 2] = n2.z;\r\n }\r\n }\r\n return geometry;\r\n};\r\n\r\nPolygonGeometryLibrary.polygonOutlinesFromHierarchy = function (\r\n polygonHierarchy,\r\n scaleToEllipsoidSurface,\r\n ellipsoid\r\n) {\r\n // create from a polygon hierarchy\r\n // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf\r\n var polygons = [];\r\n var queue = new Queue();\r\n queue.enqueue(polygonHierarchy);\r\n var i;\r\n var j;\r\n var length;\r\n while (queue.length !== 0) {\r\n var outerNode = queue.dequeue();\r\n var outerRing = outerNode.positions;\r\n if (scaleToEllipsoidSurface) {\r\n length = outerRing.length;\r\n for (i = 0; i < length; i++) {\r\n ellipsoid.scaleToGeodeticSurface(outerRing[i], outerRing[i]);\r\n }\r\n }\r\n outerRing = arrayRemoveDuplicates(\r\n outerRing,\r\n Cartesian3.equalsEpsilon,\r\n true\r\n );\r\n if (outerRing.length < 3) {\r\n continue;\r\n }\r\n\r\n var numChildren = outerNode.holes ? outerNode.holes.length : 0;\r\n // The outer polygon contains inner polygons\r\n for (i = 0; i < numChildren; i++) {\r\n var hole = outerNode.holes[i];\r\n var holePositions = hole.positions;\r\n if (scaleToEllipsoidSurface) {\r\n length = holePositions.length;\r\n for (j = 0; j < length; ++j) {\r\n ellipsoid.scaleToGeodeticSurface(holePositions[j], holePositions[j]);\r\n }\r\n }\r\n holePositions = arrayRemoveDuplicates(\r\n holePositions,\r\n Cartesian3.equalsEpsilon,\r\n true\r\n );\r\n if (holePositions.length < 3) {\r\n continue;\r\n }\r\n polygons.push(holePositions);\r\n\r\n var numGrandchildren = 0;\r\n if (defined(hole.holes)) {\r\n numGrandchildren = hole.holes.length;\r\n }\r\n\r\n for (j = 0; j < numGrandchildren; j++) {\r\n queue.enqueue(hole.holes[j]);\r\n }\r\n }\r\n\r\n polygons.push(outerRing);\r\n }\r\n\r\n return polygons;\r\n};\r\n\r\nPolygonGeometryLibrary.polygonsFromHierarchy = function (\r\n polygonHierarchy,\r\n projectPointsTo2D,\r\n scaleToEllipsoidSurface,\r\n ellipsoid\r\n) {\r\n // create from a polygon hierarchy\r\n // Algorithm adapted from http://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf\r\n var hierarchy = [];\r\n var polygons = [];\r\n\r\n var queue = new Queue();\r\n queue.enqueue(polygonHierarchy);\r\n\r\n while (queue.length !== 0) {\r\n var outerNode = queue.dequeue();\r\n var outerRing = outerNode.positions;\r\n var holes = outerNode.holes;\r\n\r\n var i;\r\n var length;\r\n if (scaleToEllipsoidSurface) {\r\n length = outerRing.length;\r\n for (i = 0; i < length; i++) {\r\n ellipsoid.scaleToGeodeticSurface(outerRing[i], outerRing[i]);\r\n }\r\n }\r\n\r\n outerRing = arrayRemoveDuplicates(\r\n outerRing,\r\n Cartesian3.equalsEpsilon,\r\n true\r\n );\r\n if (outerRing.length < 3) {\r\n continue;\r\n }\r\n\r\n var positions2D = projectPointsTo2D(outerRing);\r\n if (!defined(positions2D)) {\r\n continue;\r\n }\r\n var holeIndices = [];\r\n\r\n var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(\r\n positions2D\r\n );\r\n if (originalWindingOrder === WindingOrder.CLOCKWISE) {\r\n positions2D.reverse();\r\n outerRing = outerRing.slice().reverse();\r\n }\r\n\r\n var positions = outerRing.slice();\r\n var numChildren = defined(holes) ? holes.length : 0;\r\n var polygonHoles = [];\r\n var j;\r\n\r\n for (i = 0; i < numChildren; i++) {\r\n var hole = holes[i];\r\n var holePositions = hole.positions;\r\n if (scaleToEllipsoidSurface) {\r\n length = holePositions.length;\r\n for (j = 0; j < length; ++j) {\r\n ellipsoid.scaleToGeodeticSurface(holePositions[j], holePositions[j]);\r\n }\r\n }\r\n\r\n holePositions = arrayRemoveDuplicates(\r\n holePositions,\r\n Cartesian3.equalsEpsilon,\r\n true\r\n );\r\n if (holePositions.length < 3) {\r\n continue;\r\n }\r\n\r\n var holePositions2D = projectPointsTo2D(holePositions);\r\n if (!defined(holePositions2D)) {\r\n continue;\r\n }\r\n\r\n originalWindingOrder = PolygonPipeline.computeWindingOrder2D(\r\n holePositions2D\r\n );\r\n if (originalWindingOrder === WindingOrder.CLOCKWISE) {\r\n holePositions2D.reverse();\r\n holePositions = holePositions.slice().reverse();\r\n }\r\n\r\n polygonHoles.push(holePositions);\r\n holeIndices.push(positions.length);\r\n positions = positions.concat(holePositions);\r\n positions2D = positions2D.concat(holePositions2D);\r\n\r\n var numGrandchildren = 0;\r\n if (defined(hole.holes)) {\r\n numGrandchildren = hole.holes.length;\r\n }\r\n\r\n for (j = 0; j < numGrandchildren; j++) {\r\n queue.enqueue(hole.holes[j]);\r\n }\r\n }\r\n\r\n hierarchy.push({\r\n outerRing: outerRing,\r\n holes: polygonHoles,\r\n });\r\n polygons.push({\r\n positions: positions,\r\n positions2D: positions2D,\r\n holes: holeIndices,\r\n });\r\n }\r\n\r\n return {\r\n hierarchy: hierarchy,\r\n polygons: polygons,\r\n };\r\n};\r\n\r\nvar computeBoundingRectangleCartesian2 = new Cartesian2();\r\nvar computeBoundingRectangleCartesian3 = new Cartesian3();\r\nvar computeBoundingRectangleQuaternion = new Quaternion();\r\nvar computeBoundingRectangleMatrix3 = new Matrix3();\r\nPolygonGeometryLibrary.computeBoundingRectangle = function (\r\n planeNormal,\r\n projectPointTo2D,\r\n positions,\r\n angle,\r\n result\r\n) {\r\n var rotation = Quaternion.fromAxisAngle(\r\n planeNormal,\r\n angle,\r\n computeBoundingRectangleQuaternion\r\n );\r\n var textureMatrix = Matrix3.fromQuaternion(\r\n rotation,\r\n computeBoundingRectangleMatrix3\r\n );\r\n\r\n var minX = Number.POSITIVE_INFINITY;\r\n var maxX = Number.NEGATIVE_INFINITY;\r\n var minY = Number.POSITIVE_INFINITY;\r\n var maxY = Number.NEGATIVE_INFINITY;\r\n\r\n var length = positions.length;\r\n for (var i = 0; i < length; ++i) {\r\n var p = Cartesian3.clone(positions[i], computeBoundingRectangleCartesian3);\r\n Matrix3.multiplyByVector(textureMatrix, p, p);\r\n var st = projectPointTo2D(p, computeBoundingRectangleCartesian2);\r\n\r\n if (defined(st)) {\r\n minX = Math.min(minX, st.x);\r\n maxX = Math.max(maxX, st.x);\r\n\r\n minY = Math.min(minY, st.y);\r\n maxY = Math.max(maxY, st.y);\r\n }\r\n }\r\n\r\n result.x = minX;\r\n result.y = minY;\r\n result.width = maxX - minX;\r\n result.height = maxY - minY;\r\n return result;\r\n};\r\n\r\nPolygonGeometryLibrary.createGeometryFromPositions = function (\r\n ellipsoid,\r\n polygon,\r\n granularity,\r\n perPositionHeight,\r\n vertexFormat,\r\n arcType\r\n) {\r\n var indices = PolygonPipeline.triangulate(polygon.positions2D, polygon.holes);\r\n\r\n /* If polygon is completely unrenderable, just use the first three vertices */\r\n if (indices.length < 3) {\r\n indices = [0, 1, 2];\r\n }\r\n\r\n var positions = polygon.positions;\r\n\r\n if (perPositionHeight) {\r\n var length = positions.length;\r\n var flattenedPositions = new Array(length * 3);\r\n var index = 0;\r\n for (var i = 0; i < length; i++) {\r\n var p = positions[i];\r\n flattenedPositions[index++] = p.x;\r\n flattenedPositions[index++] = p.y;\r\n flattenedPositions[index++] = p.z;\r\n }\r\n var geometry = new Geometry({\r\n attributes: {\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: flattenedPositions,\r\n }),\r\n },\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n\r\n if (vertexFormat.normal) {\r\n return GeometryPipeline.computeNormal(geometry);\r\n }\r\n\r\n return geometry;\r\n }\r\n\r\n if (arcType === ArcType.GEODESIC) {\r\n return PolygonPipeline.computeSubdivision(\r\n ellipsoid,\r\n positions,\r\n indices,\r\n granularity\r\n );\r\n } else if (arcType === ArcType.RHUMB) {\r\n return PolygonPipeline.computeRhumbLineSubdivision(\r\n ellipsoid,\r\n positions,\r\n indices,\r\n granularity\r\n );\r\n }\r\n};\r\n\r\nvar computeWallIndicesSubdivided = [];\r\nvar p1Scratch = new Cartesian3();\r\nvar p2Scratch = new Cartesian3();\r\n\r\nPolygonGeometryLibrary.computeWallGeometry = function (\r\n positions,\r\n ellipsoid,\r\n granularity,\r\n perPositionHeight,\r\n arcType\r\n) {\r\n var edgePositions;\r\n var topEdgeLength;\r\n var i;\r\n var p1;\r\n var p2;\r\n\r\n var length = positions.length;\r\n var index = 0;\r\n\r\n if (!perPositionHeight) {\r\n var minDistance = CesiumMath.chordLength(\r\n granularity,\r\n ellipsoid.maximumRadius\r\n );\r\n\r\n var numVertices = 0;\r\n if (arcType === ArcType.GEODESIC) {\r\n for (i = 0; i < length; i++) {\r\n numVertices += PolygonGeometryLibrary.subdivideLineCount(\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance\r\n );\r\n }\r\n } else if (arcType === ArcType.RHUMB) {\r\n for (i = 0; i < length; i++) {\r\n numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(\r\n ellipsoid,\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance\r\n );\r\n }\r\n }\r\n\r\n topEdgeLength = (numVertices + length) * 3;\r\n edgePositions = new Array(topEdgeLength * 2);\r\n for (i = 0; i < length; i++) {\r\n p1 = positions[i];\r\n p2 = positions[(i + 1) % length];\r\n\r\n var tempPositions;\r\n if (arcType === ArcType.GEODESIC) {\r\n tempPositions = PolygonGeometryLibrary.subdivideLine(\r\n p1,\r\n p2,\r\n minDistance,\r\n computeWallIndicesSubdivided\r\n );\r\n } else if (arcType === ArcType.RHUMB) {\r\n tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(\r\n ellipsoid,\r\n p1,\r\n p2,\r\n minDistance,\r\n computeWallIndicesSubdivided\r\n );\r\n }\r\n var tempPositionsLength = tempPositions.length;\r\n for (var j = 0; j < tempPositionsLength; ++j, ++index) {\r\n edgePositions[index] = tempPositions[j];\r\n edgePositions[index + topEdgeLength] = tempPositions[j];\r\n }\r\n\r\n edgePositions[index] = p2.x;\r\n edgePositions[index + topEdgeLength] = p2.x;\r\n ++index;\r\n\r\n edgePositions[index] = p2.y;\r\n edgePositions[index + topEdgeLength] = p2.y;\r\n ++index;\r\n\r\n edgePositions[index] = p2.z;\r\n edgePositions[index + topEdgeLength] = p2.z;\r\n ++index;\r\n }\r\n } else {\r\n topEdgeLength = length * 3 * 2;\r\n edgePositions = new Array(topEdgeLength * 2);\r\n for (i = 0; i < length; i++) {\r\n p1 = positions[i];\r\n p2 = positions[(i + 1) % length];\r\n edgePositions[index] = edgePositions[index + topEdgeLength] = p1.x;\r\n ++index;\r\n edgePositions[index] = edgePositions[index + topEdgeLength] = p1.y;\r\n ++index;\r\n edgePositions[index] = edgePositions[index + topEdgeLength] = p1.z;\r\n ++index;\r\n edgePositions[index] = edgePositions[index + topEdgeLength] = p2.x;\r\n ++index;\r\n edgePositions[index] = edgePositions[index + topEdgeLength] = p2.y;\r\n ++index;\r\n edgePositions[index] = edgePositions[index + topEdgeLength] = p2.z;\r\n ++index;\r\n }\r\n }\r\n\r\n length = edgePositions.length;\r\n var indices = IndexDatatype.createTypedArray(\r\n length / 3,\r\n length - positions.length * 6\r\n );\r\n var edgeIndex = 0;\r\n length /= 6;\r\n\r\n for (i = 0; i < length; i++) {\r\n var UL = i;\r\n var UR = UL + 1;\r\n var LL = UL + length;\r\n var LR = LL + 1;\r\n\r\n p1 = Cartesian3.fromArray(edgePositions, UL * 3, p1Scratch);\r\n p2 = Cartesian3.fromArray(edgePositions, UR * 3, p2Scratch);\r\n if (\r\n Cartesian3.equalsEpsilon(\r\n p1,\r\n p2,\r\n CesiumMath.EPSILON10,\r\n CesiumMath.EPSILON10\r\n )\r\n ) {\r\n //skip corner\r\n continue;\r\n }\r\n\r\n indices[edgeIndex++] = UL;\r\n indices[edgeIndex++] = LL;\r\n indices[edgeIndex++] = UR;\r\n indices[edgeIndex++] = UR;\r\n indices[edgeIndex++] = LL;\r\n indices[edgeIndex++] = LR;\r\n }\r\n\r\n return new Geometry({\r\n attributes: new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: edgePositions,\r\n }),\r\n }),\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n};\r\nexport default PolygonGeometryLibrary;\r\n","import arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport BoundingRectangle from \"./BoundingRectangle.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport CoplanarPolygonGeometryLibrary from \"./CoplanarPolygonGeometryLibrary.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryInstance from \"./GeometryInstance.js\";\r\nimport GeometryPipeline from \"./GeometryPipeline.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport PolygonGeometryLibrary from \"./PolygonGeometryLibrary.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar scratchPosition = new Cartesian3();\r\nvar scratchBR = new BoundingRectangle();\r\nvar stScratch = new Cartesian2();\r\nvar textureCoordinatesOrigin = new Cartesian2();\r\nvar scratchNormal = new Cartesian3();\r\nvar scratchTangent = new Cartesian3();\r\nvar scratchBitangent = new Cartesian3();\r\nvar centerScratch = new Cartesian3();\r\nvar axis1Scratch = new Cartesian3();\r\nvar axis2Scratch = new Cartesian3();\r\nvar quaternionScratch = new Quaternion();\r\nvar textureMatrixScratch = new Matrix3();\r\nvar tangentRotationScratch = new Matrix3();\r\nvar surfaceNormalScratch = new Cartesian3();\r\n\r\nfunction createGeometryFromPolygon(\r\n polygon,\r\n vertexFormat,\r\n boundingRectangle,\r\n stRotation,\r\n projectPointTo2D,\r\n normal,\r\n tangent,\r\n bitangent\r\n) {\r\n var positions = polygon.positions;\r\n var indices = PolygonPipeline.triangulate(polygon.positions2D, polygon.holes);\r\n\r\n /* If polygon is completely unrenderable, just use the first three vertices */\r\n if (indices.length < 3) {\r\n indices = [0, 1, 2];\r\n }\r\n\r\n var newIndices = IndexDatatype.createTypedArray(\r\n positions.length,\r\n indices.length\r\n );\r\n newIndices.set(indices);\r\n\r\n var textureMatrix = textureMatrixScratch;\r\n if (stRotation !== 0.0) {\r\n var rotation = Quaternion.fromAxisAngle(\r\n normal,\r\n stRotation,\r\n quaternionScratch\r\n );\r\n textureMatrix = Matrix3.fromQuaternion(rotation, textureMatrix);\r\n\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n rotation = Quaternion.fromAxisAngle(\r\n normal,\r\n -stRotation,\r\n quaternionScratch\r\n );\r\n var tangentRotation = Matrix3.fromQuaternion(\r\n rotation,\r\n tangentRotationScratch\r\n );\r\n\r\n tangent = Cartesian3.normalize(\r\n Matrix3.multiplyByVector(tangentRotation, tangent, tangent),\r\n tangent\r\n );\r\n if (vertexFormat.bitangent) {\r\n bitangent = Cartesian3.normalize(\r\n Cartesian3.cross(normal, tangent, bitangent),\r\n bitangent\r\n );\r\n }\r\n }\r\n } else {\r\n textureMatrix = Matrix3.clone(Matrix3.IDENTITY, textureMatrix);\r\n }\r\n\r\n var stOrigin = textureCoordinatesOrigin;\r\n if (vertexFormat.st) {\r\n stOrigin.x = boundingRectangle.x;\r\n stOrigin.y = boundingRectangle.y;\r\n }\r\n\r\n var length = positions.length;\r\n var size = length * 3;\r\n var flatPositions = new Float64Array(size);\r\n var normals = vertexFormat.normal ? new Float32Array(size) : undefined;\r\n var tangents = vertexFormat.tangent ? new Float32Array(size) : undefined;\r\n var bitangents = vertexFormat.bitangent ? new Float32Array(size) : undefined;\r\n var textureCoordinates = vertexFormat.st\r\n ? new Float32Array(length * 2)\r\n : undefined;\r\n\r\n var positionIndex = 0;\r\n var normalIndex = 0;\r\n var bitangentIndex = 0;\r\n var tangentIndex = 0;\r\n var stIndex = 0;\r\n\r\n for (var i = 0; i < length; i++) {\r\n var position = positions[i];\r\n flatPositions[positionIndex++] = position.x;\r\n flatPositions[positionIndex++] = position.y;\r\n flatPositions[positionIndex++] = position.z;\r\n\r\n if (vertexFormat.st) {\r\n var p = Matrix3.multiplyByVector(\r\n textureMatrix,\r\n position,\r\n scratchPosition\r\n );\r\n var st = projectPointTo2D(p, stScratch);\r\n Cartesian2.subtract(st, stOrigin, st);\r\n\r\n var stx = CesiumMath.clamp(st.x / boundingRectangle.width, 0, 1);\r\n var sty = CesiumMath.clamp(st.y / boundingRectangle.height, 0, 1);\r\n textureCoordinates[stIndex++] = stx;\r\n textureCoordinates[stIndex++] = sty;\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n normals[normalIndex++] = normal.x;\r\n normals[normalIndex++] = normal.y;\r\n normals[normalIndex++] = normal.z;\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n tangents[tangentIndex++] = tangent.x;\r\n tangents[tangentIndex++] = tangent.y;\r\n tangents[tangentIndex++] = tangent.z;\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n bitangents[bitangentIndex++] = bitangent.x;\r\n bitangents[bitangentIndex++] = bitangent.y;\r\n bitangents[bitangentIndex++] = bitangent.z;\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n\r\n if (vertexFormat.position) {\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: flatPositions,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.st) {\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: textureCoordinates,\r\n });\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: newIndices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n}\r\n\r\n/**\r\n * A description of a polygon composed of arbitrary coplanar positions.\r\n *\r\n * @alias CoplanarPolygonGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.\r\n * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n *\r\n * @example\r\n * var polygonGeometry = new Cesium.CoplanarPolygonGeometry({\r\n * polygonHierarchy: new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArrayHeights([\r\n * -90.0, 30.0, 0.0,\r\n * -90.0, 30.0, 300000.0,\r\n * -80.0, 30.0, 300000.0,\r\n * -80.0, 30.0, 0.0\r\n * ]))\r\n * });\r\n *\r\n */\r\nfunction CoplanarPolygonGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var polygonHierarchy = options.polygonHierarchy;\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.polygonHierarchy\", polygonHierarchy);\r\n //>>includeEnd('debug');\r\n\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n this._vertexFormat = VertexFormat.clone(vertexFormat);\r\n this._polygonHierarchy = polygonHierarchy;\r\n this._stRotation = defaultValue(options.stRotation, 0.0);\r\n this._ellipsoid = Ellipsoid.clone(\r\n defaultValue(options.ellipsoid, Ellipsoid.WGS84)\r\n );\r\n this._workerName = \"createCoplanarPolygonGeometry\";\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) +\r\n VertexFormat.packedLength +\r\n Ellipsoid.packedLength +\r\n 2;\r\n}\r\n\r\n/**\r\n * A description of a coplanar polygon from an array of positions.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of positions that defined the corner points of the polygon.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @returns {CoplanarPolygonGeometry}\r\n *\r\n * @example\r\n * // create a polygon from points\r\n * var polygon = Cesium.CoplanarPolygonGeometry.fromPositions({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ])\r\n * });\r\n * var geometry = Cesium.PolygonGeometry.createGeometry(polygon);\r\n *\r\n * @see PolygonGeometry#createGeometry\r\n */\r\nCoplanarPolygonGeometry.fromPositions = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.positions\", options.positions);\r\n //>>includeEnd('debug');\r\n\r\n var newOptions = {\r\n polygonHierarchy: {\r\n positions: options.positions,\r\n },\r\n vertexFormat: options.vertexFormat,\r\n stRotation: options.stRotation,\r\n ellipsoid: options.ellipsoid,\r\n };\r\n return new CoplanarPolygonGeometry(newOptions);\r\n};\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {CoplanarPolygonGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCoplanarPolygonGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n startingIndex = PolygonGeometryLibrary.packPolygonHierarchy(\r\n value._polygonHierarchy,\r\n array,\r\n startingIndex\r\n );\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._stRotation;\r\n array[startingIndex] = value.packedLength;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n polygonHierarchy: {},\r\n};\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {CoplanarPolygonGeometry} [result] The object into which to store the result.\r\n * @returns {CoplanarPolygonGeometry} The modified result parameter or a new CoplanarPolygonGeometry instance if one was not provided.\r\n */\r\nCoplanarPolygonGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var polygonHierarchy = PolygonGeometryLibrary.unpackPolygonHierarchy(\r\n array,\r\n startingIndex\r\n );\r\n startingIndex = polygonHierarchy.startingIndex;\r\n delete polygonHierarchy.startingIndex;\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var stRotation = array[startingIndex++];\r\n var packedLength = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n result = new CoplanarPolygonGeometry(scratchOptions);\r\n }\r\n\r\n result._polygonHierarchy = polygonHierarchy;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._stRotation = stRotation;\r\n result.packedLength = packedLength;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an arbitrary coplanar polygon, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {CoplanarPolygonGeometry} polygonGeometry A description of the polygon.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nCoplanarPolygonGeometry.createGeometry = function (polygonGeometry) {\r\n var vertexFormat = polygonGeometry._vertexFormat;\r\n var polygonHierarchy = polygonGeometry._polygonHierarchy;\r\n var stRotation = polygonGeometry._stRotation;\r\n\r\n var outerPositions = polygonHierarchy.positions;\r\n outerPositions = arrayRemoveDuplicates(\r\n outerPositions,\r\n Cartesian3.equalsEpsilon,\r\n true\r\n );\r\n if (outerPositions.length < 3) {\r\n return;\r\n }\r\n\r\n var normal = scratchNormal;\r\n var tangent = scratchTangent;\r\n var bitangent = scratchBitangent;\r\n var axis1 = axis1Scratch;\r\n var axis2 = axis2Scratch;\r\n\r\n var validGeometry = CoplanarPolygonGeometryLibrary.computeProjectTo2DArguments(\r\n outerPositions,\r\n centerScratch,\r\n axis1,\r\n axis2\r\n );\r\n if (!validGeometry) {\r\n return undefined;\r\n }\r\n\r\n normal = Cartesian3.cross(axis1, axis2, normal);\r\n normal = Cartesian3.normalize(normal, normal);\r\n\r\n if (\r\n !Cartesian3.equalsEpsilon(\r\n centerScratch,\r\n Cartesian3.ZERO,\r\n CesiumMath.EPSILON6\r\n )\r\n ) {\r\n var surfaceNormal = polygonGeometry._ellipsoid.geodeticSurfaceNormal(\r\n centerScratch,\r\n surfaceNormalScratch\r\n );\r\n if (Cartesian3.dot(normal, surfaceNormal) < 0) {\r\n normal = Cartesian3.negate(normal, normal);\r\n axis1 = Cartesian3.negate(axis1, axis1);\r\n }\r\n }\r\n\r\n var projectPoints = CoplanarPolygonGeometryLibrary.createProjectPointsTo2DFunction(\r\n centerScratch,\r\n axis1,\r\n axis2\r\n );\r\n var projectPoint = CoplanarPolygonGeometryLibrary.createProjectPointTo2DFunction(\r\n centerScratch,\r\n axis1,\r\n axis2\r\n );\r\n\r\n if (vertexFormat.tangent) {\r\n tangent = Cartesian3.clone(axis1, tangent);\r\n }\r\n if (vertexFormat.bitangent) {\r\n bitangent = Cartesian3.clone(axis2, bitangent);\r\n }\r\n\r\n var results = PolygonGeometryLibrary.polygonsFromHierarchy(\r\n polygonHierarchy,\r\n projectPoints,\r\n false\r\n );\r\n var hierarchy = results.hierarchy;\r\n var polygons = results.polygons;\r\n\r\n if (hierarchy.length === 0) {\r\n return;\r\n }\r\n outerPositions = hierarchy[0].outerRing;\r\n\r\n var boundingSphere = BoundingSphere.fromPoints(outerPositions);\r\n var boundingRectangle = PolygonGeometryLibrary.computeBoundingRectangle(\r\n normal,\r\n projectPoint,\r\n outerPositions,\r\n stRotation,\r\n scratchBR\r\n );\r\n\r\n var geometries = [];\r\n for (var i = 0; i < polygons.length; i++) {\r\n var geometryInstance = new GeometryInstance({\r\n geometry: createGeometryFromPolygon(\r\n polygons[i],\r\n vertexFormat,\r\n boundingRectangle,\r\n stRotation,\r\n projectPoint,\r\n normal,\r\n tangent,\r\n bitangent\r\n ),\r\n });\r\n\r\n geometries.push(geometryInstance);\r\n }\r\n\r\n var geometry = GeometryPipeline.combineInstances(geometries)[0];\r\n geometry.attributes.position.values = new Float64Array(\r\n geometry.attributes.position.values\r\n );\r\n geometry.indices = IndexDatatype.createTypedArray(\r\n geometry.attributes.position.values.length / 3,\r\n geometry.indices\r\n );\r\n\r\n var attributes = geometry.attributes;\r\n if (!vertexFormat.position) {\r\n delete attributes.position;\r\n }\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: geometry.indices,\r\n primitiveType: geometry.primitiveType,\r\n boundingSphere: boundingSphere,\r\n });\r\n};\r\nexport default CoplanarPolygonGeometry;\r\n","import arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport CoplanarPolygonGeometryLibrary from \"./CoplanarPolygonGeometryLibrary.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryInstance from \"./GeometryInstance.js\";\r\nimport GeometryPipeline from \"./GeometryPipeline.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport PolygonGeometryLibrary from \"./PolygonGeometryLibrary.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\n\r\nfunction createGeometryFromPositions(positions) {\r\n var length = positions.length;\r\n var flatPositions = new Float64Array(length * 3);\r\n var indices = IndexDatatype.createTypedArray(length, length * 2);\r\n\r\n var positionIndex = 0;\r\n var index = 0;\r\n\r\n for (var i = 0; i < length; i++) {\r\n var position = positions[i];\r\n flatPositions[positionIndex++] = position.x;\r\n flatPositions[positionIndex++] = position.y;\r\n flatPositions[positionIndex++] = position.z;\r\n\r\n indices[index++] = i;\r\n indices[index++] = (i + 1) % length;\r\n }\r\n\r\n var attributes = new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: flatPositions,\r\n }),\r\n });\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n });\r\n}\r\n\r\n/**\r\n * A description of the outline of a polygon composed of arbitrary coplanar positions.\r\n *\r\n * @alias CoplanarPolygonOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.\r\n *\r\n * @see CoplanarPolygonOutlineGeometry.createGeometry\r\n *\r\n * @example\r\n * var polygonOutline = new Cesium.CoplanarPolygonOutlineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArrayHeights([\r\n * -90.0, 30.0, 0.0,\r\n * -90.0, 30.0, 1000.0,\r\n * -80.0, 30.0, 1000.0,\r\n * -80.0, 30.0, 0.0\r\n * ])\r\n * });\r\n * var geometry = Cesium.CoplanarPolygonOutlineGeometry.createGeometry(polygonOutline);\r\n */\r\nfunction CoplanarPolygonOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var polygonHierarchy = options.polygonHierarchy;\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.polygonHierarchy\", polygonHierarchy);\r\n //>>includeEnd('debug');\r\n\r\n this._polygonHierarchy = polygonHierarchy;\r\n this._workerName = \"createCoplanarPolygonOutlineGeometry\";\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) + 1;\r\n}\r\n\r\n/**\r\n * A description of a coplanar polygon outline from an array of positions.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of positions that defined the corner points of the polygon.\r\n * @returns {CoplanarPolygonOutlineGeometry}\r\n */\r\nCoplanarPolygonOutlineGeometry.fromPositions = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.positions\", options.positions);\r\n //>>includeEnd('debug');\r\n\r\n var newOptions = {\r\n polygonHierarchy: {\r\n positions: options.positions,\r\n },\r\n };\r\n return new CoplanarPolygonOutlineGeometry(newOptions);\r\n};\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {CoplanarPolygonOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCoplanarPolygonOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n startingIndex = PolygonGeometryLibrary.packPolygonHierarchy(\r\n value._polygonHierarchy,\r\n array,\r\n startingIndex\r\n );\r\n\r\n array[startingIndex] = value.packedLength;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchOptions = {\r\n polygonHierarchy: {},\r\n};\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {CoplanarPolygonOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {CoplanarPolygonOutlineGeometry} The modified result parameter or a new CoplanarPolygonOutlineGeometry instance if one was not provided.\r\n */\r\nCoplanarPolygonOutlineGeometry.unpack = function (\r\n array,\r\n startingIndex,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var polygonHierarchy = PolygonGeometryLibrary.unpackPolygonHierarchy(\r\n array,\r\n startingIndex\r\n );\r\n startingIndex = polygonHierarchy.startingIndex;\r\n delete polygonHierarchy.startingIndex;\r\n var packedLength = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n result = new CoplanarPolygonOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._polygonHierarchy = polygonHierarchy;\r\n result.packedLength = packedLength;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an arbitrary coplanar polygon, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {CoplanarPolygonOutlineGeometry} polygonGeometry A description of the polygon.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nCoplanarPolygonOutlineGeometry.createGeometry = function (polygonGeometry) {\r\n var polygonHierarchy = polygonGeometry._polygonHierarchy;\r\n\r\n var outerPositions = polygonHierarchy.positions;\r\n outerPositions = arrayRemoveDuplicates(\r\n outerPositions,\r\n Cartesian3.equalsEpsilon,\r\n true\r\n );\r\n if (outerPositions.length < 3) {\r\n return;\r\n }\r\n var isValid = CoplanarPolygonGeometryLibrary.validOutline(outerPositions);\r\n if (!isValid) {\r\n return undefined;\r\n }\r\n\r\n var polygons = PolygonGeometryLibrary.polygonOutlinesFromHierarchy(\r\n polygonHierarchy,\r\n false\r\n );\r\n\r\n if (polygons.length === 0) {\r\n return undefined;\r\n }\r\n\r\n var geometries = [];\r\n\r\n for (var i = 0; i < polygons.length; i++) {\r\n var geometryInstance = new GeometryInstance({\r\n geometry: createGeometryFromPositions(polygons[i]),\r\n });\r\n geometries.push(geometryInstance);\r\n }\r\n\r\n var geometry = GeometryPipeline.combineInstances(geometries)[0];\r\n var boundingSphere = BoundingSphere.fromPoints(polygonHierarchy.positions);\r\n\r\n return new Geometry({\r\n attributes: geometry.attributes,\r\n indices: geometry.indices,\r\n primitiveType: geometry.primitiveType,\r\n boundingSphere: boundingSphere,\r\n });\r\n};\r\nexport default CoplanarPolygonOutlineGeometry;\r\n","/**\r\n * Style options for corners.\r\n *\r\n * @demo The {@link https://sandcastle.cesium.com/index.html?src=Corridor.html&label=Geometries|Corridor Demo}\r\n * demonstrates the three corner types, as used by {@link CorridorGraphics}.\r\n *\r\n * @enum {Number}\r\n */\r\nvar CornerType = {\r\n /**\r\n * \r\n *\r\n * Corner has a smooth edge.\r\n * @type {Number}\r\n * @constant\r\n */\r\n ROUNDED: 0,\r\n\r\n /**\r\n * \r\n *\r\n * Corner point is the intersection of adjacent edges.\r\n * @type {Number}\r\n * @constant\r\n */\r\n MITERED: 1,\r\n\r\n /**\r\n * \r\n *\r\n * Corner is clipped.\r\n * @type {Number}\r\n * @constant\r\n */\r\n BEVELED: 2,\r\n};\r\nexport default Object.freeze(CornerType);\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nfunction setConstants(ellipsoidGeodesic) {\r\n var uSquared = ellipsoidGeodesic._uSquared;\r\n var a = ellipsoidGeodesic._ellipsoid.maximumRadius;\r\n var b = ellipsoidGeodesic._ellipsoid.minimumRadius;\r\n var f = (a - b) / a;\r\n\r\n var cosineHeading = Math.cos(ellipsoidGeodesic._startHeading);\r\n var sineHeading = Math.sin(ellipsoidGeodesic._startHeading);\r\n\r\n var tanU = (1 - f) * Math.tan(ellipsoidGeodesic._start.latitude);\r\n\r\n var cosineU = 1.0 / Math.sqrt(1.0 + tanU * tanU);\r\n var sineU = cosineU * tanU;\r\n\r\n var sigma = Math.atan2(tanU, cosineHeading);\r\n\r\n var sineAlpha = cosineU * sineHeading;\r\n var sineSquaredAlpha = sineAlpha * sineAlpha;\r\n\r\n var cosineSquaredAlpha = 1.0 - sineSquaredAlpha;\r\n var cosineAlpha = Math.sqrt(cosineSquaredAlpha);\r\n\r\n var u2Over4 = uSquared / 4.0;\r\n var u4Over16 = u2Over4 * u2Over4;\r\n var u6Over64 = u4Over16 * u2Over4;\r\n var u8Over256 = u4Over16 * u4Over16;\r\n\r\n var a0 =\r\n 1.0 +\r\n u2Over4 -\r\n (3.0 * u4Over16) / 4.0 +\r\n (5.0 * u6Over64) / 4.0 -\r\n (175.0 * u8Over256) / 64.0;\r\n var a1 = 1.0 - u2Over4 + (15.0 * u4Over16) / 8.0 - (35.0 * u6Over64) / 8.0;\r\n var a2 = 1.0 - 3.0 * u2Over4 + (35.0 * u4Over16) / 4.0;\r\n var a3 = 1.0 - 5.0 * u2Over4;\r\n\r\n var distanceRatio =\r\n a0 * sigma -\r\n (a1 * Math.sin(2.0 * sigma) * u2Over4) / 2.0 -\r\n (a2 * Math.sin(4.0 * sigma) * u4Over16) / 16.0 -\r\n (a3 * Math.sin(6.0 * sigma) * u6Over64) / 48.0 -\r\n (Math.sin(8.0 * sigma) * 5.0 * u8Over256) / 512;\r\n\r\n var constants = ellipsoidGeodesic._constants;\r\n\r\n constants.a = a;\r\n constants.b = b;\r\n constants.f = f;\r\n constants.cosineHeading = cosineHeading;\r\n constants.sineHeading = sineHeading;\r\n constants.tanU = tanU;\r\n constants.cosineU = cosineU;\r\n constants.sineU = sineU;\r\n constants.sigma = sigma;\r\n constants.sineAlpha = sineAlpha;\r\n constants.sineSquaredAlpha = sineSquaredAlpha;\r\n constants.cosineSquaredAlpha = cosineSquaredAlpha;\r\n constants.cosineAlpha = cosineAlpha;\r\n constants.u2Over4 = u2Over4;\r\n constants.u4Over16 = u4Over16;\r\n constants.u6Over64 = u6Over64;\r\n constants.u8Over256 = u8Over256;\r\n constants.a0 = a0;\r\n constants.a1 = a1;\r\n constants.a2 = a2;\r\n constants.a3 = a3;\r\n constants.distanceRatio = distanceRatio;\r\n}\r\n\r\nfunction computeC(f, cosineSquaredAlpha) {\r\n return (\r\n (f * cosineSquaredAlpha * (4.0 + f * (4.0 - 3.0 * cosineSquaredAlpha))) /\r\n 16.0\r\n );\r\n}\r\n\r\nfunction computeDeltaLambda(\r\n f,\r\n sineAlpha,\r\n cosineSquaredAlpha,\r\n sigma,\r\n sineSigma,\r\n cosineSigma,\r\n cosineTwiceSigmaMidpoint\r\n) {\r\n var C = computeC(f, cosineSquaredAlpha);\r\n\r\n return (\r\n (1.0 - C) *\r\n f *\r\n sineAlpha *\r\n (sigma +\r\n C *\r\n sineSigma *\r\n (cosineTwiceSigmaMidpoint +\r\n C *\r\n cosineSigma *\r\n (2.0 * cosineTwiceSigmaMidpoint * cosineTwiceSigmaMidpoint - 1.0)))\r\n );\r\n}\r\n\r\nfunction vincentyInverseFormula(\r\n ellipsoidGeodesic,\r\n major,\r\n minor,\r\n firstLongitude,\r\n firstLatitude,\r\n secondLongitude,\r\n secondLatitude\r\n) {\r\n var eff = (major - minor) / major;\r\n var l = secondLongitude - firstLongitude;\r\n\r\n var u1 = Math.atan((1 - eff) * Math.tan(firstLatitude));\r\n var u2 = Math.atan((1 - eff) * Math.tan(secondLatitude));\r\n\r\n var cosineU1 = Math.cos(u1);\r\n var sineU1 = Math.sin(u1);\r\n var cosineU2 = Math.cos(u2);\r\n var sineU2 = Math.sin(u2);\r\n\r\n var cc = cosineU1 * cosineU2;\r\n var cs = cosineU1 * sineU2;\r\n var ss = sineU1 * sineU2;\r\n var sc = sineU1 * cosineU2;\r\n\r\n var lambda = l;\r\n var lambdaDot = CesiumMath.TWO_PI;\r\n\r\n var cosineLambda = Math.cos(lambda);\r\n var sineLambda = Math.sin(lambda);\r\n\r\n var sigma;\r\n var cosineSigma;\r\n var sineSigma;\r\n var cosineSquaredAlpha;\r\n var cosineTwiceSigmaMidpoint;\r\n\r\n do {\r\n cosineLambda = Math.cos(lambda);\r\n sineLambda = Math.sin(lambda);\r\n\r\n var temp = cs - sc * cosineLambda;\r\n sineSigma = Math.sqrt(\r\n cosineU2 * cosineU2 * sineLambda * sineLambda + temp * temp\r\n );\r\n cosineSigma = ss + cc * cosineLambda;\r\n\r\n sigma = Math.atan2(sineSigma, cosineSigma);\r\n\r\n var sineAlpha;\r\n\r\n if (sineSigma === 0.0) {\r\n sineAlpha = 0.0;\r\n cosineSquaredAlpha = 1.0;\r\n } else {\r\n sineAlpha = (cc * sineLambda) / sineSigma;\r\n cosineSquaredAlpha = 1.0 - sineAlpha * sineAlpha;\r\n }\r\n\r\n lambdaDot = lambda;\r\n\r\n cosineTwiceSigmaMidpoint = cosineSigma - (2.0 * ss) / cosineSquaredAlpha;\r\n\r\n if (!isFinite(cosineTwiceSigmaMidpoint)) {\r\n cosineTwiceSigmaMidpoint = 0.0;\r\n }\r\n\r\n lambda =\r\n l +\r\n computeDeltaLambda(\r\n eff,\r\n sineAlpha,\r\n cosineSquaredAlpha,\r\n sigma,\r\n sineSigma,\r\n cosineSigma,\r\n cosineTwiceSigmaMidpoint\r\n );\r\n } while (Math.abs(lambda - lambdaDot) > CesiumMath.EPSILON12);\r\n\r\n var uSquared =\r\n (cosineSquaredAlpha * (major * major - minor * minor)) / (minor * minor);\r\n var A =\r\n 1.0 +\r\n (uSquared *\r\n (4096.0 + uSquared * (uSquared * (320.0 - 175.0 * uSquared) - 768.0))) /\r\n 16384.0;\r\n var B =\r\n (uSquared *\r\n (256.0 + uSquared * (uSquared * (74.0 - 47.0 * uSquared) - 128.0))) /\r\n 1024.0;\r\n\r\n var cosineSquaredTwiceSigmaMidpoint =\r\n cosineTwiceSigmaMidpoint * cosineTwiceSigmaMidpoint;\r\n var deltaSigma =\r\n B *\r\n sineSigma *\r\n (cosineTwiceSigmaMidpoint +\r\n (B *\r\n (cosineSigma * (2.0 * cosineSquaredTwiceSigmaMidpoint - 1.0) -\r\n (B *\r\n cosineTwiceSigmaMidpoint *\r\n (4.0 * sineSigma * sineSigma - 3.0) *\r\n (4.0 * cosineSquaredTwiceSigmaMidpoint - 3.0)) /\r\n 6.0)) /\r\n 4.0);\r\n\r\n var distance = minor * A * (sigma - deltaSigma);\r\n\r\n var startHeading = Math.atan2(cosineU2 * sineLambda, cs - sc * cosineLambda);\r\n var endHeading = Math.atan2(cosineU1 * sineLambda, cs * cosineLambda - sc);\r\n\r\n ellipsoidGeodesic._distance = distance;\r\n ellipsoidGeodesic._startHeading = startHeading;\r\n ellipsoidGeodesic._endHeading = endHeading;\r\n ellipsoidGeodesic._uSquared = uSquared;\r\n}\r\n\r\nvar scratchCart1 = new Cartesian3();\r\nvar scratchCart2 = new Cartesian3();\r\nfunction computeProperties(ellipsoidGeodesic, start, end, ellipsoid) {\r\n var firstCartesian = Cartesian3.normalize(\r\n ellipsoid.cartographicToCartesian(start, scratchCart2),\r\n scratchCart1\r\n );\r\n var lastCartesian = Cartesian3.normalize(\r\n ellipsoid.cartographicToCartesian(end, scratchCart2),\r\n scratchCart2\r\n );\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"value\",\r\n Math.abs(\r\n Math.abs(Cartesian3.angleBetween(firstCartesian, lastCartesian)) - Math.PI\r\n ),\r\n 0.0125\r\n );\r\n //>>includeEnd('debug');\r\n\r\n vincentyInverseFormula(\r\n ellipsoidGeodesic,\r\n ellipsoid.maximumRadius,\r\n ellipsoid.minimumRadius,\r\n start.longitude,\r\n start.latitude,\r\n end.longitude,\r\n end.latitude\r\n );\r\n\r\n ellipsoidGeodesic._start = Cartographic.clone(\r\n start,\r\n ellipsoidGeodesic._start\r\n );\r\n ellipsoidGeodesic._end = Cartographic.clone(end, ellipsoidGeodesic._end);\r\n ellipsoidGeodesic._start.height = 0;\r\n ellipsoidGeodesic._end.height = 0;\r\n\r\n setConstants(ellipsoidGeodesic);\r\n}\r\n\r\n/**\r\n * Initializes a geodesic on the ellipsoid connecting the two provided planetodetic points.\r\n *\r\n * @alias EllipsoidGeodesic\r\n * @constructor\r\n *\r\n * @param {Cartographic} [start] The initial planetodetic point on the path.\r\n * @param {Cartographic} [end] The final planetodetic point on the path.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the geodesic lies.\r\n */\r\nfunction EllipsoidGeodesic(start, end, ellipsoid) {\r\n var e = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n this._ellipsoid = e;\r\n this._start = new Cartographic();\r\n this._end = new Cartographic();\r\n\r\n this._constants = {};\r\n this._startHeading = undefined;\r\n this._endHeading = undefined;\r\n this._distance = undefined;\r\n this._uSquared = undefined;\r\n\r\n if (defined(start) && defined(end)) {\r\n computeProperties(this, start, end, e);\r\n }\r\n}\r\n\r\nObject.defineProperties(EllipsoidGeodesic.prototype, {\r\n /**\r\n * Gets the ellipsoid.\r\n * @memberof EllipsoidGeodesic.prototype\r\n * @type {Ellipsoid}\r\n * @readonly\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the surface distance between the start and end point\r\n * @memberof EllipsoidGeodesic.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n surfaceDistance: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"distance\", this._distance);\r\n //>>includeEnd('debug');\r\n\r\n return this._distance;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the initial planetodetic point on the path.\r\n * @memberof EllipsoidGeodesic.prototype\r\n * @type {Cartographic}\r\n * @readonly\r\n */\r\n start: {\r\n get: function () {\r\n return this._start;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the final planetodetic point on the path.\r\n * @memberof EllipsoidGeodesic.prototype\r\n * @type {Cartographic}\r\n * @readonly\r\n */\r\n end: {\r\n get: function () {\r\n return this._end;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the heading at the initial point.\r\n * @memberof EllipsoidGeodesic.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n startHeading: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"distance\", this._distance);\r\n //>>includeEnd('debug');\r\n\r\n return this._startHeading;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the heading at the final point.\r\n * @memberof EllipsoidGeodesic.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n endHeading: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"distance\", this._distance);\r\n //>>includeEnd('debug');\r\n\r\n return this._endHeading;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Sets the start and end points of the geodesic\r\n *\r\n * @param {Cartographic} start The initial planetodetic point on the path.\r\n * @param {Cartographic} end The final planetodetic point on the path.\r\n */\r\nEllipsoidGeodesic.prototype.setEndPoints = function (start, end) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"start\", start);\r\n Check.defined(\"end\", end);\r\n //>>includeEnd('debug');\r\n\r\n computeProperties(this, start, end, this._ellipsoid);\r\n};\r\n\r\n/**\r\n * Provides the location of a point at the indicated portion along the geodesic.\r\n *\r\n * @param {Number} fraction The portion of the distance between the initial and final points.\r\n * @param {Cartographic} [result] The object in which to store the result.\r\n * @returns {Cartographic} The location of the point along the geodesic.\r\n */\r\nEllipsoidGeodesic.prototype.interpolateUsingFraction = function (\r\n fraction,\r\n result\r\n) {\r\n return this.interpolateUsingSurfaceDistance(\r\n this._distance * fraction,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Provides the location of a point at the indicated distance along the geodesic.\r\n *\r\n * @param {Number} distance The distance from the inital point to the point of interest along the geodesic\r\n * @param {Cartographic} [result] The object in which to store the result.\r\n * @returns {Cartographic} The location of the point along the geodesic.\r\n *\r\n * @exception {DeveloperError} start and end must be set before calling function interpolateUsingSurfaceDistance\r\n */\r\nEllipsoidGeodesic.prototype.interpolateUsingSurfaceDistance = function (\r\n distance,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"distance\", this._distance);\r\n //>>includeEnd('debug');\r\n\r\n var constants = this._constants;\r\n\r\n var s = constants.distanceRatio + distance / constants.b;\r\n\r\n var cosine2S = Math.cos(2.0 * s);\r\n var cosine4S = Math.cos(4.0 * s);\r\n var cosine6S = Math.cos(6.0 * s);\r\n var sine2S = Math.sin(2.0 * s);\r\n var sine4S = Math.sin(4.0 * s);\r\n var sine6S = Math.sin(6.0 * s);\r\n var sine8S = Math.sin(8.0 * s);\r\n\r\n var s2 = s * s;\r\n var s3 = s * s2;\r\n\r\n var u8Over256 = constants.u8Over256;\r\n var u2Over4 = constants.u2Over4;\r\n var u6Over64 = constants.u6Over64;\r\n var u4Over16 = constants.u4Over16;\r\n var sigma =\r\n (2.0 * s3 * u8Over256 * cosine2S) / 3.0 +\r\n s *\r\n (1.0 -\r\n u2Over4 +\r\n (7.0 * u4Over16) / 4.0 -\r\n (15.0 * u6Over64) / 4.0 +\r\n (579.0 * u8Over256) / 64.0 -\r\n (u4Over16 - (15.0 * u6Over64) / 4.0 + (187.0 * u8Over256) / 16.0) *\r\n cosine2S -\r\n ((5.0 * u6Over64) / 4.0 - (115.0 * u8Over256) / 16.0) * cosine4S -\r\n (29.0 * u8Over256 * cosine6S) / 16.0) +\r\n (u2Over4 / 2.0 -\r\n u4Over16 +\r\n (71.0 * u6Over64) / 32.0 -\r\n (85.0 * u8Over256) / 16.0) *\r\n sine2S +\r\n ((5.0 * u4Over16) / 16.0 -\r\n (5.0 * u6Over64) / 4.0 +\r\n (383.0 * u8Over256) / 96.0) *\r\n sine4S -\r\n s2 *\r\n ((u6Over64 - (11.0 * u8Over256) / 2.0) * sine2S +\r\n (5.0 * u8Over256 * sine4S) / 2.0) +\r\n ((29.0 * u6Over64) / 96.0 - (29.0 * u8Over256) / 16.0) * sine6S +\r\n (539.0 * u8Over256 * sine8S) / 1536.0;\r\n\r\n var theta = Math.asin(Math.sin(sigma) * constants.cosineAlpha);\r\n var latitude = Math.atan((constants.a / constants.b) * Math.tan(theta));\r\n\r\n // Redefine in terms of relative argument of latitude.\r\n sigma = sigma - constants.sigma;\r\n\r\n var cosineTwiceSigmaMidpoint = Math.cos(2.0 * constants.sigma + sigma);\r\n\r\n var sineSigma = Math.sin(sigma);\r\n var cosineSigma = Math.cos(sigma);\r\n\r\n var cc = constants.cosineU * cosineSigma;\r\n var ss = constants.sineU * sineSigma;\r\n\r\n var lambda = Math.atan2(\r\n sineSigma * constants.sineHeading,\r\n cc - ss * constants.cosineHeading\r\n );\r\n\r\n var l =\r\n lambda -\r\n computeDeltaLambda(\r\n constants.f,\r\n constants.sineAlpha,\r\n constants.cosineSquaredAlpha,\r\n sigma,\r\n sineSigma,\r\n cosineSigma,\r\n cosineTwiceSigmaMidpoint\r\n );\r\n\r\n if (defined(result)) {\r\n result.longitude = this._start.longitude + l;\r\n result.latitude = latitude;\r\n result.height = 0.0;\r\n return result;\r\n }\r\n\r\n return new Cartographic(this._start.longitude + l, latitude, 0.0);\r\n};\r\nexport default EllipsoidGeodesic;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport EllipsoidGeodesic from \"./EllipsoidGeodesic.js\";\r\nimport EllipsoidRhumbLine from \"./EllipsoidRhumbLine.js\";\r\nimport IntersectionTests from \"./IntersectionTests.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport Plane from \"./Plane.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar PolylinePipeline = {};\r\n\r\nPolylinePipeline.numberOfPoints = function (p0, p1, minDistance) {\r\n var distance = Cartesian3.distance(p0, p1);\r\n return Math.ceil(distance / minDistance);\r\n};\r\n\r\nPolylinePipeline.numberOfPointsRhumbLine = function (p0, p1, granularity) {\r\n var radiansDistanceSquared =\r\n Math.pow(p0.longitude - p1.longitude, 2) +\r\n Math.pow(p0.latitude - p1.latitude, 2);\r\n\r\n return Math.max(\r\n 1,\r\n Math.ceil(Math.sqrt(radiansDistanceSquared / (granularity * granularity)))\r\n );\r\n};\r\n\r\nvar cartoScratch = new Cartographic();\r\nPolylinePipeline.extractHeights = function (positions, ellipsoid) {\r\n var length = positions.length;\r\n var heights = new Array(length);\r\n for (var i = 0; i < length; i++) {\r\n var p = positions[i];\r\n heights[i] = ellipsoid.cartesianToCartographic(p, cartoScratch).height;\r\n }\r\n return heights;\r\n};\r\n\r\nvar wrapLongitudeInversMatrix = new Matrix4();\r\nvar wrapLongitudeOrigin = new Cartesian3();\r\nvar wrapLongitudeXZNormal = new Cartesian3();\r\nvar wrapLongitudeXZPlane = new Plane(Cartesian3.UNIT_X, 0.0);\r\nvar wrapLongitudeYZNormal = new Cartesian3();\r\nvar wrapLongitudeYZPlane = new Plane(Cartesian3.UNIT_X, 0.0);\r\nvar wrapLongitudeIntersection = new Cartesian3();\r\nvar wrapLongitudeOffset = new Cartesian3();\r\n\r\nvar subdivideHeightsScratchArray = [];\r\n\r\nfunction subdivideHeights(numPoints, h0, h1) {\r\n var heights = subdivideHeightsScratchArray;\r\n heights.length = numPoints;\r\n\r\n var i;\r\n if (h0 === h1) {\r\n for (i = 0; i < numPoints; i++) {\r\n heights[i] = h0;\r\n }\r\n return heights;\r\n }\r\n\r\n var dHeight = h1 - h0;\r\n var heightPerVertex = dHeight / numPoints;\r\n\r\n for (i = 0; i < numPoints; i++) {\r\n var h = h0 + i * heightPerVertex;\r\n heights[i] = h;\r\n }\r\n\r\n return heights;\r\n}\r\n\r\nvar carto1 = new Cartographic();\r\nvar carto2 = new Cartographic();\r\nvar cartesian = new Cartesian3();\r\nvar scaleFirst = new Cartesian3();\r\nvar scaleLast = new Cartesian3();\r\nvar ellipsoidGeodesic = new EllipsoidGeodesic();\r\nvar ellipsoidRhumb = new EllipsoidRhumbLine();\r\n\r\n//Returns subdivided line scaled to ellipsoid surface starting at p1 and ending at p2.\r\n//Result includes p1, but not include p2. This function is called for a sequence of line segments,\r\n//and this prevents duplication of end point.\r\nfunction generateCartesianArc(\r\n p0,\r\n p1,\r\n minDistance,\r\n ellipsoid,\r\n h0,\r\n h1,\r\n array,\r\n offset\r\n) {\r\n var first = ellipsoid.scaleToGeodeticSurface(p0, scaleFirst);\r\n var last = ellipsoid.scaleToGeodeticSurface(p1, scaleLast);\r\n var numPoints = PolylinePipeline.numberOfPoints(p0, p1, minDistance);\r\n var start = ellipsoid.cartesianToCartographic(first, carto1);\r\n var end = ellipsoid.cartesianToCartographic(last, carto2);\r\n var heights = subdivideHeights(numPoints, h0, h1);\r\n\r\n ellipsoidGeodesic.setEndPoints(start, end);\r\n var surfaceDistanceBetweenPoints =\r\n ellipsoidGeodesic.surfaceDistance / numPoints;\r\n\r\n var index = offset;\r\n start.height = h0;\r\n var cart = ellipsoid.cartographicToCartesian(start, cartesian);\r\n Cartesian3.pack(cart, array, index);\r\n index += 3;\r\n\r\n for (var i = 1; i < numPoints; i++) {\r\n var carto = ellipsoidGeodesic.interpolateUsingSurfaceDistance(\r\n i * surfaceDistanceBetweenPoints,\r\n carto2\r\n );\r\n carto.height = heights[i];\r\n cart = ellipsoid.cartographicToCartesian(carto, cartesian);\r\n Cartesian3.pack(cart, array, index);\r\n index += 3;\r\n }\r\n\r\n return index;\r\n}\r\n\r\n//Returns subdivided line scaled to ellipsoid surface starting at p1 and ending at p2.\r\n//Result includes p1, but not include p2. This function is called for a sequence of line segments,\r\n//and this prevents duplication of end point.\r\nfunction generateCartesianRhumbArc(\r\n p0,\r\n p1,\r\n granularity,\r\n ellipsoid,\r\n h0,\r\n h1,\r\n array,\r\n offset\r\n) {\r\n var start = ellipsoid.cartesianToCartographic(p0, carto1);\r\n var end = ellipsoid.cartesianToCartographic(p1, carto2);\r\n var numPoints = PolylinePipeline.numberOfPointsRhumbLine(\r\n start,\r\n end,\r\n granularity\r\n );\r\n start.height = 0.0;\r\n end.height = 0.0;\r\n var heights = subdivideHeights(numPoints, h0, h1);\r\n\r\n if (!ellipsoidRhumb.ellipsoid.equals(ellipsoid)) {\r\n ellipsoidRhumb = new EllipsoidRhumbLine(undefined, undefined, ellipsoid);\r\n }\r\n ellipsoidRhumb.setEndPoints(start, end);\r\n var surfaceDistanceBetweenPoints = ellipsoidRhumb.surfaceDistance / numPoints;\r\n\r\n var index = offset;\r\n start.height = h0;\r\n var cart = ellipsoid.cartographicToCartesian(start, cartesian);\r\n Cartesian3.pack(cart, array, index);\r\n index += 3;\r\n\r\n for (var i = 1; i < numPoints; i++) {\r\n var carto = ellipsoidRhumb.interpolateUsingSurfaceDistance(\r\n i * surfaceDistanceBetweenPoints,\r\n carto2\r\n );\r\n carto.height = heights[i];\r\n cart = ellipsoid.cartographicToCartesian(carto, cartesian);\r\n Cartesian3.pack(cart, array, index);\r\n index += 3;\r\n }\r\n\r\n return index;\r\n}\r\n\r\n/**\r\n * Breaks a {@link Polyline} into segments such that it does not cross the ±180 degree meridian of an ellipsoid.\r\n *\r\n * @param {Cartesian3[]} positions The polyline's Cartesian positions.\r\n * @param {Matrix4} [modelMatrix=Matrix4.IDENTITY] The polyline's model matrix. Assumed to be an affine\r\n * transformation matrix, where the upper left 3x3 elements are a rotation matrix, and\r\n * the upper three elements in the fourth column are the translation. The bottom row is assumed to be [0, 0, 0, 1].\r\n * The matrix is not verified to be in the proper form.\r\n * @returns {Object} An object with a positions property that is an array of positions and a\r\n * segments property.\r\n *\r\n *\r\n * @example\r\n * var polylines = new Cesium.PolylineCollection();\r\n * var polyline = polylines.add(...);\r\n * var positions = polyline.positions;\r\n * var modelMatrix = polylines.modelMatrix;\r\n * var segments = Cesium.PolylinePipeline.wrapLongitude(positions, modelMatrix);\r\n *\r\n * @see PolygonPipeline.wrapLongitude\r\n * @see Polyline\r\n * @see PolylineCollection\r\n */\r\nPolylinePipeline.wrapLongitude = function (positions, modelMatrix) {\r\n var cartesians = [];\r\n var segments = [];\r\n\r\n if (defined(positions) && positions.length > 0) {\r\n modelMatrix = defaultValue(modelMatrix, Matrix4.IDENTITY);\r\n var inverseModelMatrix = Matrix4.inverseTransformation(\r\n modelMatrix,\r\n wrapLongitudeInversMatrix\r\n );\r\n\r\n var origin = Matrix4.multiplyByPoint(\r\n inverseModelMatrix,\r\n Cartesian3.ZERO,\r\n wrapLongitudeOrigin\r\n );\r\n var xzNormal = Cartesian3.normalize(\r\n Matrix4.multiplyByPointAsVector(\r\n inverseModelMatrix,\r\n Cartesian3.UNIT_Y,\r\n wrapLongitudeXZNormal\r\n ),\r\n wrapLongitudeXZNormal\r\n );\r\n var xzPlane = Plane.fromPointNormal(origin, xzNormal, wrapLongitudeXZPlane);\r\n var yzNormal = Cartesian3.normalize(\r\n Matrix4.multiplyByPointAsVector(\r\n inverseModelMatrix,\r\n Cartesian3.UNIT_X,\r\n wrapLongitudeYZNormal\r\n ),\r\n wrapLongitudeYZNormal\r\n );\r\n var yzPlane = Plane.fromPointNormal(origin, yzNormal, wrapLongitudeYZPlane);\r\n\r\n var count = 1;\r\n cartesians.push(Cartesian3.clone(positions[0]));\r\n var prev = cartesians[0];\r\n\r\n var length = positions.length;\r\n for (var i = 1; i < length; ++i) {\r\n var cur = positions[i];\r\n\r\n // intersects the IDL if either endpoint is on the negative side of the yz-plane\r\n if (\r\n Plane.getPointDistance(yzPlane, prev) < 0.0 ||\r\n Plane.getPointDistance(yzPlane, cur) < 0.0\r\n ) {\r\n // and intersects the xz-plane\r\n var intersection = IntersectionTests.lineSegmentPlane(\r\n prev,\r\n cur,\r\n xzPlane,\r\n wrapLongitudeIntersection\r\n );\r\n if (defined(intersection)) {\r\n // move point on the xz-plane slightly away from the plane\r\n var offset = Cartesian3.multiplyByScalar(\r\n xzNormal,\r\n 5.0e-9,\r\n wrapLongitudeOffset\r\n );\r\n if (Plane.getPointDistance(xzPlane, prev) < 0.0) {\r\n Cartesian3.negate(offset, offset);\r\n }\r\n\r\n cartesians.push(\r\n Cartesian3.add(intersection, offset, new Cartesian3())\r\n );\r\n segments.push(count + 1);\r\n\r\n Cartesian3.negate(offset, offset);\r\n cartesians.push(\r\n Cartesian3.add(intersection, offset, new Cartesian3())\r\n );\r\n count = 1;\r\n }\r\n }\r\n\r\n cartesians.push(Cartesian3.clone(positions[i]));\r\n count++;\r\n\r\n prev = cur;\r\n }\r\n\r\n segments.push(count);\r\n }\r\n\r\n return {\r\n positions: cartesians,\r\n lengths: segments,\r\n };\r\n};\r\n\r\n/**\r\n * Subdivides polyline and raises all points to the specified height. Returns an array of numbers to represent the positions.\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions The array of type {Cartesian3} representing positions.\r\n * @param {Number|Number[]} [options.height=0.0] A number or array of numbers representing the heights of each position.\r\n * @param {Number} [options.granularity = CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the positions lie.\r\n * @returns {Number[]} A new array of positions of type {Number} that have been subdivided and raised to the surface of the ellipsoid.\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromDegreesArray([\r\n * -105.0, 40.0,\r\n * -100.0, 38.0,\r\n * -105.0, 35.0,\r\n * -100.0, 32.0\r\n * ]);\r\n * var surfacePositions = Cesium.PolylinePipeline.generateArc({\r\n * positons: positions\r\n * });\r\n */\r\nPolylinePipeline.generateArc = function (options) {\r\n if (!defined(options)) {\r\n options = {};\r\n }\r\n var positions = options.positions;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions)) {\r\n throw new DeveloperError(\"options.positions is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = positions.length;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var height = defaultValue(options.height, 0);\r\n var hasHeightArray = Array.isArray(height);\r\n\r\n if (length < 1) {\r\n return [];\r\n } else if (length === 1) {\r\n var p = ellipsoid.scaleToGeodeticSurface(positions[0], scaleFirst);\r\n height = hasHeightArray ? height[0] : height;\r\n if (height !== 0) {\r\n var n = ellipsoid.geodeticSurfaceNormal(p, cartesian);\r\n Cartesian3.multiplyByScalar(n, height, n);\r\n Cartesian3.add(p, n, p);\r\n }\r\n\r\n return [p.x, p.y, p.z];\r\n }\r\n\r\n var minDistance = options.minDistance;\r\n if (!defined(minDistance)) {\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n minDistance = CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);\r\n }\r\n\r\n var numPoints = 0;\r\n var i;\r\n\r\n for (i = 0; i < length - 1; i++) {\r\n numPoints += PolylinePipeline.numberOfPoints(\r\n positions[i],\r\n positions[i + 1],\r\n minDistance\r\n );\r\n }\r\n\r\n var arrayLength = (numPoints + 1) * 3;\r\n var newPositions = new Array(arrayLength);\r\n var offset = 0;\r\n\r\n for (i = 0; i < length - 1; i++) {\r\n var p0 = positions[i];\r\n var p1 = positions[i + 1];\r\n\r\n var h0 = hasHeightArray ? height[i] : height;\r\n var h1 = hasHeightArray ? height[i + 1] : height;\r\n\r\n offset = generateCartesianArc(\r\n p0,\r\n p1,\r\n minDistance,\r\n ellipsoid,\r\n h0,\r\n h1,\r\n newPositions,\r\n offset\r\n );\r\n }\r\n\r\n subdivideHeightsScratchArray.length = 0;\r\n\r\n var lastPoint = positions[length - 1];\r\n var carto = ellipsoid.cartesianToCartographic(lastPoint, carto1);\r\n carto.height = hasHeightArray ? height[length - 1] : height;\r\n var cart = ellipsoid.cartographicToCartesian(carto, cartesian);\r\n Cartesian3.pack(cart, newPositions, arrayLength - 3);\r\n\r\n return newPositions;\r\n};\r\n\r\nvar scratchCartographic0 = new Cartographic();\r\nvar scratchCartographic1 = new Cartographic();\r\n\r\n/**\r\n * Subdivides polyline and raises all points to the specified height using Rhumb lines. Returns an array of numbers to represent the positions.\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions The array of type {Cartesian3} representing positions.\r\n * @param {Number|Number[]} [options.height=0.0] A number or array of numbers representing the heights of each position.\r\n * @param {Number} [options.granularity = CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the positions lie.\r\n * @returns {Number[]} A new array of positions of type {Number} that have been subdivided and raised to the surface of the ellipsoid.\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromDegreesArray([\r\n * -105.0, 40.0,\r\n * -100.0, 38.0,\r\n * -105.0, 35.0,\r\n * -100.0, 32.0\r\n * ]);\r\n * var surfacePositions = Cesium.PolylinePipeline.generateRhumbArc({\r\n * positons: positions\r\n * });\r\n */\r\nPolylinePipeline.generateRhumbArc = function (options) {\r\n if (!defined(options)) {\r\n options = {};\r\n }\r\n var positions = options.positions;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions)) {\r\n throw new DeveloperError(\"options.positions is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = positions.length;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var height = defaultValue(options.height, 0);\r\n var hasHeightArray = Array.isArray(height);\r\n\r\n if (length < 1) {\r\n return [];\r\n } else if (length === 1) {\r\n var p = ellipsoid.scaleToGeodeticSurface(positions[0], scaleFirst);\r\n height = hasHeightArray ? height[0] : height;\r\n if (height !== 0) {\r\n var n = ellipsoid.geodeticSurfaceNormal(p, cartesian);\r\n Cartesian3.multiplyByScalar(n, height, n);\r\n Cartesian3.add(p, n, p);\r\n }\r\n\r\n return [p.x, p.y, p.z];\r\n }\r\n\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n\r\n var numPoints = 0;\r\n var i;\r\n\r\n var c0 = ellipsoid.cartesianToCartographic(\r\n positions[0],\r\n scratchCartographic0\r\n );\r\n var c1;\r\n for (i = 0; i < length - 1; i++) {\r\n c1 = ellipsoid.cartesianToCartographic(\r\n positions[i + 1],\r\n scratchCartographic1\r\n );\r\n numPoints += PolylinePipeline.numberOfPointsRhumbLine(c0, c1, granularity);\r\n c0 = Cartographic.clone(c1, scratchCartographic0);\r\n }\r\n\r\n var arrayLength = (numPoints + 1) * 3;\r\n var newPositions = new Array(arrayLength);\r\n var offset = 0;\r\n\r\n for (i = 0; i < length - 1; i++) {\r\n var p0 = positions[i];\r\n var p1 = positions[i + 1];\r\n\r\n var h0 = hasHeightArray ? height[i] : height;\r\n var h1 = hasHeightArray ? height[i + 1] : height;\r\n\r\n offset = generateCartesianRhumbArc(\r\n p0,\r\n p1,\r\n granularity,\r\n ellipsoid,\r\n h0,\r\n h1,\r\n newPositions,\r\n offset\r\n );\r\n }\r\n\r\n subdivideHeightsScratchArray.length = 0;\r\n\r\n var lastPoint = positions[length - 1];\r\n var carto = ellipsoid.cartesianToCartographic(lastPoint, carto1);\r\n carto.height = hasHeightArray ? height[length - 1] : height;\r\n var cart = ellipsoid.cartographicToCartesian(carto, cartesian);\r\n Cartesian3.pack(cart, newPositions, arrayLength - 3);\r\n\r\n return newPositions;\r\n};\r\n\r\n/**\r\n * Subdivides polyline and raises all points to the specified height. Returns an array of new {Cartesian3} positions.\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions The array of type {Cartesian3} representing positions.\r\n * @param {Number|Number[]} [options.height=0.0] A number or array of numbers representing the heights of each position.\r\n * @param {Number} [options.granularity = CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the positions lie.\r\n * @returns {Cartesian3[]} A new array of cartesian3 positions that have been subdivided and raised to the surface of the ellipsoid.\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromDegreesArray([\r\n * -105.0, 40.0,\r\n * -100.0, 38.0,\r\n * -105.0, 35.0,\r\n * -100.0, 32.0\r\n * ]);\r\n * var surfacePositions = Cesium.PolylinePipeline.generateCartesianArc({\r\n * positons: positions\r\n * });\r\n */\r\nPolylinePipeline.generateCartesianArc = function (options) {\r\n var numberArray = PolylinePipeline.generateArc(options);\r\n var size = numberArray.length / 3;\r\n var newPositions = new Array(size);\r\n for (var i = 0; i < size; i++) {\r\n newPositions[i] = Cartesian3.unpack(numberArray, i * 3);\r\n }\r\n return newPositions;\r\n};\r\n\r\n/**\r\n * Subdivides polyline and raises all points to the specified height using Rhumb Lines. Returns an array of new {Cartesian3} positions.\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions The array of type {Cartesian3} representing positions.\r\n * @param {Number|Number[]} [options.height=0.0] A number or array of numbers representing the heights of each position.\r\n * @param {Number} [options.granularity = CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the positions lie.\r\n * @returns {Cartesian3[]} A new array of cartesian3 positions that have been subdivided and raised to the surface of the ellipsoid.\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromDegreesArray([\r\n * -105.0, 40.0,\r\n * -100.0, 38.0,\r\n * -105.0, 35.0,\r\n * -100.0, 32.0\r\n * ]);\r\n * var surfacePositions = Cesium.PolylinePipeline.generateCartesianRhumbArc({\r\n * positons: positions\r\n * });\r\n */\r\nPolylinePipeline.generateCartesianRhumbArc = function (options) {\r\n var numberArray = PolylinePipeline.generateRhumbArc(options);\r\n var size = numberArray.length / 3;\r\n var newPositions = new Array(size);\r\n for (var i = 0; i < size; i++) {\r\n newPositions[i] = Cartesian3.unpack(numberArray, i * 3);\r\n }\r\n return newPositions;\r\n};\r\nexport default PolylinePipeline;\r\n","import Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport CornerType from \"./CornerType.js\";\r\nimport EllipsoidTangentPlane from \"./EllipsoidTangentPlane.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport PolylinePipeline from \"./PolylinePipeline.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport Transforms from \"./Transforms.js\";\r\n\r\nvar scratch2Array = [new Cartesian3(), new Cartesian3()];\r\nvar scratchCartesian1 = new Cartesian3();\r\nvar scratchCartesian2 = new Cartesian3();\r\nvar scratchCartesian3 = new Cartesian3();\r\nvar scratchCartesian4 = new Cartesian3();\r\nvar scratchCartesian5 = new Cartesian3();\r\nvar scratchCartesian6 = new Cartesian3();\r\nvar scratchCartesian7 = new Cartesian3();\r\nvar scratchCartesian8 = new Cartesian3();\r\nvar scratchCartesian9 = new Cartesian3();\r\n\r\nvar scratch1 = new Cartesian3();\r\nvar scratch2 = new Cartesian3();\r\n\r\n/**\r\n * @private\r\n */\r\nvar PolylineVolumeGeometryLibrary = {};\r\n\r\nvar cartographic = new Cartographic();\r\nfunction scaleToSurface(positions, ellipsoid) {\r\n var heights = new Array(positions.length);\r\n for (var i = 0; i < positions.length; i++) {\r\n var pos = positions[i];\r\n cartographic = ellipsoid.cartesianToCartographic(pos, cartographic);\r\n heights[i] = cartographic.height;\r\n positions[i] = ellipsoid.scaleToGeodeticSurface(pos, pos);\r\n }\r\n return heights;\r\n}\r\n\r\nfunction subdivideHeights(points, h0, h1, granularity) {\r\n var p0 = points[0];\r\n var p1 = points[1];\r\n var angleBetween = Cartesian3.angleBetween(p0, p1);\r\n var numPoints = Math.ceil(angleBetween / granularity);\r\n var heights = new Array(numPoints);\r\n var i;\r\n if (h0 === h1) {\r\n for (i = 0; i < numPoints; i++) {\r\n heights[i] = h0;\r\n }\r\n heights.push(h1);\r\n return heights;\r\n }\r\n\r\n var dHeight = h1 - h0;\r\n var heightPerVertex = dHeight / numPoints;\r\n\r\n for (i = 1; i < numPoints; i++) {\r\n var h = h0 + i * heightPerVertex;\r\n heights[i] = h;\r\n }\r\n\r\n heights[0] = h0;\r\n heights.push(h1);\r\n return heights;\r\n}\r\n\r\nvar nextScratch = new Cartesian3();\r\nvar prevScratch = new Cartesian3();\r\n\r\nfunction computeRotationAngle(start, end, position, ellipsoid) {\r\n var tangentPlane = new EllipsoidTangentPlane(position, ellipsoid);\r\n var next = tangentPlane.projectPointOntoPlane(\r\n Cartesian3.add(position, start, nextScratch),\r\n nextScratch\r\n );\r\n var prev = tangentPlane.projectPointOntoPlane(\r\n Cartesian3.add(position, end, prevScratch),\r\n prevScratch\r\n );\r\n var angle = Cartesian2.angleBetween(next, prev);\r\n\r\n return prev.x * next.y - prev.y * next.x >= 0.0 ? -angle : angle;\r\n}\r\n\r\nvar negativeX = new Cartesian3(-1, 0, 0);\r\nvar transform = new Matrix4();\r\nvar translation = new Matrix4();\r\nvar rotationZ = new Matrix3();\r\nvar scaleMatrix = Matrix3.IDENTITY.clone();\r\nvar westScratch = new Cartesian3();\r\nvar finalPosScratch = new Cartesian4();\r\nvar heightCartesian = new Cartesian3();\r\nfunction addPosition(\r\n center,\r\n left,\r\n shape,\r\n finalPositions,\r\n ellipsoid,\r\n height,\r\n xScalar,\r\n repeat\r\n) {\r\n var west = westScratch;\r\n var finalPosition = finalPosScratch;\r\n transform = Transforms.eastNorthUpToFixedFrame(center, ellipsoid, transform);\r\n\r\n west = Matrix4.multiplyByPointAsVector(transform, negativeX, west);\r\n west = Cartesian3.normalize(west, west);\r\n var angle = computeRotationAngle(west, left, center, ellipsoid);\r\n rotationZ = Matrix3.fromRotationZ(angle, rotationZ);\r\n\r\n heightCartesian.z = height;\r\n transform = Matrix4.multiplyTransformation(\r\n transform,\r\n Matrix4.fromRotationTranslation(rotationZ, heightCartesian, translation),\r\n transform\r\n );\r\n var scale = scaleMatrix;\r\n scale[0] = xScalar;\r\n\r\n for (var j = 0; j < repeat; j++) {\r\n for (var i = 0; i < shape.length; i += 3) {\r\n finalPosition = Cartesian3.fromArray(shape, i, finalPosition);\r\n finalPosition = Matrix3.multiplyByVector(\r\n scale,\r\n finalPosition,\r\n finalPosition\r\n );\r\n finalPosition = Matrix4.multiplyByPoint(\r\n transform,\r\n finalPosition,\r\n finalPosition\r\n );\r\n finalPositions.push(finalPosition.x, finalPosition.y, finalPosition.z);\r\n }\r\n }\r\n\r\n return finalPositions;\r\n}\r\n\r\nvar centerScratch = new Cartesian3();\r\nfunction addPositions(\r\n centers,\r\n left,\r\n shape,\r\n finalPositions,\r\n ellipsoid,\r\n heights,\r\n xScalar\r\n) {\r\n for (var i = 0; i < centers.length; i += 3) {\r\n var center = Cartesian3.fromArray(centers, i, centerScratch);\r\n finalPositions = addPosition(\r\n center,\r\n left,\r\n shape,\r\n finalPositions,\r\n ellipsoid,\r\n heights[i / 3],\r\n xScalar,\r\n 1\r\n );\r\n }\r\n return finalPositions;\r\n}\r\n\r\nfunction convertShapeTo3DDuplicate(shape2D, boundingRectangle) {\r\n //orientate 2D shape to XZ plane center at (0, 0, 0), duplicate points\r\n var length = shape2D.length;\r\n var shape = new Array(length * 6);\r\n var index = 0;\r\n var xOffset = boundingRectangle.x + boundingRectangle.width / 2;\r\n var yOffset = boundingRectangle.y + boundingRectangle.height / 2;\r\n\r\n var point = shape2D[0];\r\n shape[index++] = point.x - xOffset;\r\n shape[index++] = 0.0;\r\n shape[index++] = point.y - yOffset;\r\n for (var i = 1; i < length; i++) {\r\n point = shape2D[i];\r\n var x = point.x - xOffset;\r\n var z = point.y - yOffset;\r\n shape[index++] = x;\r\n shape[index++] = 0.0;\r\n shape[index++] = z;\r\n\r\n shape[index++] = x;\r\n shape[index++] = 0.0;\r\n shape[index++] = z;\r\n }\r\n point = shape2D[0];\r\n shape[index++] = point.x - xOffset;\r\n shape[index++] = 0.0;\r\n shape[index++] = point.y - yOffset;\r\n\r\n return shape;\r\n}\r\n\r\nfunction convertShapeTo3D(shape2D, boundingRectangle) {\r\n //orientate 2D shape to XZ plane center at (0, 0, 0)\r\n var length = shape2D.length;\r\n var shape = new Array(length * 3);\r\n var index = 0;\r\n var xOffset = boundingRectangle.x + boundingRectangle.width / 2;\r\n var yOffset = boundingRectangle.y + boundingRectangle.height / 2;\r\n\r\n for (var i = 0; i < length; i++) {\r\n shape[index++] = shape2D[i].x - xOffset;\r\n shape[index++] = 0;\r\n shape[index++] = shape2D[i].y - yOffset;\r\n }\r\n\r\n return shape;\r\n}\r\n\r\nvar quaterion = new Quaternion();\r\nvar startPointScratch = new Cartesian3();\r\nvar rotMatrix = new Matrix3();\r\nfunction computeRoundCorner(\r\n pivot,\r\n startPoint,\r\n endPoint,\r\n cornerType,\r\n leftIsOutside,\r\n ellipsoid,\r\n finalPositions,\r\n shape,\r\n height,\r\n duplicatePoints\r\n) {\r\n var angle = Cartesian3.angleBetween(\r\n Cartesian3.subtract(startPoint, pivot, scratch1),\r\n Cartesian3.subtract(endPoint, pivot, scratch2)\r\n );\r\n var granularity =\r\n cornerType === CornerType.BEVELED\r\n ? 0\r\n : Math.ceil(angle / CesiumMath.toRadians(5));\r\n\r\n var m;\r\n if (leftIsOutside) {\r\n m = Matrix3.fromQuaternion(\r\n Quaternion.fromAxisAngle(\r\n Cartesian3.negate(pivot, scratch1),\r\n angle / (granularity + 1),\r\n quaterion\r\n ),\r\n rotMatrix\r\n );\r\n } else {\r\n m = Matrix3.fromQuaternion(\r\n Quaternion.fromAxisAngle(pivot, angle / (granularity + 1), quaterion),\r\n rotMatrix\r\n );\r\n }\r\n\r\n var left;\r\n var surfacePoint;\r\n startPoint = Cartesian3.clone(startPoint, startPointScratch);\r\n if (granularity > 0) {\r\n var repeat = duplicatePoints ? 2 : 1;\r\n for (var i = 0; i < granularity; i++) {\r\n startPoint = Matrix3.multiplyByVector(m, startPoint, startPoint);\r\n left = Cartesian3.subtract(startPoint, pivot, scratch1);\r\n left = Cartesian3.normalize(left, left);\r\n if (!leftIsOutside) {\r\n left = Cartesian3.negate(left, left);\r\n }\r\n surfacePoint = ellipsoid.scaleToGeodeticSurface(startPoint, scratch2);\r\n finalPositions = addPosition(\r\n surfacePoint,\r\n left,\r\n shape,\r\n finalPositions,\r\n ellipsoid,\r\n height,\r\n 1,\r\n repeat\r\n );\r\n }\r\n } else {\r\n left = Cartesian3.subtract(startPoint, pivot, scratch1);\r\n left = Cartesian3.normalize(left, left);\r\n if (!leftIsOutside) {\r\n left = Cartesian3.negate(left, left);\r\n }\r\n surfacePoint = ellipsoid.scaleToGeodeticSurface(startPoint, scratch2);\r\n finalPositions = addPosition(\r\n surfacePoint,\r\n left,\r\n shape,\r\n finalPositions,\r\n ellipsoid,\r\n height,\r\n 1,\r\n 1\r\n );\r\n\r\n endPoint = Cartesian3.clone(endPoint, startPointScratch);\r\n left = Cartesian3.subtract(endPoint, pivot, scratch1);\r\n left = Cartesian3.normalize(left, left);\r\n if (!leftIsOutside) {\r\n left = Cartesian3.negate(left, left);\r\n }\r\n surfacePoint = ellipsoid.scaleToGeodeticSurface(endPoint, scratch2);\r\n finalPositions = addPosition(\r\n surfacePoint,\r\n left,\r\n shape,\r\n finalPositions,\r\n ellipsoid,\r\n height,\r\n 1,\r\n 1\r\n );\r\n }\r\n\r\n return finalPositions;\r\n}\r\n\r\nPolylineVolumeGeometryLibrary.removeDuplicatesFromShape = function (\r\n shapePositions\r\n) {\r\n var length = shapePositions.length;\r\n var cleanedPositions = [];\r\n for (var i0 = length - 1, i1 = 0; i1 < length; i0 = i1++) {\r\n var v0 = shapePositions[i0];\r\n var v1 = shapePositions[i1];\r\n\r\n if (!Cartesian2.equals(v0, v1)) {\r\n cleanedPositions.push(v1); // Shallow copy!\r\n }\r\n }\r\n\r\n return cleanedPositions;\r\n};\r\n\r\nPolylineVolumeGeometryLibrary.angleIsGreaterThanPi = function (\r\n forward,\r\n backward,\r\n position,\r\n ellipsoid\r\n) {\r\n var tangentPlane = new EllipsoidTangentPlane(position, ellipsoid);\r\n var next = tangentPlane.projectPointOntoPlane(\r\n Cartesian3.add(position, forward, nextScratch),\r\n nextScratch\r\n );\r\n var prev = tangentPlane.projectPointOntoPlane(\r\n Cartesian3.add(position, backward, prevScratch),\r\n prevScratch\r\n );\r\n\r\n return prev.x * next.y - prev.y * next.x >= 0.0;\r\n};\r\n\r\nvar scratchForwardProjection = new Cartesian3();\r\nvar scratchBackwardProjection = new Cartesian3();\r\n\r\nPolylineVolumeGeometryLibrary.computePositions = function (\r\n positions,\r\n shape2D,\r\n boundingRectangle,\r\n geometry,\r\n duplicatePoints\r\n) {\r\n var ellipsoid = geometry._ellipsoid;\r\n var heights = scaleToSurface(positions, ellipsoid);\r\n var granularity = geometry._granularity;\r\n var cornerType = geometry._cornerType;\r\n var shapeForSides = duplicatePoints\r\n ? convertShapeTo3DDuplicate(shape2D, boundingRectangle)\r\n : convertShapeTo3D(shape2D, boundingRectangle);\r\n var shapeForEnds = duplicatePoints\r\n ? convertShapeTo3D(shape2D, boundingRectangle)\r\n : undefined;\r\n var heightOffset = boundingRectangle.height / 2;\r\n var width = boundingRectangle.width / 2;\r\n var length = positions.length;\r\n var finalPositions = [];\r\n var ends = duplicatePoints ? [] : undefined;\r\n\r\n var forward = scratchCartesian1;\r\n var backward = scratchCartesian2;\r\n var cornerDirection = scratchCartesian3;\r\n var surfaceNormal = scratchCartesian4;\r\n var pivot = scratchCartesian5;\r\n var start = scratchCartesian6;\r\n var end = scratchCartesian7;\r\n var left = scratchCartesian8;\r\n var previousPosition = scratchCartesian9;\r\n\r\n var position = positions[0];\r\n var nextPosition = positions[1];\r\n surfaceNormal = ellipsoid.geodeticSurfaceNormal(position, surfaceNormal);\r\n forward = Cartesian3.subtract(nextPosition, position, forward);\r\n forward = Cartesian3.normalize(forward, forward);\r\n left = Cartesian3.cross(surfaceNormal, forward, left);\r\n left = Cartesian3.normalize(left, left);\r\n var h0 = heights[0];\r\n var h1 = heights[1];\r\n if (duplicatePoints) {\r\n ends = addPosition(\r\n position,\r\n left,\r\n shapeForEnds,\r\n ends,\r\n ellipsoid,\r\n h0 + heightOffset,\r\n 1,\r\n 1\r\n );\r\n }\r\n previousPosition = Cartesian3.clone(position, previousPosition);\r\n position = nextPosition;\r\n backward = Cartesian3.negate(forward, backward);\r\n var subdividedHeights;\r\n var subdividedPositions;\r\n for (var i = 1; i < length - 1; i++) {\r\n var repeat = duplicatePoints ? 2 : 1;\r\n nextPosition = positions[i + 1];\r\n forward = Cartesian3.subtract(nextPosition, position, forward);\r\n forward = Cartesian3.normalize(forward, forward);\r\n cornerDirection = Cartesian3.add(forward, backward, cornerDirection);\r\n cornerDirection = Cartesian3.normalize(cornerDirection, cornerDirection);\r\n surfaceNormal = ellipsoid.geodeticSurfaceNormal(position, surfaceNormal);\r\n\r\n var forwardProjection = Cartesian3.multiplyByScalar(\r\n surfaceNormal,\r\n Cartesian3.dot(forward, surfaceNormal),\r\n scratchForwardProjection\r\n );\r\n Cartesian3.subtract(forward, forwardProjection, forwardProjection);\r\n Cartesian3.normalize(forwardProjection, forwardProjection);\r\n\r\n var backwardProjection = Cartesian3.multiplyByScalar(\r\n surfaceNormal,\r\n Cartesian3.dot(backward, surfaceNormal),\r\n scratchBackwardProjection\r\n );\r\n Cartesian3.subtract(backward, backwardProjection, backwardProjection);\r\n Cartesian3.normalize(backwardProjection, backwardProjection);\r\n\r\n var doCorner = !CesiumMath.equalsEpsilon(\r\n Math.abs(Cartesian3.dot(forwardProjection, backwardProjection)),\r\n 1.0,\r\n CesiumMath.EPSILON7\r\n );\r\n\r\n if (doCorner) {\r\n cornerDirection = Cartesian3.cross(\r\n cornerDirection,\r\n surfaceNormal,\r\n cornerDirection\r\n );\r\n cornerDirection = Cartesian3.cross(\r\n surfaceNormal,\r\n cornerDirection,\r\n cornerDirection\r\n );\r\n cornerDirection = Cartesian3.normalize(cornerDirection, cornerDirection);\r\n var scalar =\r\n 1 /\r\n Math.max(\r\n 0.25,\r\n Cartesian3.magnitude(\r\n Cartesian3.cross(cornerDirection, backward, scratch1)\r\n )\r\n );\r\n var leftIsOutside = PolylineVolumeGeometryLibrary.angleIsGreaterThanPi(\r\n forward,\r\n backward,\r\n position,\r\n ellipsoid\r\n );\r\n if (leftIsOutside) {\r\n pivot = Cartesian3.add(\r\n position,\r\n Cartesian3.multiplyByScalar(\r\n cornerDirection,\r\n scalar * width,\r\n cornerDirection\r\n ),\r\n pivot\r\n );\r\n start = Cartesian3.add(\r\n pivot,\r\n Cartesian3.multiplyByScalar(left, width, start),\r\n start\r\n );\r\n scratch2Array[0] = Cartesian3.clone(previousPosition, scratch2Array[0]);\r\n scratch2Array[1] = Cartesian3.clone(start, scratch2Array[1]);\r\n subdividedHeights = subdivideHeights(\r\n scratch2Array,\r\n h0 + heightOffset,\r\n h1 + heightOffset,\r\n granularity\r\n );\r\n subdividedPositions = PolylinePipeline.generateArc({\r\n positions: scratch2Array,\r\n granularity: granularity,\r\n ellipsoid: ellipsoid,\r\n });\r\n finalPositions = addPositions(\r\n subdividedPositions,\r\n left,\r\n shapeForSides,\r\n finalPositions,\r\n ellipsoid,\r\n subdividedHeights,\r\n 1\r\n );\r\n left = Cartesian3.cross(surfaceNormal, forward, left);\r\n left = Cartesian3.normalize(left, left);\r\n end = Cartesian3.add(\r\n pivot,\r\n Cartesian3.multiplyByScalar(left, width, end),\r\n end\r\n );\r\n if (\r\n cornerType === CornerType.ROUNDED ||\r\n cornerType === CornerType.BEVELED\r\n ) {\r\n computeRoundCorner(\r\n pivot,\r\n start,\r\n end,\r\n cornerType,\r\n leftIsOutside,\r\n ellipsoid,\r\n finalPositions,\r\n shapeForSides,\r\n h1 + heightOffset,\r\n duplicatePoints\r\n );\r\n } else {\r\n cornerDirection = Cartesian3.negate(cornerDirection, cornerDirection);\r\n finalPositions = addPosition(\r\n position,\r\n cornerDirection,\r\n shapeForSides,\r\n finalPositions,\r\n ellipsoid,\r\n h1 + heightOffset,\r\n scalar,\r\n repeat\r\n );\r\n }\r\n previousPosition = Cartesian3.clone(end, previousPosition);\r\n } else {\r\n pivot = Cartesian3.add(\r\n position,\r\n Cartesian3.multiplyByScalar(\r\n cornerDirection,\r\n scalar * width,\r\n cornerDirection\r\n ),\r\n pivot\r\n );\r\n start = Cartesian3.add(\r\n pivot,\r\n Cartesian3.multiplyByScalar(left, -width, start),\r\n start\r\n );\r\n scratch2Array[0] = Cartesian3.clone(previousPosition, scratch2Array[0]);\r\n scratch2Array[1] = Cartesian3.clone(start, scratch2Array[1]);\r\n subdividedHeights = subdivideHeights(\r\n scratch2Array,\r\n h0 + heightOffset,\r\n h1 + heightOffset,\r\n granularity\r\n );\r\n subdividedPositions = PolylinePipeline.generateArc({\r\n positions: scratch2Array,\r\n granularity: granularity,\r\n ellipsoid: ellipsoid,\r\n });\r\n finalPositions = addPositions(\r\n subdividedPositions,\r\n left,\r\n shapeForSides,\r\n finalPositions,\r\n ellipsoid,\r\n subdividedHeights,\r\n 1\r\n );\r\n left = Cartesian3.cross(surfaceNormal, forward, left);\r\n left = Cartesian3.normalize(left, left);\r\n end = Cartesian3.add(\r\n pivot,\r\n Cartesian3.multiplyByScalar(left, -width, end),\r\n end\r\n );\r\n if (\r\n cornerType === CornerType.ROUNDED ||\r\n cornerType === CornerType.BEVELED\r\n ) {\r\n computeRoundCorner(\r\n pivot,\r\n start,\r\n end,\r\n cornerType,\r\n leftIsOutside,\r\n ellipsoid,\r\n finalPositions,\r\n shapeForSides,\r\n h1 + heightOffset,\r\n duplicatePoints\r\n );\r\n } else {\r\n finalPositions = addPosition(\r\n position,\r\n cornerDirection,\r\n shapeForSides,\r\n finalPositions,\r\n ellipsoid,\r\n h1 + heightOffset,\r\n scalar,\r\n repeat\r\n );\r\n }\r\n previousPosition = Cartesian3.clone(end, previousPosition);\r\n }\r\n backward = Cartesian3.negate(forward, backward);\r\n } else {\r\n finalPositions = addPosition(\r\n previousPosition,\r\n left,\r\n shapeForSides,\r\n finalPositions,\r\n ellipsoid,\r\n h0 + heightOffset,\r\n 1,\r\n 1\r\n );\r\n previousPosition = position;\r\n }\r\n h0 = h1;\r\n h1 = heights[i + 1];\r\n position = nextPosition;\r\n }\r\n\r\n scratch2Array[0] = Cartesian3.clone(previousPosition, scratch2Array[0]);\r\n scratch2Array[1] = Cartesian3.clone(position, scratch2Array[1]);\r\n subdividedHeights = subdivideHeights(\r\n scratch2Array,\r\n h0 + heightOffset,\r\n h1 + heightOffset,\r\n granularity\r\n );\r\n subdividedPositions = PolylinePipeline.generateArc({\r\n positions: scratch2Array,\r\n granularity: granularity,\r\n ellipsoid: ellipsoid,\r\n });\r\n finalPositions = addPositions(\r\n subdividedPositions,\r\n left,\r\n shapeForSides,\r\n finalPositions,\r\n ellipsoid,\r\n subdividedHeights,\r\n 1\r\n );\r\n if (duplicatePoints) {\r\n ends = addPosition(\r\n position,\r\n left,\r\n shapeForEnds,\r\n ends,\r\n ellipsoid,\r\n h1 + heightOffset,\r\n 1,\r\n 1\r\n );\r\n }\r\n\r\n length = finalPositions.length;\r\n var posLength = duplicatePoints ? length + ends.length : length;\r\n var combinedPositions = new Float64Array(posLength);\r\n combinedPositions.set(finalPositions);\r\n if (duplicatePoints) {\r\n combinedPositions.set(ends, length);\r\n }\r\n\r\n return combinedPositions;\r\n};\r\nexport default PolylineVolumeGeometryLibrary;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport CornerType from \"./CornerType.js\";\r\nimport defined from \"./defined.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport PolylinePipeline from \"./PolylinePipeline.js\";\r\nimport PolylineVolumeGeometryLibrary from \"./PolylineVolumeGeometryLibrary.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar CorridorGeometryLibrary = {};\r\n\r\nvar scratch1 = new Cartesian3();\r\nvar scratch2 = new Cartesian3();\r\nvar scratch3 = new Cartesian3();\r\nvar scratch4 = new Cartesian3();\r\n\r\nvar scaleArray2 = [new Cartesian3(), new Cartesian3()];\r\n\r\nvar cartesian1 = new Cartesian3();\r\nvar cartesian2 = new Cartesian3();\r\nvar cartesian3 = new Cartesian3();\r\nvar cartesian4 = new Cartesian3();\r\nvar cartesian5 = new Cartesian3();\r\nvar cartesian6 = new Cartesian3();\r\nvar cartesian7 = new Cartesian3();\r\nvar cartesian8 = new Cartesian3();\r\nvar cartesian9 = new Cartesian3();\r\nvar cartesian10 = new Cartesian3();\r\n\r\nvar quaterion = new Quaternion();\r\nvar rotMatrix = new Matrix3();\r\nfunction computeRoundCorner(\r\n cornerPoint,\r\n startPoint,\r\n endPoint,\r\n cornerType,\r\n leftIsOutside\r\n) {\r\n var angle = Cartesian3.angleBetween(\r\n Cartesian3.subtract(startPoint, cornerPoint, scratch1),\r\n Cartesian3.subtract(endPoint, cornerPoint, scratch2)\r\n );\r\n var granularity =\r\n cornerType === CornerType.BEVELED\r\n ? 1\r\n : Math.ceil(angle / CesiumMath.toRadians(5)) + 1;\r\n\r\n var size = granularity * 3;\r\n var array = new Array(size);\r\n\r\n array[size - 3] = endPoint.x;\r\n array[size - 2] = endPoint.y;\r\n array[size - 1] = endPoint.z;\r\n\r\n var m;\r\n if (leftIsOutside) {\r\n m = Matrix3.fromQuaternion(\r\n Quaternion.fromAxisAngle(\r\n Cartesian3.negate(cornerPoint, scratch1),\r\n angle / granularity,\r\n quaterion\r\n ),\r\n rotMatrix\r\n );\r\n } else {\r\n m = Matrix3.fromQuaternion(\r\n Quaternion.fromAxisAngle(cornerPoint, angle / granularity, quaterion),\r\n rotMatrix\r\n );\r\n }\r\n\r\n var index = 0;\r\n startPoint = Cartesian3.clone(startPoint, scratch1);\r\n for (var i = 0; i < granularity; i++) {\r\n startPoint = Matrix3.multiplyByVector(m, startPoint, startPoint);\r\n array[index++] = startPoint.x;\r\n array[index++] = startPoint.y;\r\n array[index++] = startPoint.z;\r\n }\r\n\r\n return array;\r\n}\r\n\r\nfunction addEndCaps(calculatedPositions) {\r\n var cornerPoint = cartesian1;\r\n var startPoint = cartesian2;\r\n var endPoint = cartesian3;\r\n\r\n var leftEdge = calculatedPositions[1];\r\n startPoint = Cartesian3.fromArray(\r\n calculatedPositions[1],\r\n leftEdge.length - 3,\r\n startPoint\r\n );\r\n endPoint = Cartesian3.fromArray(calculatedPositions[0], 0, endPoint);\r\n cornerPoint = Cartesian3.midpoint(startPoint, endPoint, cornerPoint);\r\n var firstEndCap = computeRoundCorner(\r\n cornerPoint,\r\n startPoint,\r\n endPoint,\r\n CornerType.ROUNDED,\r\n false\r\n );\r\n\r\n var length = calculatedPositions.length - 1;\r\n var rightEdge = calculatedPositions[length - 1];\r\n leftEdge = calculatedPositions[length];\r\n startPoint = Cartesian3.fromArray(\r\n rightEdge,\r\n rightEdge.length - 3,\r\n startPoint\r\n );\r\n endPoint = Cartesian3.fromArray(leftEdge, 0, endPoint);\r\n cornerPoint = Cartesian3.midpoint(startPoint, endPoint, cornerPoint);\r\n var lastEndCap = computeRoundCorner(\r\n cornerPoint,\r\n startPoint,\r\n endPoint,\r\n CornerType.ROUNDED,\r\n false\r\n );\r\n\r\n return [firstEndCap, lastEndCap];\r\n}\r\n\r\nfunction computeMiteredCorner(\r\n position,\r\n leftCornerDirection,\r\n lastPoint,\r\n leftIsOutside\r\n) {\r\n var cornerPoint = scratch1;\r\n if (leftIsOutside) {\r\n cornerPoint = Cartesian3.add(position, leftCornerDirection, cornerPoint);\r\n } else {\r\n leftCornerDirection = Cartesian3.negate(\r\n leftCornerDirection,\r\n leftCornerDirection\r\n );\r\n cornerPoint = Cartesian3.add(position, leftCornerDirection, cornerPoint);\r\n }\r\n return [\r\n cornerPoint.x,\r\n cornerPoint.y,\r\n cornerPoint.z,\r\n lastPoint.x,\r\n lastPoint.y,\r\n lastPoint.z,\r\n ];\r\n}\r\n\r\nfunction addShiftedPositions(positions, left, scalar, calculatedPositions) {\r\n var rightPositions = new Array(positions.length);\r\n var leftPositions = new Array(positions.length);\r\n var scaledLeft = Cartesian3.multiplyByScalar(left, scalar, scratch1);\r\n var scaledRight = Cartesian3.negate(scaledLeft, scratch2);\r\n var rightIndex = 0;\r\n var leftIndex = positions.length - 1;\r\n\r\n for (var i = 0; i < positions.length; i += 3) {\r\n var pos = Cartesian3.fromArray(positions, i, scratch3);\r\n var rightPos = Cartesian3.add(pos, scaledRight, scratch4);\r\n rightPositions[rightIndex++] = rightPos.x;\r\n rightPositions[rightIndex++] = rightPos.y;\r\n rightPositions[rightIndex++] = rightPos.z;\r\n\r\n var leftPos = Cartesian3.add(pos, scaledLeft, scratch4);\r\n leftPositions[leftIndex--] = leftPos.z;\r\n leftPositions[leftIndex--] = leftPos.y;\r\n leftPositions[leftIndex--] = leftPos.x;\r\n }\r\n calculatedPositions.push(rightPositions, leftPositions);\r\n\r\n return calculatedPositions;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nCorridorGeometryLibrary.addAttribute = function (\r\n attribute,\r\n value,\r\n front,\r\n back\r\n) {\r\n var x = value.x;\r\n var y = value.y;\r\n var z = value.z;\r\n if (defined(front)) {\r\n attribute[front] = x;\r\n attribute[front + 1] = y;\r\n attribute[front + 2] = z;\r\n }\r\n if (defined(back)) {\r\n attribute[back] = z;\r\n attribute[back - 1] = y;\r\n attribute[back - 2] = x;\r\n }\r\n};\r\n\r\nvar scratchForwardProjection = new Cartesian3();\r\nvar scratchBackwardProjection = new Cartesian3();\r\n\r\n/**\r\n * @private\r\n */\r\nCorridorGeometryLibrary.computePositions = function (params) {\r\n var granularity = params.granularity;\r\n var positions = params.positions;\r\n var ellipsoid = params.ellipsoid;\r\n var width = params.width / 2;\r\n var cornerType = params.cornerType;\r\n var saveAttributes = params.saveAttributes;\r\n var normal = cartesian1;\r\n var forward = cartesian2;\r\n var backward = cartesian3;\r\n var left = cartesian4;\r\n var cornerDirection = cartesian5;\r\n var startPoint = cartesian6;\r\n var previousPos = cartesian7;\r\n var rightPos = cartesian8;\r\n var leftPos = cartesian9;\r\n var center = cartesian10;\r\n var calculatedPositions = [];\r\n var calculatedLefts = saveAttributes ? [] : undefined;\r\n var calculatedNormals = saveAttributes ? [] : undefined;\r\n var position = positions[0]; //add first point\r\n var nextPosition = positions[1];\r\n\r\n forward = Cartesian3.normalize(\r\n Cartesian3.subtract(nextPosition, position, forward),\r\n forward\r\n );\r\n normal = ellipsoid.geodeticSurfaceNormal(position, normal);\r\n left = Cartesian3.normalize(Cartesian3.cross(normal, forward, left), left);\r\n if (saveAttributes) {\r\n calculatedLefts.push(left.x, left.y, left.z);\r\n calculatedNormals.push(normal.x, normal.y, normal.z);\r\n }\r\n previousPos = Cartesian3.clone(position, previousPos);\r\n position = nextPosition;\r\n backward = Cartesian3.negate(forward, backward);\r\n\r\n var subdividedPositions;\r\n var corners = [];\r\n var i;\r\n var length = positions.length;\r\n for (i = 1; i < length - 1; i++) {\r\n // add middle points and corners\r\n normal = ellipsoid.geodeticSurfaceNormal(position, normal);\r\n nextPosition = positions[i + 1];\r\n forward = Cartesian3.normalize(\r\n Cartesian3.subtract(nextPosition, position, forward),\r\n forward\r\n );\r\n cornerDirection = Cartesian3.normalize(\r\n Cartesian3.add(forward, backward, cornerDirection),\r\n cornerDirection\r\n );\r\n\r\n var forwardProjection = Cartesian3.multiplyByScalar(\r\n normal,\r\n Cartesian3.dot(forward, normal),\r\n scratchForwardProjection\r\n );\r\n Cartesian3.subtract(forward, forwardProjection, forwardProjection);\r\n Cartesian3.normalize(forwardProjection, forwardProjection);\r\n\r\n var backwardProjection = Cartesian3.multiplyByScalar(\r\n normal,\r\n Cartesian3.dot(backward, normal),\r\n scratchBackwardProjection\r\n );\r\n Cartesian3.subtract(backward, backwardProjection, backwardProjection);\r\n Cartesian3.normalize(backwardProjection, backwardProjection);\r\n\r\n var doCorner = !CesiumMath.equalsEpsilon(\r\n Math.abs(Cartesian3.dot(forwardProjection, backwardProjection)),\r\n 1.0,\r\n CesiumMath.EPSILON7\r\n );\r\n\r\n if (doCorner) {\r\n cornerDirection = Cartesian3.cross(\r\n cornerDirection,\r\n normal,\r\n cornerDirection\r\n );\r\n cornerDirection = Cartesian3.cross(\r\n normal,\r\n cornerDirection,\r\n cornerDirection\r\n );\r\n cornerDirection = Cartesian3.normalize(cornerDirection, cornerDirection);\r\n var scalar =\r\n width /\r\n Math.max(\r\n 0.25,\r\n Cartesian3.magnitude(\r\n Cartesian3.cross(cornerDirection, backward, scratch1)\r\n )\r\n );\r\n var leftIsOutside = PolylineVolumeGeometryLibrary.angleIsGreaterThanPi(\r\n forward,\r\n backward,\r\n position,\r\n ellipsoid\r\n );\r\n cornerDirection = Cartesian3.multiplyByScalar(\r\n cornerDirection,\r\n scalar,\r\n cornerDirection\r\n );\r\n if (leftIsOutside) {\r\n rightPos = Cartesian3.add(position, cornerDirection, rightPos);\r\n center = Cartesian3.add(\r\n rightPos,\r\n Cartesian3.multiplyByScalar(left, width, center),\r\n center\r\n );\r\n leftPos = Cartesian3.add(\r\n rightPos,\r\n Cartesian3.multiplyByScalar(left, width * 2, leftPos),\r\n leftPos\r\n );\r\n scaleArray2[0] = Cartesian3.clone(previousPos, scaleArray2[0]);\r\n scaleArray2[1] = Cartesian3.clone(center, scaleArray2[1]);\r\n subdividedPositions = PolylinePipeline.generateArc({\r\n positions: scaleArray2,\r\n granularity: granularity,\r\n ellipsoid: ellipsoid,\r\n });\r\n calculatedPositions = addShiftedPositions(\r\n subdividedPositions,\r\n left,\r\n width,\r\n calculatedPositions\r\n );\r\n if (saveAttributes) {\r\n calculatedLefts.push(left.x, left.y, left.z);\r\n calculatedNormals.push(normal.x, normal.y, normal.z);\r\n }\r\n startPoint = Cartesian3.clone(leftPos, startPoint);\r\n left = Cartesian3.normalize(\r\n Cartesian3.cross(normal, forward, left),\r\n left\r\n );\r\n leftPos = Cartesian3.add(\r\n rightPos,\r\n Cartesian3.multiplyByScalar(left, width * 2, leftPos),\r\n leftPos\r\n );\r\n previousPos = Cartesian3.add(\r\n rightPos,\r\n Cartesian3.multiplyByScalar(left, width, previousPos),\r\n previousPos\r\n );\r\n if (\r\n cornerType === CornerType.ROUNDED ||\r\n cornerType === CornerType.BEVELED\r\n ) {\r\n corners.push({\r\n leftPositions: computeRoundCorner(\r\n rightPos,\r\n startPoint,\r\n leftPos,\r\n cornerType,\r\n leftIsOutside\r\n ),\r\n });\r\n } else {\r\n corners.push({\r\n leftPositions: computeMiteredCorner(\r\n position,\r\n Cartesian3.negate(cornerDirection, cornerDirection),\r\n leftPos,\r\n leftIsOutside\r\n ),\r\n });\r\n }\r\n } else {\r\n leftPos = Cartesian3.add(position, cornerDirection, leftPos);\r\n center = Cartesian3.add(\r\n leftPos,\r\n Cartesian3.negate(\r\n Cartesian3.multiplyByScalar(left, width, center),\r\n center\r\n ),\r\n center\r\n );\r\n rightPos = Cartesian3.add(\r\n leftPos,\r\n Cartesian3.negate(\r\n Cartesian3.multiplyByScalar(left, width * 2, rightPos),\r\n rightPos\r\n ),\r\n rightPos\r\n );\r\n scaleArray2[0] = Cartesian3.clone(previousPos, scaleArray2[0]);\r\n scaleArray2[1] = Cartesian3.clone(center, scaleArray2[1]);\r\n subdividedPositions = PolylinePipeline.generateArc({\r\n positions: scaleArray2,\r\n granularity: granularity,\r\n ellipsoid: ellipsoid,\r\n });\r\n calculatedPositions = addShiftedPositions(\r\n subdividedPositions,\r\n left,\r\n width,\r\n calculatedPositions\r\n );\r\n if (saveAttributes) {\r\n calculatedLefts.push(left.x, left.y, left.z);\r\n calculatedNormals.push(normal.x, normal.y, normal.z);\r\n }\r\n startPoint = Cartesian3.clone(rightPos, startPoint);\r\n left = Cartesian3.normalize(\r\n Cartesian3.cross(normal, forward, left),\r\n left\r\n );\r\n rightPos = Cartesian3.add(\r\n leftPos,\r\n Cartesian3.negate(\r\n Cartesian3.multiplyByScalar(left, width * 2, rightPos),\r\n rightPos\r\n ),\r\n rightPos\r\n );\r\n previousPos = Cartesian3.add(\r\n leftPos,\r\n Cartesian3.negate(\r\n Cartesian3.multiplyByScalar(left, width, previousPos),\r\n previousPos\r\n ),\r\n previousPos\r\n );\r\n if (\r\n cornerType === CornerType.ROUNDED ||\r\n cornerType === CornerType.BEVELED\r\n ) {\r\n corners.push({\r\n rightPositions: computeRoundCorner(\r\n leftPos,\r\n startPoint,\r\n rightPos,\r\n cornerType,\r\n leftIsOutside\r\n ),\r\n });\r\n } else {\r\n corners.push({\r\n rightPositions: computeMiteredCorner(\r\n position,\r\n cornerDirection,\r\n rightPos,\r\n leftIsOutside\r\n ),\r\n });\r\n }\r\n }\r\n backward = Cartesian3.negate(forward, backward);\r\n }\r\n position = nextPosition;\r\n }\r\n\r\n normal = ellipsoid.geodeticSurfaceNormal(position, normal);\r\n scaleArray2[0] = Cartesian3.clone(previousPos, scaleArray2[0]);\r\n scaleArray2[1] = Cartesian3.clone(position, scaleArray2[1]);\r\n subdividedPositions = PolylinePipeline.generateArc({\r\n positions: scaleArray2,\r\n granularity: granularity,\r\n ellipsoid: ellipsoid,\r\n });\r\n calculatedPositions = addShiftedPositions(\r\n subdividedPositions,\r\n left,\r\n width,\r\n calculatedPositions\r\n );\r\n if (saveAttributes) {\r\n calculatedLefts.push(left.x, left.y, left.z);\r\n calculatedNormals.push(normal.x, normal.y, normal.z);\r\n }\r\n\r\n var endPositions;\r\n if (cornerType === CornerType.ROUNDED) {\r\n endPositions = addEndCaps(calculatedPositions);\r\n }\r\n\r\n return {\r\n positions: calculatedPositions,\r\n corners: corners,\r\n lefts: calculatedLefts,\r\n normals: calculatedNormals,\r\n endPositions: endPositions,\r\n };\r\n};\r\nexport default CorridorGeometryLibrary;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport CornerType from \"./CornerType.js\";\r\nimport CorridorGeometryLibrary from \"./CorridorGeometryLibrary.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar cartesian1 = new Cartesian3();\r\nvar cartesian2 = new Cartesian3();\r\nvar cartesian3 = new Cartesian3();\r\nvar cartesian4 = new Cartesian3();\r\nvar cartesian5 = new Cartesian3();\r\nvar cartesian6 = new Cartesian3();\r\n\r\nvar scratch1 = new Cartesian3();\r\nvar scratch2 = new Cartesian3();\r\n\r\nfunction scaleToSurface(positions, ellipsoid) {\r\n for (var i = 0; i < positions.length; i++) {\r\n positions[i] = ellipsoid.scaleToGeodeticSurface(positions[i], positions[i]);\r\n }\r\n return positions;\r\n}\r\n\r\nfunction addNormals(attr, normal, left, front, back, vertexFormat) {\r\n var normals = attr.normals;\r\n var tangents = attr.tangents;\r\n var bitangents = attr.bitangents;\r\n var forward = Cartesian3.normalize(\r\n Cartesian3.cross(left, normal, scratch1),\r\n scratch1\r\n );\r\n if (vertexFormat.normal) {\r\n CorridorGeometryLibrary.addAttribute(normals, normal, front, back);\r\n }\r\n if (vertexFormat.tangent) {\r\n CorridorGeometryLibrary.addAttribute(tangents, forward, front, back);\r\n }\r\n if (vertexFormat.bitangent) {\r\n CorridorGeometryLibrary.addAttribute(bitangents, left, front, back);\r\n }\r\n}\r\n\r\nfunction combine(computedPositions, vertexFormat, ellipsoid) {\r\n var positions = computedPositions.positions;\r\n var corners = computedPositions.corners;\r\n var endPositions = computedPositions.endPositions;\r\n var computedLefts = computedPositions.lefts;\r\n var computedNormals = computedPositions.normals;\r\n var attributes = new GeometryAttributes();\r\n var corner;\r\n var leftCount = 0;\r\n var rightCount = 0;\r\n var i;\r\n var indicesLength = 0;\r\n var length;\r\n for (i = 0; i < positions.length; i += 2) {\r\n length = positions[i].length - 3;\r\n leftCount += length; //subtracting 3 to account for duplicate points at corners\r\n indicesLength += length * 2;\r\n rightCount += positions[i + 1].length - 3;\r\n }\r\n leftCount += 3; //add back count for end positions\r\n rightCount += 3;\r\n for (i = 0; i < corners.length; i++) {\r\n corner = corners[i];\r\n var leftSide = corners[i].leftPositions;\r\n if (defined(leftSide)) {\r\n length = leftSide.length;\r\n leftCount += length;\r\n indicesLength += length;\r\n } else {\r\n length = corners[i].rightPositions.length;\r\n rightCount += length;\r\n indicesLength += length;\r\n }\r\n }\r\n\r\n var addEndPositions = defined(endPositions);\r\n var endPositionLength;\r\n if (addEndPositions) {\r\n endPositionLength = endPositions[0].length - 3;\r\n leftCount += endPositionLength;\r\n rightCount += endPositionLength;\r\n endPositionLength /= 3;\r\n indicesLength += endPositionLength * 6;\r\n }\r\n var size = leftCount + rightCount;\r\n var finalPositions = new Float64Array(size);\r\n var normals = vertexFormat.normal ? new Float32Array(size) : undefined;\r\n var tangents = vertexFormat.tangent ? new Float32Array(size) : undefined;\r\n var bitangents = vertexFormat.bitangent ? new Float32Array(size) : undefined;\r\n var attr = {\r\n normals: normals,\r\n tangents: tangents,\r\n bitangents: bitangents,\r\n };\r\n var front = 0;\r\n var back = size - 1;\r\n var UL, LL, UR, LR;\r\n var normal = cartesian1;\r\n var left = cartesian2;\r\n var rightPos, leftPos;\r\n var halfLength = endPositionLength / 2;\r\n\r\n var indices = IndexDatatype.createTypedArray(size / 3, indicesLength);\r\n var index = 0;\r\n if (addEndPositions) {\r\n // add rounded end\r\n leftPos = cartesian3;\r\n rightPos = cartesian4;\r\n var firstEndPositions = endPositions[0];\r\n normal = Cartesian3.fromArray(computedNormals, 0, normal);\r\n left = Cartesian3.fromArray(computedLefts, 0, left);\r\n for (i = 0; i < halfLength; i++) {\r\n leftPos = Cartesian3.fromArray(\r\n firstEndPositions,\r\n (halfLength - 1 - i) * 3,\r\n leftPos\r\n );\r\n rightPos = Cartesian3.fromArray(\r\n firstEndPositions,\r\n (halfLength + i) * 3,\r\n rightPos\r\n );\r\n CorridorGeometryLibrary.addAttribute(finalPositions, rightPos, front);\r\n CorridorGeometryLibrary.addAttribute(\r\n finalPositions,\r\n leftPos,\r\n undefined,\r\n back\r\n );\r\n addNormals(attr, normal, left, front, back, vertexFormat);\r\n\r\n LL = front / 3;\r\n LR = LL + 1;\r\n UL = (back - 2) / 3;\r\n UR = UL - 1;\r\n indices[index++] = UL;\r\n indices[index++] = LL;\r\n indices[index++] = UR;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n\r\n front += 3;\r\n back -= 3;\r\n }\r\n }\r\n\r\n var posIndex = 0;\r\n var compIndex = 0;\r\n var rightEdge = positions[posIndex++]; //add first two edges\r\n var leftEdge = positions[posIndex++];\r\n finalPositions.set(rightEdge, front);\r\n finalPositions.set(leftEdge, back - leftEdge.length + 1);\r\n\r\n left = Cartesian3.fromArray(computedLefts, compIndex, left);\r\n var rightNormal;\r\n var leftNormal;\r\n length = leftEdge.length - 3;\r\n for (i = 0; i < length; i += 3) {\r\n rightNormal = ellipsoid.geodeticSurfaceNormal(\r\n Cartesian3.fromArray(rightEdge, i, scratch1),\r\n scratch1\r\n );\r\n leftNormal = ellipsoid.geodeticSurfaceNormal(\r\n Cartesian3.fromArray(leftEdge, length - i, scratch2),\r\n scratch2\r\n );\r\n normal = Cartesian3.normalize(\r\n Cartesian3.add(rightNormal, leftNormal, normal),\r\n normal\r\n );\r\n addNormals(attr, normal, left, front, back, vertexFormat);\r\n\r\n LL = front / 3;\r\n LR = LL + 1;\r\n UL = (back - 2) / 3;\r\n UR = UL - 1;\r\n indices[index++] = UL;\r\n indices[index++] = LL;\r\n indices[index++] = UR;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n\r\n front += 3;\r\n back -= 3;\r\n }\r\n\r\n rightNormal = ellipsoid.geodeticSurfaceNormal(\r\n Cartesian3.fromArray(rightEdge, length, scratch1),\r\n scratch1\r\n );\r\n leftNormal = ellipsoid.geodeticSurfaceNormal(\r\n Cartesian3.fromArray(leftEdge, length, scratch2),\r\n scratch2\r\n );\r\n normal = Cartesian3.normalize(\r\n Cartesian3.add(rightNormal, leftNormal, normal),\r\n normal\r\n );\r\n compIndex += 3;\r\n for (i = 0; i < corners.length; i++) {\r\n var j;\r\n corner = corners[i];\r\n var l = corner.leftPositions;\r\n var r = corner.rightPositions;\r\n var pivot;\r\n var start;\r\n var outsidePoint = cartesian6;\r\n var previousPoint = cartesian3;\r\n var nextPoint = cartesian4;\r\n normal = Cartesian3.fromArray(computedNormals, compIndex, normal);\r\n if (defined(l)) {\r\n addNormals(attr, normal, left, undefined, back, vertexFormat);\r\n back -= 3;\r\n pivot = LR;\r\n start = UR;\r\n for (j = 0; j < l.length / 3; j++) {\r\n outsidePoint = Cartesian3.fromArray(l, j * 3, outsidePoint);\r\n indices[index++] = pivot;\r\n indices[index++] = start - j - 1;\r\n indices[index++] = start - j;\r\n CorridorGeometryLibrary.addAttribute(\r\n finalPositions,\r\n outsidePoint,\r\n undefined,\r\n back\r\n );\r\n previousPoint = Cartesian3.fromArray(\r\n finalPositions,\r\n (start - j - 1) * 3,\r\n previousPoint\r\n );\r\n nextPoint = Cartesian3.fromArray(finalPositions, pivot * 3, nextPoint);\r\n left = Cartesian3.normalize(\r\n Cartesian3.subtract(previousPoint, nextPoint, left),\r\n left\r\n );\r\n addNormals(attr, normal, left, undefined, back, vertexFormat);\r\n back -= 3;\r\n }\r\n outsidePoint = Cartesian3.fromArray(\r\n finalPositions,\r\n pivot * 3,\r\n outsidePoint\r\n );\r\n previousPoint = Cartesian3.subtract(\r\n Cartesian3.fromArray(finalPositions, start * 3, previousPoint),\r\n outsidePoint,\r\n previousPoint\r\n );\r\n nextPoint = Cartesian3.subtract(\r\n Cartesian3.fromArray(finalPositions, (start - j) * 3, nextPoint),\r\n outsidePoint,\r\n nextPoint\r\n );\r\n left = Cartesian3.normalize(\r\n Cartesian3.add(previousPoint, nextPoint, left),\r\n left\r\n );\r\n addNormals(attr, normal, left, front, undefined, vertexFormat);\r\n front += 3;\r\n } else {\r\n addNormals(attr, normal, left, front, undefined, vertexFormat);\r\n front += 3;\r\n pivot = UR;\r\n start = LR;\r\n for (j = 0; j < r.length / 3; j++) {\r\n outsidePoint = Cartesian3.fromArray(r, j * 3, outsidePoint);\r\n indices[index++] = pivot;\r\n indices[index++] = start + j;\r\n indices[index++] = start + j + 1;\r\n CorridorGeometryLibrary.addAttribute(\r\n finalPositions,\r\n outsidePoint,\r\n front\r\n );\r\n previousPoint = Cartesian3.fromArray(\r\n finalPositions,\r\n pivot * 3,\r\n previousPoint\r\n );\r\n nextPoint = Cartesian3.fromArray(\r\n finalPositions,\r\n (start + j) * 3,\r\n nextPoint\r\n );\r\n left = Cartesian3.normalize(\r\n Cartesian3.subtract(previousPoint, nextPoint, left),\r\n left\r\n );\r\n addNormals(attr, normal, left, front, undefined, vertexFormat);\r\n front += 3;\r\n }\r\n outsidePoint = Cartesian3.fromArray(\r\n finalPositions,\r\n pivot * 3,\r\n outsidePoint\r\n );\r\n previousPoint = Cartesian3.subtract(\r\n Cartesian3.fromArray(finalPositions, (start + j) * 3, previousPoint),\r\n outsidePoint,\r\n previousPoint\r\n );\r\n nextPoint = Cartesian3.subtract(\r\n Cartesian3.fromArray(finalPositions, start * 3, nextPoint),\r\n outsidePoint,\r\n nextPoint\r\n );\r\n left = Cartesian3.normalize(\r\n Cartesian3.negate(Cartesian3.add(nextPoint, previousPoint, left), left),\r\n left\r\n );\r\n addNormals(attr, normal, left, undefined, back, vertexFormat);\r\n back -= 3;\r\n }\r\n rightEdge = positions[posIndex++];\r\n leftEdge = positions[posIndex++];\r\n rightEdge.splice(0, 3); //remove duplicate points added by corner\r\n leftEdge.splice(leftEdge.length - 3, 3);\r\n finalPositions.set(rightEdge, front);\r\n finalPositions.set(leftEdge, back - leftEdge.length + 1);\r\n length = leftEdge.length - 3;\r\n\r\n compIndex += 3;\r\n left = Cartesian3.fromArray(computedLefts, compIndex, left);\r\n for (j = 0; j < leftEdge.length; j += 3) {\r\n rightNormal = ellipsoid.geodeticSurfaceNormal(\r\n Cartesian3.fromArray(rightEdge, j, scratch1),\r\n scratch1\r\n );\r\n leftNormal = ellipsoid.geodeticSurfaceNormal(\r\n Cartesian3.fromArray(leftEdge, length - j, scratch2),\r\n scratch2\r\n );\r\n normal = Cartesian3.normalize(\r\n Cartesian3.add(rightNormal, leftNormal, normal),\r\n normal\r\n );\r\n addNormals(attr, normal, left, front, back, vertexFormat);\r\n\r\n LR = front / 3;\r\n LL = LR - 1;\r\n UR = (back - 2) / 3;\r\n UL = UR + 1;\r\n indices[index++] = UL;\r\n indices[index++] = LL;\r\n indices[index++] = UR;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n\r\n front += 3;\r\n back -= 3;\r\n }\r\n front -= 3;\r\n back += 3;\r\n }\r\n normal = Cartesian3.fromArray(\r\n computedNormals,\r\n computedNormals.length - 3,\r\n normal\r\n );\r\n addNormals(attr, normal, left, front, back, vertexFormat);\r\n\r\n if (addEndPositions) {\r\n // add rounded end\r\n front += 3;\r\n back -= 3;\r\n leftPos = cartesian3;\r\n rightPos = cartesian4;\r\n var lastEndPositions = endPositions[1];\r\n for (i = 0; i < halfLength; i++) {\r\n leftPos = Cartesian3.fromArray(\r\n lastEndPositions,\r\n (endPositionLength - i - 1) * 3,\r\n leftPos\r\n );\r\n rightPos = Cartesian3.fromArray(lastEndPositions, i * 3, rightPos);\r\n CorridorGeometryLibrary.addAttribute(\r\n finalPositions,\r\n leftPos,\r\n undefined,\r\n back\r\n );\r\n CorridorGeometryLibrary.addAttribute(finalPositions, rightPos, front);\r\n addNormals(attr, normal, left, front, back, vertexFormat);\r\n\r\n LR = front / 3;\r\n LL = LR - 1;\r\n UR = (back - 2) / 3;\r\n UL = UR + 1;\r\n indices[index++] = UL;\r\n indices[index++] = LL;\r\n indices[index++] = UR;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n\r\n front += 3;\r\n back -= 3;\r\n }\r\n }\r\n\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: finalPositions,\r\n });\r\n\r\n if (vertexFormat.st) {\r\n var st = new Float32Array((size / 3) * 2);\r\n var rightSt;\r\n var leftSt;\r\n var stIndex = 0;\r\n if (addEndPositions) {\r\n leftCount /= 3;\r\n rightCount /= 3;\r\n var theta = Math.PI / (endPositionLength + 1);\r\n leftSt = 1 / (leftCount - endPositionLength + 1);\r\n rightSt = 1 / (rightCount - endPositionLength + 1);\r\n var a;\r\n var halfEndPos = endPositionLength / 2;\r\n for (i = halfEndPos + 1; i < endPositionLength + 1; i++) {\r\n // lower left rounded end\r\n a = CesiumMath.PI_OVER_TWO + theta * i;\r\n st[stIndex++] = rightSt * (1 + Math.cos(a));\r\n st[stIndex++] = 0.5 * (1 + Math.sin(a));\r\n }\r\n for (i = 1; i < rightCount - endPositionLength + 1; i++) {\r\n // bottom edge\r\n st[stIndex++] = i * rightSt;\r\n st[stIndex++] = 0;\r\n }\r\n for (i = endPositionLength; i > halfEndPos; i--) {\r\n // lower right rounded end\r\n a = CesiumMath.PI_OVER_TWO - i * theta;\r\n st[stIndex++] = 1 - rightSt * (1 + Math.cos(a));\r\n st[stIndex++] = 0.5 * (1 + Math.sin(a));\r\n }\r\n for (i = halfEndPos; i > 0; i--) {\r\n // upper right rounded end\r\n a = CesiumMath.PI_OVER_TWO - theta * i;\r\n st[stIndex++] = 1 - leftSt * (1 + Math.cos(a));\r\n st[stIndex++] = 0.5 * (1 + Math.sin(a));\r\n }\r\n for (i = leftCount - endPositionLength; i > 0; i--) {\r\n // top edge\r\n st[stIndex++] = i * leftSt;\r\n st[stIndex++] = 1;\r\n }\r\n for (i = 1; i < halfEndPos + 1; i++) {\r\n // upper left rounded end\r\n a = CesiumMath.PI_OVER_TWO + theta * i;\r\n st[stIndex++] = leftSt * (1 + Math.cos(a));\r\n st[stIndex++] = 0.5 * (1 + Math.sin(a));\r\n }\r\n } else {\r\n leftCount /= 3;\r\n rightCount /= 3;\r\n leftSt = 1 / (leftCount - 1);\r\n rightSt = 1 / (rightCount - 1);\r\n for (i = 0; i < rightCount; i++) {\r\n // bottom edge\r\n st[stIndex++] = i * rightSt;\r\n st[stIndex++] = 0;\r\n }\r\n for (i = leftCount; i > 0; i--) {\r\n // top edge\r\n st[stIndex++] = (i - 1) * leftSt;\r\n st[stIndex++] = 1;\r\n }\r\n }\r\n\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: st,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: attr.normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: attr.tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: attr.bitangents,\r\n });\r\n }\r\n\r\n return {\r\n attributes: attributes,\r\n indices: indices,\r\n };\r\n}\r\n\r\nfunction extrudedAttributes(attributes, vertexFormat) {\r\n if (\r\n !vertexFormat.normal &&\r\n !vertexFormat.tangent &&\r\n !vertexFormat.bitangent &&\r\n !vertexFormat.st\r\n ) {\r\n return attributes;\r\n }\r\n var positions = attributes.position.values;\r\n var topNormals;\r\n var topBitangents;\r\n if (vertexFormat.normal || vertexFormat.bitangent) {\r\n topNormals = attributes.normal.values;\r\n topBitangents = attributes.bitangent.values;\r\n }\r\n var size = attributes.position.values.length / 18;\r\n var threeSize = size * 3;\r\n var twoSize = size * 2;\r\n var sixSize = threeSize * 2;\r\n var i;\r\n if (vertexFormat.normal || vertexFormat.bitangent || vertexFormat.tangent) {\r\n var normals = vertexFormat.normal\r\n ? new Float32Array(threeSize * 6)\r\n : undefined;\r\n var tangents = vertexFormat.tangent\r\n ? new Float32Array(threeSize * 6)\r\n : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(threeSize * 6)\r\n : undefined;\r\n var topPosition = cartesian1;\r\n var bottomPosition = cartesian2;\r\n var previousPosition = cartesian3;\r\n var normal = cartesian4;\r\n var tangent = cartesian5;\r\n var bitangent = cartesian6;\r\n var attrIndex = sixSize;\r\n for (i = 0; i < threeSize; i += 3) {\r\n var attrIndexOffset = attrIndex + sixSize;\r\n topPosition = Cartesian3.fromArray(positions, i, topPosition);\r\n bottomPosition = Cartesian3.fromArray(\r\n positions,\r\n i + threeSize,\r\n bottomPosition\r\n );\r\n previousPosition = Cartesian3.fromArray(\r\n positions,\r\n (i + 3) % threeSize,\r\n previousPosition\r\n );\r\n bottomPosition = Cartesian3.subtract(\r\n bottomPosition,\r\n topPosition,\r\n bottomPosition\r\n );\r\n previousPosition = Cartesian3.subtract(\r\n previousPosition,\r\n topPosition,\r\n previousPosition\r\n );\r\n normal = Cartesian3.normalize(\r\n Cartesian3.cross(bottomPosition, previousPosition, normal),\r\n normal\r\n );\r\n if (vertexFormat.normal) {\r\n CorridorGeometryLibrary.addAttribute(normals, normal, attrIndexOffset);\r\n CorridorGeometryLibrary.addAttribute(\r\n normals,\r\n normal,\r\n attrIndexOffset + 3\r\n );\r\n CorridorGeometryLibrary.addAttribute(normals, normal, attrIndex);\r\n CorridorGeometryLibrary.addAttribute(normals, normal, attrIndex + 3);\r\n }\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n bitangent = Cartesian3.fromArray(topNormals, i, bitangent);\r\n if (vertexFormat.bitangent) {\r\n CorridorGeometryLibrary.addAttribute(\r\n bitangents,\r\n bitangent,\r\n attrIndexOffset\r\n );\r\n CorridorGeometryLibrary.addAttribute(\r\n bitangents,\r\n bitangent,\r\n attrIndexOffset + 3\r\n );\r\n CorridorGeometryLibrary.addAttribute(\r\n bitangents,\r\n bitangent,\r\n attrIndex\r\n );\r\n CorridorGeometryLibrary.addAttribute(\r\n bitangents,\r\n bitangent,\r\n attrIndex + 3\r\n );\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n tangent = Cartesian3.normalize(\r\n Cartesian3.cross(bitangent, normal, tangent),\r\n tangent\r\n );\r\n CorridorGeometryLibrary.addAttribute(\r\n tangents,\r\n tangent,\r\n attrIndexOffset\r\n );\r\n CorridorGeometryLibrary.addAttribute(\r\n tangents,\r\n tangent,\r\n attrIndexOffset + 3\r\n );\r\n CorridorGeometryLibrary.addAttribute(tangents, tangent, attrIndex);\r\n CorridorGeometryLibrary.addAttribute(\r\n tangents,\r\n tangent,\r\n attrIndex + 3\r\n );\r\n }\r\n }\r\n attrIndex += 6;\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n normals.set(topNormals); //top\r\n for (i = 0; i < threeSize; i += 3) {\r\n //bottom normals\r\n normals[i + threeSize] = -topNormals[i];\r\n normals[i + threeSize + 1] = -topNormals[i + 1];\r\n normals[i + threeSize + 2] = -topNormals[i + 2];\r\n }\r\n attributes.normal.values = normals;\r\n } else {\r\n attributes.normal = undefined;\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n bitangents.set(topBitangents); //top\r\n bitangents.set(topBitangents, threeSize); //bottom\r\n attributes.bitangent.values = bitangents;\r\n } else {\r\n attributes.bitangent = undefined;\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n var topTangents = attributes.tangent.values;\r\n tangents.set(topTangents); //top\r\n tangents.set(topTangents, threeSize); //bottom\r\n attributes.tangent.values = tangents;\r\n }\r\n }\r\n if (vertexFormat.st) {\r\n var topSt = attributes.st.values;\r\n var st = new Float32Array(twoSize * 6);\r\n st.set(topSt); //top\r\n st.set(topSt, twoSize); //bottom\r\n var index = twoSize * 2;\r\n\r\n for (var j = 0; j < 2; j++) {\r\n st[index++] = topSt[0];\r\n st[index++] = topSt[1];\r\n for (i = 2; i < twoSize; i += 2) {\r\n var s = topSt[i];\r\n var t = topSt[i + 1];\r\n st[index++] = s;\r\n st[index++] = t;\r\n st[index++] = s;\r\n st[index++] = t;\r\n }\r\n st[index++] = topSt[0];\r\n st[index++] = topSt[1];\r\n }\r\n attributes.st.values = st;\r\n }\r\n\r\n return attributes;\r\n}\r\n\r\nfunction addWallPositions(positions, index, wallPositions) {\r\n wallPositions[index++] = positions[0];\r\n wallPositions[index++] = positions[1];\r\n wallPositions[index++] = positions[2];\r\n for (var i = 3; i < positions.length; i += 3) {\r\n var x = positions[i];\r\n var y = positions[i + 1];\r\n var z = positions[i + 2];\r\n wallPositions[index++] = x;\r\n wallPositions[index++] = y;\r\n wallPositions[index++] = z;\r\n wallPositions[index++] = x;\r\n wallPositions[index++] = y;\r\n wallPositions[index++] = z;\r\n }\r\n wallPositions[index++] = positions[0];\r\n wallPositions[index++] = positions[1];\r\n wallPositions[index++] = positions[2];\r\n\r\n return wallPositions;\r\n}\r\n\r\nfunction computePositionsExtruded(params, vertexFormat) {\r\n var topVertexFormat = new VertexFormat({\r\n position: vertexFormat.position,\r\n normal:\r\n vertexFormat.normal || vertexFormat.bitangent || params.shadowVolume,\r\n tangent: vertexFormat.tangent,\r\n bitangent: vertexFormat.normal || vertexFormat.bitangent,\r\n st: vertexFormat.st,\r\n });\r\n var ellipsoid = params.ellipsoid;\r\n var computedPositions = CorridorGeometryLibrary.computePositions(params);\r\n var attr = combine(computedPositions, topVertexFormat, ellipsoid);\r\n var height = params.height;\r\n var extrudedHeight = params.extrudedHeight;\r\n var attributes = attr.attributes;\r\n var indices = attr.indices;\r\n var positions = attributes.position.values;\r\n var length = positions.length;\r\n var newPositions = new Float64Array(length * 6);\r\n var extrudedPositions = new Float64Array(length);\r\n extrudedPositions.set(positions);\r\n var wallPositions = new Float64Array(length * 4);\r\n\r\n positions = PolygonPipeline.scaleToGeodeticHeight(\r\n positions,\r\n height,\r\n ellipsoid\r\n );\r\n wallPositions = addWallPositions(positions, 0, wallPositions);\r\n extrudedPositions = PolygonPipeline.scaleToGeodeticHeight(\r\n extrudedPositions,\r\n extrudedHeight,\r\n ellipsoid\r\n );\r\n wallPositions = addWallPositions(\r\n extrudedPositions,\r\n length * 2,\r\n wallPositions\r\n );\r\n newPositions.set(positions);\r\n newPositions.set(extrudedPositions, length);\r\n newPositions.set(wallPositions, length * 2);\r\n attributes.position.values = newPositions;\r\n\r\n attributes = extrudedAttributes(attributes, vertexFormat);\r\n var i;\r\n var size = length / 3;\r\n if (params.shadowVolume) {\r\n var topNormals = attributes.normal.values;\r\n length = topNormals.length;\r\n\r\n var extrudeNormals = new Float32Array(length * 6);\r\n for (i = 0; i < length; i++) {\r\n topNormals[i] = -topNormals[i];\r\n }\r\n //only get normals for bottom layer that's going to be pushed down\r\n extrudeNormals.set(topNormals, length); //bottom face\r\n extrudeNormals = addWallPositions(topNormals, length * 4, extrudeNormals); //bottom wall\r\n attributes.extrudeDirection = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: extrudeNormals,\r\n });\r\n if (!vertexFormat.normal) {\r\n attributes.normal = undefined;\r\n }\r\n }\r\n if (defined(params.offsetAttribute)) {\r\n var applyOffset = new Uint8Array(size * 6);\r\n if (params.offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n applyOffset = arrayFill(applyOffset, 1, 0, size); // top face\r\n applyOffset = arrayFill(applyOffset, 1, size * 2, size * 4); // top wall\r\n } else {\r\n var applyOffsetValue =\r\n params.offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n applyOffset = arrayFill(applyOffset, applyOffsetValue);\r\n }\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n var iLength = indices.length;\r\n var twoSize = size + size;\r\n var newIndices = IndexDatatype.createTypedArray(\r\n newPositions.length / 3,\r\n iLength * 2 + twoSize * 3\r\n );\r\n newIndices.set(indices);\r\n var index = iLength;\r\n for (i = 0; i < iLength; i += 3) {\r\n // bottom indices\r\n var v0 = indices[i];\r\n var v1 = indices[i + 1];\r\n var v2 = indices[i + 2];\r\n newIndices[index++] = v2 + size;\r\n newIndices[index++] = v1 + size;\r\n newIndices[index++] = v0 + size;\r\n }\r\n\r\n var UL, LL, UR, LR;\r\n\r\n for (i = 0; i < twoSize; i += 2) {\r\n //wall indices\r\n UL = i + twoSize;\r\n LL = UL + twoSize;\r\n UR = UL + 1;\r\n LR = LL + 1;\r\n newIndices[index++] = UL;\r\n newIndices[index++] = LL;\r\n newIndices[index++] = UR;\r\n newIndices[index++] = UR;\r\n newIndices[index++] = LL;\r\n newIndices[index++] = LR;\r\n }\r\n\r\n return {\r\n attributes: attributes,\r\n indices: newIndices,\r\n };\r\n}\r\n\r\nvar scratchCartesian1 = new Cartesian3();\r\nvar scratchCartesian2 = new Cartesian3();\r\nvar scratchCartographic = new Cartographic();\r\n\r\nfunction computeOffsetPoints(\r\n position1,\r\n position2,\r\n ellipsoid,\r\n halfWidth,\r\n min,\r\n max\r\n) {\r\n // Compute direction of offset the point\r\n var direction = Cartesian3.subtract(position2, position1, scratchCartesian1);\r\n Cartesian3.normalize(direction, direction);\r\n var normal = ellipsoid.geodeticSurfaceNormal(position1, scratchCartesian2);\r\n var offsetDirection = Cartesian3.cross(direction, normal, scratchCartesian1);\r\n Cartesian3.multiplyByScalar(offsetDirection, halfWidth, offsetDirection);\r\n\r\n var minLat = min.latitude;\r\n var minLon = min.longitude;\r\n var maxLat = max.latitude;\r\n var maxLon = max.longitude;\r\n\r\n // Compute 2 offset points\r\n Cartesian3.add(position1, offsetDirection, scratchCartesian2);\r\n ellipsoid.cartesianToCartographic(scratchCartesian2, scratchCartographic);\r\n\r\n var lat = scratchCartographic.latitude;\r\n var lon = scratchCartographic.longitude;\r\n minLat = Math.min(minLat, lat);\r\n minLon = Math.min(minLon, lon);\r\n maxLat = Math.max(maxLat, lat);\r\n maxLon = Math.max(maxLon, lon);\r\n\r\n Cartesian3.subtract(position1, offsetDirection, scratchCartesian2);\r\n ellipsoid.cartesianToCartographic(scratchCartesian2, scratchCartographic);\r\n\r\n lat = scratchCartographic.latitude;\r\n lon = scratchCartographic.longitude;\r\n minLat = Math.min(minLat, lat);\r\n minLon = Math.min(minLon, lon);\r\n maxLat = Math.max(maxLat, lat);\r\n maxLon = Math.max(maxLon, lon);\r\n\r\n min.latitude = minLat;\r\n min.longitude = minLon;\r\n max.latitude = maxLat;\r\n max.longitude = maxLon;\r\n}\r\n\r\nvar scratchCartesianOffset = new Cartesian3();\r\nvar scratchCartesianEnds = new Cartesian3();\r\nvar scratchCartographicMin = new Cartographic();\r\nvar scratchCartographicMax = new Cartographic();\r\n\r\nfunction computeRectangle(positions, ellipsoid, width, cornerType, result) {\r\n positions = scaleToSurface(positions, ellipsoid);\r\n var cleanPositions = arrayRemoveDuplicates(\r\n positions,\r\n Cartesian3.equalsEpsilon\r\n );\r\n var length = cleanPositions.length;\r\n if (length < 2 || width <= 0) {\r\n return new Rectangle();\r\n }\r\n var halfWidth = width * 0.5;\r\n\r\n scratchCartographicMin.latitude = Number.POSITIVE_INFINITY;\r\n scratchCartographicMin.longitude = Number.POSITIVE_INFINITY;\r\n scratchCartographicMax.latitude = Number.NEGATIVE_INFINITY;\r\n scratchCartographicMax.longitude = Number.NEGATIVE_INFINITY;\r\n\r\n var lat, lon;\r\n if (cornerType === CornerType.ROUNDED) {\r\n // Compute start cap\r\n var first = cleanPositions[0];\r\n Cartesian3.subtract(first, cleanPositions[1], scratchCartesianOffset);\r\n Cartesian3.normalize(scratchCartesianOffset, scratchCartesianOffset);\r\n Cartesian3.multiplyByScalar(\r\n scratchCartesianOffset,\r\n halfWidth,\r\n scratchCartesianOffset\r\n );\r\n Cartesian3.add(first, scratchCartesianOffset, scratchCartesianEnds);\r\n\r\n ellipsoid.cartesianToCartographic(\r\n scratchCartesianEnds,\r\n scratchCartographic\r\n );\r\n lat = scratchCartographic.latitude;\r\n lon = scratchCartographic.longitude;\r\n scratchCartographicMin.latitude = Math.min(\r\n scratchCartographicMin.latitude,\r\n lat\r\n );\r\n scratchCartographicMin.longitude = Math.min(\r\n scratchCartographicMin.longitude,\r\n lon\r\n );\r\n scratchCartographicMax.latitude = Math.max(\r\n scratchCartographicMax.latitude,\r\n lat\r\n );\r\n scratchCartographicMax.longitude = Math.max(\r\n scratchCartographicMax.longitude,\r\n lon\r\n );\r\n }\r\n\r\n // Compute the rest\r\n for (var i = 0; i < length - 1; ++i) {\r\n computeOffsetPoints(\r\n cleanPositions[i],\r\n cleanPositions[i + 1],\r\n ellipsoid,\r\n halfWidth,\r\n scratchCartographicMin,\r\n scratchCartographicMax\r\n );\r\n }\r\n\r\n // Compute ending point\r\n var last = cleanPositions[length - 1];\r\n Cartesian3.subtract(last, cleanPositions[length - 2], scratchCartesianOffset);\r\n Cartesian3.normalize(scratchCartesianOffset, scratchCartesianOffset);\r\n Cartesian3.multiplyByScalar(\r\n scratchCartesianOffset,\r\n halfWidth,\r\n scratchCartesianOffset\r\n );\r\n Cartesian3.add(last, scratchCartesianOffset, scratchCartesianEnds);\r\n computeOffsetPoints(\r\n last,\r\n scratchCartesianEnds,\r\n ellipsoid,\r\n halfWidth,\r\n scratchCartographicMin,\r\n scratchCartographicMax\r\n );\r\n\r\n if (cornerType === CornerType.ROUNDED) {\r\n // Compute end cap\r\n ellipsoid.cartesianToCartographic(\r\n scratchCartesianEnds,\r\n scratchCartographic\r\n );\r\n lat = scratchCartographic.latitude;\r\n lon = scratchCartographic.longitude;\r\n scratchCartographicMin.latitude = Math.min(\r\n scratchCartographicMin.latitude,\r\n lat\r\n );\r\n scratchCartographicMin.longitude = Math.min(\r\n scratchCartographicMin.longitude,\r\n lon\r\n );\r\n scratchCartographicMax.latitude = Math.max(\r\n scratchCartographicMax.latitude,\r\n lat\r\n );\r\n scratchCartographicMax.longitude = Math.max(\r\n scratchCartographicMax.longitude,\r\n lon\r\n );\r\n }\r\n\r\n var rectangle = defined(result) ? result : new Rectangle();\r\n rectangle.north = scratchCartographicMax.latitude;\r\n rectangle.south = scratchCartographicMin.latitude;\r\n rectangle.east = scratchCartographicMax.longitude;\r\n rectangle.west = scratchCartographicMin.longitude;\r\n\r\n return rectangle;\r\n}\r\n\r\n/**\r\n * A description of a corridor. Corridor geometry can be rendered with both {@link Primitive} and {@link GroundPrimitive}.\r\n *\r\n * @alias CorridorGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of positions that define the center of the corridor.\r\n * @param {Number} options.width The distance between the edges of the corridor in meters.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Number} [options.height=0] The distance in meters between the ellipsoid surface and the positions.\r\n * @param {Number} [options.extrudedHeight] The distance in meters between the ellipsoid surface and the extruded face.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {CornerType} [options.cornerType=CornerType.ROUNDED] Determines the style of the corners.\r\n *\r\n * @see CorridorGeometry.createGeometry\r\n * @see Packable\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Corridor.html|Cesium Sandcastle Corridor Demo}\r\n *\r\n * @example\r\n * var corridor = new Cesium.CorridorGeometry({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_ONLY,\r\n * positions : Cesium.Cartesian3.fromDegreesArray([-72.0, 40.0, -70.0, 35.0]),\r\n * width : 100000\r\n * });\r\n */\r\nfunction CorridorGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.positions;\r\n var width = options.width;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.positions\", positions);\r\n Check.defined(\"options.width\", width);\r\n //>>includeEnd('debug');\r\n\r\n var height = defaultValue(options.height, 0.0);\r\n var extrudedHeight = defaultValue(options.extrudedHeight, height);\r\n\r\n this._positions = positions;\r\n this._ellipsoid = Ellipsoid.clone(\r\n defaultValue(options.ellipsoid, Ellipsoid.WGS84)\r\n );\r\n this._vertexFormat = VertexFormat.clone(\r\n defaultValue(options.vertexFormat, VertexFormat.DEFAULT)\r\n );\r\n this._width = width;\r\n this._height = Math.max(height, extrudedHeight);\r\n this._extrudedHeight = Math.min(height, extrudedHeight);\r\n this._cornerType = defaultValue(options.cornerType, CornerType.ROUNDED);\r\n this._granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n this._shadowVolume = defaultValue(options.shadowVolume, false);\r\n this._workerName = \"createCorridorGeometry\";\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._rectangle = undefined;\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n 1 +\r\n positions.length * Cartesian3.packedLength +\r\n Ellipsoid.packedLength +\r\n VertexFormat.packedLength +\r\n 7;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {CorridorGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCorridorGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var positions = value._positions;\r\n var length = positions.length;\r\n array[startingIndex++] = length;\r\n\r\n for (var i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._width;\r\n array[startingIndex++] = value._height;\r\n array[startingIndex++] = value._extrudedHeight;\r\n array[startingIndex++] = value._cornerType;\r\n array[startingIndex++] = value._granularity;\r\n array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n positions: undefined,\r\n ellipsoid: scratchEllipsoid,\r\n vertexFormat: scratchVertexFormat,\r\n width: undefined,\r\n height: undefined,\r\n extrudedHeight: undefined,\r\n cornerType: undefined,\r\n granularity: undefined,\r\n shadowVolume: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {CorridorGeometry} [result] The object into which to store the result.\r\n * @returns {CorridorGeometry} The modified result parameter or a new CorridorGeometry instance if one was not provided.\r\n */\r\nCorridorGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var length = array[startingIndex++];\r\n var positions = new Array(length);\r\n\r\n for (var i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var width = array[startingIndex++];\r\n var height = array[startingIndex++];\r\n var extrudedHeight = array[startingIndex++];\r\n var cornerType = array[startingIndex++];\r\n var granularity = array[startingIndex++];\r\n var shadowVolume = array[startingIndex++] === 1.0;\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.positions = positions;\r\n scratchOptions.width = width;\r\n scratchOptions.height = height;\r\n scratchOptions.extrudedHeight = extrudedHeight;\r\n scratchOptions.cornerType = cornerType;\r\n scratchOptions.granularity = granularity;\r\n scratchOptions.shadowVolume = shadowVolume;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return new CorridorGeometry(scratchOptions);\r\n }\r\n\r\n result._positions = positions;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._width = width;\r\n result._height = height;\r\n result._extrudedHeight = extrudedHeight;\r\n result._cornerType = cornerType;\r\n result._granularity = granularity;\r\n result._shadowVolume = shadowVolume;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the bounding rectangle given the provided options\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of positions that define the center of the corridor.\r\n * @param {Number} options.width The distance between the edges of the corridor in meters.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {CornerType} [options.cornerType=CornerType.ROUNDED] Determines the style of the corners.\r\n * @param {Rectangle} [result] An object in which to store the result.\r\n *\r\n * @returns {Rectangle} The result rectangle.\r\n */\r\nCorridorGeometry.computeRectangle = function (options, result) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.positions;\r\n var width = options.width;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.positions\", positions);\r\n Check.defined(\"options.width\", width);\r\n //>>includeEnd('debug');\r\n\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var cornerType = defaultValue(options.cornerType, CornerType.ROUNDED);\r\n\r\n return computeRectangle(positions, ellipsoid, width, cornerType, result);\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a corridor, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {CorridorGeometry} corridorGeometry A description of the corridor.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nCorridorGeometry.createGeometry = function (corridorGeometry) {\r\n var positions = corridorGeometry._positions;\r\n var width = corridorGeometry._width;\r\n var ellipsoid = corridorGeometry._ellipsoid;\r\n\r\n positions = scaleToSurface(positions, ellipsoid);\r\n var cleanPositions = arrayRemoveDuplicates(\r\n positions,\r\n Cartesian3.equalsEpsilon\r\n );\r\n\r\n if (cleanPositions.length < 2 || width <= 0) {\r\n return;\r\n }\r\n\r\n var height = corridorGeometry._height;\r\n var extrudedHeight = corridorGeometry._extrudedHeight;\r\n var extrude = !CesiumMath.equalsEpsilon(\r\n height,\r\n extrudedHeight,\r\n 0,\r\n CesiumMath.EPSILON2\r\n );\r\n\r\n var vertexFormat = corridorGeometry._vertexFormat;\r\n var params = {\r\n ellipsoid: ellipsoid,\r\n positions: cleanPositions,\r\n width: width,\r\n cornerType: corridorGeometry._cornerType,\r\n granularity: corridorGeometry._granularity,\r\n saveAttributes: true,\r\n };\r\n var attr;\r\n if (extrude) {\r\n params.height = height;\r\n params.extrudedHeight = extrudedHeight;\r\n params.shadowVolume = corridorGeometry._shadowVolume;\r\n params.offsetAttribute = corridorGeometry._offsetAttribute;\r\n attr = computePositionsExtruded(params, vertexFormat);\r\n } else {\r\n var computedPositions = CorridorGeometryLibrary.computePositions(params);\r\n attr = combine(computedPositions, vertexFormat, ellipsoid);\r\n attr.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(\r\n attr.attributes.position.values,\r\n height,\r\n ellipsoid\r\n );\r\n\r\n if (defined(corridorGeometry._offsetAttribute)) {\r\n var applyOffsetValue =\r\n corridorGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n var length = attr.attributes.position.values.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n arrayFill(applyOffset, applyOffsetValue);\r\n attr.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n }\r\n var attributes = attr.attributes;\r\n var boundingSphere = BoundingSphere.fromVertices(\r\n attributes.position.values,\r\n undefined,\r\n 3\r\n );\r\n if (!vertexFormat.position) {\r\n attr.attributes.position.values = undefined;\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: attr.indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: boundingSphere,\r\n offsetAttribute: corridorGeometry._offsetAttribute,\r\n });\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCorridorGeometry.createShadowVolume = function (\r\n corridorGeometry,\r\n minHeightFunc,\r\n maxHeightFunc\r\n) {\r\n var granularity = corridorGeometry._granularity;\r\n var ellipsoid = corridorGeometry._ellipsoid;\r\n\r\n var minHeight = minHeightFunc(granularity, ellipsoid);\r\n var maxHeight = maxHeightFunc(granularity, ellipsoid);\r\n\r\n return new CorridorGeometry({\r\n positions: corridorGeometry._positions,\r\n width: corridorGeometry._width,\r\n cornerType: corridorGeometry._cornerType,\r\n ellipsoid: ellipsoid,\r\n granularity: granularity,\r\n extrudedHeight: minHeight,\r\n height: maxHeight,\r\n vertexFormat: VertexFormat.POSITION_ONLY,\r\n shadowVolume: true,\r\n });\r\n};\r\n\r\nObject.defineProperties(CorridorGeometry.prototype, {\r\n /**\r\n * @private\r\n */\r\n rectangle: {\r\n get: function () {\r\n if (!defined(this._rectangle)) {\r\n this._rectangle = computeRectangle(\r\n this._positions,\r\n this._ellipsoid,\r\n this._width,\r\n this._cornerType\r\n );\r\n }\r\n return this._rectangle;\r\n },\r\n },\r\n /**\r\n * For remapping texture coordinates when rendering CorridorGeometries as GroundPrimitives.\r\n *\r\n * Corridors don't support stRotation,\r\n * so just return the corners of the original system.\r\n * @private\r\n */\r\n textureCoordinateRotationPoints: {\r\n get: function () {\r\n return [0, 0, 0, 1, 1, 0];\r\n },\r\n },\r\n});\r\nexport default CorridorGeometry;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport CornerType from \"./CornerType.js\";\r\nimport CorridorGeometryLibrary from \"./CorridorGeometryLibrary.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\n\r\nvar cartesian1 = new Cartesian3();\r\nvar cartesian2 = new Cartesian3();\r\nvar cartesian3 = new Cartesian3();\r\n\r\nfunction scaleToSurface(positions, ellipsoid) {\r\n for (var i = 0; i < positions.length; i++) {\r\n positions[i] = ellipsoid.scaleToGeodeticSurface(positions[i], positions[i]);\r\n }\r\n return positions;\r\n}\r\n\r\nfunction combine(computedPositions, cornerType) {\r\n var wallIndices = [];\r\n var positions = computedPositions.positions;\r\n var corners = computedPositions.corners;\r\n var endPositions = computedPositions.endPositions;\r\n var attributes = new GeometryAttributes();\r\n var corner;\r\n var leftCount = 0;\r\n var rightCount = 0;\r\n var i;\r\n var indicesLength = 0;\r\n var length;\r\n for (i = 0; i < positions.length; i += 2) {\r\n length = positions[i].length - 3;\r\n leftCount += length; //subtracting 3 to account for duplicate points at corners\r\n indicesLength += (length / 3) * 4;\r\n rightCount += positions[i + 1].length - 3;\r\n }\r\n leftCount += 3; //add back count for end positions\r\n rightCount += 3;\r\n for (i = 0; i < corners.length; i++) {\r\n corner = corners[i];\r\n var leftSide = corners[i].leftPositions;\r\n if (defined(leftSide)) {\r\n length = leftSide.length;\r\n leftCount += length;\r\n indicesLength += (length / 3) * 2;\r\n } else {\r\n length = corners[i].rightPositions.length;\r\n rightCount += length;\r\n indicesLength += (length / 3) * 2;\r\n }\r\n }\r\n\r\n var addEndPositions = defined(endPositions);\r\n var endPositionLength;\r\n if (addEndPositions) {\r\n endPositionLength = endPositions[0].length - 3;\r\n leftCount += endPositionLength;\r\n rightCount += endPositionLength;\r\n endPositionLength /= 3;\r\n indicesLength += endPositionLength * 4;\r\n }\r\n var size = leftCount + rightCount;\r\n var finalPositions = new Float64Array(size);\r\n var front = 0;\r\n var back = size - 1;\r\n var UL, LL, UR, LR;\r\n var rightPos, leftPos;\r\n var halfLength = endPositionLength / 2;\r\n\r\n var indices = IndexDatatype.createTypedArray(size / 3, indicesLength + 4);\r\n var index = 0;\r\n\r\n indices[index++] = front / 3;\r\n indices[index++] = (back - 2) / 3;\r\n if (addEndPositions) {\r\n // add rounded end\r\n wallIndices.push(front / 3);\r\n leftPos = cartesian1;\r\n rightPos = cartesian2;\r\n var firstEndPositions = endPositions[0];\r\n for (i = 0; i < halfLength; i++) {\r\n leftPos = Cartesian3.fromArray(\r\n firstEndPositions,\r\n (halfLength - 1 - i) * 3,\r\n leftPos\r\n );\r\n rightPos = Cartesian3.fromArray(\r\n firstEndPositions,\r\n (halfLength + i) * 3,\r\n rightPos\r\n );\r\n CorridorGeometryLibrary.addAttribute(finalPositions, rightPos, front);\r\n CorridorGeometryLibrary.addAttribute(\r\n finalPositions,\r\n leftPos,\r\n undefined,\r\n back\r\n );\r\n\r\n LL = front / 3;\r\n LR = LL + 1;\r\n UL = (back - 2) / 3;\r\n UR = UL - 1;\r\n indices[index++] = UL;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n\r\n front += 3;\r\n back -= 3;\r\n }\r\n }\r\n\r\n var posIndex = 0;\r\n var rightEdge = positions[posIndex++]; //add first two edges\r\n var leftEdge = positions[posIndex++];\r\n finalPositions.set(rightEdge, front);\r\n finalPositions.set(leftEdge, back - leftEdge.length + 1);\r\n\r\n length = leftEdge.length - 3;\r\n wallIndices.push(front / 3, (back - 2) / 3);\r\n for (i = 0; i < length; i += 3) {\r\n LL = front / 3;\r\n LR = LL + 1;\r\n UL = (back - 2) / 3;\r\n UR = UL - 1;\r\n indices[index++] = UL;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n\r\n front += 3;\r\n back -= 3;\r\n }\r\n\r\n for (i = 0; i < corners.length; i++) {\r\n var j;\r\n corner = corners[i];\r\n var l = corner.leftPositions;\r\n var r = corner.rightPositions;\r\n var start;\r\n var outsidePoint = cartesian3;\r\n if (defined(l)) {\r\n back -= 3;\r\n start = UR;\r\n wallIndices.push(LR);\r\n for (j = 0; j < l.length / 3; j++) {\r\n outsidePoint = Cartesian3.fromArray(l, j * 3, outsidePoint);\r\n indices[index++] = start - j - 1;\r\n indices[index++] = start - j;\r\n CorridorGeometryLibrary.addAttribute(\r\n finalPositions,\r\n outsidePoint,\r\n undefined,\r\n back\r\n );\r\n back -= 3;\r\n }\r\n wallIndices.push(start - Math.floor(l.length / 6));\r\n if (cornerType === CornerType.BEVELED) {\r\n wallIndices.push((back - 2) / 3 + 1);\r\n }\r\n front += 3;\r\n } else {\r\n front += 3;\r\n start = LR;\r\n wallIndices.push(UR);\r\n for (j = 0; j < r.length / 3; j++) {\r\n outsidePoint = Cartesian3.fromArray(r, j * 3, outsidePoint);\r\n indices[index++] = start + j;\r\n indices[index++] = start + j + 1;\r\n CorridorGeometryLibrary.addAttribute(\r\n finalPositions,\r\n outsidePoint,\r\n front\r\n );\r\n front += 3;\r\n }\r\n wallIndices.push(start + Math.floor(r.length / 6));\r\n if (cornerType === CornerType.BEVELED) {\r\n wallIndices.push(front / 3 - 1);\r\n }\r\n back -= 3;\r\n }\r\n rightEdge = positions[posIndex++];\r\n leftEdge = positions[posIndex++];\r\n rightEdge.splice(0, 3); //remove duplicate points added by corner\r\n leftEdge.splice(leftEdge.length - 3, 3);\r\n finalPositions.set(rightEdge, front);\r\n finalPositions.set(leftEdge, back - leftEdge.length + 1);\r\n length = leftEdge.length - 3;\r\n\r\n for (j = 0; j < leftEdge.length; j += 3) {\r\n LR = front / 3;\r\n LL = LR - 1;\r\n UR = (back - 2) / 3;\r\n UL = UR + 1;\r\n indices[index++] = UL;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n front += 3;\r\n back -= 3;\r\n }\r\n front -= 3;\r\n back += 3;\r\n wallIndices.push(front / 3, (back - 2) / 3);\r\n }\r\n\r\n if (addEndPositions) {\r\n // add rounded end\r\n front += 3;\r\n back -= 3;\r\n leftPos = cartesian1;\r\n rightPos = cartesian2;\r\n var lastEndPositions = endPositions[1];\r\n for (i = 0; i < halfLength; i++) {\r\n leftPos = Cartesian3.fromArray(\r\n lastEndPositions,\r\n (endPositionLength - i - 1) * 3,\r\n leftPos\r\n );\r\n rightPos = Cartesian3.fromArray(lastEndPositions, i * 3, rightPos);\r\n CorridorGeometryLibrary.addAttribute(\r\n finalPositions,\r\n leftPos,\r\n undefined,\r\n back\r\n );\r\n CorridorGeometryLibrary.addAttribute(finalPositions, rightPos, front);\r\n\r\n LR = front / 3;\r\n LL = LR - 1;\r\n UR = (back - 2) / 3;\r\n UL = UR + 1;\r\n indices[index++] = UL;\r\n indices[index++] = UR;\r\n indices[index++] = LL;\r\n indices[index++] = LR;\r\n\r\n front += 3;\r\n back -= 3;\r\n }\r\n\r\n wallIndices.push(front / 3);\r\n } else {\r\n wallIndices.push(front / 3, (back - 2) / 3);\r\n }\r\n indices[index++] = front / 3;\r\n indices[index++] = (back - 2) / 3;\r\n\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: finalPositions,\r\n });\r\n\r\n return {\r\n attributes: attributes,\r\n indices: indices,\r\n wallIndices: wallIndices,\r\n };\r\n}\r\n\r\nfunction computePositionsExtruded(params) {\r\n var ellipsoid = params.ellipsoid;\r\n var computedPositions = CorridorGeometryLibrary.computePositions(params);\r\n var attr = combine(computedPositions, params.cornerType);\r\n var wallIndices = attr.wallIndices;\r\n var height = params.height;\r\n var extrudedHeight = params.extrudedHeight;\r\n var attributes = attr.attributes;\r\n var indices = attr.indices;\r\n var positions = attributes.position.values;\r\n var length = positions.length;\r\n var extrudedPositions = new Float64Array(length);\r\n extrudedPositions.set(positions);\r\n var newPositions = new Float64Array(length * 2);\r\n\r\n positions = PolygonPipeline.scaleToGeodeticHeight(\r\n positions,\r\n height,\r\n ellipsoid\r\n );\r\n extrudedPositions = PolygonPipeline.scaleToGeodeticHeight(\r\n extrudedPositions,\r\n extrudedHeight,\r\n ellipsoid\r\n );\r\n newPositions.set(positions);\r\n newPositions.set(extrudedPositions, length);\r\n attributes.position.values = newPositions;\r\n\r\n length /= 3;\r\n if (defined(params.offsetAttribute)) {\r\n var applyOffset = new Uint8Array(length * 2);\r\n if (params.offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n applyOffset = arrayFill(applyOffset, 1, 0, length);\r\n } else {\r\n var applyOffsetValue =\r\n params.offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n applyOffset = arrayFill(applyOffset, applyOffsetValue);\r\n }\r\n\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n var i;\r\n var iLength = indices.length;\r\n var newIndices = IndexDatatype.createTypedArray(\r\n newPositions.length / 3,\r\n (iLength + wallIndices.length) * 2\r\n );\r\n newIndices.set(indices);\r\n var index = iLength;\r\n for (i = 0; i < iLength; i += 2) {\r\n // bottom indices\r\n var v0 = indices[i];\r\n var v1 = indices[i + 1];\r\n newIndices[index++] = v0 + length;\r\n newIndices[index++] = v1 + length;\r\n }\r\n\r\n var UL, LL;\r\n for (i = 0; i < wallIndices.length; i++) {\r\n //wall indices\r\n UL = wallIndices[i];\r\n LL = UL + length;\r\n newIndices[index++] = UL;\r\n newIndices[index++] = LL;\r\n }\r\n\r\n return {\r\n attributes: attributes,\r\n indices: newIndices,\r\n };\r\n}\r\n\r\n/**\r\n * A description of a corridor outline.\r\n *\r\n * @alias CorridorOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of positions that define the center of the corridor outline.\r\n * @param {Number} options.width The distance between the edges of the corridor outline.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Number} [options.height=0] The distance in meters between the positions and the ellipsoid surface.\r\n * @param {Number} [options.extrudedHeight] The distance in meters between the extruded face and the ellipsoid surface.\r\n * @param {CornerType} [options.cornerType=CornerType.ROUNDED] Determines the style of the corners.\r\n *\r\n * @see CorridorOutlineGeometry.createGeometry\r\n *\r\n * @example\r\n * var corridor = new Cesium.CorridorOutlineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([-72.0, 40.0, -70.0, 35.0]),\r\n * width : 100000\r\n * });\r\n */\r\nfunction CorridorOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.positions;\r\n var width = options.width;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options.positions\", positions);\r\n Check.typeOf.number(\"options.width\", width);\r\n //>>includeEnd('debug');\r\n\r\n var height = defaultValue(options.height, 0.0);\r\n var extrudedHeight = defaultValue(options.extrudedHeight, height);\r\n\r\n this._positions = positions;\r\n this._ellipsoid = Ellipsoid.clone(\r\n defaultValue(options.ellipsoid, Ellipsoid.WGS84)\r\n );\r\n this._width = width;\r\n this._height = Math.max(height, extrudedHeight);\r\n this._extrudedHeight = Math.min(height, extrudedHeight);\r\n this._cornerType = defaultValue(options.cornerType, CornerType.ROUNDED);\r\n this._granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createCorridorOutlineGeometry\";\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n 1 + positions.length * Cartesian3.packedLength + Ellipsoid.packedLength + 6;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {CorridorOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCorridorOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.typeOf.object(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var positions = value._positions;\r\n var length = positions.length;\r\n array[startingIndex++] = length;\r\n\r\n for (var i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n array[startingIndex++] = value._width;\r\n array[startingIndex++] = value._height;\r\n array[startingIndex++] = value._extrudedHeight;\r\n array[startingIndex++] = value._cornerType;\r\n array[startingIndex++] = value._granularity;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchOptions = {\r\n positions: undefined,\r\n ellipsoid: scratchEllipsoid,\r\n width: undefined,\r\n height: undefined,\r\n extrudedHeight: undefined,\r\n cornerType: undefined,\r\n granularity: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {CorridorOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {CorridorOutlineGeometry} The modified result parameter or a new CorridorOutlineGeometry instance if one was not provided.\r\n */\r\nCorridorOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var length = array[startingIndex++];\r\n var positions = new Array(length);\r\n\r\n for (var i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var width = array[startingIndex++];\r\n var height = array[startingIndex++];\r\n var extrudedHeight = array[startingIndex++];\r\n var cornerType = array[startingIndex++];\r\n var granularity = array[startingIndex++];\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.positions = positions;\r\n scratchOptions.width = width;\r\n scratchOptions.height = height;\r\n scratchOptions.extrudedHeight = extrudedHeight;\r\n scratchOptions.cornerType = cornerType;\r\n scratchOptions.granularity = granularity;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n return new CorridorOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._positions = positions;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._width = width;\r\n result._height = height;\r\n result._extrudedHeight = extrudedHeight;\r\n result._cornerType = cornerType;\r\n result._granularity = granularity;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a corridor, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {CorridorOutlineGeometry} corridorOutlineGeometry A description of the corridor.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nCorridorOutlineGeometry.createGeometry = function (corridorOutlineGeometry) {\r\n var positions = corridorOutlineGeometry._positions;\r\n var width = corridorOutlineGeometry._width;\r\n var ellipsoid = corridorOutlineGeometry._ellipsoid;\r\n\r\n positions = scaleToSurface(positions, ellipsoid);\r\n var cleanPositions = arrayRemoveDuplicates(\r\n positions,\r\n Cartesian3.equalsEpsilon\r\n );\r\n\r\n if (cleanPositions.length < 2 || width <= 0) {\r\n return;\r\n }\r\n\r\n var height = corridorOutlineGeometry._height;\r\n var extrudedHeight = corridorOutlineGeometry._extrudedHeight;\r\n var extrude = !CesiumMath.equalsEpsilon(\r\n height,\r\n extrudedHeight,\r\n 0,\r\n CesiumMath.EPSILON2\r\n );\r\n\r\n var params = {\r\n ellipsoid: ellipsoid,\r\n positions: cleanPositions,\r\n width: width,\r\n cornerType: corridorOutlineGeometry._cornerType,\r\n granularity: corridorOutlineGeometry._granularity,\r\n saveAttributes: false,\r\n };\r\n var attr;\r\n if (extrude) {\r\n params.height = height;\r\n params.extrudedHeight = extrudedHeight;\r\n params.offsetAttribute = corridorOutlineGeometry._offsetAttribute;\r\n attr = computePositionsExtruded(params);\r\n } else {\r\n var computedPositions = CorridorGeometryLibrary.computePositions(params);\r\n attr = combine(computedPositions, params.cornerType);\r\n attr.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(\r\n attr.attributes.position.values,\r\n height,\r\n ellipsoid\r\n );\r\n\r\n if (defined(corridorOutlineGeometry._offsetAttribute)) {\r\n var length = attr.attributes.position.values.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n corridorOutlineGeometry._offsetAttribute ===\r\n GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n attr.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n }\r\n var attributes = attr.attributes;\r\n var boundingSphere = BoundingSphere.fromVertices(\r\n attributes.position.values,\r\n undefined,\r\n 3\r\n );\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: attr.indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: boundingSphere,\r\n offsetAttribute: corridorOutlineGeometry._offsetAttribute,\r\n });\r\n};\r\nexport default CorridorOutlineGeometry;\r\n","/**\r\n * Creates a Globally unique identifier (GUID) string. A GUID is 128 bits long, and can guarantee uniqueness across space and time.\r\n *\r\n * @function\r\n *\r\n * @returns {String}\r\n *\r\n *\r\n * @example\r\n * this.guid = Cesium.createGuid();\r\n *\r\n * @see {@link http://www.ietf.org/rfc/rfc4122.txt|RFC 4122 A Universally Unique IDentifier (UUID) URN Namespace}\r\n */\r\nfunction createGuid() {\r\n // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript\r\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, function (c) {\r\n var r = (Math.random() * 16) | 0;\r\n var v = c === \"x\" ? r : (r & 0x3) | 0x8;\r\n return v.toString(16);\r\n });\r\n}\r\nexport default createGuid;\r\n","import Credit from \"./Credit.js\";\r\nimport defined from \"./defined.js\";\r\nimport Resource from \"./Resource.js\";\r\n\r\nvar defaultTokenCredit;\r\nvar defaultAccessToken =\r\n \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJlNzhiOGFmZi0wMDhkLTQyZGItODMxYi1jZTE1Yzc1YWU5NDAiLCJpZCI6MjU5LCJpYXQiOjE2MTcyOTExODV9.ZMm6ggSpVEnvlUfE_sa-ZQ5AXhPAFVjshKZMB48w0AE\";\r\n/**\r\n * Default settings for accessing the Cesium ion API.\r\n *\r\n * An ion access token is only required if you are using any ion related APIs.\r\n * A default access token is provided for evaluation purposes only.\r\n * Sign up for a free ion account and get your own access token at {@link https://cesium.com}\r\n *\r\n * @see IonResource\r\n * @see IonImageryProvider\r\n * @see IonGeocoderService\r\n * @see createWorldImagery\r\n * @see createWorldTerrain\r\n * @namespace Ion\r\n */\r\nvar Ion = {};\r\n\r\n/**\r\n * Gets or sets the default Cesium ion access token.\r\n *\r\n * @type {String}\r\n */\r\nIon.defaultAccessToken = defaultAccessToken;\r\n\r\n/**\r\n * Gets or sets the default Cesium ion server.\r\n *\r\n * @type {String|Resource}\r\n * @default https://api.cesium.com\r\n */\r\nIon.defaultServer = new Resource({ url: \"https://api.cesium.com/\" });\r\n\r\nIon.getDefaultTokenCredit = function (providedKey) {\r\n if (providedKey !== defaultAccessToken) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(defaultTokenCredit)) {\r\n var defaultTokenMessage =\r\n ' \\\r\n This application is using Cesium\\'s default ion access token. Please assign Cesium.Ion.defaultAccessToken \\\r\n with an access token from your ion account before making any Cesium API calls. \\\r\n You can sign up for a free ion account at https://cesium.com.';\r\n\r\n defaultTokenCredit = new Credit(defaultTokenMessage, true);\r\n }\r\n\r\n return defaultTokenCredit;\r\n};\r\nexport default Ion;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Check from \"./Check.js\";\r\nimport Credit from \"./Credit.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ion from \"./Ion.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\n\r\n/**\r\n * A {@link Resource} instance that encapsulates Cesium ion asset access.\r\n * This object is normally not instantiated directly, use {@link IonResource.fromAssetId}.\r\n *\r\n * @alias IonResource\r\n * @constructor\r\n * @augments Resource\r\n *\r\n * @param {Object} endpoint The result of the Cesium ion asset endpoint service.\r\n * @param {Resource} endpointResource The resource used to retreive the endpoint.\r\n *\r\n * @see Ion\r\n * @see IonImageryProvider\r\n * @see createWorldTerrain\r\n * @see https://cesium.com\r\n */\r\nfunction IonResource(endpoint, endpointResource) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"endpoint\", endpoint);\r\n Check.defined(\"endpointResource\", endpointResource);\r\n //>>includeEnd('debug');\r\n\r\n var options;\r\n var externalType = endpoint.externalType;\r\n var isExternal = defined(externalType);\r\n\r\n if (!isExternal) {\r\n options = {\r\n url: endpoint.url,\r\n retryAttempts: 1,\r\n retryCallback: retryCallback,\r\n };\r\n } else if (\r\n externalType === \"3DTILES\" ||\r\n externalType === \"STK_TERRAIN_SERVER\"\r\n ) {\r\n // 3D Tiles and STK Terrain Server external assets can still be represented as an IonResource\r\n options = { url: endpoint.options.url };\r\n } else {\r\n //External imagery assets have additional configuration that can't be represented as a Resource\r\n throw new RuntimeError(\r\n \"Ion.createResource does not support external imagery assets; use IonImageryProvider instead.\"\r\n );\r\n }\r\n\r\n Resource.call(this, options);\r\n\r\n // The asset endpoint data returned from ion.\r\n this._ionEndpoint = endpoint;\r\n this._ionEndpointDomain = isExternal\r\n ? undefined\r\n : new Uri(endpoint.url).authority;\r\n\r\n // The endpoint resource to fetch when a new token is needed\r\n this._ionEndpointResource = endpointResource;\r\n\r\n // The primary IonResource from which an instance is derived\r\n this._ionRoot = undefined;\r\n\r\n // Shared promise for endpooint requests amd credits (only ever set on the root request)\r\n this._pendingPromise = undefined;\r\n this._credits = undefined;\r\n this._isExternal = isExternal;\r\n}\r\n\r\nif (defined(Object.create)) {\r\n IonResource.prototype = Object.create(Resource.prototype);\r\n IonResource.prototype.constructor = IonResource;\r\n}\r\n\r\n/**\r\n * Asynchronously creates an instance.\r\n *\r\n * @param {Number} assetId The Cesium ion asset id.\r\n * @param {Object} [options] An object with the following properties:\r\n * @param {String} [options.accessToken=Ion.defaultAccessToken] The access token to use.\r\n * @param {String|Resource} [options.server=Ion.defaultServer] The resource to the Cesium ion API server.\r\n * @returns {Promise.} A Promise to am instance representing the Cesium ion Asset.\r\n *\r\n * @example\r\n * //Load a Cesium3DTileset with asset ID of 124624234\r\n * viewer.scene.primitives.add(new Cesium.Cesium3DTileset({ url: Cesium.IonResource.fromAssetId(124624234) }));\r\n *\r\n * @example\r\n * //Load a CZML file with asset ID of 10890\r\n * Cesium.IonResource.fromAssetId(10890)\r\n * .then(function (resource) {\r\n * viewer.dataSources.add(Cesium.CzmlDataSource.load(resource));\r\n * });\r\n */\r\nIonResource.fromAssetId = function (assetId, options) {\r\n var endpointResource = IonResource._createEndpointResource(assetId, options);\r\n\r\n return endpointResource.fetchJson().then(function (endpoint) {\r\n return new IonResource(endpoint, endpointResource);\r\n });\r\n};\r\n\r\nObject.defineProperties(IonResource.prototype, {\r\n /**\r\n * Gets the credits required for attribution of the asset.\r\n *\r\n * @memberof IonResource.prototype\r\n * @type {Credit[]}\r\n * @readonly\r\n */\r\n credits: {\r\n get: function () {\r\n // Only we're not the root, return its credits;\r\n if (defined(this._ionRoot)) {\r\n return this._ionRoot.credits;\r\n }\r\n\r\n // We are the root\r\n if (defined(this._credits)) {\r\n return this._credits;\r\n }\r\n\r\n this._credits = IonResource.getCreditsFromEndpoint(\r\n this._ionEndpoint,\r\n this._ionEndpointResource\r\n );\r\n\r\n return this._credits;\r\n },\r\n },\r\n});\r\n\r\n/** @private */\r\nIonResource.getCreditsFromEndpoint = function (endpoint, endpointResource) {\r\n var credits = endpoint.attributions.map(Credit.getIonCredit);\r\n var defaultTokenCredit = Ion.getDefaultTokenCredit(\r\n endpointResource.queryParameters.access_token\r\n );\r\n if (defined(defaultTokenCredit)) {\r\n credits.push(Credit.clone(defaultTokenCredit));\r\n }\r\n return credits;\r\n};\r\n\r\n/** @inheritdoc */\r\nIonResource.prototype.clone = function (result) {\r\n // We always want to use the root's information because it's the most up-to-date\r\n var ionRoot = defaultValue(this._ionRoot, this);\r\n\r\n if (!defined(result)) {\r\n result = new IonResource(\r\n ionRoot._ionEndpoint,\r\n ionRoot._ionEndpointResource\r\n );\r\n }\r\n\r\n result = Resource.prototype.clone.call(this, result);\r\n result._ionRoot = ionRoot;\r\n result._isExternal = this._isExternal;\r\n\r\n return result;\r\n};\r\n\r\nIonResource.prototype.fetchImage = function (options) {\r\n if (!this._isExternal) {\r\n var userOptions = options;\r\n options = {\r\n preferBlob: true,\r\n };\r\n if (defined(userOptions)) {\r\n options.flipY = userOptions.flipY;\r\n options.preferImageBitmap = userOptions.preferImageBitmap;\r\n }\r\n }\r\n\r\n return Resource.prototype.fetchImage.call(this, options);\r\n};\r\n\r\nIonResource.prototype._makeRequest = function (options) {\r\n // Don't send ion access token to non-ion servers.\r\n if (\r\n this._isExternal ||\r\n new Uri(this.url).authority !== this._ionEndpointDomain\r\n ) {\r\n return Resource.prototype._makeRequest.call(this, options);\r\n }\r\n\r\n if (!defined(options.headers)) {\r\n options.headers = {};\r\n }\r\n options.headers.Authorization = \"Bearer \" + this._ionEndpoint.accessToken;\r\n\r\n return Resource.prototype._makeRequest.call(this, options);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nIonResource._createEndpointResource = function (assetId, options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"assetId\", assetId);\r\n //>>includeEnd('debug');\r\n\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var server = defaultValue(options.server, Ion.defaultServer);\r\n var accessToken = defaultValue(options.accessToken, Ion.defaultAccessToken);\r\n server = Resource.createIfNeeded(server);\r\n\r\n var resourceOptions = {\r\n url: \"v1/assets/\" + assetId + \"/endpoint\",\r\n };\r\n\r\n if (defined(accessToken)) {\r\n resourceOptions.queryParameters = { access_token: accessToken };\r\n }\r\n\r\n return server.getDerivedResource(resourceOptions);\r\n};\r\n\r\nfunction retryCallback(that, error) {\r\n var ionRoot = defaultValue(that._ionRoot, that);\r\n var endpointResource = ionRoot._ionEndpointResource;\r\n\r\n // Image is not available in worker threads, so this avoids\r\n // a ReferenceError\r\n var imageDefined = typeof Image !== \"undefined\";\r\n\r\n // We only want to retry in the case of invalid credentials (401) or image\r\n // requests(since Image failures can not provide a status code)\r\n if (\r\n !defined(error) ||\r\n (error.statusCode !== 401 &&\r\n !(imageDefined && error.target instanceof Image))\r\n ) {\r\n return when.resolve(false);\r\n }\r\n\r\n // We use a shared pending promise for all derived assets, since they share\r\n // a common access_token. If we're already requesting a new token for this\r\n // asset, we wait on the same promise.\r\n if (!defined(ionRoot._pendingPromise)) {\r\n ionRoot._pendingPromise = endpointResource\r\n .fetchJson()\r\n .then(function (newEndpoint) {\r\n //Set the token for root resource so new derived resources automatically pick it up\r\n ionRoot._ionEndpoint = newEndpoint;\r\n return newEndpoint;\r\n })\r\n .always(function (newEndpoint) {\r\n // Pass or fail, we're done with this promise, the next failure should use a new one.\r\n ionRoot._pendingPromise = undefined;\r\n return newEndpoint;\r\n });\r\n }\r\n\r\n return ionRoot._pendingPromise.then(function (newEndpoint) {\r\n // Set the new token and endpoint for this resource\r\n that._ionEndpoint = newEndpoint;\r\n return true;\r\n });\r\n}\r\nexport default IonResource;\r\n","import CesiumTerrainProvider from \"./CesiumTerrainProvider.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport IonResource from \"./IonResource.js\";\r\n\r\n/**\r\n * Creates a {@link CesiumTerrainProvider} instance for the {@link https://cesium.com/content/#cesium-world-terrain|Cesium World Terrain}.\r\n *\r\n * @function\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server if available.\r\n * @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server if available.\r\n * @returns {CesiumTerrainProvider}\r\n *\r\n * @see Ion\r\n *\r\n * @example\r\n * // Create Cesium World Terrain with default settings\r\n * var viewer = new Cesium.Viewer('cesiumContainer', {\r\n * terrainProvider : Cesium.createWorldTerrain();\r\n * });\r\n *\r\n * @example\r\n * // Create Cesium World Terrain with water and normals.\r\n * var viewer = new Cesium.Viewer('cesiumContainer', {\r\n * terrainProvider : Cesium.createWorldTerrain({\r\n * requestWaterMask : true,\r\n * requestVertexNormals : true\r\n * });\r\n * });\r\n *\r\n */\r\nfunction createWorldTerrain(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n return new CesiumTerrainProvider({\r\n url: IonResource.fromAssetId(1),\r\n requestVertexNormals: defaultValue(options.requestVertexNormals, false),\r\n requestWaterMask: defaultValue(options.requestWaterMask, false),\r\n });\r\n}\r\nexport default createWorldTerrain;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Intersect from \"./Intersect.js\";\r\nimport Plane from \"./Plane.js\";\r\n\r\n/**\r\n * The culling volume defined by planes.\r\n *\r\n * @alias CullingVolume\r\n * @constructor\r\n *\r\n * @param {Cartesian4[]} [planes] An array of clipping planes.\r\n */\r\nfunction CullingVolume(planes) {\r\n /**\r\n * Each plane is represented by a Cartesian4 object, where the x, y, and z components\r\n * define the unit vector normal to the plane, and the w component is the distance of the\r\n * plane from the origin.\r\n * @type {Cartesian4[]}\r\n * @default []\r\n */\r\n this.planes = defaultValue(planes, []);\r\n}\r\n\r\nvar faces = [new Cartesian3(), new Cartesian3(), new Cartesian3()];\r\nCartesian3.clone(Cartesian3.UNIT_X, faces[0]);\r\nCartesian3.clone(Cartesian3.UNIT_Y, faces[1]);\r\nCartesian3.clone(Cartesian3.UNIT_Z, faces[2]);\r\n\r\nvar scratchPlaneCenter = new Cartesian3();\r\nvar scratchPlaneNormal = new Cartesian3();\r\nvar scratchPlane = new Plane(new Cartesian3(1.0, 0.0, 0.0), 0.0);\r\n\r\n/**\r\n * Constructs a culling volume from a bounding sphere. Creates six planes that create a box containing the sphere.\r\n * The planes are aligned to the x, y, and z axes in world coordinates.\r\n *\r\n * @param {BoundingSphere} boundingSphere The bounding sphere used to create the culling volume.\r\n * @param {CullingVolume} [result] The object onto which to store the result.\r\n * @returns {CullingVolume} The culling volume created from the bounding sphere.\r\n */\r\nCullingVolume.fromBoundingSphere = function (boundingSphere, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(boundingSphere)) {\r\n throw new DeveloperError(\"boundingSphere is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new CullingVolume();\r\n }\r\n\r\n var length = faces.length;\r\n var planes = result.planes;\r\n planes.length = 2 * length;\r\n\r\n var center = boundingSphere.center;\r\n var radius = boundingSphere.radius;\r\n\r\n var planeIndex = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var faceNormal = faces[i];\r\n\r\n var plane0 = planes[planeIndex];\r\n var plane1 = planes[planeIndex + 1];\r\n\r\n if (!defined(plane0)) {\r\n plane0 = planes[planeIndex] = new Cartesian4();\r\n }\r\n if (!defined(plane1)) {\r\n plane1 = planes[planeIndex + 1] = new Cartesian4();\r\n }\r\n\r\n Cartesian3.multiplyByScalar(faceNormal, -radius, scratchPlaneCenter);\r\n Cartesian3.add(center, scratchPlaneCenter, scratchPlaneCenter);\r\n\r\n plane0.x = faceNormal.x;\r\n plane0.y = faceNormal.y;\r\n plane0.z = faceNormal.z;\r\n plane0.w = -Cartesian3.dot(faceNormal, scratchPlaneCenter);\r\n\r\n Cartesian3.multiplyByScalar(faceNormal, radius, scratchPlaneCenter);\r\n Cartesian3.add(center, scratchPlaneCenter, scratchPlaneCenter);\r\n\r\n plane1.x = -faceNormal.x;\r\n plane1.y = -faceNormal.y;\r\n plane1.z = -faceNormal.z;\r\n plane1.w = -Cartesian3.dot(\r\n Cartesian3.negate(faceNormal, scratchPlaneNormal),\r\n scratchPlaneCenter\r\n );\r\n\r\n planeIndex += 2;\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines whether a bounding volume intersects the culling volume.\r\n *\r\n * @param {Object} boundingVolume The bounding volume whose intersection with the culling volume is to be tested.\r\n * @returns {Intersect} Intersect.OUTSIDE, Intersect.INTERSECTING, or Intersect.INSIDE.\r\n */\r\nCullingVolume.prototype.computeVisibility = function (boundingVolume) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(boundingVolume)) {\r\n throw new DeveloperError(\"boundingVolume is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var planes = this.planes;\r\n var intersecting = false;\r\n for (var k = 0, len = planes.length; k < len; ++k) {\r\n var result = boundingVolume.intersectPlane(\r\n Plane.fromCartesian4(planes[k], scratchPlane)\r\n );\r\n if (result === Intersect.OUTSIDE) {\r\n return Intersect.OUTSIDE;\r\n } else if (result === Intersect.INTERSECTING) {\r\n intersecting = true;\r\n }\r\n }\r\n\r\n return intersecting ? Intersect.INTERSECTING : Intersect.INSIDE;\r\n};\r\n\r\n/**\r\n * Determines whether a bounding volume intersects the culling volume.\r\n *\r\n * @param {Object} boundingVolume The bounding volume whose intersection with the culling volume is to be tested.\r\n * @param {Number} parentPlaneMask A bit mask from the boundingVolume's parent's check against the same culling\r\n * volume, such that if (planeMask & (1 << planeIndex) === 0), for k < 31, then\r\n * the parent (and therefore this) volume is completely inside plane[planeIndex]\r\n * and that plane check can be skipped.\r\n * @returns {Number} A plane mask as described above (which can be applied to this boundingVolume's children).\r\n *\r\n * @private\r\n */\r\nCullingVolume.prototype.computeVisibilityWithPlaneMask = function (\r\n boundingVolume,\r\n parentPlaneMask\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(boundingVolume)) {\r\n throw new DeveloperError(\"boundingVolume is required.\");\r\n }\r\n if (!defined(parentPlaneMask)) {\r\n throw new DeveloperError(\"parentPlaneMask is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (\r\n parentPlaneMask === CullingVolume.MASK_OUTSIDE ||\r\n parentPlaneMask === CullingVolume.MASK_INSIDE\r\n ) {\r\n // parent is completely outside or completely inside, so this child is as well.\r\n return parentPlaneMask;\r\n }\r\n\r\n // Start with MASK_INSIDE (all zeros) so that after the loop, the return value can be compared with MASK_INSIDE.\r\n // (Because if there are fewer than 31 planes, the upper bits wont be changed.)\r\n var mask = CullingVolume.MASK_INSIDE;\r\n\r\n var planes = this.planes;\r\n for (var k = 0, len = planes.length; k < len; ++k) {\r\n // For k greater than 31 (since 31 is the maximum number of INSIDE/INTERSECTING bits we can store), skip the optimization.\r\n var flag = k < 31 ? 1 << k : 0;\r\n if (k < 31 && (parentPlaneMask & flag) === 0) {\r\n // boundingVolume is known to be INSIDE this plane.\r\n continue;\r\n }\r\n\r\n var result = boundingVolume.intersectPlane(\r\n Plane.fromCartesian4(planes[k], scratchPlane)\r\n );\r\n if (result === Intersect.OUTSIDE) {\r\n return CullingVolume.MASK_OUTSIDE;\r\n } else if (result === Intersect.INTERSECTING) {\r\n mask |= flag;\r\n }\r\n }\r\n\r\n return mask;\r\n};\r\n\r\n/**\r\n * For plane masks (as used in {@link CullingVolume#computeVisibilityWithPlaneMask}), this special value\r\n * represents the case where the object bounding volume is entirely outside the culling volume.\r\n *\r\n * @type {Number}\r\n * @private\r\n */\r\nCullingVolume.MASK_OUTSIDE = 0xffffffff;\r\n\r\n/**\r\n * For plane masks (as used in {@link CullingVolume.prototype.computeVisibilityWithPlaneMask}), this value\r\n * represents the case where the object bounding volume is entirely inside the culling volume.\r\n *\r\n * @type {Number}\r\n * @private\r\n */\r\nCullingVolume.MASK_INSIDE = 0x00000000;\r\n\r\n/**\r\n * For plane masks (as used in {@link CullingVolume.prototype.computeVisibilityWithPlaneMask}), this value\r\n * represents the case where the object bounding volume (may) intersect all planes of the culling volume.\r\n *\r\n * @type {Number}\r\n * @private\r\n */\r\nCullingVolume.MASK_INDETERMINATE = 0x7fffffff;\r\nexport default CullingVolume;\r\n","import CesiumMath from \"./Math.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar CylinderGeometryLibrary = {};\r\n\r\n/**\r\n * @private\r\n */\r\nCylinderGeometryLibrary.computePositions = function (\r\n length,\r\n topRadius,\r\n bottomRadius,\r\n slices,\r\n fill\r\n) {\r\n var topZ = length * 0.5;\r\n var bottomZ = -topZ;\r\n\r\n var twoSlice = slices + slices;\r\n var size = fill ? 2 * twoSlice : twoSlice;\r\n var positions = new Float64Array(size * 3);\r\n var i;\r\n var index = 0;\r\n var tbIndex = 0;\r\n var bottomOffset = fill ? twoSlice * 3 : 0;\r\n var topOffset = fill ? (twoSlice + slices) * 3 : slices * 3;\r\n\r\n for (i = 0; i < slices; i++) {\r\n var angle = (i / slices) * CesiumMath.TWO_PI;\r\n var x = Math.cos(angle);\r\n var y = Math.sin(angle);\r\n var bottomX = x * bottomRadius;\r\n var bottomY = y * bottomRadius;\r\n var topX = x * topRadius;\r\n var topY = y * topRadius;\r\n\r\n positions[tbIndex + bottomOffset] = bottomX;\r\n positions[tbIndex + bottomOffset + 1] = bottomY;\r\n positions[tbIndex + bottomOffset + 2] = bottomZ;\r\n\r\n positions[tbIndex + topOffset] = topX;\r\n positions[tbIndex + topOffset + 1] = topY;\r\n positions[tbIndex + topOffset + 2] = topZ;\r\n tbIndex += 3;\r\n if (fill) {\r\n positions[index++] = bottomX;\r\n positions[index++] = bottomY;\r\n positions[index++] = bottomZ;\r\n positions[index++] = topX;\r\n positions[index++] = topY;\r\n positions[index++] = topZ;\r\n }\r\n }\r\n\r\n return positions;\r\n};\r\nexport default CylinderGeometryLibrary;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport CylinderGeometryLibrary from \"./CylinderGeometryLibrary.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar radiusScratch = new Cartesian2();\r\nvar normalScratch = new Cartesian3();\r\nvar bitangentScratch = new Cartesian3();\r\nvar tangentScratch = new Cartesian3();\r\nvar positionScratch = new Cartesian3();\r\n\r\n/**\r\n * A description of a cylinder.\r\n *\r\n * @alias CylinderGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number} options.length The length of the cylinder.\r\n * @param {Number} options.topRadius The radius of the top of the cylinder.\r\n * @param {Number} options.bottomRadius The radius of the bottom of the cylinder.\r\n * @param {Number} [options.slices=128] The number of edges around the perimeter of the cylinder.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n *\r\n * @exception {DeveloperError} options.slices must be greater than or equal to 3.\r\n *\r\n * @see CylinderGeometry.createGeometry\r\n *\r\n * @example\r\n * // create cylinder geometry\r\n * var cylinder = new Cesium.CylinderGeometry({\r\n * length: 200000,\r\n * topRadius: 80000,\r\n * bottomRadius: 200000,\r\n * });\r\n * var geometry = Cesium.CylinderGeometry.createGeometry(cylinder);\r\n */\r\nfunction CylinderGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var length = options.length;\r\n var topRadius = options.topRadius;\r\n var bottomRadius = options.bottomRadius;\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n var slices = defaultValue(options.slices, 128);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(length)) {\r\n throw new DeveloperError(\"options.length must be defined.\");\r\n }\r\n if (!defined(topRadius)) {\r\n throw new DeveloperError(\"options.topRadius must be defined.\");\r\n }\r\n if (!defined(bottomRadius)) {\r\n throw new DeveloperError(\"options.bottomRadius must be defined.\");\r\n }\r\n if (slices < 3) {\r\n throw new DeveloperError(\r\n \"options.slices must be greater than or equal to 3.\"\r\n );\r\n }\r\n if (\r\n defined(options.offsetAttribute) &&\r\n options.offsetAttribute === GeometryOffsetAttribute.TOP\r\n ) {\r\n throw new DeveloperError(\r\n \"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._length = length;\r\n this._topRadius = topRadius;\r\n this._bottomRadius = bottomRadius;\r\n this._vertexFormat = VertexFormat.clone(vertexFormat);\r\n this._slices = slices;\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createCylinderGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nCylinderGeometry.packedLength = VertexFormat.packedLength + 5;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {CylinderGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCylinderGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._length;\r\n array[startingIndex++] = value._topRadius;\r\n array[startingIndex++] = value._bottomRadius;\r\n array[startingIndex++] = value._slices;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n vertexFormat: scratchVertexFormat,\r\n length: undefined,\r\n topRadius: undefined,\r\n bottomRadius: undefined,\r\n slices: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {CylinderGeometry} [result] The object into which to store the result.\r\n * @returns {CylinderGeometry} The modified result parameter or a new CylinderGeometry instance if one was not provided.\r\n */\r\nCylinderGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var length = array[startingIndex++];\r\n var topRadius = array[startingIndex++];\r\n var bottomRadius = array[startingIndex++];\r\n var slices = array[startingIndex++];\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.length = length;\r\n scratchOptions.topRadius = topRadius;\r\n scratchOptions.bottomRadius = bottomRadius;\r\n scratchOptions.slices = slices;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n return new CylinderGeometry(scratchOptions);\r\n }\r\n\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._length = length;\r\n result._topRadius = topRadius;\r\n result._bottomRadius = bottomRadius;\r\n result._slices = slices;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a cylinder, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {CylinderGeometry} cylinderGeometry A description of the cylinder.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nCylinderGeometry.createGeometry = function (cylinderGeometry) {\r\n var length = cylinderGeometry._length;\r\n var topRadius = cylinderGeometry._topRadius;\r\n var bottomRadius = cylinderGeometry._bottomRadius;\r\n var vertexFormat = cylinderGeometry._vertexFormat;\r\n var slices = cylinderGeometry._slices;\r\n\r\n if (\r\n length <= 0 ||\r\n topRadius < 0 ||\r\n bottomRadius < 0 ||\r\n (topRadius === 0 && bottomRadius === 0)\r\n ) {\r\n return;\r\n }\r\n\r\n var twoSlices = slices + slices;\r\n var threeSlices = slices + twoSlices;\r\n var numVertices = twoSlices + twoSlices;\r\n\r\n var positions = CylinderGeometryLibrary.computePositions(\r\n length,\r\n topRadius,\r\n bottomRadius,\r\n slices,\r\n true\r\n );\r\n\r\n var st = vertexFormat.st ? new Float32Array(numVertices * 2) : undefined;\r\n var normals = vertexFormat.normal\r\n ? new Float32Array(numVertices * 3)\r\n : undefined;\r\n var tangents = vertexFormat.tangent\r\n ? new Float32Array(numVertices * 3)\r\n : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(numVertices * 3)\r\n : undefined;\r\n\r\n var i;\r\n var computeNormal =\r\n vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent;\r\n\r\n if (computeNormal) {\r\n var computeTangent = vertexFormat.tangent || vertexFormat.bitangent;\r\n\r\n var normalIndex = 0;\r\n var tangentIndex = 0;\r\n var bitangentIndex = 0;\r\n\r\n var theta = Math.atan2(bottomRadius - topRadius, length);\r\n var normal = normalScratch;\r\n normal.z = Math.sin(theta);\r\n var normalScale = Math.cos(theta);\r\n var tangent = tangentScratch;\r\n var bitangent = bitangentScratch;\r\n\r\n for (i = 0; i < slices; i++) {\r\n var angle = (i / slices) * CesiumMath.TWO_PI;\r\n var x = normalScale * Math.cos(angle);\r\n var y = normalScale * Math.sin(angle);\r\n if (computeNormal) {\r\n normal.x = x;\r\n normal.y = y;\r\n\r\n if (computeTangent) {\r\n tangent = Cartesian3.normalize(\r\n Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent),\r\n tangent\r\n );\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n normals[normalIndex++] = normal.x;\r\n normals[normalIndex++] = normal.y;\r\n normals[normalIndex++] = normal.z;\r\n normals[normalIndex++] = normal.x;\r\n normals[normalIndex++] = normal.y;\r\n normals[normalIndex++] = normal.z;\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n tangents[tangentIndex++] = tangent.x;\r\n tangents[tangentIndex++] = tangent.y;\r\n tangents[tangentIndex++] = tangent.z;\r\n tangents[tangentIndex++] = tangent.x;\r\n tangents[tangentIndex++] = tangent.y;\r\n tangents[tangentIndex++] = tangent.z;\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n bitangent = Cartesian3.normalize(\r\n Cartesian3.cross(normal, tangent, bitangent),\r\n bitangent\r\n );\r\n bitangents[bitangentIndex++] = bitangent.x;\r\n bitangents[bitangentIndex++] = bitangent.y;\r\n bitangents[bitangentIndex++] = bitangent.z;\r\n bitangents[bitangentIndex++] = bitangent.x;\r\n bitangents[bitangentIndex++] = bitangent.y;\r\n bitangents[bitangentIndex++] = bitangent.z;\r\n }\r\n }\r\n }\r\n\r\n for (i = 0; i < slices; i++) {\r\n if (vertexFormat.normal) {\r\n normals[normalIndex++] = 0;\r\n normals[normalIndex++] = 0;\r\n normals[normalIndex++] = -1;\r\n }\r\n if (vertexFormat.tangent) {\r\n tangents[tangentIndex++] = 1;\r\n tangents[tangentIndex++] = 0;\r\n tangents[tangentIndex++] = 0;\r\n }\r\n if (vertexFormat.bitangent) {\r\n bitangents[bitangentIndex++] = 0;\r\n bitangents[bitangentIndex++] = -1;\r\n bitangents[bitangentIndex++] = 0;\r\n }\r\n }\r\n\r\n for (i = 0; i < slices; i++) {\r\n if (vertexFormat.normal) {\r\n normals[normalIndex++] = 0;\r\n normals[normalIndex++] = 0;\r\n normals[normalIndex++] = 1;\r\n }\r\n if (vertexFormat.tangent) {\r\n tangents[tangentIndex++] = 1;\r\n tangents[tangentIndex++] = 0;\r\n tangents[tangentIndex++] = 0;\r\n }\r\n if (vertexFormat.bitangent) {\r\n bitangents[bitangentIndex++] = 0;\r\n bitangents[bitangentIndex++] = 1;\r\n bitangents[bitangentIndex++] = 0;\r\n }\r\n }\r\n }\r\n\r\n var numIndices = 12 * slices - 12;\r\n var indices = IndexDatatype.createTypedArray(numVertices, numIndices);\r\n var index = 0;\r\n var j = 0;\r\n for (i = 0; i < slices - 1; i++) {\r\n indices[index++] = j;\r\n indices[index++] = j + 2;\r\n indices[index++] = j + 3;\r\n\r\n indices[index++] = j;\r\n indices[index++] = j + 3;\r\n indices[index++] = j + 1;\r\n\r\n j += 2;\r\n }\r\n\r\n indices[index++] = twoSlices - 2;\r\n indices[index++] = 0;\r\n indices[index++] = 1;\r\n indices[index++] = twoSlices - 2;\r\n indices[index++] = 1;\r\n indices[index++] = twoSlices - 1;\r\n\r\n for (i = 1; i < slices - 1; i++) {\r\n indices[index++] = twoSlices + i + 1;\r\n indices[index++] = twoSlices + i;\r\n indices[index++] = twoSlices;\r\n }\r\n\r\n for (i = 1; i < slices - 1; i++) {\r\n indices[index++] = threeSlices;\r\n indices[index++] = threeSlices + i;\r\n indices[index++] = threeSlices + i + 1;\r\n }\r\n\r\n var textureCoordIndex = 0;\r\n if (vertexFormat.st) {\r\n var rad = Math.max(topRadius, bottomRadius);\r\n for (i = 0; i < numVertices; i++) {\r\n var position = Cartesian3.fromArray(positions, i * 3, positionScratch);\r\n st[textureCoordIndex++] = (position.x + rad) / (2.0 * rad);\r\n st[textureCoordIndex++] = (position.y + rad) / (2.0 * rad);\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n if (vertexFormat.position) {\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.st) {\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: st,\r\n });\r\n }\r\n\r\n radiusScratch.x = length * 0.5;\r\n radiusScratch.y = Math.max(bottomRadius, topRadius);\r\n\r\n var boundingSphere = new BoundingSphere(\r\n Cartesian3.ZERO,\r\n Cartesian2.magnitude(radiusScratch)\r\n );\r\n\r\n if (defined(cylinderGeometry._offsetAttribute)) {\r\n length = positions.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n cylinderGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: boundingSphere,\r\n offsetAttribute: cylinderGeometry._offsetAttribute,\r\n });\r\n};\r\n\r\nvar unitCylinderGeometry;\r\n\r\n/**\r\n * Returns the geometric representation of a unit cylinder, including its vertices, indices, and a bounding sphere.\r\n * @returns {Geometry} The computed vertices and indices.\r\n *\r\n * @private\r\n */\r\nCylinderGeometry.getUnitCylinder = function () {\r\n if (!defined(unitCylinderGeometry)) {\r\n unitCylinderGeometry = CylinderGeometry.createGeometry(\r\n new CylinderGeometry({\r\n topRadius: 1.0,\r\n bottomRadius: 1.0,\r\n length: 1.0,\r\n vertexFormat: VertexFormat.POSITION_ONLY,\r\n })\r\n );\r\n }\r\n return unitCylinderGeometry;\r\n};\r\nexport default CylinderGeometry;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport CylinderGeometryLibrary from \"./CylinderGeometryLibrary.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\n\r\nvar radiusScratch = new Cartesian2();\r\n\r\n/**\r\n * A description of the outline of a cylinder.\r\n *\r\n * @alias CylinderOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number} options.length The length of the cylinder.\r\n * @param {Number} options.topRadius The radius of the top of the cylinder.\r\n * @param {Number} options.bottomRadius The radius of the bottom of the cylinder.\r\n * @param {Number} [options.slices=128] The number of edges around the perimeter of the cylinder.\r\n * @param {Number} [options.numberOfVerticalLines=16] Number of lines to draw between the top and bottom surfaces of the cylinder.\r\n *\r\n * @exception {DeveloperError} options.length must be greater than 0.\r\n * @exception {DeveloperError} options.topRadius must be greater than 0.\r\n * @exception {DeveloperError} options.bottomRadius must be greater than 0.\r\n * @exception {DeveloperError} bottomRadius and topRadius cannot both equal 0.\r\n * @exception {DeveloperError} options.slices must be greater than or equal to 3.\r\n *\r\n * @see CylinderOutlineGeometry.createGeometry\r\n *\r\n * @example\r\n * // create cylinder geometry\r\n * var cylinder = new Cesium.CylinderOutlineGeometry({\r\n * length: 200000,\r\n * topRadius: 80000,\r\n * bottomRadius: 200000,\r\n * });\r\n * var geometry = Cesium.CylinderOutlineGeometry.createGeometry(cylinder);\r\n */\r\nfunction CylinderOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var length = options.length;\r\n var topRadius = options.topRadius;\r\n var bottomRadius = options.bottomRadius;\r\n var slices = defaultValue(options.slices, 128);\r\n var numberOfVerticalLines = Math.max(\r\n defaultValue(options.numberOfVerticalLines, 16),\r\n 0\r\n );\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"options.positions\", length);\r\n Check.typeOf.number(\"options.topRadius\", topRadius);\r\n Check.typeOf.number(\"options.bottomRadius\", bottomRadius);\r\n Check.typeOf.number.greaterThanOrEquals(\"options.slices\", slices, 3);\r\n if (\r\n defined(options.offsetAttribute) &&\r\n options.offsetAttribute === GeometryOffsetAttribute.TOP\r\n ) {\r\n throw new DeveloperError(\r\n \"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._length = length;\r\n this._topRadius = topRadius;\r\n this._bottomRadius = bottomRadius;\r\n this._slices = slices;\r\n this._numberOfVerticalLines = numberOfVerticalLines;\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createCylinderOutlineGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nCylinderOutlineGeometry.packedLength = 6;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {CylinderOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nCylinderOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value._length;\r\n array[startingIndex++] = value._topRadius;\r\n array[startingIndex++] = value._bottomRadius;\r\n array[startingIndex++] = value._slices;\r\n array[startingIndex++] = value._numberOfVerticalLines;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchOptions = {\r\n length: undefined,\r\n topRadius: undefined,\r\n bottomRadius: undefined,\r\n slices: undefined,\r\n numberOfVerticalLines: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {CylinderOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {CylinderOutlineGeometry} The modified result parameter or a new CylinderOutlineGeometry instance if one was not provided.\r\n */\r\nCylinderOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var length = array[startingIndex++];\r\n var topRadius = array[startingIndex++];\r\n var bottomRadius = array[startingIndex++];\r\n var slices = array[startingIndex++];\r\n var numberOfVerticalLines = array[startingIndex++];\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.length = length;\r\n scratchOptions.topRadius = topRadius;\r\n scratchOptions.bottomRadius = bottomRadius;\r\n scratchOptions.slices = slices;\r\n scratchOptions.numberOfVerticalLines = numberOfVerticalLines;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n return new CylinderOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._length = length;\r\n result._topRadius = topRadius;\r\n result._bottomRadius = bottomRadius;\r\n result._slices = slices;\r\n result._numberOfVerticalLines = numberOfVerticalLines;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an outline of a cylinder, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {CylinderOutlineGeometry} cylinderGeometry A description of the cylinder outline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nCylinderOutlineGeometry.createGeometry = function (cylinderGeometry) {\r\n var length = cylinderGeometry._length;\r\n var topRadius = cylinderGeometry._topRadius;\r\n var bottomRadius = cylinderGeometry._bottomRadius;\r\n var slices = cylinderGeometry._slices;\r\n var numberOfVerticalLines = cylinderGeometry._numberOfVerticalLines;\r\n\r\n if (\r\n length <= 0 ||\r\n topRadius < 0 ||\r\n bottomRadius < 0 ||\r\n (topRadius === 0 && bottomRadius === 0)\r\n ) {\r\n return;\r\n }\r\n\r\n var numVertices = slices * 2;\r\n\r\n var positions = CylinderGeometryLibrary.computePositions(\r\n length,\r\n topRadius,\r\n bottomRadius,\r\n slices,\r\n false\r\n );\r\n var numIndices = slices * 2;\r\n var numSide;\r\n if (numberOfVerticalLines > 0) {\r\n var numSideLines = Math.min(numberOfVerticalLines, slices);\r\n numSide = Math.round(slices / numSideLines);\r\n numIndices += numSideLines;\r\n }\r\n\r\n var indices = IndexDatatype.createTypedArray(numVertices, numIndices * 2);\r\n var index = 0;\r\n var i;\r\n for (i = 0; i < slices - 1; i++) {\r\n indices[index++] = i;\r\n indices[index++] = i + 1;\r\n indices[index++] = i + slices;\r\n indices[index++] = i + 1 + slices;\r\n }\r\n\r\n indices[index++] = slices - 1;\r\n indices[index++] = 0;\r\n indices[index++] = slices + slices - 1;\r\n indices[index++] = slices;\r\n\r\n if (numberOfVerticalLines > 0) {\r\n for (i = 0; i < slices; i += numSide) {\r\n indices[index++] = i;\r\n indices[index++] = i + slices;\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n\r\n radiusScratch.x = length * 0.5;\r\n radiusScratch.y = Math.max(bottomRadius, topRadius);\r\n\r\n var boundingSphere = new BoundingSphere(\r\n Cartesian3.ZERO,\r\n Cartesian2.magnitude(radiusScratch)\r\n );\r\n\r\n if (defined(cylinderGeometry._offsetAttribute)) {\r\n length = positions.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n cylinderGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: boundingSphere,\r\n offsetAttribute: cylinderGeometry._offsetAttribute,\r\n });\r\n};\r\nexport default CylinderOutlineGeometry;\r\n","import Check from \"./Check.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\n\r\nvar compressedMagic = 0x7468dead;\r\nvar compressedMagicSwap = 0xadde6874;\r\n\r\n/**\r\n * Decodes data that is received from the Google Earth Enterprise server.\r\n *\r\n * @param {ArrayBuffer} key The key used during decoding.\r\n * @param {ArrayBuffer} data The data to be decoded.\r\n *\r\n * @private\r\n */\r\nfunction decodeGoogleEarthEnterpriseData(key, data) {\r\n if (decodeGoogleEarthEnterpriseData.passThroughDataForTesting) {\r\n return data;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"key\", key);\r\n Check.typeOf.object(\"data\", data);\r\n //>>includeEnd('debug');\r\n\r\n var keyLength = key.byteLength;\r\n if (keyLength === 0 || keyLength % 4 !== 0) {\r\n throw new RuntimeError(\r\n \"The length of key must be greater than 0 and a multiple of 4.\"\r\n );\r\n }\r\n\r\n var dataView = new DataView(data);\r\n var magic = dataView.getUint32(0, true);\r\n if (magic === compressedMagic || magic === compressedMagicSwap) {\r\n // Occasionally packets don't come back encoded, so just return\r\n return data;\r\n }\r\n\r\n var keyView = new DataView(key);\r\n\r\n var dp = 0;\r\n var dpend = data.byteLength;\r\n var dpend64 = dpend - (dpend % 8);\r\n var kpend = keyLength;\r\n var kp;\r\n var off = 8;\r\n\r\n // This algorithm is intentionally asymmetric to make it more difficult to\r\n // guess. Security through obscurity. :-(\r\n\r\n // while we have a full uint64 (8 bytes) left to do\r\n // assumes buffer is 64bit aligned (or processor doesn't care)\r\n while (dp < dpend64) {\r\n // rotate the key each time through by using the offets 16,0,8,16,0,8,...\r\n off = (off + 8) % 24;\r\n kp = off;\r\n\r\n // run through one key length xor'ing one uint64 at a time\r\n // then drop out to rotate the key for the next bit\r\n while (dp < dpend64 && kp < kpend) {\r\n dataView.setUint32(\r\n dp,\r\n dataView.getUint32(dp, true) ^ keyView.getUint32(kp, true),\r\n true\r\n );\r\n dataView.setUint32(\r\n dp + 4,\r\n dataView.getUint32(dp + 4, true) ^ keyView.getUint32(kp + 4, true),\r\n true\r\n );\r\n dp += 8;\r\n kp += 24;\r\n }\r\n }\r\n\r\n // now the remaining 1 to 7 bytes\r\n if (dp < dpend) {\r\n if (kp >= kpend) {\r\n // rotate the key one last time (if necessary)\r\n off = (off + 8) % 24;\r\n kp = off;\r\n }\r\n\r\n while (dp < dpend) {\r\n dataView.setUint8(dp, dataView.getUint8(dp) ^ keyView.getUint8(kp));\r\n dp++;\r\n kp++;\r\n }\r\n }\r\n}\r\n\r\ndecodeGoogleEarthEnterpriseData.passThroughDataForTesting = false;\r\nexport default decodeGoogleEarthEnterpriseData;\r\n","import AttributeCompression from \"./AttributeCompression.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nvar maxShort = 32767;\r\n\r\nvar scratchBVCartographic = new Cartographic();\r\nvar scratchEncodedPosition = new Cartesian3();\r\n\r\nfunction decodeVectorPolylinePositions(\r\n positions,\r\n rectangle,\r\n minimumHeight,\r\n maximumHeight,\r\n ellipsoid\r\n) {\r\n var positionsLength = positions.length / 3;\r\n var uBuffer = positions.subarray(0, positionsLength);\r\n var vBuffer = positions.subarray(positionsLength, 2 * positionsLength);\r\n var heightBuffer = positions.subarray(\r\n 2 * positionsLength,\r\n 3 * positionsLength\r\n );\r\n AttributeCompression.zigZagDeltaDecode(uBuffer, vBuffer, heightBuffer);\r\n\r\n var decoded = new Float64Array(positions.length);\r\n for (var i = 0; i < positionsLength; ++i) {\r\n var u = uBuffer[i];\r\n var v = vBuffer[i];\r\n var h = heightBuffer[i];\r\n\r\n var lon = CesiumMath.lerp(rectangle.west, rectangle.east, u / maxShort);\r\n var lat = CesiumMath.lerp(rectangle.south, rectangle.north, v / maxShort);\r\n var alt = CesiumMath.lerp(minimumHeight, maximumHeight, h / maxShort);\r\n\r\n var cartographic = Cartographic.fromRadians(\r\n lon,\r\n lat,\r\n alt,\r\n scratchBVCartographic\r\n );\r\n var decodedPosition = ellipsoid.cartographicToCartesian(\r\n cartographic,\r\n scratchEncodedPosition\r\n );\r\n Cartesian3.pack(decodedPosition, decoded, i * 3);\r\n }\r\n return decoded;\r\n}\r\nexport default decodeVectorPolylinePositions;\r\n","/**\r\n * A simple proxy that appends the desired resource as the sole query parameter\r\n * to the given proxy URL.\r\n *\r\n * @alias DefaultProxy\r\n * @constructor\r\n * @extends {Proxy}\r\n *\r\n * @param {String} proxy The proxy URL that will be used to requests all resources.\r\n */\r\nfunction DefaultProxy(proxy) {\r\n this.proxy = proxy;\r\n}\r\n\r\n/**\r\n * Get the final URL to use to request a given resource.\r\n *\r\n * @param {String} resource The resource to request.\r\n * @returns {String} proxied resource\r\n */\r\nDefaultProxy.prototype.getURL = function (resource) {\r\n var prefix = this.proxy.indexOf(\"?\") === -1 ? \"?\" : \"\";\r\n return this.proxy + prefix + encodeURIComponent(resource);\r\n};\r\n\r\nexport default DefaultProxy;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\nvar warnings = {};\r\n\r\n/**\r\n * Logs a one time message to the console. Use this function instead of\r\n * console.log directly since this does not log duplicate messages\r\n * unless it is called from multiple workers.\r\n *\r\n * @function oneTimeWarning\r\n *\r\n * @param {String} identifier The unique identifier for this warning.\r\n * @param {String} [message=identifier] The message to log to the console.\r\n *\r\n * @example\r\n * for(var i=0;i>includeStart('debug', pragmas.debug);\r\n if (!defined(identifier)) {\r\n throw new DeveloperError(\"identifier is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(warnings[identifier])) {\r\n warnings[identifier] = true;\r\n console.warn(defaultValue(message, identifier));\r\n }\r\n}\r\n\r\noneTimeWarning.geometryOutlines =\r\n \"Entity geometry outlines are unsupported on terrain. Outlines will be disabled. To enable outlines, disable geometry terrain clamping by explicitly setting height to 0.\";\r\n\r\noneTimeWarning.geometryZIndex =\r\n \"Entity geometry with zIndex are unsupported when height or extrudedHeight are defined. zIndex will be ignored\";\r\n\r\noneTimeWarning.geometryHeightReference =\r\n \"Entity corridor, ellipse, polygon or rectangle with heightReference must also have a defined height. heightReference will be ignored\";\r\noneTimeWarning.geometryExtrudedHeightReference =\r\n \"Entity corridor, ellipse, polygon or rectangle with extrudedHeightReference must also have a defined extrudedHeight. extrudedHeightReference will be ignored\";\r\nexport default oneTimeWarning;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport oneTimeWarning from \"./oneTimeWarning.js\";\r\n\r\n/**\r\n * Logs a deprecation message to the console. Use this function instead of\r\n * console.log directly since this does not log duplicate messages\r\n * unless it is called from multiple workers.\r\n *\r\n * @function deprecationWarning\r\n *\r\n * @param {String} identifier The unique identifier for this deprecated API.\r\n * @param {String} message The message to log to the console.\r\n *\r\n * @example\r\n * // Deprecated function or class\r\n * function Foo() {\r\n * deprecationWarning('Foo', 'Foo was deprecated in Cesium 1.01. It will be removed in 1.03. Use newFoo instead.');\r\n * // ...\r\n * }\r\n *\r\n * // Deprecated function\r\n * Bar.prototype.func = function() {\r\n * deprecationWarning('Bar.func', 'Bar.func() was deprecated in Cesium 1.01. It will be removed in 1.03. Use Bar.newFunc() instead.');\r\n * // ...\r\n * };\r\n *\r\n * // Deprecated property\r\n * Object.defineProperties(Bar.prototype, {\r\n * prop : {\r\n * get : function() {\r\n * deprecationWarning('Bar.prop', 'Bar.prop was deprecated in Cesium 1.01. It will be removed in 1.03. Use Bar.newProp instead.');\r\n * // ...\r\n * },\r\n * set : function(value) {\r\n * deprecationWarning('Bar.prop', 'Bar.prop was deprecated in Cesium 1.01. It will be removed in 1.03. Use Bar.newProp instead.');\r\n * // ...\r\n * }\r\n * }\r\n * });\r\n *\r\n * @private\r\n */\r\nfunction deprecationWarning(identifier, message) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(identifier) || !defined(message)) {\r\n throw new DeveloperError(\"identifier and message are required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n oneTimeWarning(identifier, message);\r\n}\r\nexport default deprecationWarning;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Determines visibility based on the distance to the camera.\r\n *\r\n * @alias DistanceDisplayCondition\r\n * @constructor\r\n *\r\n * @param {Number} [near=0.0] The smallest distance in the interval where the object is visible.\r\n * @param {Number} [far=Number.MAX_VALUE] The largest distance in the interval where the object is visible.\r\n *\r\n * @example\r\n * // Make a billboard that is only visible when the distance to the camera is between 10 and 20 meters.\r\n * billboard.distanceDisplayCondition = new Cesium.DistanceDisplayCondition(10.0, 20.0);\r\n */\r\nfunction DistanceDisplayCondition(near, far) {\r\n near = defaultValue(near, 0.0);\r\n this._near = near;\r\n\r\n far = defaultValue(far, Number.MAX_VALUE);\r\n this._far = far;\r\n}\r\n\r\nObject.defineProperties(DistanceDisplayCondition.prototype, {\r\n /**\r\n * The smallest distance in the interval where the object is visible.\r\n * @memberof DistanceDisplayCondition.prototype\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n near: {\r\n get: function () {\r\n return this._near;\r\n },\r\n set: function (value) {\r\n this._near = value;\r\n },\r\n },\r\n /**\r\n * The largest distance in the interval where the object is visible.\r\n * @memberof DistanceDisplayCondition.prototype\r\n * @type {Number}\r\n * @default Number.MAX_VALUE\r\n */\r\n far: {\r\n get: function () {\r\n return this._far;\r\n },\r\n set: function (value) {\r\n this._far = value;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nDistanceDisplayCondition.packedLength = 2;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {DistanceDisplayCondition} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nDistanceDisplayCondition.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.near;\r\n array[startingIndex] = value.far;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {DistanceDisplayCondition} [result] The object into which to store the result.\r\n * @returns {DistanceDisplayCondition} The modified result parameter or a new DistanceDisplayCondition instance if one was not provided.\r\n */\r\nDistanceDisplayCondition.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new DistanceDisplayCondition();\r\n }\r\n result.near = array[startingIndex++];\r\n result.far = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines if two distance display conditions are equal.\r\n *\r\n * @param {DistanceDisplayCondition} left A distance display condition.\r\n * @param {DistanceDisplayCondition} right Another distance display condition.\r\n * @return {Boolean} Whether the two distance display conditions are equal.\r\n */\r\nDistanceDisplayCondition.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.near === right.near &&\r\n left.far === right.far)\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates a distance display condition instance.\r\n *\r\n * @param {DistanceDisplayCondition} [value] The distance display condition to duplicate.\r\n * @param {DistanceDisplayCondition} [result] The result onto which to store the result.\r\n * @return {DistanceDisplayCondition} The duplicated instance.\r\n */\r\nDistanceDisplayCondition.clone = function (value, result) {\r\n if (!defined(value)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new DistanceDisplayCondition();\r\n }\r\n\r\n result.near = value.near;\r\n result.far = value.far;\r\n return result;\r\n};\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {DistanceDisplayCondition} [result] The result onto which to store the result.\r\n * @return {DistanceDisplayCondition} The duplicated instance.\r\n */\r\nDistanceDisplayCondition.prototype.clone = function (result) {\r\n return DistanceDisplayCondition.clone(this, result);\r\n};\r\n\r\n/**\r\n * Determines if this distance display condition is equal to another.\r\n *\r\n * @param {DistanceDisplayCondition} other Another distance display condition.\r\n * @return {Boolean} Whether this distance display condition is equal to the other.\r\n */\r\nDistanceDisplayCondition.prototype.equals = function (other) {\r\n return DistanceDisplayCondition.equals(this, other);\r\n};\r\nexport default DistanceDisplayCondition;\r\n","import ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Value and type information for per-instance geometry attribute that determines if the geometry instance has a distance display condition.\r\n *\r\n * @alias DistanceDisplayConditionGeometryInstanceAttribute\r\n * @constructor\r\n *\r\n * @param {Number} [near=0.0] The near distance.\r\n * @param {Number} [far=Number.MAX_VALUE] The far distance.\r\n *\r\n * @exception {DeveloperError} far must be greater than near.\r\n *\r\n * @example\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.BoxGeometry({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL,\r\n * minimum : new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0),\r\n * maximum : new Cesium.Cartesian3(250000.0, 250000.0, 250000.0)\r\n * }),\r\n * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(\r\n * Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 1000000.0), new Cesium.Matrix4()),\r\n * id : 'box',\r\n * attributes : {\r\n * distanceDisplayCondition : new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(100.0, 10000.0)\r\n * }\r\n * });\r\n *\r\n * @see GeometryInstance\r\n * @see GeometryInstanceAttribute\r\n */\r\nfunction DistanceDisplayConditionGeometryInstanceAttribute(near, far) {\r\n near = defaultValue(near, 0.0);\r\n far = defaultValue(far, Number.MAX_VALUE);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (far <= near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * The values for the attributes stored in a typed array.\r\n *\r\n * @type Float32Array\r\n *\r\n * @default [0.0, 0.0, Number.MAX_VALUE]\r\n */\r\n this.value = new Float32Array([near, far]);\r\n}\r\n\r\nObject.defineProperties(\r\n DistanceDisplayConditionGeometryInstanceAttribute.prototype,\r\n {\r\n /**\r\n * The datatype of each component in the attribute, e.g., individual elements in\r\n * {@link DistanceDisplayConditionGeometryInstanceAttribute#value}.\r\n *\r\n * @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype\r\n *\r\n * @type {ComponentDatatype}\r\n * @readonly\r\n *\r\n * @default {@link ComponentDatatype.FLOAT}\r\n */\r\n componentDatatype: {\r\n get: function () {\r\n return ComponentDatatype.FLOAT;\r\n },\r\n },\r\n\r\n /**\r\n * The number of components in the attributes, i.e., {@link DistanceDisplayConditionGeometryInstanceAttribute#value}.\r\n *\r\n * @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n *\r\n * @default 3\r\n */\r\n componentsPerAttribute: {\r\n get: function () {\r\n return 2;\r\n },\r\n },\r\n\r\n /**\r\n * When true and componentDatatype is an integer format,\r\n * indicate that the components should be mapped to the range [0, 1] (unsigned)\r\n * or [-1, 1] (signed) when they are accessed as floating-point for rendering.\r\n *\r\n * @memberof DistanceDisplayConditionGeometryInstanceAttribute.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n normalize: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n }\r\n);\r\n\r\n/**\r\n * Creates a new {@link DistanceDisplayConditionGeometryInstanceAttribute} instance given the provided an enabled flag and {@link DistanceDisplayCondition}.\r\n *\r\n * @param {DistanceDisplayCondition} distanceDisplayCondition The distance display condition.\r\n * @returns {DistanceDisplayConditionGeometryInstanceAttribute} The new {@link DistanceDisplayConditionGeometryInstanceAttribute} instance.\r\n *\r\n * @exception {DeveloperError} distanceDisplayCondition.far must be greater than distanceDisplayCondition.near\r\n *\r\n * @example\r\n * var distanceDisplayCondition = new Cesium.DistanceDisplayCondition(100.0, 10000.0);\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : geometry,\r\n * attributes : {\r\n * distanceDisplayCondition : Cesium.DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(distanceDisplayCondition)\r\n * }\r\n * });\r\n */\r\nDistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition = function (\r\n distanceDisplayCondition\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(distanceDisplayCondition)) {\r\n throw new DeveloperError(\"distanceDisplayCondition is required.\");\r\n }\r\n if (distanceDisplayCondition.far <= distanceDisplayCondition.near) {\r\n throw new DeveloperError(\r\n \"distanceDisplayCondition.far distance must be greater than distanceDisplayCondition.near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return new DistanceDisplayConditionGeometryInstanceAttribute(\r\n distanceDisplayCondition.near,\r\n distanceDisplayCondition.far\r\n );\r\n};\r\n\r\n/**\r\n * Converts a distance display condition to a typed array that can be used to assign a distance display condition attribute.\r\n *\r\n * @param {DistanceDisplayCondition} distanceDisplayCondition The distance display condition value.\r\n * @param {Float32Array} [result] The array to store the result in, if undefined a new instance will be created.\r\n * @returns {Float32Array} The modified result parameter or a new instance if result was undefined.\r\n *\r\n * @example\r\n * var attributes = primitive.getGeometryInstanceAttributes('an id');\r\n * attributes.distanceDisplayCondition = Cesium.DistanceDisplayConditionGeometryInstanceAttribute.toValue(distanceDisplayCondition, attributes.distanceDisplayCondition);\r\n */\r\nDistanceDisplayConditionGeometryInstanceAttribute.toValue = function (\r\n distanceDisplayCondition,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(distanceDisplayCondition)) {\r\n throw new DeveloperError(\"distanceDisplayCondition is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Float32Array([\r\n distanceDisplayCondition.near,\r\n distanceDisplayCondition.far,\r\n ]);\r\n }\r\n result[0] = distanceDisplayCondition.near;\r\n result[1] = distanceDisplayCondition.far;\r\n return result;\r\n};\r\nexport default DistanceDisplayConditionGeometryInstanceAttribute;\r\n","import CesiumMath from \"./Math.js\";\r\nimport Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * Array-backed min-max heap implementation of a double-ended priority queue.\r\n * This data structure allows for efficient removal of minimum and maximum elements.\r\n *\r\n * @alias DoubleEndedPriorityQueue\r\n * @constructor\r\n * @private\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {DoubleEndedPriorityQueue.ComparatorCallback} options.comparator The comparator to use for the queue. If comparator(a, b) is less than 0, a is lower priority than b.\r\n * @param {Number} [options.maximumLength] The maximum length of the queue. If an element is inserted when the queue is at full capacity, the minimum element is removed. By default, the size of the queue is unlimited.\r\n */\r\nfunction DoubleEndedPriorityQueue(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.defined(\"options.comparator\", options.comparator);\r\n if (defined(options.maximumLength)) {\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"options.maximumLength\",\r\n options.maximumLength,\r\n 0\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._comparator = options.comparator;\r\n this._maximumLength = options.maximumLength;\r\n this._array = defined(options.maximumLength)\r\n ? new Array(options.maximumLength)\r\n : [];\r\n this._length = 0;\r\n}\r\n\r\nObject.defineProperties(DoubleEndedPriorityQueue.prototype, {\r\n /**\r\n * Gets the number of elements in the queue.\r\n *\r\n * @memberof DoubleEndedPriorityQueue.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._length;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the maximum number of elements in the queue.\r\n * If set to a smaller value than the current length of the queue, the lowest priority elements are removed.\r\n * If an element is inserted when the queue is at full capacity, the minimum element is removed.\r\n * If set to undefined, the size of the queue is unlimited.\r\n *\r\n * @memberof DoubleEndedPriorityQueue.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n maximumLength: {\r\n get: function () {\r\n return this._maximumLength;\r\n },\r\n set: function (value) {\r\n if (defined(value)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"maximumLength\", value, 0);\r\n //>>includeEnd('debug');\r\n\r\n // Remove elements until the maximum length is met.\r\n while (this._length > value) {\r\n this.removeMinimum();\r\n }\r\n\r\n // The array size is fixed to the maximum length\r\n this._array.length = value;\r\n }\r\n this._maximumLength = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the internal array.\r\n *\r\n * @memberof DoubleEndedPriorityQueue.prototype\r\n *\r\n * @type {Array}\r\n * @readonly\r\n */\r\n internalArray: {\r\n get: function () {\r\n return this._array;\r\n },\r\n },\r\n\r\n /**\r\n * The comparator used by the queue.\r\n * If comparator(a, b) is less than 0, a is lower priority than b.\r\n *\r\n * @memberof DoubleEndedPriorityQueue.prototype\r\n *\r\n * @type {DoubleEndedPriorityQueue.ComparatorCallback}\r\n * @readonly\r\n */\r\n comparator: {\r\n get: function () {\r\n return this._comparator;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Clones the double ended priority queue.\r\n *\r\n * @returns {DoubleEndedPriorityQueue} The cloned double ended priority queue.\r\n */\r\nDoubleEndedPriorityQueue.prototype.clone = function () {\r\n var maximumLength = this._maximumLength;\r\n var comparator = this._comparator;\r\n var array = this._array;\r\n var length = this._length;\r\n\r\n var result = new DoubleEndedPriorityQueue({\r\n comparator: comparator,\r\n maximumLength: maximumLength,\r\n });\r\n\r\n result._length = length;\r\n for (var i = 0; i < length; i++) {\r\n result._array[i] = array[i];\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Removes all elements from the queue.\r\n */\r\nDoubleEndedPriorityQueue.prototype.reset = function () {\r\n this._length = 0;\r\n\r\n // Dereference elements\r\n var maximumLength = this._maximumLength;\r\n if (defined(maximumLength)) {\r\n // Dereference all elements but keep the array the same size\r\n for (var i = 0; i < maximumLength; i++) {\r\n this._array[i] = undefined;\r\n }\r\n } else {\r\n // Dereference all elements by clearing the array\r\n this._array.length = 0;\r\n }\r\n};\r\n\r\n/**\r\n * Resort the queue.\r\n */\r\nDoubleEndedPriorityQueue.prototype.resort = function () {\r\n var length = this._length;\r\n\r\n // Fix the queue from the top-down\r\n for (var i = 0; i < length; i++) {\r\n pushUp(this, i);\r\n }\r\n};\r\n\r\n/**\r\n * Inserts an element into the queue.\r\n * If the queue is at full capacity, the minimum element is removed.\r\n * The new element is returned (and not added) if it is less than or equal priority to the minimum element.\r\n *\r\n * @param {*} element\r\n * @returns {*|undefined} The minimum element if the queue is at full capacity. Returns undefined if there is no maximum length.\r\n */\r\nDoubleEndedPriorityQueue.prototype.insert = function (element) {\r\n var removedElement;\r\n\r\n var maximumLength = this._maximumLength;\r\n if (defined(maximumLength)) {\r\n if (maximumLength === 0) {\r\n return undefined;\r\n } else if (this._length === maximumLength) {\r\n // It's faster to access the minimum directly instead of calling the getter\r\n // because it avoids the length === 0 check.\r\n var minimumElement = this._array[0];\r\n if (this._comparator(element, minimumElement) <= 0.0) {\r\n // The element that is being inserted is less than or equal to\r\n // the minimum element, so don't insert anything and exit early.\r\n return element;\r\n }\r\n removedElement = this.removeMinimum();\r\n }\r\n }\r\n\r\n var index = this._length;\r\n this._array[index] = element;\r\n this._length++;\r\n pushUp(this, index);\r\n\r\n return removedElement;\r\n};\r\n\r\n/**\r\n * Removes the minimum element from the queue and returns it.\r\n * If the queue is empty, the return value is undefined.\r\n *\r\n * @returns {*|undefined} The minimum element, or undefined if the queue is empty.\r\n */\r\nDoubleEndedPriorityQueue.prototype.removeMinimum = function () {\r\n var length = this._length;\r\n if (length === 0) {\r\n return undefined;\r\n }\r\n\r\n this._length--;\r\n\r\n // The minimum element is always the root\r\n var minimumElement = this._array[0];\r\n\r\n if (length >= 2) {\r\n this._array[0] = this._array[length - 1];\r\n pushDown(this, 0);\r\n }\r\n\r\n // Dereference removed element\r\n this._array[length - 1] = undefined;\r\n\r\n return minimumElement;\r\n};\r\n\r\n/**\r\n * Removes the maximum element from the queue and returns it.\r\n * If the queue is empty, the return value is undefined.\r\n *\r\n * @returns {*|undefined} The maximum element, or undefined if the queue is empty.\r\n */\r\nDoubleEndedPriorityQueue.prototype.removeMaximum = function () {\r\n var length = this._length;\r\n if (length === 0) {\r\n return undefined;\r\n }\r\n\r\n this._length--;\r\n var maximumElement;\r\n\r\n // If the root has no children, the maximum is the root.\r\n // If the root has one child, the maximum is the child.\r\n if (length <= 2) {\r\n maximumElement = this._array[length - 1];\r\n } else {\r\n // Otherwise, the maximum is the larger of the root's two children.\r\n var maximumElementIndex = greaterThan(this, 1, 2) ? 1 : 2;\r\n maximumElement = this._array[maximumElementIndex];\r\n\r\n // Re-balance the heap\r\n this._array[maximumElementIndex] = this._array[length - 1];\r\n if (length >= 4) {\r\n pushDown(this, maximumElementIndex);\r\n }\r\n }\r\n\r\n // Dereference removed element\r\n this._array[length - 1] = undefined;\r\n\r\n return maximumElement;\r\n};\r\n\r\n/**\r\n * Gets the minimum element in the queue.\r\n * If the queue is empty, the result is undefined.\r\n *\r\n * @returns {*|undefined} element\r\n */\r\n\r\nDoubleEndedPriorityQueue.prototype.getMinimum = function () {\r\n var length = this._length;\r\n if (length === 0) {\r\n return undefined;\r\n }\r\n\r\n // The minimum element is always the root\r\n return this._array[0];\r\n};\r\n\r\n/**\r\n * Gets the maximum element in the queue.\r\n * If the queue is empty, the result is undefined.\r\n *\r\n * @returns {*|undefined} element\r\n */\r\nDoubleEndedPriorityQueue.prototype.getMaximum = function () {\r\n var length = this._length;\r\n if (length === 0) {\r\n return undefined;\r\n }\r\n\r\n // If the root has no children, the maximum is the root.\r\n // If the root has one child, the maximum is the child.\r\n if (length <= 2) {\r\n return this._array[length - 1];\r\n }\r\n\r\n // Otherwise, the maximum is the larger of the root's two children.\r\n return this._array[greaterThan(this, 1, 2) ? 1 : 2];\r\n};\r\n\r\n// Helper functions\r\n\r\nfunction swap(that, indexA, indexB) {\r\n var array = that._array;\r\n var temp = array[indexA];\r\n array[indexA] = array[indexB];\r\n array[indexB] = temp;\r\n}\r\n\r\nfunction lessThan(that, indexA, indexB) {\r\n return that._comparator(that._array[indexA], that._array[indexB]) < 0.0;\r\n}\r\n\r\nfunction greaterThan(that, indexA, indexB) {\r\n return that._comparator(that._array[indexA], that._array[indexB]) > 0.0;\r\n}\r\n\r\nfunction pushUp(that, index) {\r\n if (index === 0) {\r\n return;\r\n }\r\n var onMinLevel = Math.floor(CesiumMath.log2(index + 1)) % 2 === 0;\r\n var parentIndex = Math.floor((index - 1) / 2);\r\n var lessThanParent = lessThan(that, index, parentIndex);\r\n\r\n // Get the element onto the correct level if it's not already\r\n if (lessThanParent !== onMinLevel) {\r\n swap(that, index, parentIndex);\r\n index = parentIndex;\r\n }\r\n\r\n // Swap element with grandparent as long as it:\r\n // 1) has a grandparent\r\n // 2A) is less than the grandparent when on a min level\r\n // 2B) is greater than the grandparent when on a max level\r\n while (index >= 3) {\r\n var grandparentIndex = Math.floor((index - 3) / 4);\r\n if (lessThan(that, index, grandparentIndex) !== lessThanParent) {\r\n break;\r\n }\r\n swap(that, index, grandparentIndex);\r\n index = grandparentIndex;\r\n }\r\n}\r\n\r\nfunction pushDown(that, index) {\r\n var length = that._length;\r\n var onMinLevel = Math.floor(CesiumMath.log2(index + 1)) % 2 === 0;\r\n\r\n // Loop as long as there is a left child.\r\n var leftChildIndex;\r\n while ((leftChildIndex = 2 * index + 1) < length) {\r\n // Find the minimum (or maximum) child or grandchild\r\n var target = leftChildIndex;\r\n var rightChildIndex = leftChildIndex + 1;\r\n if (rightChildIndex < length) {\r\n if (lessThan(that, rightChildIndex, target) === onMinLevel) {\r\n target = rightChildIndex;\r\n }\r\n var grandChildStart = 2 * leftChildIndex + 1;\r\n var grandChildCount = Math.max(Math.min(length - grandChildStart, 4), 0);\r\n for (var i = 0; i < grandChildCount; i++) {\r\n var grandChildIndex = grandChildStart + i;\r\n if (lessThan(that, grandChildIndex, target) === onMinLevel) {\r\n target = grandChildIndex;\r\n }\r\n }\r\n }\r\n\r\n // Swap the element into the correct spot\r\n if (lessThan(that, target, index) === onMinLevel) {\r\n swap(that, target, index);\r\n if (target !== leftChildIndex && target !== rightChildIndex) {\r\n var parentOfGrandchildIndex = Math.floor((target - 1) / 2);\r\n if (greaterThan(that, target, parentOfGrandchildIndex) === onMinLevel) {\r\n swap(that, target, parentOfGrandchildIndex);\r\n }\r\n }\r\n }\r\n\r\n index = target;\r\n }\r\n}\r\n\r\n/**\r\n * The comparator to use for the queue.\r\n * @callback DoubleEndedPriorityQueue.ComparatorCallback\r\n * @param {*} a An element in the queue.\r\n * @param {*} b An element in the queue.\r\n * @returns {Number} If the result of the comparison is less than 0, a is lower priority than b.\r\n */\r\nexport default DoubleEndedPriorityQueue;\r\n","import defined from \"./defined.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DoublyLinkedList() {\r\n this.head = undefined;\r\n this.tail = undefined;\r\n this._length = 0;\r\n}\r\n\r\nObject.defineProperties(DoublyLinkedList.prototype, {\r\n length: {\r\n get: function () {\r\n return this._length;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DoublyLinkedListNode(item, previous, next) {\r\n this.item = item;\r\n this.previous = previous;\r\n this.next = next;\r\n}\r\n\r\n/**\r\n * Adds the item to the end of the list\r\n * @param {*} [item]\r\n * @return {DoublyLinkedListNode}\r\n */\r\nDoublyLinkedList.prototype.add = function (item) {\r\n var node = new DoublyLinkedListNode(item, this.tail, undefined);\r\n\r\n if (defined(this.tail)) {\r\n this.tail.next = node;\r\n this.tail = node;\r\n } else {\r\n this.head = node;\r\n this.tail = node;\r\n }\r\n\r\n ++this._length;\r\n\r\n return node;\r\n};\r\n\r\nfunction remove(list, node) {\r\n if (defined(node.previous) && defined(node.next)) {\r\n node.previous.next = node.next;\r\n node.next.previous = node.previous;\r\n } else if (defined(node.previous)) {\r\n // Remove last node\r\n node.previous.next = undefined;\r\n list.tail = node.previous;\r\n } else if (defined(node.next)) {\r\n // Remove first node\r\n node.next.previous = undefined;\r\n list.head = node.next;\r\n } else {\r\n // Remove last node in the linked list\r\n list.head = undefined;\r\n list.tail = undefined;\r\n }\r\n\r\n node.next = undefined;\r\n node.previous = undefined;\r\n}\r\n\r\n/**\r\n * Removes the given node from the list\r\n * @param {DoublyLinkedListNode} node\r\n */\r\nDoublyLinkedList.prototype.remove = function (node) {\r\n if (!defined(node)) {\r\n return;\r\n }\r\n\r\n remove(this, node);\r\n\r\n --this._length;\r\n};\r\n\r\n/**\r\n * Moves nextNode after node\r\n * @param {DoublyLinkedListNode} node\r\n * @param {DoublyLinkedListNode} nextNode\r\n */\r\nDoublyLinkedList.prototype.splice = function (node, nextNode) {\r\n if (node === nextNode) {\r\n return;\r\n }\r\n\r\n // Remove nextNode, then insert after node\r\n remove(this, nextNode);\r\n\r\n var oldNodeNext = node.next;\r\n node.next = nextNode;\r\n\r\n // nextNode is the new tail\r\n if (this.tail === node) {\r\n this.tail = nextNode;\r\n } else {\r\n oldNodeNext.previous = nextNode;\r\n }\r\n\r\n nextNode.next = oldNodeNext;\r\n nextNode.previous = node;\r\n};\r\nexport default DoublyLinkedList;\r\n","/**\r\n@license\r\ntween.js - https://github.com/sole/tween.js\r\n\r\nCopyright (c) 2010-2012 Tween.js authors.\r\n\r\nEasing equations Copyright (c) 2001 Robert Penner http://robertpenner.com/easing/\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in\r\nall copies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\nTHE SOFTWARE.\r\n*/\r\n\r\n/**\r\n * @author sole / http://soledadpenades.com\r\n * @author mrdoob / http://mrdoob.com\r\n * @author Robert Eisele / http://www.xarg.org\r\n * @author Philippe / http://philippe.elsass.me\r\n * @author Robert Penner / http://www.robertpenner.com/easing_terms_of_use.html\r\n * @author Paul Lewis / http://www.aerotwist.com/\r\n * @author lechecacharro\r\n * @author Josh Faul / http://jocafa.com/\r\n * @author egraether / http://egraether.com/\r\n * @author endel / http://endel.me\r\n * @author Ben Delarre / http://delarre.net\r\n */\r\n\r\n // Date.now shim for (ahem) Internet Explo(d|r)er\r\n if ( Date.now === undefined ) {\r\n\r\n Date.now = function () {\r\n\r\n return new Date().valueOf();\r\n\r\n };\r\n\r\n }\r\n\r\n var TWEEN = TWEEN || ( function () {\r\n\r\n var _tweens = [];\r\n\r\n return {\r\n\r\n REVISION: '13',\r\n\r\n getAll: function () {\r\n\r\n return _tweens;\r\n\r\n },\r\n\r\n removeAll: function () {\r\n\r\n _tweens = [];\r\n\r\n },\r\n\r\n add: function ( tween ) {\r\n\r\n _tweens.push( tween );\r\n\r\n },\r\n\r\n remove: function ( tween ) {\r\n\r\n var i = _tweens.indexOf( tween );\r\n\r\n if ( i !== -1 ) {\r\n\r\n _tweens.splice( i, 1 );\r\n\r\n }\r\n\r\n },\r\n\r\n update: function ( time ) {\r\n\r\n if ( _tweens.length === 0 ) return false;\r\n\r\n var i = 0;\r\n\r\n time = time !== undefined ? time : ( typeof window !== 'undefined' && window.performance !== undefined && window.performance.now !== undefined ? window.performance.now() : Date.now() );\r\n\r\n while ( i < _tweens.length ) {\r\n\r\n if ( _tweens[ i ].update( time ) ) {\r\n\r\n i++;\r\n\r\n } else {\r\n\r\n _tweens.splice( i, 1 );\r\n\r\n }\r\n\r\n }\r\n\r\n return true;\r\n\r\n }\r\n };\r\n\r\n } )();\r\n\r\n TWEEN.Tween = function ( object ) {\r\n\r\n var _object = object;\r\n var _valuesStart = {};\r\n var _valuesEnd = {};\r\n var _valuesStartRepeat = {};\r\n var _duration = 1000;\r\n var _repeat = 0;\r\n var _yoyo = false;\r\n var _isPlaying = false;\r\n var _reversed = false;\r\n var _delayTime = 0;\r\n var _startTime = null;\r\n var _easingFunction = TWEEN.Easing.Linear.None;\r\n var _interpolationFunction = TWEEN.Interpolation.Linear;\r\n var _chainedTweens = [];\r\n var _onStartCallback = null;\r\n var _onStartCallbackFired = false;\r\n var _onUpdateCallback = null;\r\n var _onCompleteCallback = null;\r\n var _onStopCallback = null;\r\n\r\n // Set all starting values present on the target object\r\n for ( var field in object ) {\r\n\r\n _valuesStart[ field ] = parseFloat(object[field], 10);\r\n\r\n }\r\n\r\n this.to = function ( properties, duration ) {\r\n\r\n if ( duration !== undefined ) {\r\n\r\n _duration = duration;\r\n\r\n }\r\n\r\n _valuesEnd = properties;\r\n\r\n return this;\r\n\r\n };\r\n\r\n this.start = function ( time ) {\r\n\r\n TWEEN.add( this );\r\n\r\n _isPlaying = true;\r\n\r\n _onStartCallbackFired = false;\r\n\r\n _startTime = time !== undefined ? time : ( typeof window !== 'undefined' && window.performance !== undefined && window.performance.now !== undefined ? window.performance.now() : Date.now() );\r\n _startTime += _delayTime;\r\n\r\n for ( var property in _valuesEnd ) {\r\n\r\n // check if an Array was provided as property value\r\n if ( _valuesEnd[ property ] instanceof Array ) {\r\n\r\n if ( _valuesEnd[ property ].length === 0 ) {\r\n\r\n continue;\r\n\r\n }\r\n\r\n // create a local copy of the Array with the start value at the front\r\n _valuesEnd[ property ] = [ _object[ property ] ].concat( _valuesEnd[ property ] );\r\n\r\n }\r\n\r\n _valuesStart[ property ] = _object[ property ];\r\n\r\n if( ( _valuesStart[ property ] instanceof Array ) === false ) {\r\n _valuesStart[ property ] *= 1.0; // Ensures we're using numbers, not strings\r\n }\r\n\r\n _valuesStartRepeat[ property ] = _valuesStart[ property ] || 0;\r\n\r\n }\r\n\r\n return this;\r\n\r\n };\r\n\r\n this.stop = function () {\r\n\r\n if ( !_isPlaying ) {\r\n return this;\r\n }\r\n\r\n TWEEN.remove( this );\r\n _isPlaying = false;\r\n\r\n if ( _onStopCallback !== null ) {\r\n\r\n _onStopCallback.call( _object );\r\n\r\n }\r\n\r\n this.stopChainedTweens();\r\n return this;\r\n\r\n };\r\n\r\n this.stopChainedTweens = function () {\r\n\r\n for ( var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++ ) {\r\n\r\n _chainedTweens[ i ].stop();\r\n\r\n }\r\n\r\n };\r\n\r\n this.delay = function ( amount ) {\r\n\r\n _delayTime = amount;\r\n return this;\r\n\r\n };\r\n\r\n this.repeat = function ( times ) {\r\n\r\n _repeat = times;\r\n return this;\r\n\r\n };\r\n\r\n this.yoyo = function( yoyo ) {\r\n\r\n _yoyo = yoyo;\r\n return this;\r\n\r\n };\r\n\r\n\r\n this.easing = function ( easing ) {\r\n\r\n _easingFunction = easing;\r\n return this;\r\n\r\n };\r\n\r\n this.interpolation = function ( interpolation ) {\r\n\r\n _interpolationFunction = interpolation;\r\n return this;\r\n\r\n };\r\n\r\n this.chain = function () {\r\n\r\n _chainedTweens = arguments;\r\n return this;\r\n\r\n };\r\n\r\n this.onStart = function ( callback ) {\r\n\r\n _onStartCallback = callback;\r\n return this;\r\n\r\n };\r\n\r\n this.onUpdate = function ( callback ) {\r\n\r\n _onUpdateCallback = callback;\r\n return this;\r\n\r\n };\r\n\r\n this.onComplete = function ( callback ) {\r\n\r\n _onCompleteCallback = callback;\r\n return this;\r\n\r\n };\r\n\r\n this.onStop = function ( callback ) {\r\n\r\n _onStopCallback = callback;\r\n return this;\r\n\r\n };\r\n\r\n this.update = function ( time ) {\r\n\r\n var property;\r\n\r\n if ( time < _startTime ) {\r\n\r\n return true;\r\n\r\n }\r\n\r\n if ( _onStartCallbackFired === false ) {\r\n\r\n if ( _onStartCallback !== null ) {\r\n\r\n _onStartCallback.call( _object );\r\n\r\n }\r\n\r\n _onStartCallbackFired = true;\r\n\r\n }\r\n\r\n var elapsed = ( time - _startTime ) / _duration;\r\n elapsed = elapsed > 1 ? 1 : elapsed;\r\n\r\n var value = _easingFunction( elapsed );\r\n\r\n for ( property in _valuesEnd ) {\r\n\r\n var start = _valuesStart[ property ] || 0;\r\n var end = _valuesEnd[ property ];\r\n\r\n if ( end instanceof Array ) {\r\n\r\n _object[ property ] = _interpolationFunction( end, value );\r\n\r\n } else {\r\n\r\n // Parses relative end values with start as base (e.g.: +10, -3)\r\n if ( typeof(end) === \"string\" ) {\r\n end = start + parseFloat(end, 10);\r\n }\r\n\r\n // protect against non numeric properties.\r\n if ( typeof(end) === \"number\" ) {\r\n _object[ property ] = start + ( end - start ) * value;\r\n }\r\n\r\n }\r\n\r\n }\r\n\r\n if ( _onUpdateCallback !== null ) {\r\n\r\n _onUpdateCallback.call( _object, value );\r\n\r\n }\r\n\r\n if ( elapsed == 1 ) {\r\n\r\n if ( _repeat > 0 ) {\r\n\r\n if( isFinite( _repeat ) ) {\r\n _repeat--;\r\n }\r\n\r\n // reassign starting values, restart by making startTime = now\r\n for( property in _valuesStartRepeat ) {\r\n\r\n if ( typeof( _valuesEnd[ property ] ) === \"string\" ) {\r\n _valuesStartRepeat[ property ] = _valuesStartRepeat[ property ] + parseFloat(_valuesEnd[ property ], 10);\r\n }\r\n\r\n if (_yoyo) {\r\n var tmp = _valuesStartRepeat[ property ];\r\n _valuesStartRepeat[ property ] = _valuesEnd[ property ];\r\n _valuesEnd[ property ] = tmp;\r\n }\r\n\r\n _valuesStart[ property ] = _valuesStartRepeat[ property ];\r\n\r\n }\r\n\r\n if (_yoyo) {\r\n _reversed = !_reversed;\r\n }\r\n\r\n _startTime = time + _delayTime;\r\n\r\n return true;\r\n\r\n } else {\r\n\r\n if ( _onCompleteCallback !== null ) {\r\n\r\n _onCompleteCallback.call( _object );\r\n\r\n }\r\n\r\n for ( var i = 0, numChainedTweens = _chainedTweens.length; i < numChainedTweens; i++ ) {\r\n\r\n _chainedTweens[ i ].start( time );\r\n\r\n }\r\n\r\n return false;\r\n\r\n }\r\n\r\n }\r\n\r\n return true;\r\n\r\n };\r\n\r\n };\r\n\r\n\r\n TWEEN.Easing = {\r\n\r\n Linear: {\r\n\r\n None: function ( k ) {\r\n\r\n return k;\r\n\r\n }\r\n\r\n },\r\n\r\n Quadratic: {\r\n\r\n In: function ( k ) {\r\n\r\n return k * k;\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n return k * ( 2 - k );\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n if ( ( k *= 2 ) < 1 ) return 0.5 * k * k;\r\n return - 0.5 * ( --k * ( k - 2 ) - 1 );\r\n\r\n }\r\n\r\n },\r\n\r\n Cubic: {\r\n\r\n In: function ( k ) {\r\n\r\n return k * k * k;\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n return --k * k * k + 1;\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n if ( ( k *= 2 ) < 1 ) return 0.5 * k * k * k;\r\n return 0.5 * ( ( k -= 2 ) * k * k + 2 );\r\n\r\n }\r\n\r\n },\r\n\r\n Quartic: {\r\n\r\n In: function ( k ) {\r\n\r\n return k * k * k * k;\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n return 1 - ( --k * k * k * k );\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n if ( ( k *= 2 ) < 1) return 0.5 * k * k * k * k;\r\n return - 0.5 * ( ( k -= 2 ) * k * k * k - 2 );\r\n\r\n }\r\n\r\n },\r\n\r\n Quintic: {\r\n\r\n In: function ( k ) {\r\n\r\n return k * k * k * k * k;\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n return --k * k * k * k * k + 1;\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n if ( ( k *= 2 ) < 1 ) return 0.5 * k * k * k * k * k;\r\n return 0.5 * ( ( k -= 2 ) * k * k * k * k + 2 );\r\n\r\n }\r\n\r\n },\r\n\r\n Sinusoidal: {\r\n\r\n In: function ( k ) {\r\n\r\n return 1 - Math.cos( k * Math.PI / 2 );\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n return Math.sin( k * Math.PI / 2 );\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n return 0.5 * ( 1 - Math.cos( Math.PI * k ) );\r\n\r\n }\r\n\r\n },\r\n\r\n Exponential: {\r\n\r\n In: function ( k ) {\r\n\r\n return k === 0 ? 0 : Math.pow( 1024, k - 1 );\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n return k === 1 ? 1 : 1 - Math.pow( 2, - 10 * k );\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n if ( k === 0 ) return 0;\r\n if ( k === 1 ) return 1;\r\n if ( ( k *= 2 ) < 1 ) return 0.5 * Math.pow( 1024, k - 1 );\r\n return 0.5 * ( - Math.pow( 2, - 10 * ( k - 1 ) ) + 2 );\r\n\r\n }\r\n\r\n },\r\n\r\n Circular: {\r\n\r\n In: function ( k ) {\r\n\r\n return 1 - Math.sqrt( 1 - k * k );\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n return Math.sqrt( 1 - ( --k * k ) );\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n if ( ( k *= 2 ) < 1) return - 0.5 * ( Math.sqrt( 1 - k * k) - 1);\r\n return 0.5 * ( Math.sqrt( 1 - ( k -= 2) * k) + 1);\r\n\r\n }\r\n\r\n },\r\n\r\n Elastic: {\r\n\r\n In: function ( k ) {\r\n\r\n var s, a = 0.1, p = 0.4;\r\n if ( k === 0 ) return 0;\r\n if ( k === 1 ) return 1;\r\n if ( !a || a < 1 ) { a = 1; s = p / 4; }\r\n else s = p * Math.asin( 1 / a ) / ( 2 * Math.PI );\r\n return - ( a * Math.pow( 2, 10 * ( k -= 1 ) ) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) );\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n var s, a = 0.1, p = 0.4;\r\n if ( k === 0 ) return 0;\r\n if ( k === 1 ) return 1;\r\n if ( !a || a < 1 ) { a = 1; s = p / 4; }\r\n else s = p * Math.asin( 1 / a ) / ( 2 * Math.PI );\r\n return ( a * Math.pow( 2, - 10 * k) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) + 1 );\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n var s, a = 0.1, p = 0.4;\r\n if ( k === 0 ) return 0;\r\n if ( k === 1 ) return 1;\r\n if ( !a || a < 1 ) { a = 1; s = p / 4; }\r\n else s = p * Math.asin( 1 / a ) / ( 2 * Math.PI );\r\n if ( ( k *= 2 ) < 1 ) return - 0.5 * ( a * Math.pow( 2, 10 * ( k -= 1 ) ) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) );\r\n return a * Math.pow( 2, -10 * ( k -= 1 ) ) * Math.sin( ( k - s ) * ( 2 * Math.PI ) / p ) * 0.5 + 1;\r\n\r\n }\r\n\r\n },\r\n\r\n Back: {\r\n\r\n In: function ( k ) {\r\n\r\n var s = 1.70158;\r\n return k * k * ( ( s + 1 ) * k - s );\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n var s = 1.70158;\r\n return --k * k * ( ( s + 1 ) * k + s ) + 1;\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n var s = 1.70158 * 1.525;\r\n if ( ( k *= 2 ) < 1 ) return 0.5 * ( k * k * ( ( s + 1 ) * k - s ) );\r\n return 0.5 * ( ( k -= 2 ) * k * ( ( s + 1 ) * k + s ) + 2 );\r\n\r\n }\r\n\r\n },\r\n\r\n Bounce: {\r\n\r\n In: function ( k ) {\r\n\r\n return 1 - TWEEN.Easing.Bounce.Out( 1 - k );\r\n\r\n },\r\n\r\n Out: function ( k ) {\r\n\r\n if ( k < ( 1 / 2.75 ) ) {\r\n\r\n return 7.5625 * k * k;\r\n\r\n } else if ( k < ( 2 / 2.75 ) ) {\r\n\r\n return 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;\r\n\r\n } else if ( k < ( 2.5 / 2.75 ) ) {\r\n\r\n return 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;\r\n\r\n } else {\r\n\r\n return 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;\r\n\r\n }\r\n\r\n },\r\n\r\n InOut: function ( k ) {\r\n\r\n if ( k < 0.5 ) return TWEEN.Easing.Bounce.In( k * 2 ) * 0.5;\r\n return TWEEN.Easing.Bounce.Out( k * 2 - 1 ) * 0.5 + 0.5;\r\n\r\n }\r\n\r\n }\r\n\r\n };\r\n\r\n TWEEN.Interpolation = {\r\n\r\n Linear: function ( v, k ) {\r\n\r\n var m = v.length - 1, f = m * k, i = Math.floor( f ), fn = TWEEN.Interpolation.Utils.Linear;\r\n\r\n if ( k < 0 ) return fn( v[ 0 ], v[ 1 ], f );\r\n if ( k > 1 ) return fn( v[ m ], v[ m - 1 ], m - f );\r\n\r\n return fn( v[ i ], v[ i + 1 > m ? m : i + 1 ], f - i );\r\n\r\n },\r\n\r\n Bezier: function ( v, k ) {\r\n\r\n var b = 0, n = v.length - 1, pw = Math.pow, bn = TWEEN.Interpolation.Utils.Bernstein, i;\r\n\r\n for ( i = 0; i <= n; i++ ) {\r\n b += pw( 1 - k, n - i ) * pw( k, i ) * v[ i ] * bn( n, i );\r\n }\r\n\r\n return b;\r\n\r\n },\r\n\r\n CatmullRom: function ( v, k ) {\r\n\r\n var m = v.length - 1, f = m * k, i = Math.floor( f ), fn = TWEEN.Interpolation.Utils.CatmullRom;\r\n\r\n if ( v[ 0 ] === v[ m ] ) {\r\n\r\n if ( k < 0 ) i = Math.floor( f = m * ( 1 + k ) );\r\n\r\n return fn( v[ ( i - 1 + m ) % m ], v[ i ], v[ ( i + 1 ) % m ], v[ ( i + 2 ) % m ], f - i );\r\n\r\n } else {\r\n\r\n if ( k < 0 ) return v[ 0 ] - ( fn( v[ 0 ], v[ 0 ], v[ 1 ], v[ 1 ], -f ) - v[ 0 ] );\r\n if ( k > 1 ) return v[ m ] - ( fn( v[ m ], v[ m ], v[ m - 1 ], v[ m - 1 ], f - m ) - v[ m ] );\r\n\r\n return fn( v[ i ? i - 1 : 0 ], v[ i ], v[ m < i + 1 ? m : i + 1 ], v[ m < i + 2 ? m : i + 2 ], f - i );\r\n\r\n }\r\n\r\n },\r\n\r\n Utils: {\r\n\r\n Linear: function ( p0, p1, t ) {\r\n\r\n return ( p1 - p0 ) * t + p0;\r\n\r\n },\r\n\r\n Bernstein: function ( n , i ) {\r\n\r\n var fc = TWEEN.Interpolation.Utils.Factorial;\r\n return fc( n ) / fc( i ) / fc( n - i );\r\n\r\n },\r\n\r\n Factorial: ( function () {\r\n\r\n var a = [ 1 ];\r\n\r\n return function ( n ) {\r\n\r\n var s = 1, i;\r\n if ( a[ n ] ) return a[ n ];\r\n for ( i = n; i > 1; i-- ) s *= i;\r\n return a[ n ] = s;\r\n\r\n };\r\n\r\n } )(),\r\n\r\n CatmullRom: function ( p0, p1, p2, p3, t ) {\r\n\r\n var v0 = ( p2 - p0 ) * 0.5, v1 = ( p3 - p1 ) * 0.5, t2 = t * t, t3 = t * t2;\r\n return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;\r\n\r\n }\r\n\r\n }\r\n\r\n };\r\n\r\nexport default TWEEN;\r\n","import Tween from \"../ThirdParty/Tween.js\";\r\n\r\n/**\r\n * Easing functions for use with TweenCollection. These function are from\r\n * {@link https://github.com/sole/tween.js/|Tween.js} and Robert Penner. See the\r\n * {@link http://sole.github.io/tween.js/examples/03_graphs.html|Tween.js graphs for each function}.\r\n *\r\n * @namespace\r\n */\r\nvar EasingFunction = {\r\n /**\r\n * Linear easing.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n LINEAR_NONE: Tween.Easing.Linear.None,\r\n\r\n /**\r\n * Quadratic in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUADRATIC_IN: Tween.Easing.Quadratic.In,\r\n /**\r\n * Quadratic out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUADRATIC_OUT: Tween.Easing.Quadratic.Out,\r\n /**\r\n * Quadratic in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUADRATIC_IN_OUT: Tween.Easing.Quadratic.InOut,\r\n\r\n /**\r\n * Cubic in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n CUBIC_IN: Tween.Easing.Cubic.In,\r\n /**\r\n * Cubic out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n CUBIC_OUT: Tween.Easing.Cubic.Out,\r\n /**\r\n * Cubic in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n CUBIC_IN_OUT: Tween.Easing.Cubic.InOut,\r\n\r\n /**\r\n * Quartic in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUARTIC_IN: Tween.Easing.Quartic.In,\r\n /**\r\n * Quartic out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUARTIC_OUT: Tween.Easing.Quartic.Out,\r\n /**\r\n * Quartic in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUARTIC_IN_OUT: Tween.Easing.Quartic.InOut,\r\n\r\n /**\r\n * Quintic in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUINTIC_IN: Tween.Easing.Quintic.In,\r\n /**\r\n * Quintic out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUINTIC_OUT: Tween.Easing.Quintic.Out,\r\n /**\r\n * Quintic in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n QUINTIC_IN_OUT: Tween.Easing.Quintic.InOut,\r\n\r\n /**\r\n * Sinusoidal in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n SINUSOIDAL_IN: Tween.Easing.Sinusoidal.In,\r\n /**\r\n * Sinusoidal out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n SINUSOIDAL_OUT: Tween.Easing.Sinusoidal.Out,\r\n /**\r\n * Sinusoidal in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n SINUSOIDAL_IN_OUT: Tween.Easing.Sinusoidal.InOut,\r\n\r\n /**\r\n * Exponential in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n EXPONENTIAL_IN: Tween.Easing.Exponential.In,\r\n /**\r\n * Exponential out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n EXPONENTIAL_OUT: Tween.Easing.Exponential.Out,\r\n /**\r\n * Exponential in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n EXPONENTIAL_IN_OUT: Tween.Easing.Exponential.InOut,\r\n\r\n /**\r\n * Circular in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n CIRCULAR_IN: Tween.Easing.Circular.In,\r\n /**\r\n * Circular out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n CIRCULAR_OUT: Tween.Easing.Circular.Out,\r\n /**\r\n * Circular in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n CIRCULAR_IN_OUT: Tween.Easing.Circular.InOut,\r\n\r\n /**\r\n * Elastic in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n ELASTIC_IN: Tween.Easing.Elastic.In,\r\n /**\r\n * Elastic out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n ELASTIC_OUT: Tween.Easing.Elastic.Out,\r\n /**\r\n * Elastic in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n ELASTIC_IN_OUT: Tween.Easing.Elastic.InOut,\r\n\r\n /**\r\n * Back in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n BACK_IN: Tween.Easing.Back.In,\r\n /**\r\n * Back out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n BACK_OUT: Tween.Easing.Back.Out,\r\n /**\r\n * Back in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n BACK_IN_OUT: Tween.Easing.Back.InOut,\r\n\r\n /**\r\n * Bounce in.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n BOUNCE_IN: Tween.Easing.Bounce.In,\r\n /**\r\n * Bounce out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n BOUNCE_OUT: Tween.Easing.Bounce.Out,\r\n /**\r\n * Bounce in then out.\r\n *\r\n * @type {EasingFunction.Callback}\r\n * @constant\r\n */\r\n BOUNCE_IN_OUT: Tween.Easing.Bounce.InOut,\r\n};\r\n\r\n/**\r\n * Function interface for implementing a custom easing function.\r\n * @callback EasingFunction.Callback\r\n * @param {Number} time The time in the range [0, 1].\r\n * @returns {Number} The value of the function at the given time.\r\n *\r\n * @example\r\n * function quadraticIn(time) {\r\n * return time * time;\r\n * }\r\n *\r\n * @example\r\n * function quadraticOut(time) {\r\n * return time * (2.0 - time);\r\n * }\r\n */\r\n\r\nexport default Object.freeze(EasingFunction);\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar scratchPosition = new Cartesian3();\r\nvar scratchNormal = new Cartesian3();\r\nvar scratchTangent = new Cartesian3();\r\nvar scratchBitangent = new Cartesian3();\r\nvar scratchNormalST = new Cartesian3();\r\nvar defaultRadii = new Cartesian3(1.0, 1.0, 1.0);\r\n\r\nvar cos = Math.cos;\r\nvar sin = Math.sin;\r\n\r\n/**\r\n * A description of an ellipsoid centered at the origin.\r\n *\r\n * @alias EllipsoidGeometry\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Cartesian3} [options.radii=Cartesian3(1.0, 1.0, 1.0)] The radii of the ellipsoid in the x, y, and z directions.\r\n * @param {Cartesian3} [options.innerRadii=options.radii] The inner radii of the ellipsoid in the x, y, and z directions.\r\n * @param {Number} [options.minimumClock=0.0] The minimum angle lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.\r\n * @param {Number} [options.maximumClock=2*PI] The maximum angle lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.\r\n * @param {Number} [options.minimumCone=0.0] The minimum angle measured from the positive z-axis and toward the negative z-axis.\r\n * @param {Number} [options.maximumCone=PI] The maximum angle measured from the positive z-axis and toward the negative z-axis.\r\n * @param {Number} [options.stackPartitions=64] The number of times to partition the ellipsoid into stacks.\r\n * @param {Number} [options.slicePartitions=64] The number of times to partition the ellipsoid into radial slices.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n *\r\n * @exception {DeveloperError} options.slicePartitions cannot be less than three.\r\n * @exception {DeveloperError} options.stackPartitions cannot be less than three.\r\n *\r\n * @see EllipsoidGeometry#createGeometry\r\n *\r\n * @example\r\n * var ellipsoid = new Cesium.EllipsoidGeometry({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_ONLY,\r\n * radii : new Cesium.Cartesian3(1000000.0, 500000.0, 500000.0)\r\n * });\r\n * var geometry = Cesium.EllipsoidGeometry.createGeometry(ellipsoid);\r\n */\r\nfunction EllipsoidGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var radii = defaultValue(options.radii, defaultRadii);\r\n var innerRadii = defaultValue(options.innerRadii, radii);\r\n var minimumClock = defaultValue(options.minimumClock, 0.0);\r\n var maximumClock = defaultValue(options.maximumClock, CesiumMath.TWO_PI);\r\n var minimumCone = defaultValue(options.minimumCone, 0.0);\r\n var maximumCone = defaultValue(options.maximumCone, CesiumMath.PI);\r\n var stackPartitions = Math.round(defaultValue(options.stackPartitions, 64));\r\n var slicePartitions = Math.round(defaultValue(options.slicePartitions, 64));\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (slicePartitions < 3) {\r\n throw new DeveloperError(\r\n \"options.slicePartitions cannot be less than three.\"\r\n );\r\n }\r\n if (stackPartitions < 3) {\r\n throw new DeveloperError(\r\n \"options.stackPartitions cannot be less than three.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._radii = Cartesian3.clone(radii);\r\n this._innerRadii = Cartesian3.clone(innerRadii);\r\n this._minimumClock = minimumClock;\r\n this._maximumClock = maximumClock;\r\n this._minimumCone = minimumCone;\r\n this._maximumCone = maximumCone;\r\n this._stackPartitions = stackPartitions;\r\n this._slicePartitions = slicePartitions;\r\n this._vertexFormat = VertexFormat.clone(vertexFormat);\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createEllipsoidGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nEllipsoidGeometry.packedLength =\r\n 2 * Cartesian3.packedLength + VertexFormat.packedLength + 7;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {EllipsoidGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nEllipsoidGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Cartesian3.pack(value._radii, array, startingIndex);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n Cartesian3.pack(value._innerRadii, array, startingIndex);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._minimumClock;\r\n array[startingIndex++] = value._maximumClock;\r\n array[startingIndex++] = value._minimumCone;\r\n array[startingIndex++] = value._maximumCone;\r\n array[startingIndex++] = value._stackPartitions;\r\n array[startingIndex++] = value._slicePartitions;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchRadii = new Cartesian3();\r\nvar scratchInnerRadii = new Cartesian3();\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n radii: scratchRadii,\r\n innerRadii: scratchInnerRadii,\r\n vertexFormat: scratchVertexFormat,\r\n minimumClock: undefined,\r\n maximumClock: undefined,\r\n minimumCone: undefined,\r\n maximumCone: undefined,\r\n stackPartitions: undefined,\r\n slicePartitions: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {EllipsoidGeometry} [result] The object into which to store the result.\r\n * @returns {EllipsoidGeometry} The modified result parameter or a new EllipsoidGeometry instance if one was not provided.\r\n */\r\nEllipsoidGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var radii = Cartesian3.unpack(array, startingIndex, scratchRadii);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n var innerRadii = Cartesian3.unpack(array, startingIndex, scratchInnerRadii);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var minimumClock = array[startingIndex++];\r\n var maximumClock = array[startingIndex++];\r\n var minimumCone = array[startingIndex++];\r\n var maximumCone = array[startingIndex++];\r\n var stackPartitions = array[startingIndex++];\r\n var slicePartitions = array[startingIndex++];\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.minimumClock = minimumClock;\r\n scratchOptions.maximumClock = maximumClock;\r\n scratchOptions.minimumCone = minimumCone;\r\n scratchOptions.maximumCone = maximumCone;\r\n scratchOptions.stackPartitions = stackPartitions;\r\n scratchOptions.slicePartitions = slicePartitions;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n return new EllipsoidGeometry(scratchOptions);\r\n }\r\n\r\n result._radii = Cartesian3.clone(radii, result._radii);\r\n result._innerRadii = Cartesian3.clone(innerRadii, result._innerRadii);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._minimumClock = minimumClock;\r\n result._maximumClock = maximumClock;\r\n result._minimumCone = minimumCone;\r\n result._maximumCone = maximumCone;\r\n result._stackPartitions = stackPartitions;\r\n result._slicePartitions = slicePartitions;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an ellipsoid, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {EllipsoidGeometry} ellipsoidGeometry A description of the ellipsoid.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nEllipsoidGeometry.createGeometry = function (ellipsoidGeometry) {\r\n var radii = ellipsoidGeometry._radii;\r\n if (radii.x <= 0 || radii.y <= 0 || radii.z <= 0) {\r\n return;\r\n }\r\n\r\n var innerRadii = ellipsoidGeometry._innerRadii;\r\n if (innerRadii.x <= 0 || innerRadii.y <= 0 || innerRadii.z <= 0) {\r\n return;\r\n }\r\n\r\n var minimumClock = ellipsoidGeometry._minimumClock;\r\n var maximumClock = ellipsoidGeometry._maximumClock;\r\n var minimumCone = ellipsoidGeometry._minimumCone;\r\n var maximumCone = ellipsoidGeometry._maximumCone;\r\n var vertexFormat = ellipsoidGeometry._vertexFormat;\r\n\r\n // Add an extra slice and stack so that the number of partitions is the\r\n // number of surfaces rather than the number of joints\r\n var slicePartitions = ellipsoidGeometry._slicePartitions + 1;\r\n var stackPartitions = ellipsoidGeometry._stackPartitions + 1;\r\n\r\n slicePartitions = Math.round(\r\n (slicePartitions * Math.abs(maximumClock - minimumClock)) /\r\n CesiumMath.TWO_PI\r\n );\r\n stackPartitions = Math.round(\r\n (stackPartitions * Math.abs(maximumCone - minimumCone)) / CesiumMath.PI\r\n );\r\n\r\n if (slicePartitions < 2) {\r\n slicePartitions = 2;\r\n }\r\n if (stackPartitions < 2) {\r\n stackPartitions = 2;\r\n }\r\n\r\n var i;\r\n var j;\r\n var index = 0;\r\n\r\n // Create arrays for theta and phi. Duplicate first and last angle to\r\n // allow different normals at the intersections.\r\n var phis = [minimumCone];\r\n var thetas = [minimumClock];\r\n for (i = 0; i < stackPartitions; i++) {\r\n phis.push(\r\n minimumCone + (i * (maximumCone - minimumCone)) / (stackPartitions - 1)\r\n );\r\n }\r\n phis.push(maximumCone);\r\n for (j = 0; j < slicePartitions; j++) {\r\n thetas.push(\r\n minimumClock + (j * (maximumClock - minimumClock)) / (slicePartitions - 1)\r\n );\r\n }\r\n thetas.push(maximumClock);\r\n var numPhis = phis.length;\r\n var numThetas = thetas.length;\r\n\r\n // Allow for extra indices if there is an inner surface and if we need\r\n // to close the sides if the clock range is not a full circle\r\n var extraIndices = 0;\r\n var vertexMultiplier = 1.0;\r\n var hasInnerSurface =\r\n innerRadii.x !== radii.x ||\r\n innerRadii.y !== radii.y ||\r\n innerRadii.z !== radii.z;\r\n var isTopOpen = false;\r\n var isBotOpen = false;\r\n var isClockOpen = false;\r\n if (hasInnerSurface) {\r\n vertexMultiplier = 2.0;\r\n if (minimumCone > 0.0) {\r\n isTopOpen = true;\r\n extraIndices += slicePartitions - 1;\r\n }\r\n if (maximumCone < Math.PI) {\r\n isBotOpen = true;\r\n extraIndices += slicePartitions - 1;\r\n }\r\n if ((maximumClock - minimumClock) % CesiumMath.TWO_PI) {\r\n isClockOpen = true;\r\n extraIndices += (stackPartitions - 1) * 2 + 1;\r\n } else {\r\n extraIndices += 1;\r\n }\r\n }\r\n\r\n var vertexCount = numThetas * numPhis * vertexMultiplier;\r\n var positions = new Float64Array(vertexCount * 3);\r\n var isInner = arrayFill(new Array(vertexCount), false);\r\n var negateNormal = arrayFill(new Array(vertexCount), false);\r\n\r\n // Multiply by 6 because there are two triangles per sector\r\n var indexCount = slicePartitions * stackPartitions * vertexMultiplier;\r\n var numIndices =\r\n 6 *\r\n (indexCount +\r\n extraIndices +\r\n 1 -\r\n (slicePartitions + stackPartitions) * vertexMultiplier);\r\n var indices = IndexDatatype.createTypedArray(indexCount, numIndices);\r\n\r\n var normals = vertexFormat.normal\r\n ? new Float32Array(vertexCount * 3)\r\n : undefined;\r\n var tangents = vertexFormat.tangent\r\n ? new Float32Array(vertexCount * 3)\r\n : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(vertexCount * 3)\r\n : undefined;\r\n var st = vertexFormat.st ? new Float32Array(vertexCount * 2) : undefined;\r\n\r\n // Calculate sin/cos phi\r\n var sinPhi = new Array(numPhis);\r\n var cosPhi = new Array(numPhis);\r\n for (i = 0; i < numPhis; i++) {\r\n sinPhi[i] = sin(phis[i]);\r\n cosPhi[i] = cos(phis[i]);\r\n }\r\n\r\n // Calculate sin/cos theta\r\n var sinTheta = new Array(numThetas);\r\n var cosTheta = new Array(numThetas);\r\n for (j = 0; j < numThetas; j++) {\r\n cosTheta[j] = cos(thetas[j]);\r\n sinTheta[j] = sin(thetas[j]);\r\n }\r\n\r\n // Create outer surface\r\n for (i = 0; i < numPhis; i++) {\r\n for (j = 0; j < numThetas; j++) {\r\n positions[index++] = radii.x * sinPhi[i] * cosTheta[j];\r\n positions[index++] = radii.y * sinPhi[i] * sinTheta[j];\r\n positions[index++] = radii.z * cosPhi[i];\r\n }\r\n }\r\n\r\n // Create inner surface\r\n var vertexIndex = vertexCount / 2.0;\r\n if (hasInnerSurface) {\r\n for (i = 0; i < numPhis; i++) {\r\n for (j = 0; j < numThetas; j++) {\r\n positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];\r\n positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];\r\n positions[index++] = innerRadii.z * cosPhi[i];\r\n\r\n // Keep track of which vertices are the inner and which ones\r\n // need the normal to be negated\r\n isInner[vertexIndex] = true;\r\n if (i > 0 && i !== numPhis - 1 && j !== 0 && j !== numThetas - 1) {\r\n negateNormal[vertexIndex] = true;\r\n }\r\n vertexIndex++;\r\n }\r\n }\r\n }\r\n\r\n // Create indices for outer surface\r\n index = 0;\r\n var topOffset;\r\n var bottomOffset;\r\n for (i = 1; i < numPhis - 2; i++) {\r\n topOffset = i * numThetas;\r\n bottomOffset = (i + 1) * numThetas;\r\n\r\n for (j = 1; j < numThetas - 2; j++) {\r\n indices[index++] = bottomOffset + j;\r\n indices[index++] = bottomOffset + j + 1;\r\n indices[index++] = topOffset + j + 1;\r\n\r\n indices[index++] = bottomOffset + j;\r\n indices[index++] = topOffset + j + 1;\r\n indices[index++] = topOffset + j;\r\n }\r\n }\r\n\r\n // Create indices for inner surface\r\n if (hasInnerSurface) {\r\n var offset = numPhis * numThetas;\r\n for (i = 1; i < numPhis - 2; i++) {\r\n topOffset = offset + i * numThetas;\r\n bottomOffset = offset + (i + 1) * numThetas;\r\n\r\n for (j = 1; j < numThetas - 2; j++) {\r\n indices[index++] = bottomOffset + j;\r\n indices[index++] = topOffset + j;\r\n indices[index++] = topOffset + j + 1;\r\n\r\n indices[index++] = bottomOffset + j;\r\n indices[index++] = topOffset + j + 1;\r\n indices[index++] = bottomOffset + j + 1;\r\n }\r\n }\r\n }\r\n\r\n var outerOffset;\r\n var innerOffset;\r\n if (hasInnerSurface) {\r\n if (isTopOpen) {\r\n // Connect the top of the inner surface to the top of the outer surface\r\n innerOffset = numPhis * numThetas;\r\n for (i = 1; i < numThetas - 2; i++) {\r\n indices[index++] = i;\r\n indices[index++] = i + 1;\r\n indices[index++] = innerOffset + i + 1;\r\n\r\n indices[index++] = i;\r\n indices[index++] = innerOffset + i + 1;\r\n indices[index++] = innerOffset + i;\r\n }\r\n }\r\n\r\n if (isBotOpen) {\r\n // Connect the bottom of the inner surface to the bottom of the outer surface\r\n outerOffset = numPhis * numThetas - numThetas;\r\n innerOffset = numPhis * numThetas * vertexMultiplier - numThetas;\r\n for (i = 1; i < numThetas - 2; i++) {\r\n indices[index++] = outerOffset + i + 1;\r\n indices[index++] = outerOffset + i;\r\n indices[index++] = innerOffset + i;\r\n\r\n indices[index++] = outerOffset + i + 1;\r\n indices[index++] = innerOffset + i;\r\n indices[index++] = innerOffset + i + 1;\r\n }\r\n }\r\n }\r\n\r\n // Connect the edges if clock is not closed\r\n if (isClockOpen) {\r\n for (i = 1; i < numPhis - 2; i++) {\r\n innerOffset = numThetas * numPhis + numThetas * i;\r\n outerOffset = numThetas * i;\r\n indices[index++] = innerOffset;\r\n indices[index++] = outerOffset + numThetas;\r\n indices[index++] = outerOffset;\r\n\r\n indices[index++] = innerOffset;\r\n indices[index++] = innerOffset + numThetas;\r\n indices[index++] = outerOffset + numThetas;\r\n }\r\n\r\n for (i = 1; i < numPhis - 2; i++) {\r\n innerOffset = numThetas * numPhis + numThetas * (i + 1) - 1;\r\n outerOffset = numThetas * (i + 1) - 1;\r\n indices[index++] = outerOffset + numThetas;\r\n indices[index++] = innerOffset;\r\n indices[index++] = outerOffset;\r\n\r\n indices[index++] = outerOffset + numThetas;\r\n indices[index++] = innerOffset + numThetas;\r\n indices[index++] = innerOffset;\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n\r\n if (vertexFormat.position) {\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n }\r\n\r\n var stIndex = 0;\r\n var normalIndex = 0;\r\n var tangentIndex = 0;\r\n var bitangentIndex = 0;\r\n var vertexCountHalf = vertexCount / 2.0;\r\n\r\n var ellipsoid;\r\n var ellipsoidOuter = Ellipsoid.fromCartesian3(radii);\r\n var ellipsoidInner = Ellipsoid.fromCartesian3(innerRadii);\r\n\r\n if (\r\n vertexFormat.st ||\r\n vertexFormat.normal ||\r\n vertexFormat.tangent ||\r\n vertexFormat.bitangent\r\n ) {\r\n for (i = 0; i < vertexCount; i++) {\r\n ellipsoid = isInner[i] ? ellipsoidInner : ellipsoidOuter;\r\n var position = Cartesian3.fromArray(positions, i * 3, scratchPosition);\r\n var normal = ellipsoid.geodeticSurfaceNormal(position, scratchNormal);\r\n if (negateNormal[i]) {\r\n Cartesian3.negate(normal, normal);\r\n }\r\n\r\n if (vertexFormat.st) {\r\n var normalST = Cartesian2.negate(normal, scratchNormalST);\r\n st[stIndex++] =\r\n Math.atan2(normalST.y, normalST.x) / CesiumMath.TWO_PI + 0.5;\r\n st[stIndex++] = Math.asin(normal.z) / Math.PI + 0.5;\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n normals[normalIndex++] = normal.x;\r\n normals[normalIndex++] = normal.y;\r\n normals[normalIndex++] = normal.z;\r\n }\r\n\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n var tangent = scratchTangent;\r\n\r\n // Use UNIT_X for the poles\r\n var tangetOffset = 0;\r\n var unit;\r\n if (isInner[i]) {\r\n tangetOffset = vertexCountHalf;\r\n }\r\n if (\r\n !isTopOpen &&\r\n i >= tangetOffset &&\r\n i < tangetOffset + numThetas * 2\r\n ) {\r\n unit = Cartesian3.UNIT_X;\r\n } else {\r\n unit = Cartesian3.UNIT_Z;\r\n }\r\n Cartesian3.cross(unit, normal, tangent);\r\n Cartesian3.normalize(tangent, tangent);\r\n\r\n if (vertexFormat.tangent) {\r\n tangents[tangentIndex++] = tangent.x;\r\n tangents[tangentIndex++] = tangent.y;\r\n tangents[tangentIndex++] = tangent.z;\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n var bitangent = Cartesian3.cross(normal, tangent, scratchBitangent);\r\n Cartesian3.normalize(bitangent, bitangent);\r\n\r\n bitangents[bitangentIndex++] = bitangent.x;\r\n bitangents[bitangentIndex++] = bitangent.y;\r\n bitangents[bitangentIndex++] = bitangent.z;\r\n }\r\n }\r\n }\r\n\r\n if (vertexFormat.st) {\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: st,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n }\r\n\r\n if (defined(ellipsoidGeometry._offsetAttribute)) {\r\n var length = positions.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n ellipsoidGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: BoundingSphere.fromEllipsoid(ellipsoidOuter),\r\n offsetAttribute: ellipsoidGeometry._offsetAttribute,\r\n });\r\n};\r\n\r\nvar unitEllipsoidGeometry;\r\n\r\n/**\r\n * Returns the geometric representation of a unit ellipsoid, including its vertices, indices, and a bounding sphere.\r\n * @returns {Geometry} The computed vertices and indices.\r\n *\r\n * @private\r\n */\r\nEllipsoidGeometry.getUnitEllipsoid = function () {\r\n if (!defined(unitEllipsoidGeometry)) {\r\n unitEllipsoidGeometry = EllipsoidGeometry.createGeometry(\r\n new EllipsoidGeometry({\r\n radii: new Cartesian3(1.0, 1.0, 1.0),\r\n vertexFormat: VertexFormat.POSITION_ONLY,\r\n })\r\n );\r\n }\r\n return unitEllipsoidGeometry;\r\n};\r\nexport default EllipsoidGeometry;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\n\r\nvar defaultRadii = new Cartesian3(1.0, 1.0, 1.0);\r\nvar cos = Math.cos;\r\nvar sin = Math.sin;\r\n\r\n/**\r\n * A description of the outline of an ellipsoid centered at the origin.\r\n *\r\n * @alias EllipsoidOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Cartesian3} [options.radii=Cartesian3(1.0, 1.0, 1.0)] The radii of the ellipsoid in the x, y, and z directions.\r\n * @param {Cartesian3} [options.innerRadii=options.radii] The inner radii of the ellipsoid in the x, y, and z directions.\r\n * @param {Number} [options.minimumClock=0.0] The minimum angle lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.\r\n * @param {Number} [options.maximumClock=2*PI] The maximum angle lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.\r\n * @param {Number} [options.minimumCone=0.0] The minimum angle measured from the positive z-axis and toward the negative z-axis.\r\n * @param {Number} [options.maximumCone=PI] The maximum angle measured from the positive z-axis and toward the negative z-axis.\r\n * @param {Number} [options.stackPartitions=10] The count of stacks for the ellipsoid (1 greater than the number of parallel lines).\r\n * @param {Number} [options.slicePartitions=8] The count of slices for the ellipsoid (Equal to the number of radial lines).\r\n * @param {Number} [options.subdivisions=128] The number of points per line, determining the granularity of the curvature.\r\n *\r\n * @exception {DeveloperError} options.stackPartitions must be greater than or equal to one.\r\n * @exception {DeveloperError} options.slicePartitions must be greater than or equal to zero.\r\n * @exception {DeveloperError} options.subdivisions must be greater than or equal to zero.\r\n *\r\n * @example\r\n * var ellipsoid = new Cesium.EllipsoidOutlineGeometry({\r\n * radii : new Cesium.Cartesian3(1000000.0, 500000.0, 500000.0),\r\n * stackPartitions: 6,\r\n * slicePartitions: 5\r\n * });\r\n * var geometry = Cesium.EllipsoidOutlineGeometry.createGeometry(ellipsoid);\r\n */\r\nfunction EllipsoidOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var radii = defaultValue(options.radii, defaultRadii);\r\n var innerRadii = defaultValue(options.innerRadii, radii);\r\n var minimumClock = defaultValue(options.minimumClock, 0.0);\r\n var maximumClock = defaultValue(options.maximumClock, CesiumMath.TWO_PI);\r\n var minimumCone = defaultValue(options.minimumCone, 0.0);\r\n var maximumCone = defaultValue(options.maximumCone, CesiumMath.PI);\r\n var stackPartitions = Math.round(defaultValue(options.stackPartitions, 10));\r\n var slicePartitions = Math.round(defaultValue(options.slicePartitions, 8));\r\n var subdivisions = Math.round(defaultValue(options.subdivisions, 128));\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (stackPartitions < 1) {\r\n throw new DeveloperError(\"options.stackPartitions cannot be less than 1\");\r\n }\r\n if (slicePartitions < 0) {\r\n throw new DeveloperError(\"options.slicePartitions cannot be less than 0\");\r\n }\r\n if (subdivisions < 0) {\r\n throw new DeveloperError(\r\n \"options.subdivisions must be greater than or equal to zero.\"\r\n );\r\n }\r\n if (\r\n defined(options.offsetAttribute) &&\r\n options.offsetAttribute === GeometryOffsetAttribute.TOP\r\n ) {\r\n throw new DeveloperError(\r\n \"GeometryOffsetAttribute.TOP is not a supported options.offsetAttribute for this geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._radii = Cartesian3.clone(radii);\r\n this._innerRadii = Cartesian3.clone(innerRadii);\r\n this._minimumClock = minimumClock;\r\n this._maximumClock = maximumClock;\r\n this._minimumCone = minimumCone;\r\n this._maximumCone = maximumCone;\r\n this._stackPartitions = stackPartitions;\r\n this._slicePartitions = slicePartitions;\r\n this._subdivisions = subdivisions;\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createEllipsoidOutlineGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nEllipsoidOutlineGeometry.packedLength = 2 * Cartesian3.packedLength + 8;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {EllipsoidOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nEllipsoidOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Cartesian3.pack(value._radii, array, startingIndex);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n Cartesian3.pack(value._innerRadii, array, startingIndex);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n array[startingIndex++] = value._minimumClock;\r\n array[startingIndex++] = value._maximumClock;\r\n array[startingIndex++] = value._minimumCone;\r\n array[startingIndex++] = value._maximumCone;\r\n array[startingIndex++] = value._stackPartitions;\r\n array[startingIndex++] = value._slicePartitions;\r\n array[startingIndex++] = value._subdivisions;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchRadii = new Cartesian3();\r\nvar scratchInnerRadii = new Cartesian3();\r\nvar scratchOptions = {\r\n radii: scratchRadii,\r\n innerRadii: scratchInnerRadii,\r\n minimumClock: undefined,\r\n maximumClock: undefined,\r\n minimumCone: undefined,\r\n maximumCone: undefined,\r\n stackPartitions: undefined,\r\n slicePartitions: undefined,\r\n subdivisions: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {EllipsoidOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {EllipsoidOutlineGeometry} The modified result parameter or a new EllipsoidOutlineGeometry instance if one was not provided.\r\n */\r\nEllipsoidOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var radii = Cartesian3.unpack(array, startingIndex, scratchRadii);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n var innerRadii = Cartesian3.unpack(array, startingIndex, scratchInnerRadii);\r\n startingIndex += Cartesian3.packedLength;\r\n\r\n var minimumClock = array[startingIndex++];\r\n var maximumClock = array[startingIndex++];\r\n var minimumCone = array[startingIndex++];\r\n var maximumCone = array[startingIndex++];\r\n var stackPartitions = array[startingIndex++];\r\n var slicePartitions = array[startingIndex++];\r\n var subdivisions = array[startingIndex++];\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.minimumClock = minimumClock;\r\n scratchOptions.maximumClock = maximumClock;\r\n scratchOptions.minimumCone = minimumCone;\r\n scratchOptions.maximumCone = maximumCone;\r\n scratchOptions.stackPartitions = stackPartitions;\r\n scratchOptions.slicePartitions = slicePartitions;\r\n scratchOptions.subdivisions = subdivisions;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n return new EllipsoidOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._radii = Cartesian3.clone(radii, result._radii);\r\n result._innerRadii = Cartesian3.clone(innerRadii, result._innerRadii);\r\n result._minimumClock = minimumClock;\r\n result._maximumClock = maximumClock;\r\n result._minimumCone = minimumCone;\r\n result._maximumCone = maximumCone;\r\n result._stackPartitions = stackPartitions;\r\n result._slicePartitions = slicePartitions;\r\n result._subdivisions = subdivisions;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an outline of an ellipsoid, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {EllipsoidOutlineGeometry} ellipsoidGeometry A description of the ellipsoid outline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nEllipsoidOutlineGeometry.createGeometry = function (ellipsoidGeometry) {\r\n var radii = ellipsoidGeometry._radii;\r\n if (radii.x <= 0 || radii.y <= 0 || radii.z <= 0) {\r\n return;\r\n }\r\n\r\n var innerRadii = ellipsoidGeometry._innerRadii;\r\n if (innerRadii.x <= 0 || innerRadii.y <= 0 || innerRadii.z <= 0) {\r\n return;\r\n }\r\n\r\n var minimumClock = ellipsoidGeometry._minimumClock;\r\n var maximumClock = ellipsoidGeometry._maximumClock;\r\n var minimumCone = ellipsoidGeometry._minimumCone;\r\n var maximumCone = ellipsoidGeometry._maximumCone;\r\n var subdivisions = ellipsoidGeometry._subdivisions;\r\n var ellipsoid = Ellipsoid.fromCartesian3(radii);\r\n\r\n // Add an extra slice and stack to remain consistent with EllipsoidGeometry\r\n var slicePartitions = ellipsoidGeometry._slicePartitions + 1;\r\n var stackPartitions = ellipsoidGeometry._stackPartitions + 1;\r\n\r\n slicePartitions = Math.round(\r\n (slicePartitions * Math.abs(maximumClock - minimumClock)) /\r\n CesiumMath.TWO_PI\r\n );\r\n stackPartitions = Math.round(\r\n (stackPartitions * Math.abs(maximumCone - minimumCone)) / CesiumMath.PI\r\n );\r\n\r\n if (slicePartitions < 2) {\r\n slicePartitions = 2;\r\n }\r\n if (stackPartitions < 2) {\r\n stackPartitions = 2;\r\n }\r\n\r\n var extraIndices = 0;\r\n var vertexMultiplier = 1.0;\r\n var hasInnerSurface =\r\n innerRadii.x !== radii.x ||\r\n innerRadii.y !== radii.y ||\r\n innerRadii.z !== radii.z;\r\n var isTopOpen = false;\r\n var isBotOpen = false;\r\n if (hasInnerSurface) {\r\n vertexMultiplier = 2.0;\r\n // Add 2x slicePartitions to connect the top/bottom of the outer to\r\n // the top/bottom of the inner\r\n if (minimumCone > 0.0) {\r\n isTopOpen = true;\r\n extraIndices += slicePartitions;\r\n }\r\n if (maximumCone < Math.PI) {\r\n isBotOpen = true;\r\n extraIndices += slicePartitions;\r\n }\r\n }\r\n\r\n var vertexCount =\r\n subdivisions * vertexMultiplier * (stackPartitions + slicePartitions);\r\n var positions = new Float64Array(vertexCount * 3);\r\n\r\n // Multiply by two because two points define each line segment\r\n var numIndices =\r\n 2 *\r\n (vertexCount +\r\n extraIndices -\r\n (slicePartitions + stackPartitions) * vertexMultiplier);\r\n var indices = IndexDatatype.createTypedArray(vertexCount, numIndices);\r\n\r\n var i;\r\n var j;\r\n var theta;\r\n var phi;\r\n var index = 0;\r\n\r\n // Calculate sin/cos phi\r\n var sinPhi = new Array(stackPartitions);\r\n var cosPhi = new Array(stackPartitions);\r\n for (i = 0; i < stackPartitions; i++) {\r\n phi =\r\n minimumCone + (i * (maximumCone - minimumCone)) / (stackPartitions - 1);\r\n sinPhi[i] = sin(phi);\r\n cosPhi[i] = cos(phi);\r\n }\r\n\r\n // Calculate sin/cos theta\r\n var sinTheta = new Array(subdivisions);\r\n var cosTheta = new Array(subdivisions);\r\n for (i = 0; i < subdivisions; i++) {\r\n theta =\r\n minimumClock + (i * (maximumClock - minimumClock)) / (subdivisions - 1);\r\n sinTheta[i] = sin(theta);\r\n cosTheta[i] = cos(theta);\r\n }\r\n\r\n // Calculate the latitude lines on the outer surface\r\n for (i = 0; i < stackPartitions; i++) {\r\n for (j = 0; j < subdivisions; j++) {\r\n positions[index++] = radii.x * sinPhi[i] * cosTheta[j];\r\n positions[index++] = radii.y * sinPhi[i] * sinTheta[j];\r\n positions[index++] = radii.z * cosPhi[i];\r\n }\r\n }\r\n\r\n // Calculate the latitude lines on the inner surface\r\n if (hasInnerSurface) {\r\n for (i = 0; i < stackPartitions; i++) {\r\n for (j = 0; j < subdivisions; j++) {\r\n positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];\r\n positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];\r\n positions[index++] = innerRadii.z * cosPhi[i];\r\n }\r\n }\r\n }\r\n\r\n // Calculate sin/cos phi\r\n sinPhi.length = subdivisions;\r\n cosPhi.length = subdivisions;\r\n for (i = 0; i < subdivisions; i++) {\r\n phi = minimumCone + (i * (maximumCone - minimumCone)) / (subdivisions - 1);\r\n sinPhi[i] = sin(phi);\r\n cosPhi[i] = cos(phi);\r\n }\r\n\r\n // Calculate sin/cos theta for each slice partition\r\n sinTheta.length = slicePartitions;\r\n cosTheta.length = slicePartitions;\r\n for (i = 0; i < slicePartitions; i++) {\r\n theta =\r\n minimumClock +\r\n (i * (maximumClock - minimumClock)) / (slicePartitions - 1);\r\n sinTheta[i] = sin(theta);\r\n cosTheta[i] = cos(theta);\r\n }\r\n\r\n // Calculate the longitude lines on the outer surface\r\n for (i = 0; i < subdivisions; i++) {\r\n for (j = 0; j < slicePartitions; j++) {\r\n positions[index++] = radii.x * sinPhi[i] * cosTheta[j];\r\n positions[index++] = radii.y * sinPhi[i] * sinTheta[j];\r\n positions[index++] = radii.z * cosPhi[i];\r\n }\r\n }\r\n\r\n // Calculate the longitude lines on the inner surface\r\n if (hasInnerSurface) {\r\n for (i = 0; i < subdivisions; i++) {\r\n for (j = 0; j < slicePartitions; j++) {\r\n positions[index++] = innerRadii.x * sinPhi[i] * cosTheta[j];\r\n positions[index++] = innerRadii.y * sinPhi[i] * sinTheta[j];\r\n positions[index++] = innerRadii.z * cosPhi[i];\r\n }\r\n }\r\n }\r\n\r\n // Create indices for the latitude lines\r\n index = 0;\r\n for (i = 0; i < stackPartitions * vertexMultiplier; i++) {\r\n var topOffset = i * subdivisions;\r\n for (j = 0; j < subdivisions - 1; j++) {\r\n indices[index++] = topOffset + j;\r\n indices[index++] = topOffset + j + 1;\r\n }\r\n }\r\n\r\n // Create indices for the outer longitude lines\r\n var offset = stackPartitions * subdivisions * vertexMultiplier;\r\n for (i = 0; i < slicePartitions; i++) {\r\n for (j = 0; j < subdivisions - 1; j++) {\r\n indices[index++] = offset + i + j * slicePartitions;\r\n indices[index++] = offset + i + (j + 1) * slicePartitions;\r\n }\r\n }\r\n\r\n // Create indices for the inner longitude lines\r\n if (hasInnerSurface) {\r\n offset =\r\n stackPartitions * subdivisions * vertexMultiplier +\r\n slicePartitions * subdivisions;\r\n for (i = 0; i < slicePartitions; i++) {\r\n for (j = 0; j < subdivisions - 1; j++) {\r\n indices[index++] = offset + i + j * slicePartitions;\r\n indices[index++] = offset + i + (j + 1) * slicePartitions;\r\n }\r\n }\r\n }\r\n\r\n if (hasInnerSurface) {\r\n var outerOffset = stackPartitions * subdivisions * vertexMultiplier;\r\n var innerOffset = outerOffset + subdivisions * slicePartitions;\r\n if (isTopOpen) {\r\n // Draw lines from the top of the inner surface to the top of the outer surface\r\n for (i = 0; i < slicePartitions; i++) {\r\n indices[index++] = outerOffset + i;\r\n indices[index++] = innerOffset + i;\r\n }\r\n }\r\n\r\n if (isBotOpen) {\r\n // Draw lines from the top of the inner surface to the top of the outer surface\r\n outerOffset += subdivisions * slicePartitions - slicePartitions;\r\n innerOffset += subdivisions * slicePartitions - slicePartitions;\r\n for (i = 0; i < slicePartitions; i++) {\r\n indices[index++] = outerOffset + i;\r\n indices[index++] = innerOffset + i;\r\n }\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n }),\r\n });\r\n\r\n if (defined(ellipsoidGeometry._offsetAttribute)) {\r\n var length = positions.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n ellipsoidGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: BoundingSphere.fromEllipsoid(ellipsoid),\r\n offsetAttribute: ellipsoidGeometry._offsetAttribute,\r\n });\r\n};\r\nexport default EllipsoidOutlineGeometry;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Event from \"./Event.js\";\r\nimport GeographicTilingScheme from \"./GeographicTilingScheme.js\";\r\nimport HeightmapTerrainData from \"./HeightmapTerrainData.js\";\r\nimport TerrainProvider from \"./TerrainProvider.js\";\r\n\r\n/**\r\n * A very simple {@link TerrainProvider} that produces geometry by tessellating an ellipsoidal\r\n * surface.\r\n *\r\n * @alias EllipsoidTerrainProvider\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {TilingScheme} [options.tilingScheme] The tiling scheme specifying how the ellipsoidal\r\n * surface is broken into tiles. If this parameter is not provided, a {@link GeographicTilingScheme}\r\n * is used.\r\n * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If the tilingScheme is specified,\r\n * this parameter is ignored and the tiling scheme's ellipsoid is used instead. If neither\r\n * parameter is specified, the WGS84 ellipsoid is used.\r\n *\r\n * @see TerrainProvider\r\n */\r\nfunction EllipsoidTerrainProvider(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._tilingScheme = options.tilingScheme;\r\n if (!defined(this._tilingScheme)) {\r\n this._tilingScheme = new GeographicTilingScheme({\r\n ellipsoid: defaultValue(options.ellipsoid, Ellipsoid.WGS84),\r\n });\r\n }\r\n\r\n // Note: the 64 below does NOT need to match the actual vertex dimensions, because\r\n // the ellipsoid is significantly smoother than actual terrain.\r\n this._levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(\r\n this._tilingScheme.ellipsoid,\r\n 64,\r\n this._tilingScheme.getNumberOfXTilesAtLevel(0)\r\n );\r\n\r\n this._errorEvent = new Event();\r\n this._readyPromise = when.resolve(true);\r\n}\r\n\r\nObject.defineProperties(EllipsoidTerrainProvider.prototype, {\r\n /**\r\n * Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing\r\n * to the event, you will be notified of the error and can potentially recover from it. Event listeners\r\n * are passed an instance of {@link TileProviderError}.\r\n * @memberof EllipsoidTerrainProvider.prototype\r\n * @type {Event}\r\n */\r\n errorEvent: {\r\n get: function () {\r\n return this._errorEvent;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the credit to display when this terrain provider is active. Typically this is used to credit\r\n * the source of the terrain. This function should not be called before {@link EllipsoidTerrainProvider#ready} returns true.\r\n * @memberof EllipsoidTerrainProvider.prototype\r\n * @type {Credit}\r\n */\r\n credit: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tiling scheme used by this provider. This function should\r\n * not be called before {@link EllipsoidTerrainProvider#ready} returns true.\r\n * @memberof EllipsoidTerrainProvider.prototype\r\n * @type {GeographicTilingScheme}\r\n */\r\n tilingScheme: {\r\n get: function () {\r\n return this._tilingScheme;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider is ready for use.\r\n * @memberof EllipsoidTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n ready: {\r\n get: function () {\r\n return true;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves to true when the provider is ready for use.\r\n * @memberof EllipsoidTerrainProvider.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider includes a water mask. The water mask\r\n * indicates which areas of the globe are water rather than land, so they can be rendered\r\n * as a reflective surface with animated waves. This function should not be\r\n * called before {@link EllipsoidTerrainProvider#ready} returns true.\r\n * @memberof EllipsoidTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasWaterMask: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the requested tiles include vertex normals.\r\n * This function should not be called before {@link EllipsoidTerrainProvider#ready} returns true.\r\n * @memberof EllipsoidTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasVertexNormals: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n /**\r\n * Gets an object that can be used to determine availability of terrain from this provider, such as\r\n * at points and in rectangles. This function should not be called before\r\n * {@link TerrainProvider#ready} returns true. This property may be undefined if availability\r\n * information is not available.\r\n * @memberof EllipsoidTerrainProvider.prototype\r\n * @type {TileAvailability}\r\n */\r\n availability: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Requests the geometry for a given tile. This function should not be called before\r\n * {@link TerrainProvider#ready} returns true. The result includes terrain\r\n * data and indicates that all child tiles are available.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @param {Request} [request] The request object. Intended for internal use only.\r\n *\r\n * @returns {Promise.|undefined} A promise for the requested geometry. If this method\r\n * returns undefined instead of a promise, it is an indication that too many requests are already\r\n * pending and the request will be retried later.\r\n */\r\nEllipsoidTerrainProvider.prototype.requestTileGeometry = function (\r\n x,\r\n y,\r\n level,\r\n request\r\n) {\r\n var width = 16;\r\n var height = 16;\r\n return when.resolve(\r\n new HeightmapTerrainData({\r\n buffer: new Uint8Array(width * height),\r\n width: width,\r\n height: height,\r\n })\r\n );\r\n};\r\n\r\n/**\r\n * Gets the maximum geometric error allowed in a tile at a given level.\r\n *\r\n * @param {Number} level The tile level for which to get the maximum geometric error.\r\n * @returns {Number} The maximum geometric error.\r\n */\r\nEllipsoidTerrainProvider.prototype.getLevelMaximumGeometricError = function (\r\n level\r\n) {\r\n return this._levelZeroMaximumGeometricError / (1 << level);\r\n};\r\n\r\n/**\r\n * Determines whether data for a tile is available to be loaded.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {Boolean} Undefined if not supported, otherwise true or false.\r\n */\r\nEllipsoidTerrainProvider.prototype.getTileDataAvailable = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Makes sure we load availability data for a tile\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {undefined|Promise} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded\r\n */\r\nEllipsoidTerrainProvider.prototype.loadTileDataAvailability = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n return undefined;\r\n};\r\nexport default EllipsoidTerrainProvider;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * A convenience object that simplifies the common pattern of attaching event listeners\r\n * to several events, then removing all those listeners at once later, for example, in\r\n * a destroy method.\r\n *\r\n * @alias EventHelper\r\n * @constructor\r\n *\r\n *\r\n * @example\r\n * var helper = new Cesium.EventHelper();\r\n *\r\n * helper.add(someObject.event, listener1, this);\r\n * helper.add(otherObject.event, listener2, this);\r\n *\r\n * // later...\r\n * helper.removeAll();\r\n *\r\n * @see Event\r\n */\r\nfunction EventHelper() {\r\n this._removalFunctions = [];\r\n}\r\n\r\n/**\r\n * Adds a listener to an event, and records the registration to be cleaned up later.\r\n *\r\n * @param {Event} event The event to attach to.\r\n * @param {Function} listener The function to be executed when the event is raised.\r\n * @param {Object} [scope] An optional object scope to serve as the this\r\n * pointer in which the listener function will execute.\r\n * @returns {EventHelper.RemoveCallback} A function that will remove this event listener when invoked.\r\n *\r\n * @see Event#addEventListener\r\n */\r\nEventHelper.prototype.add = function (event, listener, scope) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(event)) {\r\n throw new DeveloperError(\"event is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var removalFunction = event.addEventListener(listener, scope);\r\n this._removalFunctions.push(removalFunction);\r\n\r\n var that = this;\r\n return function () {\r\n removalFunction();\r\n var removalFunctions = that._removalFunctions;\r\n removalFunctions.splice(removalFunctions.indexOf(removalFunction), 1);\r\n };\r\n};\r\n\r\n/**\r\n * Unregisters all previously added listeners.\r\n *\r\n * @see Event#removeEventListener\r\n */\r\nEventHelper.prototype.removeAll = function () {\r\n var removalFunctions = this._removalFunctions;\r\n for (var i = 0, len = removalFunctions.length; i < len; ++i) {\r\n removalFunctions[i]();\r\n }\r\n removalFunctions.length = 0;\r\n};\r\n\r\n/**\r\n * A function that removes a listener.\r\n * @callback EventHelper.RemoveCallback\r\n */\r\nexport default EventHelper;\r\n","/**\r\n * Constants to determine how an interpolated value is extrapolated\r\n * when querying outside the bounds of available data.\r\n *\r\n * @enum {Number}\r\n *\r\n * @see SampledProperty\r\n */\r\nvar ExtrapolationType = {\r\n /**\r\n * No extrapolation occurs.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NONE: 0,\r\n\r\n /**\r\n * The first or last value is used when outside the range of sample data.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n HOLD: 1,\r\n\r\n /**\r\n * The value is extrapolated.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n EXTRAPOLATE: 2,\r\n};\r\nexport default Object.freeze(ExtrapolationType);\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport CullingVolume from \"./CullingVolume.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\n\r\n/**\r\n * The viewing frustum is defined by 6 planes.\r\n * Each plane is represented by a {@link Cartesian4} object, where the x, y, and z components\r\n * define the unit vector normal to the plane, and the w component is the distance of the\r\n * plane from the origin/camera position.\r\n *\r\n * @alias OrthographicOffCenterFrustum\r\n * @constructor\r\n *\r\n * @param {Object} [options] An object with the following properties:\r\n * @param {Number} [options.left] The left clipping plane distance.\r\n * @param {Number} [options.right] The right clipping plane distance.\r\n * @param {Number} [options.top] The top clipping plane distance.\r\n * @param {Number} [options.bottom] The bottom clipping plane distance.\r\n * @param {Number} [options.near=1.0] The near clipping plane distance.\r\n * @param {Number} [options.far=500000000.0] The far clipping plane distance.\r\n *\r\n * @example\r\n * var maxRadii = ellipsoid.maximumRadius;\r\n *\r\n * var frustum = new Cesium.OrthographicOffCenterFrustum();\r\n * frustum.right = maxRadii * Cesium.Math.PI;\r\n * frustum.left = -c.frustum.right;\r\n * frustum.top = c.frustum.right * (canvas.clientHeight / canvas.clientWidth);\r\n * frustum.bottom = -c.frustum.top;\r\n * frustum.near = 0.01 * maxRadii;\r\n * frustum.far = 50.0 * maxRadii;\r\n */\r\nfunction OrthographicOffCenterFrustum(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * The left clipping plane.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.left = options.left;\r\n this._left = undefined;\r\n\r\n /**\r\n * The right clipping plane.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.right = options.right;\r\n this._right = undefined;\r\n\r\n /**\r\n * The top clipping plane.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.top = options.top;\r\n this._top = undefined;\r\n\r\n /**\r\n * The bottom clipping plane.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.bottom = options.bottom;\r\n this._bottom = undefined;\r\n\r\n /**\r\n * The distance of the near plane.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.near = defaultValue(options.near, 1.0);\r\n this._near = this.near;\r\n\r\n /**\r\n * The distance of the far plane.\r\n * @type {Number}\r\n * @default 500000000.0;\r\n */\r\n this.far = defaultValue(options.far, 500000000.0);\r\n this._far = this.far;\r\n\r\n this._cullingVolume = new CullingVolume();\r\n this._orthographicMatrix = new Matrix4();\r\n}\r\n\r\nfunction update(frustum) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(frustum.right) ||\r\n !defined(frustum.left) ||\r\n !defined(frustum.top) ||\r\n !defined(frustum.bottom) ||\r\n !defined(frustum.near) ||\r\n !defined(frustum.far)\r\n ) {\r\n throw new DeveloperError(\r\n \"right, left, top, bottom, near, or far parameters are not set.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (\r\n frustum.top !== frustum._top ||\r\n frustum.bottom !== frustum._bottom ||\r\n frustum.left !== frustum._left ||\r\n frustum.right !== frustum._right ||\r\n frustum.near !== frustum._near ||\r\n frustum.far !== frustum._far\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (frustum.left > frustum.right) {\r\n throw new DeveloperError(\"right must be greater than left.\");\r\n }\r\n if (frustum.bottom > frustum.top) {\r\n throw new DeveloperError(\"top must be greater than bottom.\");\r\n }\r\n if (frustum.near <= 0 || frustum.near > frustum.far) {\r\n throw new DeveloperError(\r\n \"near must be greater than zero and less than far.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n frustum._left = frustum.left;\r\n frustum._right = frustum.right;\r\n frustum._top = frustum.top;\r\n frustum._bottom = frustum.bottom;\r\n frustum._near = frustum.near;\r\n frustum._far = frustum.far;\r\n frustum._orthographicMatrix = Matrix4.computeOrthographicOffCenter(\r\n frustum.left,\r\n frustum.right,\r\n frustum.bottom,\r\n frustum.top,\r\n frustum.near,\r\n frustum.far,\r\n frustum._orthographicMatrix\r\n );\r\n }\r\n}\r\n\r\nObject.defineProperties(OrthographicOffCenterFrustum.prototype, {\r\n /**\r\n * Gets the orthographic projection matrix computed from the view frustum.\r\n * @memberof OrthographicOffCenterFrustum.prototype\r\n * @type {Matrix4}\r\n * @readonly\r\n */\r\n projectionMatrix: {\r\n get: function () {\r\n update(this);\r\n return this._orthographicMatrix;\r\n },\r\n },\r\n});\r\n\r\nvar getPlanesRight = new Cartesian3();\r\nvar getPlanesNearCenter = new Cartesian3();\r\nvar getPlanesPoint = new Cartesian3();\r\nvar negateScratch = new Cartesian3();\r\n\r\n/**\r\n * Creates a culling volume for this frustum.\r\n *\r\n * @param {Cartesian3} position The eye position.\r\n * @param {Cartesian3} direction The view direction.\r\n * @param {Cartesian3} up The up direction.\r\n * @returns {CullingVolume} A culling volume at the given position and orientation.\r\n *\r\n * @example\r\n * // Check if a bounding volume intersects the frustum.\r\n * var cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);\r\n * var intersect = cullingVolume.computeVisibility(boundingVolume);\r\n */\r\nOrthographicOffCenterFrustum.prototype.computeCullingVolume = function (\r\n position,\r\n direction,\r\n up\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(position)) {\r\n throw new DeveloperError(\"position is required.\");\r\n }\r\n if (!defined(direction)) {\r\n throw new DeveloperError(\"direction is required.\");\r\n }\r\n if (!defined(up)) {\r\n throw new DeveloperError(\"up is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var planes = this._cullingVolume.planes;\r\n var t = this.top;\r\n var b = this.bottom;\r\n var r = this.right;\r\n var l = this.left;\r\n var n = this.near;\r\n var f = this.far;\r\n\r\n var right = Cartesian3.cross(direction, up, getPlanesRight);\r\n Cartesian3.normalize(right, right);\r\n var nearCenter = getPlanesNearCenter;\r\n Cartesian3.multiplyByScalar(direction, n, nearCenter);\r\n Cartesian3.add(position, nearCenter, nearCenter);\r\n\r\n var point = getPlanesPoint;\r\n\r\n // Left plane\r\n Cartesian3.multiplyByScalar(right, l, point);\r\n Cartesian3.add(nearCenter, point, point);\r\n\r\n var plane = planes[0];\r\n if (!defined(plane)) {\r\n plane = planes[0] = new Cartesian4();\r\n }\r\n plane.x = right.x;\r\n plane.y = right.y;\r\n plane.z = right.z;\r\n plane.w = -Cartesian3.dot(right, point);\r\n\r\n // Right plane\r\n Cartesian3.multiplyByScalar(right, r, point);\r\n Cartesian3.add(nearCenter, point, point);\r\n\r\n plane = planes[1];\r\n if (!defined(plane)) {\r\n plane = planes[1] = new Cartesian4();\r\n }\r\n plane.x = -right.x;\r\n plane.y = -right.y;\r\n plane.z = -right.z;\r\n plane.w = -Cartesian3.dot(Cartesian3.negate(right, negateScratch), point);\r\n\r\n // Bottom plane\r\n Cartesian3.multiplyByScalar(up, b, point);\r\n Cartesian3.add(nearCenter, point, point);\r\n\r\n plane = planes[2];\r\n if (!defined(plane)) {\r\n plane = planes[2] = new Cartesian4();\r\n }\r\n plane.x = up.x;\r\n plane.y = up.y;\r\n plane.z = up.z;\r\n plane.w = -Cartesian3.dot(up, point);\r\n\r\n // Top plane\r\n Cartesian3.multiplyByScalar(up, t, point);\r\n Cartesian3.add(nearCenter, point, point);\r\n\r\n plane = planes[3];\r\n if (!defined(plane)) {\r\n plane = planes[3] = new Cartesian4();\r\n }\r\n plane.x = -up.x;\r\n plane.y = -up.y;\r\n plane.z = -up.z;\r\n plane.w = -Cartesian3.dot(Cartesian3.negate(up, negateScratch), point);\r\n\r\n // Near plane\r\n plane = planes[4];\r\n if (!defined(plane)) {\r\n plane = planes[4] = new Cartesian4();\r\n }\r\n plane.x = direction.x;\r\n plane.y = direction.y;\r\n plane.z = direction.z;\r\n plane.w = -Cartesian3.dot(direction, nearCenter);\r\n\r\n // Far plane\r\n Cartesian3.multiplyByScalar(direction, f, point);\r\n Cartesian3.add(position, point, point);\r\n\r\n plane = planes[5];\r\n if (!defined(plane)) {\r\n plane = planes[5] = new Cartesian4();\r\n }\r\n plane.x = -direction.x;\r\n plane.y = -direction.y;\r\n plane.z = -direction.z;\r\n plane.w = -Cartesian3.dot(Cartesian3.negate(direction, negateScratch), point);\r\n\r\n return this._cullingVolume;\r\n};\r\n\r\n/**\r\n * Returns the pixel's width and height in meters.\r\n *\r\n * @param {Number} drawingBufferWidth The width of the drawing buffer.\r\n * @param {Number} drawingBufferHeight The height of the drawing buffer.\r\n * @param {Number} distance The distance to the near plane in meters.\r\n * @param {Number} pixelRatio The scaling factor from pixel space to coordinate space.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new instance of {@link Cartesian2} with the pixel's width and height in the x and y properties, respectively.\r\n *\r\n * @exception {DeveloperError} drawingBufferWidth must be greater than zero.\r\n * @exception {DeveloperError} drawingBufferHeight must be greater than zero.\r\n * @exception {DeveloperError} pixelRatio must be greater than zero.\r\n *\r\n * @example\r\n * // Example 1\r\n * // Get the width and height of a pixel.\r\n * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 0.0, scene.pixelRatio, new Cesium.Cartesian2());\r\n */\r\nOrthographicOffCenterFrustum.prototype.getPixelDimensions = function (\r\n drawingBufferWidth,\r\n drawingBufferHeight,\r\n distance,\r\n pixelRatio,\r\n result\r\n) {\r\n update(this);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(drawingBufferWidth) || !defined(drawingBufferHeight)) {\r\n throw new DeveloperError(\r\n \"Both drawingBufferWidth and drawingBufferHeight are required.\"\r\n );\r\n }\r\n if (drawingBufferWidth <= 0) {\r\n throw new DeveloperError(\"drawingBufferWidth must be greater than zero.\");\r\n }\r\n if (drawingBufferHeight <= 0) {\r\n throw new DeveloperError(\"drawingBufferHeight must be greater than zero.\");\r\n }\r\n if (!defined(distance)) {\r\n throw new DeveloperError(\"distance is required.\");\r\n }\r\n if (!defined(pixelRatio)) {\r\n throw new DeveloperError(\"pixelRatio is required.\");\r\n }\r\n if (pixelRatio <= 0) {\r\n throw new DeveloperError(\"pixelRatio must be greater than zero.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"A result object is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var frustumWidth = this.right - this.left;\r\n var frustumHeight = this.top - this.bottom;\r\n var pixelWidth = (pixelRatio * frustumWidth) / drawingBufferWidth;\r\n var pixelHeight = (pixelRatio * frustumHeight) / drawingBufferHeight;\r\n\r\n result.x = pixelWidth;\r\n result.y = pixelHeight;\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns a duplicate of a OrthographicOffCenterFrustum instance.\r\n *\r\n * @param {OrthographicOffCenterFrustum} [result] The object onto which to store the result.\r\n * @returns {OrthographicOffCenterFrustum} The modified result parameter or a new OrthographicOffCenterFrustum instance if one was not provided.\r\n */\r\nOrthographicOffCenterFrustum.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n result = new OrthographicOffCenterFrustum();\r\n }\r\n\r\n result.left = this.left;\r\n result.right = this.right;\r\n result.top = this.top;\r\n result.bottom = this.bottom;\r\n result.near = this.near;\r\n result.far = this.far;\r\n\r\n // force update of clone to compute matrices\r\n result._left = undefined;\r\n result._right = undefined;\r\n result._top = undefined;\r\n result._bottom = undefined;\r\n result._near = undefined;\r\n result._far = undefined;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided OrthographicOffCenterFrustum componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {OrthographicOffCenterFrustum} [other] The right hand side OrthographicOffCenterFrustum.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nOrthographicOffCenterFrustum.prototype.equals = function (other) {\r\n return (\r\n defined(other) &&\r\n other instanceof OrthographicOffCenterFrustum &&\r\n this.right === other.right &&\r\n this.left === other.left &&\r\n this.top === other.top &&\r\n this.bottom === other.bottom &&\r\n this.near === other.near &&\r\n this.far === other.far\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided OrthographicOffCenterFrustum componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {OrthographicOffCenterFrustum} other The right hand side OrthographicOffCenterFrustum.\r\n * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if this and other are within the provided epsilon, false otherwise.\r\n */\r\nOrthographicOffCenterFrustum.prototype.equalsEpsilon = function (\r\n other,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return (\r\n other === this ||\r\n (defined(other) &&\r\n other instanceof OrthographicOffCenterFrustum &&\r\n CesiumMath.equalsEpsilon(\r\n this.right,\r\n other.right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.left,\r\n other.left,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.top,\r\n other.top,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.bottom,\r\n other.bottom,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.near,\r\n other.near,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.far,\r\n other.far,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ))\r\n );\r\n};\r\nexport default OrthographicOffCenterFrustum;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport OrthographicOffCenterFrustum from \"./OrthographicOffCenterFrustum.js\";\r\n\r\n/**\r\n * The viewing frustum is defined by 6 planes.\r\n * Each plane is represented by a {@link Cartesian4} object, where the x, y, and z components\r\n * define the unit vector normal to the plane, and the w component is the distance of the\r\n * plane from the origin/camera position.\r\n *\r\n * @alias OrthographicFrustum\r\n * @constructor\r\n *\r\n * @param {Object} [options] An object with the following properties:\r\n * @param {Number} [options.width] The width of the frustum in meters.\r\n * @param {Number} [options.aspectRatio] The aspect ratio of the frustum's width to it's height.\r\n * @param {Number} [options.near=1.0] The distance of the near plane.\r\n * @param {Number} [options.far=500000000.0] The distance of the far plane.\r\n *\r\n * @example\r\n * var maxRadii = ellipsoid.maximumRadius;\r\n *\r\n * var frustum = new Cesium.OrthographicFrustum();\r\n * frustum.near = 0.01 * maxRadii;\r\n * frustum.far = 50.0 * maxRadii;\r\n */\r\nfunction OrthographicFrustum(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._offCenterFrustum = new OrthographicOffCenterFrustum();\r\n\r\n /**\r\n * The horizontal width of the frustum in meters.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.width = options.width;\r\n this._width = undefined;\r\n\r\n /**\r\n * The aspect ratio of the frustum's width to it's height.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.aspectRatio = options.aspectRatio;\r\n this._aspectRatio = undefined;\r\n\r\n /**\r\n * The distance of the near plane.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.near = defaultValue(options.near, 1.0);\r\n this._near = this.near;\r\n\r\n /**\r\n * The distance of the far plane.\r\n * @type {Number}\r\n * @default 500000000.0;\r\n */\r\n this.far = defaultValue(options.far, 500000000.0);\r\n this._far = this.far;\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nOrthographicFrustum.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {OrthographicFrustum} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nOrthographicFrustum.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.width;\r\n array[startingIndex++] = value.aspectRatio;\r\n array[startingIndex++] = value.near;\r\n array[startingIndex] = value.far;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {OrthographicFrustum} [result] The object into which to store the result.\r\n * @returns {OrthographicFrustum} The modified result parameter or a new OrthographicFrustum instance if one was not provided.\r\n */\r\nOrthographicFrustum.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new OrthographicFrustum();\r\n }\r\n\r\n result.width = array[startingIndex++];\r\n result.aspectRatio = array[startingIndex++];\r\n result.near = array[startingIndex++];\r\n result.far = array[startingIndex];\r\n\r\n return result;\r\n};\r\n\r\nfunction update(frustum) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(frustum.width) ||\r\n !defined(frustum.aspectRatio) ||\r\n !defined(frustum.near) ||\r\n !defined(frustum.far)\r\n ) {\r\n throw new DeveloperError(\r\n \"width, aspectRatio, near, or far parameters are not set.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var f = frustum._offCenterFrustum;\r\n\r\n if (\r\n frustum.width !== frustum._width ||\r\n frustum.aspectRatio !== frustum._aspectRatio ||\r\n frustum.near !== frustum._near ||\r\n frustum.far !== frustum._far\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (frustum.aspectRatio < 0) {\r\n throw new DeveloperError(\"aspectRatio must be positive.\");\r\n }\r\n if (frustum.near < 0 || frustum.near > frustum.far) {\r\n throw new DeveloperError(\r\n \"near must be greater than zero and less than far.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n frustum._aspectRatio = frustum.aspectRatio;\r\n frustum._width = frustum.width;\r\n frustum._near = frustum.near;\r\n frustum._far = frustum.far;\r\n\r\n var ratio = 1.0 / frustum.aspectRatio;\r\n f.right = frustum.width * 0.5;\r\n f.left = -f.right;\r\n f.top = ratio * f.right;\r\n f.bottom = -f.top;\r\n f.near = frustum.near;\r\n f.far = frustum.far;\r\n }\r\n}\r\n\r\nObject.defineProperties(OrthographicFrustum.prototype, {\r\n /**\r\n * Gets the orthographic projection matrix computed from the view frustum.\r\n * @memberof OrthographicFrustum.prototype\r\n * @type {Matrix4}\r\n * @readonly\r\n */\r\n projectionMatrix: {\r\n get: function () {\r\n update(this);\r\n return this._offCenterFrustum.projectionMatrix;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates a culling volume for this frustum.\r\n *\r\n * @param {Cartesian3} position The eye position.\r\n * @param {Cartesian3} direction The view direction.\r\n * @param {Cartesian3} up The up direction.\r\n * @returns {CullingVolume} A culling volume at the given position and orientation.\r\n *\r\n * @example\r\n * // Check if a bounding volume intersects the frustum.\r\n * var cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);\r\n * var intersect = cullingVolume.computeVisibility(boundingVolume);\r\n */\r\nOrthographicFrustum.prototype.computeCullingVolume = function (\r\n position,\r\n direction,\r\n up\r\n) {\r\n update(this);\r\n return this._offCenterFrustum.computeCullingVolume(position, direction, up);\r\n};\r\n\r\n/**\r\n * Returns the pixel's width and height in meters.\r\n *\r\n * @param {Number} drawingBufferWidth The width of the drawing buffer.\r\n * @param {Number} drawingBufferHeight The height of the drawing buffer.\r\n * @param {Number} distance The distance to the near plane in meters.\r\n * @param {Number} pixelRatio The scaling factor from pixel space to coordinate space.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new instance of {@link Cartesian2} with the pixel's width and height in the x and y properties, respectively.\r\n *\r\n * @exception {DeveloperError} drawingBufferWidth must be greater than zero.\r\n * @exception {DeveloperError} drawingBufferHeight must be greater than zero.\r\n * @exception {DeveloperError} pixelRatio must be greater than zero.\r\n *\r\n * @example\r\n * // Example 1\r\n * // Get the width and height of a pixel.\r\n * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 0.0, scene.pixelRatio, new Cesium.Cartesian2());\r\n */\r\nOrthographicFrustum.prototype.getPixelDimensions = function (\r\n drawingBufferWidth,\r\n drawingBufferHeight,\r\n distance,\r\n pixelRatio,\r\n result\r\n) {\r\n update(this);\r\n return this._offCenterFrustum.getPixelDimensions(\r\n drawingBufferWidth,\r\n drawingBufferHeight,\r\n distance,\r\n pixelRatio,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Returns a duplicate of a OrthographicFrustum instance.\r\n *\r\n * @param {OrthographicFrustum} [result] The object onto which to store the result.\r\n * @returns {OrthographicFrustum} The modified result parameter or a new OrthographicFrustum instance if one was not provided.\r\n */\r\nOrthographicFrustum.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n result = new OrthographicFrustum();\r\n }\r\n\r\n result.aspectRatio = this.aspectRatio;\r\n result.width = this.width;\r\n result.near = this.near;\r\n result.far = this.far;\r\n\r\n // force update of clone to compute matrices\r\n result._aspectRatio = undefined;\r\n result._width = undefined;\r\n result._near = undefined;\r\n result._far = undefined;\r\n\r\n this._offCenterFrustum.clone(result._offCenterFrustum);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided OrthographicFrustum componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {OrthographicFrustum} [other] The right hand side OrthographicFrustum.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nOrthographicFrustum.prototype.equals = function (other) {\r\n if (!defined(other) || !(other instanceof OrthographicFrustum)) {\r\n return false;\r\n }\r\n\r\n update(this);\r\n update(other);\r\n\r\n return (\r\n this.width === other.width &&\r\n this.aspectRatio === other.aspectRatio &&\r\n this._offCenterFrustum.equals(other._offCenterFrustum)\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided OrthographicFrustum componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {OrthographicFrustum} other The right hand side OrthographicFrustum.\r\n * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if this and other are within the provided epsilon, false otherwise.\r\n */\r\nOrthographicFrustum.prototype.equalsEpsilon = function (\r\n other,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n if (!defined(other) || !(other instanceof OrthographicFrustum)) {\r\n return false;\r\n }\r\n\r\n update(this);\r\n update(other);\r\n\r\n return (\r\n CesiumMath.equalsEpsilon(\r\n this.width,\r\n other.width,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.aspectRatio,\r\n other.aspectRatio,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n this._offCenterFrustum.equalsEpsilon(\r\n other._offCenterFrustum,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n )\r\n );\r\n};\r\nexport default OrthographicFrustum;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport CullingVolume from \"./CullingVolume.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\n\r\n/**\r\n * The viewing frustum is defined by 6 planes.\r\n * Each plane is represented by a {@link Cartesian4} object, where the x, y, and z components\r\n * define the unit vector normal to the plane, and the w component is the distance of the\r\n * plane from the origin/camera position.\r\n *\r\n * @alias PerspectiveOffCenterFrustum\r\n * @constructor\r\n *\r\n * @param {Object} [options] An object with the following properties:\r\n * @param {Number} [options.left] The left clipping plane distance.\r\n * @param {Number} [options.right] The right clipping plane distance.\r\n * @param {Number} [options.top] The top clipping plane distance.\r\n * @param {Number} [options.bottom] The bottom clipping plane distance.\r\n * @param {Number} [options.near=1.0] The near clipping plane distance.\r\n * @param {Number} [options.far=500000000.0] The far clipping plane distance.\r\n *\r\n * @example\r\n * var frustum = new Cesium.PerspectiveOffCenterFrustum({\r\n * left : -1.0,\r\n * right : 1.0,\r\n * top : 1.0,\r\n * bottom : -1.0,\r\n * near : 1.0,\r\n * far : 100.0\r\n * });\r\n *\r\n * @see PerspectiveFrustum\r\n */\r\nfunction PerspectiveOffCenterFrustum(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * Defines the left clipping plane.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.left = options.left;\r\n this._left = undefined;\r\n\r\n /**\r\n * Defines the right clipping plane.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.right = options.right;\r\n this._right = undefined;\r\n\r\n /**\r\n * Defines the top clipping plane.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.top = options.top;\r\n this._top = undefined;\r\n\r\n /**\r\n * Defines the bottom clipping plane.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.bottom = options.bottom;\r\n this._bottom = undefined;\r\n\r\n /**\r\n * The distance of the near plane.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.near = defaultValue(options.near, 1.0);\r\n this._near = this.near;\r\n\r\n /**\r\n * The distance of the far plane.\r\n * @type {Number}\r\n * @default 500000000.0\r\n */\r\n this.far = defaultValue(options.far, 500000000.0);\r\n this._far = this.far;\r\n\r\n this._cullingVolume = new CullingVolume();\r\n this._perspectiveMatrix = new Matrix4();\r\n this._infinitePerspective = new Matrix4();\r\n}\r\n\r\nfunction update(frustum) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(frustum.right) ||\r\n !defined(frustum.left) ||\r\n !defined(frustum.top) ||\r\n !defined(frustum.bottom) ||\r\n !defined(frustum.near) ||\r\n !defined(frustum.far)\r\n ) {\r\n throw new DeveloperError(\r\n \"right, left, top, bottom, near, or far parameters are not set.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var t = frustum.top;\r\n var b = frustum.bottom;\r\n var r = frustum.right;\r\n var l = frustum.left;\r\n var n = frustum.near;\r\n var f = frustum.far;\r\n\r\n if (\r\n t !== frustum._top ||\r\n b !== frustum._bottom ||\r\n l !== frustum._left ||\r\n r !== frustum._right ||\r\n n !== frustum._near ||\r\n f !== frustum._far\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (frustum.near <= 0 || frustum.near > frustum.far) {\r\n throw new DeveloperError(\r\n \"near must be greater than zero and less than far.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n frustum._left = l;\r\n frustum._right = r;\r\n frustum._top = t;\r\n frustum._bottom = b;\r\n frustum._near = n;\r\n frustum._far = f;\r\n frustum._perspectiveMatrix = Matrix4.computePerspectiveOffCenter(\r\n l,\r\n r,\r\n b,\r\n t,\r\n n,\r\n f,\r\n frustum._perspectiveMatrix\r\n );\r\n frustum._infinitePerspective = Matrix4.computeInfinitePerspectiveOffCenter(\r\n l,\r\n r,\r\n b,\r\n t,\r\n n,\r\n frustum._infinitePerspective\r\n );\r\n }\r\n}\r\n\r\nObject.defineProperties(PerspectiveOffCenterFrustum.prototype, {\r\n /**\r\n * Gets the perspective projection matrix computed from the view frustum.\r\n * @memberof PerspectiveOffCenterFrustum.prototype\r\n * @type {Matrix4}\r\n * @readonly\r\n *\r\n * @see PerspectiveOffCenterFrustum#infiniteProjectionMatrix\r\n */\r\n projectionMatrix: {\r\n get: function () {\r\n update(this);\r\n return this._perspectiveMatrix;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the perspective projection matrix computed from the view frustum with an infinite far plane.\r\n * @memberof PerspectiveOffCenterFrustum.prototype\r\n * @type {Matrix4}\r\n * @readonly\r\n *\r\n * @see PerspectiveOffCenterFrustum#projectionMatrix\r\n */\r\n infiniteProjectionMatrix: {\r\n get: function () {\r\n update(this);\r\n return this._infinitePerspective;\r\n },\r\n },\r\n});\r\n\r\nvar getPlanesRight = new Cartesian3();\r\nvar getPlanesNearCenter = new Cartesian3();\r\nvar getPlanesFarCenter = new Cartesian3();\r\nvar getPlanesNormal = new Cartesian3();\r\n/**\r\n * Creates a culling volume for this frustum.\r\n *\r\n * @param {Cartesian3} position The eye position.\r\n * @param {Cartesian3} direction The view direction.\r\n * @param {Cartesian3} up The up direction.\r\n * @returns {CullingVolume} A culling volume at the given position and orientation.\r\n *\r\n * @example\r\n * // Check if a bounding volume intersects the frustum.\r\n * var cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);\r\n * var intersect = cullingVolume.computeVisibility(boundingVolume);\r\n */\r\nPerspectiveOffCenterFrustum.prototype.computeCullingVolume = function (\r\n position,\r\n direction,\r\n up\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(position)) {\r\n throw new DeveloperError(\"position is required.\");\r\n }\r\n\r\n if (!defined(direction)) {\r\n throw new DeveloperError(\"direction is required.\");\r\n }\r\n\r\n if (!defined(up)) {\r\n throw new DeveloperError(\"up is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var planes = this._cullingVolume.planes;\r\n\r\n var t = this.top;\r\n var b = this.bottom;\r\n var r = this.right;\r\n var l = this.left;\r\n var n = this.near;\r\n var f = this.far;\r\n\r\n var right = Cartesian3.cross(direction, up, getPlanesRight);\r\n\r\n var nearCenter = getPlanesNearCenter;\r\n Cartesian3.multiplyByScalar(direction, n, nearCenter);\r\n Cartesian3.add(position, nearCenter, nearCenter);\r\n\r\n var farCenter = getPlanesFarCenter;\r\n Cartesian3.multiplyByScalar(direction, f, farCenter);\r\n Cartesian3.add(position, farCenter, farCenter);\r\n\r\n var normal = getPlanesNormal;\r\n\r\n //Left plane computation\r\n Cartesian3.multiplyByScalar(right, l, normal);\r\n Cartesian3.add(nearCenter, normal, normal);\r\n Cartesian3.subtract(normal, position, normal);\r\n Cartesian3.normalize(normal, normal);\r\n Cartesian3.cross(normal, up, normal);\r\n Cartesian3.normalize(normal, normal);\r\n\r\n var plane = planes[0];\r\n if (!defined(plane)) {\r\n plane = planes[0] = new Cartesian4();\r\n }\r\n plane.x = normal.x;\r\n plane.y = normal.y;\r\n plane.z = normal.z;\r\n plane.w = -Cartesian3.dot(normal, position);\r\n\r\n //Right plane computation\r\n Cartesian3.multiplyByScalar(right, r, normal);\r\n Cartesian3.add(nearCenter, normal, normal);\r\n Cartesian3.subtract(normal, position, normal);\r\n Cartesian3.cross(up, normal, normal);\r\n Cartesian3.normalize(normal, normal);\r\n\r\n plane = planes[1];\r\n if (!defined(plane)) {\r\n plane = planes[1] = new Cartesian4();\r\n }\r\n plane.x = normal.x;\r\n plane.y = normal.y;\r\n plane.z = normal.z;\r\n plane.w = -Cartesian3.dot(normal, position);\r\n\r\n //Bottom plane computation\r\n Cartesian3.multiplyByScalar(up, b, normal);\r\n Cartesian3.add(nearCenter, normal, normal);\r\n Cartesian3.subtract(normal, position, normal);\r\n Cartesian3.cross(right, normal, normal);\r\n Cartesian3.normalize(normal, normal);\r\n\r\n plane = planes[2];\r\n if (!defined(plane)) {\r\n plane = planes[2] = new Cartesian4();\r\n }\r\n plane.x = normal.x;\r\n plane.y = normal.y;\r\n plane.z = normal.z;\r\n plane.w = -Cartesian3.dot(normal, position);\r\n\r\n //Top plane computation\r\n Cartesian3.multiplyByScalar(up, t, normal);\r\n Cartesian3.add(nearCenter, normal, normal);\r\n Cartesian3.subtract(normal, position, normal);\r\n Cartesian3.cross(normal, right, normal);\r\n Cartesian3.normalize(normal, normal);\r\n\r\n plane = planes[3];\r\n if (!defined(plane)) {\r\n plane = planes[3] = new Cartesian4();\r\n }\r\n plane.x = normal.x;\r\n plane.y = normal.y;\r\n plane.z = normal.z;\r\n plane.w = -Cartesian3.dot(normal, position);\r\n\r\n //Near plane computation\r\n plane = planes[4];\r\n if (!defined(plane)) {\r\n plane = planes[4] = new Cartesian4();\r\n }\r\n plane.x = direction.x;\r\n plane.y = direction.y;\r\n plane.z = direction.z;\r\n plane.w = -Cartesian3.dot(direction, nearCenter);\r\n\r\n //Far plane computation\r\n Cartesian3.negate(direction, normal);\r\n\r\n plane = planes[5];\r\n if (!defined(plane)) {\r\n plane = planes[5] = new Cartesian4();\r\n }\r\n plane.x = normal.x;\r\n plane.y = normal.y;\r\n plane.z = normal.z;\r\n plane.w = -Cartesian3.dot(normal, farCenter);\r\n\r\n return this._cullingVolume;\r\n};\r\n\r\n/**\r\n * Returns the pixel's width and height in meters.\r\n *\r\n * @param {Number} drawingBufferWidth The width of the drawing buffer.\r\n * @param {Number} drawingBufferHeight The height of the drawing buffer.\r\n * @param {Number} distance The distance to the near plane in meters.\r\n * @param {Number} pixelRatio The scaling factor from pixel space to coordinate space.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new instance of {@link Cartesian2} with the pixel's width and height in the x and y properties, respectively.\r\n *\r\n * @exception {DeveloperError} drawingBufferWidth must be greater than zero.\r\n * @exception {DeveloperError} drawingBufferHeight must be greater than zero.\r\n * @exception {DeveloperError} pixelRatio must be greater than zero.\r\n *\r\n * @example\r\n * // Example 1\r\n * // Get the width and height of a pixel.\r\n * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 1.0, scene.pixelRatio, new Cesium.Cartesian2());\r\n *\r\n * @example\r\n * // Example 2\r\n * // Get the width and height of a pixel if the near plane was set to 'distance'.\r\n * // For example, get the size of a pixel of an image on a billboard.\r\n * var position = camera.position;\r\n * var direction = camera.direction;\r\n * var toCenter = Cesium.Cartesian3.subtract(primitive.boundingVolume.center, position, new Cesium.Cartesian3()); // vector from camera to a primitive\r\n * var toCenterProj = Cesium.Cartesian3.multiplyByScalar(direction, Cesium.Cartesian3.dot(direction, toCenter), new Cesium.Cartesian3()); // project vector onto camera direction vector\r\n * var distance = Cesium.Cartesian3.magnitude(toCenterProj);\r\n * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, distance, scene.pixelRatio, new Cesium.Cartesian2());\r\n */\r\nPerspectiveOffCenterFrustum.prototype.getPixelDimensions = function (\r\n drawingBufferWidth,\r\n drawingBufferHeight,\r\n distance,\r\n pixelRatio,\r\n result\r\n) {\r\n update(this);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(drawingBufferWidth) || !defined(drawingBufferHeight)) {\r\n throw new DeveloperError(\r\n \"Both drawingBufferWidth and drawingBufferHeight are required.\"\r\n );\r\n }\r\n if (drawingBufferWidth <= 0) {\r\n throw new DeveloperError(\"drawingBufferWidth must be greater than zero.\");\r\n }\r\n if (drawingBufferHeight <= 0) {\r\n throw new DeveloperError(\"drawingBufferHeight must be greater than zero.\");\r\n }\r\n if (!defined(distance)) {\r\n throw new DeveloperError(\"distance is required.\");\r\n }\r\n if (!defined(pixelRatio)) {\r\n throw new DeveloperError(\"pixelRatio is required\");\r\n }\r\n if (pixelRatio <= 0) {\r\n throw new DeveloperError(\"pixelRatio must be greater than zero.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"A result object is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var inverseNear = 1.0 / this.near;\r\n var tanTheta = this.top * inverseNear;\r\n var pixelHeight =\r\n (2.0 * pixelRatio * distance * tanTheta) / drawingBufferHeight;\r\n tanTheta = this.right * inverseNear;\r\n var pixelWidth =\r\n (2.0 * pixelRatio * distance * tanTheta) / drawingBufferWidth;\r\n\r\n result.x = pixelWidth;\r\n result.y = pixelHeight;\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns a duplicate of a PerspectiveOffCenterFrustum instance.\r\n *\r\n * @param {PerspectiveOffCenterFrustum} [result] The object onto which to store the result.\r\n * @returns {PerspectiveOffCenterFrustum} The modified result parameter or a new PerspectiveFrustum instance if one was not provided.\r\n */\r\nPerspectiveOffCenterFrustum.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n result = new PerspectiveOffCenterFrustum();\r\n }\r\n\r\n result.right = this.right;\r\n result.left = this.left;\r\n result.top = this.top;\r\n result.bottom = this.bottom;\r\n result.near = this.near;\r\n result.far = this.far;\r\n\r\n // force update of clone to compute matrices\r\n result._left = undefined;\r\n result._right = undefined;\r\n result._top = undefined;\r\n result._bottom = undefined;\r\n result._near = undefined;\r\n result._far = undefined;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided PerspectiveOffCenterFrustum componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {PerspectiveOffCenterFrustum} [other] The right hand side PerspectiveOffCenterFrustum.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nPerspectiveOffCenterFrustum.prototype.equals = function (other) {\r\n return (\r\n defined(other) &&\r\n other instanceof PerspectiveOffCenterFrustum &&\r\n this.right === other.right &&\r\n this.left === other.left &&\r\n this.top === other.top &&\r\n this.bottom === other.bottom &&\r\n this.near === other.near &&\r\n this.far === other.far\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided PerspectiveOffCenterFrustum componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {PerspectiveOffCenterFrustum} other The right hand side PerspectiveOffCenterFrustum.\r\n * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if this and other are within the provided epsilon, false otherwise.\r\n */\r\nPerspectiveOffCenterFrustum.prototype.equalsEpsilon = function (\r\n other,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n return (\r\n other === this ||\r\n (defined(other) &&\r\n other instanceof PerspectiveOffCenterFrustum &&\r\n CesiumMath.equalsEpsilon(\r\n this.right,\r\n other.right,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.left,\r\n other.left,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.top,\r\n other.top,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.bottom,\r\n other.bottom,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.near,\r\n other.near,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.far,\r\n other.far,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ))\r\n );\r\n};\r\nexport default PerspectiveOffCenterFrustum;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PerspectiveOffCenterFrustum from \"./PerspectiveOffCenterFrustum.js\";\r\n\r\n/**\r\n * The viewing frustum is defined by 6 planes.\r\n * Each plane is represented by a {@link Cartesian4} object, where the x, y, and z components\r\n * define the unit vector normal to the plane, and the w component is the distance of the\r\n * plane from the origin/camera position.\r\n *\r\n * @alias PerspectiveFrustum\r\n * @constructor\r\n *\r\n * @param {Object} [options] An object with the following properties:\r\n * @param {Number} [options.fov] The angle of the field of view (FOV), in radians.\r\n * @param {Number} [options.aspectRatio] The aspect ratio of the frustum's width to it's height.\r\n * @param {Number} [options.near=1.0] The distance of the near plane.\r\n * @param {Number} [options.far=500000000.0] The distance of the far plane.\r\n * @param {Number} [options.xOffset=0.0] The offset in the x direction.\r\n * @param {Number} [options.yOffset=0.0] The offset in the y direction.\r\n *\r\n * @example\r\n * var frustum = new Cesium.PerspectiveFrustum({\r\n * fov : Cesium.Math.PI_OVER_THREE,\r\n * aspectRatio : canvas.clientWidth / canvas.clientHeight\r\n * near : 1.0,\r\n * far : 1000.0\r\n * });\r\n *\r\n * @see PerspectiveOffCenterFrustum\r\n */\r\nfunction PerspectiveFrustum(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._offCenterFrustum = new PerspectiveOffCenterFrustum();\r\n\r\n /**\r\n * The angle of the field of view (FOV), in radians. This angle will be used\r\n * as the horizontal FOV if the width is greater than the height, otherwise\r\n * it will be the vertical FOV.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.fov = options.fov;\r\n this._fov = undefined;\r\n this._fovy = undefined;\r\n\r\n this._sseDenominator = undefined;\r\n\r\n /**\r\n * The aspect ratio of the frustum's width to it's height.\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n this.aspectRatio = options.aspectRatio;\r\n this._aspectRatio = undefined;\r\n\r\n /**\r\n * The distance of the near plane.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.near = defaultValue(options.near, 1.0);\r\n this._near = this.near;\r\n\r\n /**\r\n * The distance of the far plane.\r\n * @type {Number}\r\n * @default 500000000.0\r\n */\r\n this.far = defaultValue(options.far, 500000000.0);\r\n this._far = this.far;\r\n\r\n /**\r\n * Offsets the frustum in the x direction.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.xOffset = defaultValue(options.xOffset, 0.0);\r\n this._xOffset = this.xOffset;\r\n\r\n /**\r\n * Offsets the frustum in the y direction.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.yOffset = defaultValue(options.yOffset, 0.0);\r\n this._yOffset = this.yOffset;\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nPerspectiveFrustum.packedLength = 6;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PerspectiveFrustum} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nPerspectiveFrustum.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.fov;\r\n array[startingIndex++] = value.aspectRatio;\r\n array[startingIndex++] = value.near;\r\n array[startingIndex++] = value.far;\r\n array[startingIndex++] = value.xOffset;\r\n array[startingIndex] = value.yOffset;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PerspectiveFrustum} [result] The object into which to store the result.\r\n * @returns {PerspectiveFrustum} The modified result parameter or a new PerspectiveFrustum instance if one was not provided.\r\n */\r\nPerspectiveFrustum.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new PerspectiveFrustum();\r\n }\r\n\r\n result.fov = array[startingIndex++];\r\n result.aspectRatio = array[startingIndex++];\r\n result.near = array[startingIndex++];\r\n result.far = array[startingIndex++];\r\n result.xOffset = array[startingIndex++];\r\n result.yOffset = array[startingIndex];\r\n\r\n return result;\r\n};\r\n\r\nfunction update(frustum) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(frustum.fov) ||\r\n !defined(frustum.aspectRatio) ||\r\n !defined(frustum.near) ||\r\n !defined(frustum.far)\r\n ) {\r\n throw new DeveloperError(\r\n \"fov, aspectRatio, near, or far parameters are not set.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var f = frustum._offCenterFrustum;\r\n\r\n if (\r\n frustum.fov !== frustum._fov ||\r\n frustum.aspectRatio !== frustum._aspectRatio ||\r\n frustum.near !== frustum._near ||\r\n frustum.far !== frustum._far ||\r\n frustum.xOffset !== frustum._xOffset ||\r\n frustum.yOffset !== frustum._yOffset\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (frustum.fov < 0 || frustum.fov >= Math.PI) {\r\n throw new DeveloperError(\"fov must be in the range [0, PI).\");\r\n }\r\n\r\n if (frustum.aspectRatio < 0) {\r\n throw new DeveloperError(\"aspectRatio must be positive.\");\r\n }\r\n\r\n if (frustum.near < 0 || frustum.near > frustum.far) {\r\n throw new DeveloperError(\r\n \"near must be greater than zero and less than far.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n frustum._aspectRatio = frustum.aspectRatio;\r\n frustum._fov = frustum.fov;\r\n frustum._fovy =\r\n frustum.aspectRatio <= 1\r\n ? frustum.fov\r\n : Math.atan(Math.tan(frustum.fov * 0.5) / frustum.aspectRatio) * 2.0;\r\n frustum._near = frustum.near;\r\n frustum._far = frustum.far;\r\n frustum._sseDenominator = 2.0 * Math.tan(0.5 * frustum._fovy);\r\n frustum._xOffset = frustum.xOffset;\r\n frustum._yOffset = frustum.yOffset;\r\n\r\n f.top = frustum.near * Math.tan(0.5 * frustum._fovy);\r\n f.bottom = -f.top;\r\n f.right = frustum.aspectRatio * f.top;\r\n f.left = -f.right;\r\n f.near = frustum.near;\r\n f.far = frustum.far;\r\n\r\n f.right += frustum.xOffset;\r\n f.left += frustum.xOffset;\r\n f.top += frustum.yOffset;\r\n f.bottom += frustum.yOffset;\r\n }\r\n}\r\n\r\nObject.defineProperties(PerspectiveFrustum.prototype, {\r\n /**\r\n * Gets the perspective projection matrix computed from the view frustum.\r\n * @memberof PerspectiveFrustum.prototype\r\n * @type {Matrix4}\r\n * @readonly\r\n *\r\n * @see PerspectiveFrustum#infiniteProjectionMatrix\r\n */\r\n projectionMatrix: {\r\n get: function () {\r\n update(this);\r\n return this._offCenterFrustum.projectionMatrix;\r\n },\r\n },\r\n\r\n /**\r\n * The perspective projection matrix computed from the view frustum with an infinite far plane.\r\n * @memberof PerspectiveFrustum.prototype\r\n * @type {Matrix4}\r\n * @readonly\r\n *\r\n * @see PerspectiveFrustum#projectionMatrix\r\n */\r\n infiniteProjectionMatrix: {\r\n get: function () {\r\n update(this);\r\n return this._offCenterFrustum.infiniteProjectionMatrix;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the angle of the vertical field of view, in radians.\r\n * @memberof PerspectiveFrustum.prototype\r\n * @type {Number}\r\n * @readonly\r\n * @default undefined\r\n */\r\n fovy: {\r\n get: function () {\r\n update(this);\r\n return this._fovy;\r\n },\r\n },\r\n\r\n /**\r\n * @readonly\r\n * @private\r\n */\r\n sseDenominator: {\r\n get: function () {\r\n update(this);\r\n return this._sseDenominator;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates a culling volume for this frustum.\r\n *\r\n * @param {Cartesian3} position The eye position.\r\n * @param {Cartesian3} direction The view direction.\r\n * @param {Cartesian3} up The up direction.\r\n * @returns {CullingVolume} A culling volume at the given position and orientation.\r\n *\r\n * @example\r\n * // Check if a bounding volume intersects the frustum.\r\n * var cullingVolume = frustum.computeCullingVolume(cameraPosition, cameraDirection, cameraUp);\r\n * var intersect = cullingVolume.computeVisibility(boundingVolume);\r\n */\r\nPerspectiveFrustum.prototype.computeCullingVolume = function (\r\n position,\r\n direction,\r\n up\r\n) {\r\n update(this);\r\n return this._offCenterFrustum.computeCullingVolume(position, direction, up);\r\n};\r\n\r\n/**\r\n * Returns the pixel's width and height in meters.\r\n *\r\n * @param {Number} drawingBufferWidth The width of the drawing buffer.\r\n * @param {Number} drawingBufferHeight The height of the drawing buffer.\r\n * @param {Number} distance The distance to the near plane in meters.\r\n * @param {Number} pixelRatio The scaling factor from pixel space to coordinate space.\r\n * @param {Cartesian2} result The object onto which to store the result.\r\n * @returns {Cartesian2} The modified result parameter or a new instance of {@link Cartesian2} with the pixel's width and height in the x and y properties, respectively.\r\n *\r\n * @exception {DeveloperError} drawingBufferWidth must be greater than zero.\r\n * @exception {DeveloperError} drawingBufferHeight must be greater than zero.\r\n * @exception {DeveloperError} pixelRatio must be greater than zero.\r\n *\r\n * @example\r\n * // Example 1\r\n * // Get the width and height of a pixel.\r\n * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, 1.0, scene.pixelRatio, new Cesium.Cartesian2());\r\n *\r\n * @example\r\n * // Example 2\r\n * // Get the width and height of a pixel if the near plane was set to 'distance'.\r\n * // For example, get the size of a pixel of an image on a billboard.\r\n * var position = camera.position;\r\n * var direction = camera.direction;\r\n * var toCenter = Cesium.Cartesian3.subtract(primitive.boundingVolume.center, position, new Cesium.Cartesian3()); // vector from camera to a primitive\r\n * var toCenterProj = Cesium.Cartesian3.multiplyByScalar(direction, Cesium.Cartesian3.dot(direction, toCenter), new Cesium.Cartesian3()); // project vector onto camera direction vector\r\n * var distance = Cesium.Cartesian3.magnitude(toCenterProj);\r\n * var pixelSize = camera.frustum.getPixelDimensions(scene.drawingBufferWidth, scene.drawingBufferHeight, distance, scene.pixelRatio, new Cesium.Cartesian2());\r\n */\r\nPerspectiveFrustum.prototype.getPixelDimensions = function (\r\n drawingBufferWidth,\r\n drawingBufferHeight,\r\n distance,\r\n pixelRatio,\r\n result\r\n) {\r\n update(this);\r\n return this._offCenterFrustum.getPixelDimensions(\r\n drawingBufferWidth,\r\n drawingBufferHeight,\r\n distance,\r\n pixelRatio,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Returns a duplicate of a PerspectiveFrustum instance.\r\n *\r\n * @param {PerspectiveFrustum} [result] The object onto which to store the result.\r\n * @returns {PerspectiveFrustum} The modified result parameter or a new PerspectiveFrustum instance if one was not provided.\r\n */\r\nPerspectiveFrustum.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n result = new PerspectiveFrustum();\r\n }\r\n\r\n result.aspectRatio = this.aspectRatio;\r\n result.fov = this.fov;\r\n result.near = this.near;\r\n result.far = this.far;\r\n\r\n // force update of clone to compute matrices\r\n result._aspectRatio = undefined;\r\n result._fov = undefined;\r\n result._near = undefined;\r\n result._far = undefined;\r\n\r\n this._offCenterFrustum.clone(result._offCenterFrustum);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided PerspectiveFrustum componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {PerspectiveFrustum} [other] The right hand side PerspectiveFrustum.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nPerspectiveFrustum.prototype.equals = function (other) {\r\n if (!defined(other) || !(other instanceof PerspectiveFrustum)) {\r\n return false;\r\n }\r\n\r\n update(this);\r\n update(other);\r\n\r\n return (\r\n this.fov === other.fov &&\r\n this.aspectRatio === other.aspectRatio &&\r\n this._offCenterFrustum.equals(other._offCenterFrustum)\r\n );\r\n};\r\n\r\n/**\r\n * Compares the provided PerspectiveFrustum componentwise and returns\r\n * true if they pass an absolute or relative tolerance test,\r\n * false otherwise.\r\n *\r\n * @param {PerspectiveFrustum} other The right hand side PerspectiveFrustum.\r\n * @param {Number} relativeEpsilon The relative epsilon tolerance to use for equality testing.\r\n * @param {Number} [absoluteEpsilon=relativeEpsilon] The absolute epsilon tolerance to use for equality testing.\r\n * @returns {Boolean} true if this and other are within the provided epsilon, false otherwise.\r\n */\r\nPerspectiveFrustum.prototype.equalsEpsilon = function (\r\n other,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n) {\r\n if (!defined(other) || !(other instanceof PerspectiveFrustum)) {\r\n return false;\r\n }\r\n\r\n update(this);\r\n update(other);\r\n\r\n return (\r\n CesiumMath.equalsEpsilon(\r\n this.fov,\r\n other.fov,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n CesiumMath.equalsEpsilon(\r\n this.aspectRatio,\r\n other.aspectRatio,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n ) &&\r\n this._offCenterFrustum.equalsEpsilon(\r\n other._offCenterFrustum,\r\n relativeEpsilon,\r\n absoluteEpsilon\r\n )\r\n );\r\n};\r\nexport default PerspectiveFrustum;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartesian4 from \"./Cartesian4.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Matrix4 from \"./Matrix4.js\";\r\nimport OrthographicFrustum from \"./OrthographicFrustum.js\";\r\nimport PerspectiveFrustum from \"./PerspectiveFrustum.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar PERSPECTIVE = 0;\r\nvar ORTHOGRAPHIC = 1;\r\n\r\n/**\r\n * Describes a frustum at the given the origin and orientation.\r\n *\r\n * @alias FrustumGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {PerspectiveFrustum|OrthographicFrustum} options.frustum The frustum.\r\n * @param {Cartesian3} options.origin The origin of the frustum.\r\n * @param {Quaternion} options.orientation The orientation of the frustum.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n */\r\nfunction FrustumGeometry(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.object(\"options.frustum\", options.frustum);\r\n Check.typeOf.object(\"options.origin\", options.origin);\r\n Check.typeOf.object(\"options.orientation\", options.orientation);\r\n //>>includeEnd('debug');\r\n\r\n var frustum = options.frustum;\r\n var orientation = options.orientation;\r\n var origin = options.origin;\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n\r\n // This is private because it is used by DebugCameraPrimitive to draw a multi-frustum by\r\n // creating multiple FrustumGeometrys. This way the near plane of one frustum doesn't overlap\r\n // the far plane of another.\r\n var drawNearPlane = defaultValue(options._drawNearPlane, true);\r\n\r\n var frustumType;\r\n var frustumPackedLength;\r\n if (frustum instanceof PerspectiveFrustum) {\r\n frustumType = PERSPECTIVE;\r\n frustumPackedLength = PerspectiveFrustum.packedLength;\r\n } else if (frustum instanceof OrthographicFrustum) {\r\n frustumType = ORTHOGRAPHIC;\r\n frustumPackedLength = OrthographicFrustum.packedLength;\r\n }\r\n\r\n this._frustumType = frustumType;\r\n this._frustum = frustum.clone();\r\n this._origin = Cartesian3.clone(origin);\r\n this._orientation = Quaternion.clone(orientation);\r\n this._drawNearPlane = drawNearPlane;\r\n this._vertexFormat = vertexFormat;\r\n this._workerName = \"createFrustumGeometry\";\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n 2 +\r\n frustumPackedLength +\r\n Cartesian3.packedLength +\r\n Quaternion.packedLength +\r\n VertexFormat.packedLength;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {FrustumGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nFrustumGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var frustumType = value._frustumType;\r\n var frustum = value._frustum;\r\n\r\n array[startingIndex++] = frustumType;\r\n\r\n if (frustumType === PERSPECTIVE) {\r\n PerspectiveFrustum.pack(frustum, array, startingIndex);\r\n startingIndex += PerspectiveFrustum.packedLength;\r\n } else {\r\n OrthographicFrustum.pack(frustum, array, startingIndex);\r\n startingIndex += OrthographicFrustum.packedLength;\r\n }\r\n\r\n Cartesian3.pack(value._origin, array, startingIndex);\r\n startingIndex += Cartesian3.packedLength;\r\n Quaternion.pack(value._orientation, array, startingIndex);\r\n startingIndex += Quaternion.packedLength;\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n array[startingIndex] = value._drawNearPlane ? 1.0 : 0.0;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchPackPerspective = new PerspectiveFrustum();\r\nvar scratchPackOrthographic = new OrthographicFrustum();\r\nvar scratchPackQuaternion = new Quaternion();\r\nvar scratchPackorigin = new Cartesian3();\r\nvar scratchVertexFormat = new VertexFormat();\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {FrustumGeometry} [result] The object into which to store the result.\r\n */\r\nFrustumGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var frustumType = array[startingIndex++];\r\n\r\n var frustum;\r\n if (frustumType === PERSPECTIVE) {\r\n frustum = PerspectiveFrustum.unpack(\r\n array,\r\n startingIndex,\r\n scratchPackPerspective\r\n );\r\n startingIndex += PerspectiveFrustum.packedLength;\r\n } else {\r\n frustum = OrthographicFrustum.unpack(\r\n array,\r\n startingIndex,\r\n scratchPackOrthographic\r\n );\r\n startingIndex += OrthographicFrustum.packedLength;\r\n }\r\n\r\n var origin = Cartesian3.unpack(array, startingIndex, scratchPackorigin);\r\n startingIndex += Cartesian3.packedLength;\r\n var orientation = Quaternion.unpack(\r\n array,\r\n startingIndex,\r\n scratchPackQuaternion\r\n );\r\n startingIndex += Quaternion.packedLength;\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n var drawNearPlane = array[startingIndex] === 1.0;\r\n\r\n if (!defined(result)) {\r\n return new FrustumGeometry({\r\n frustum: frustum,\r\n origin: origin,\r\n orientation: orientation,\r\n vertexFormat: vertexFormat,\r\n _drawNearPlane: drawNearPlane,\r\n });\r\n }\r\n\r\n var frustumResult =\r\n frustumType === result._frustumType ? result._frustum : undefined;\r\n result._frustum = frustum.clone(frustumResult);\r\n\r\n result._frustumType = frustumType;\r\n result._origin = Cartesian3.clone(origin, result._origin);\r\n result._orientation = Quaternion.clone(orientation, result._orientation);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._drawNearPlane = drawNearPlane;\r\n\r\n return result;\r\n};\r\n\r\nfunction getAttributes(\r\n offset,\r\n normals,\r\n tangents,\r\n bitangents,\r\n st,\r\n normal,\r\n tangent,\r\n bitangent\r\n) {\r\n var stOffset = (offset / 3) * 2;\r\n\r\n for (var i = 0; i < 4; ++i) {\r\n if (defined(normals)) {\r\n normals[offset] = normal.x;\r\n normals[offset + 1] = normal.y;\r\n normals[offset + 2] = normal.z;\r\n }\r\n if (defined(tangents)) {\r\n tangents[offset] = tangent.x;\r\n tangents[offset + 1] = tangent.y;\r\n tangents[offset + 2] = tangent.z;\r\n }\r\n if (defined(bitangents)) {\r\n bitangents[offset] = bitangent.x;\r\n bitangents[offset + 1] = bitangent.y;\r\n bitangents[offset + 2] = bitangent.z;\r\n }\r\n offset += 3;\r\n }\r\n\r\n st[stOffset] = 0.0;\r\n st[stOffset + 1] = 0.0;\r\n st[stOffset + 2] = 1.0;\r\n st[stOffset + 3] = 0.0;\r\n st[stOffset + 4] = 1.0;\r\n st[stOffset + 5] = 1.0;\r\n st[stOffset + 6] = 0.0;\r\n st[stOffset + 7] = 1.0;\r\n}\r\n\r\nvar scratchRotationMatrix = new Matrix3();\r\nvar scratchViewMatrix = new Matrix4();\r\nvar scratchInverseMatrix = new Matrix4();\r\n\r\nvar scratchXDirection = new Cartesian3();\r\nvar scratchYDirection = new Cartesian3();\r\nvar scratchZDirection = new Cartesian3();\r\nvar scratchNegativeX = new Cartesian3();\r\nvar scratchNegativeY = new Cartesian3();\r\nvar scratchNegativeZ = new Cartesian3();\r\n\r\nvar frustumSplits = new Array(3);\r\n\r\nvar frustumCornersNDC = new Array(4);\r\nfrustumCornersNDC[0] = new Cartesian4(-1.0, -1.0, 1.0, 1.0);\r\nfrustumCornersNDC[1] = new Cartesian4(1.0, -1.0, 1.0, 1.0);\r\nfrustumCornersNDC[2] = new Cartesian4(1.0, 1.0, 1.0, 1.0);\r\nfrustumCornersNDC[3] = new Cartesian4(-1.0, 1.0, 1.0, 1.0);\r\n\r\nvar scratchFrustumCorners = new Array(4);\r\nfor (var i = 0; i < 4; ++i) {\r\n scratchFrustumCorners[i] = new Cartesian4();\r\n}\r\n\r\nFrustumGeometry._computeNearFarPlanes = function (\r\n origin,\r\n orientation,\r\n frustumType,\r\n frustum,\r\n positions,\r\n xDirection,\r\n yDirection,\r\n zDirection\r\n) {\r\n var rotationMatrix = Matrix3.fromQuaternion(\r\n orientation,\r\n scratchRotationMatrix\r\n );\r\n var x = defaultValue(xDirection, scratchXDirection);\r\n var y = defaultValue(yDirection, scratchYDirection);\r\n var z = defaultValue(zDirection, scratchZDirection);\r\n\r\n x = Matrix3.getColumn(rotationMatrix, 0, x);\r\n y = Matrix3.getColumn(rotationMatrix, 1, y);\r\n z = Matrix3.getColumn(rotationMatrix, 2, z);\r\n\r\n Cartesian3.normalize(x, x);\r\n Cartesian3.normalize(y, y);\r\n Cartesian3.normalize(z, z);\r\n\r\n Cartesian3.negate(x, x);\r\n\r\n var view = Matrix4.computeView(origin, z, y, x, scratchViewMatrix);\r\n\r\n var inverseView;\r\n var inverseViewProjection;\r\n if (frustumType === PERSPECTIVE) {\r\n var projection = frustum.projectionMatrix;\r\n var viewProjection = Matrix4.multiply(\r\n projection,\r\n view,\r\n scratchInverseMatrix\r\n );\r\n inverseViewProjection = Matrix4.inverse(\r\n viewProjection,\r\n scratchInverseMatrix\r\n );\r\n } else {\r\n inverseView = Matrix4.inverseTransformation(view, scratchInverseMatrix);\r\n }\r\n\r\n if (defined(inverseViewProjection)) {\r\n frustumSplits[0] = frustum.near;\r\n frustumSplits[1] = frustum.far;\r\n } else {\r\n frustumSplits[0] = 0.0;\r\n frustumSplits[1] = frustum.near;\r\n frustumSplits[2] = frustum.far;\r\n }\r\n\r\n for (var i = 0; i < 2; ++i) {\r\n for (var j = 0; j < 4; ++j) {\r\n var corner = Cartesian4.clone(\r\n frustumCornersNDC[j],\r\n scratchFrustumCorners[j]\r\n );\r\n\r\n if (!defined(inverseViewProjection)) {\r\n if (defined(frustum._offCenterFrustum)) {\r\n frustum = frustum._offCenterFrustum;\r\n }\r\n\r\n var near = frustumSplits[i];\r\n var far = frustumSplits[i + 1];\r\n\r\n corner.x =\r\n (corner.x * (frustum.right - frustum.left) +\r\n frustum.left +\r\n frustum.right) *\r\n 0.5;\r\n corner.y =\r\n (corner.y * (frustum.top - frustum.bottom) +\r\n frustum.bottom +\r\n frustum.top) *\r\n 0.5;\r\n corner.z = (corner.z * (near - far) - near - far) * 0.5;\r\n corner.w = 1.0;\r\n\r\n Matrix4.multiplyByVector(inverseView, corner, corner);\r\n } else {\r\n corner = Matrix4.multiplyByVector(\r\n inverseViewProjection,\r\n corner,\r\n corner\r\n );\r\n\r\n // Reverse perspective divide\r\n var w = 1.0 / corner.w;\r\n Cartesian3.multiplyByScalar(corner, w, corner);\r\n\r\n Cartesian3.subtract(corner, origin, corner);\r\n Cartesian3.normalize(corner, corner);\r\n\r\n var fac = Cartesian3.dot(z, corner);\r\n Cartesian3.multiplyByScalar(corner, frustumSplits[i] / fac, corner);\r\n Cartesian3.add(corner, origin, corner);\r\n }\r\n\r\n positions[12 * i + j * 3] = corner.x;\r\n positions[12 * i + j * 3 + 1] = corner.y;\r\n positions[12 * i + j * 3 + 2] = corner.z;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a frustum, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {FrustumGeometry} frustumGeometry A description of the frustum.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nFrustumGeometry.createGeometry = function (frustumGeometry) {\r\n var frustumType = frustumGeometry._frustumType;\r\n var frustum = frustumGeometry._frustum;\r\n var origin = frustumGeometry._origin;\r\n var orientation = frustumGeometry._orientation;\r\n var drawNearPlane = frustumGeometry._drawNearPlane;\r\n var vertexFormat = frustumGeometry._vertexFormat;\r\n\r\n var numberOfPlanes = drawNearPlane ? 6 : 5;\r\n var positions = new Float64Array(3 * 4 * 6);\r\n FrustumGeometry._computeNearFarPlanes(\r\n origin,\r\n orientation,\r\n frustumType,\r\n frustum,\r\n positions\r\n );\r\n\r\n // -x plane\r\n var offset = 3 * 4 * 2;\r\n positions[offset] = positions[3 * 4];\r\n positions[offset + 1] = positions[3 * 4 + 1];\r\n positions[offset + 2] = positions[3 * 4 + 2];\r\n positions[offset + 3] = positions[0];\r\n positions[offset + 4] = positions[1];\r\n positions[offset + 5] = positions[2];\r\n positions[offset + 6] = positions[3 * 3];\r\n positions[offset + 7] = positions[3 * 3 + 1];\r\n positions[offset + 8] = positions[3 * 3 + 2];\r\n positions[offset + 9] = positions[3 * 7];\r\n positions[offset + 10] = positions[3 * 7 + 1];\r\n positions[offset + 11] = positions[3 * 7 + 2];\r\n\r\n // -y plane\r\n offset += 3 * 4;\r\n positions[offset] = positions[3 * 5];\r\n positions[offset + 1] = positions[3 * 5 + 1];\r\n positions[offset + 2] = positions[3 * 5 + 2];\r\n positions[offset + 3] = positions[3];\r\n positions[offset + 4] = positions[3 + 1];\r\n positions[offset + 5] = positions[3 + 2];\r\n positions[offset + 6] = positions[0];\r\n positions[offset + 7] = positions[1];\r\n positions[offset + 8] = positions[2];\r\n positions[offset + 9] = positions[3 * 4];\r\n positions[offset + 10] = positions[3 * 4 + 1];\r\n positions[offset + 11] = positions[3 * 4 + 2];\r\n\r\n // +x plane\r\n offset += 3 * 4;\r\n positions[offset] = positions[3];\r\n positions[offset + 1] = positions[3 + 1];\r\n positions[offset + 2] = positions[3 + 2];\r\n positions[offset + 3] = positions[3 * 5];\r\n positions[offset + 4] = positions[3 * 5 + 1];\r\n positions[offset + 5] = positions[3 * 5 + 2];\r\n positions[offset + 6] = positions[3 * 6];\r\n positions[offset + 7] = positions[3 * 6 + 1];\r\n positions[offset + 8] = positions[3 * 6 + 2];\r\n positions[offset + 9] = positions[3 * 2];\r\n positions[offset + 10] = positions[3 * 2 + 1];\r\n positions[offset + 11] = positions[3 * 2 + 2];\r\n\r\n // +y plane\r\n offset += 3 * 4;\r\n positions[offset] = positions[3 * 2];\r\n positions[offset + 1] = positions[3 * 2 + 1];\r\n positions[offset + 2] = positions[3 * 2 + 2];\r\n positions[offset + 3] = positions[3 * 6];\r\n positions[offset + 4] = positions[3 * 6 + 1];\r\n positions[offset + 5] = positions[3 * 6 + 2];\r\n positions[offset + 6] = positions[3 * 7];\r\n positions[offset + 7] = positions[3 * 7 + 1];\r\n positions[offset + 8] = positions[3 * 7 + 2];\r\n positions[offset + 9] = positions[3 * 3];\r\n positions[offset + 10] = positions[3 * 3 + 1];\r\n positions[offset + 11] = positions[3 * 3 + 2];\r\n\r\n if (!drawNearPlane) {\r\n positions = positions.subarray(3 * 4);\r\n }\r\n\r\n var attributes = new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n }),\r\n });\r\n\r\n if (\r\n defined(vertexFormat.normal) ||\r\n defined(vertexFormat.tangent) ||\r\n defined(vertexFormat.bitangent) ||\r\n defined(vertexFormat.st)\r\n ) {\r\n var normals = defined(vertexFormat.normal)\r\n ? new Float32Array(3 * 4 * numberOfPlanes)\r\n : undefined;\r\n var tangents = defined(vertexFormat.tangent)\r\n ? new Float32Array(3 * 4 * numberOfPlanes)\r\n : undefined;\r\n var bitangents = defined(vertexFormat.bitangent)\r\n ? new Float32Array(3 * 4 * numberOfPlanes)\r\n : undefined;\r\n var st = defined(vertexFormat.st)\r\n ? new Float32Array(2 * 4 * numberOfPlanes)\r\n : undefined;\r\n\r\n var x = scratchXDirection;\r\n var y = scratchYDirection;\r\n var z = scratchZDirection;\r\n\r\n var negativeX = Cartesian3.negate(x, scratchNegativeX);\r\n var negativeY = Cartesian3.negate(y, scratchNegativeY);\r\n var negativeZ = Cartesian3.negate(z, scratchNegativeZ);\r\n\r\n offset = 0;\r\n if (drawNearPlane) {\r\n getAttributes(offset, normals, tangents, bitangents, st, negativeZ, x, y); // near\r\n offset += 3 * 4;\r\n }\r\n getAttributes(offset, normals, tangents, bitangents, st, z, negativeX, y); // far\r\n offset += 3 * 4;\r\n getAttributes(\r\n offset,\r\n normals,\r\n tangents,\r\n bitangents,\r\n st,\r\n negativeX,\r\n negativeZ,\r\n y\r\n ); // -x\r\n offset += 3 * 4;\r\n getAttributes(\r\n offset,\r\n normals,\r\n tangents,\r\n bitangents,\r\n st,\r\n negativeY,\r\n negativeZ,\r\n negativeX\r\n ); // -y\r\n offset += 3 * 4;\r\n getAttributes(offset, normals, tangents, bitangents, st, x, z, y); // +x\r\n offset += 3 * 4;\r\n getAttributes(offset, normals, tangents, bitangents, st, y, z, negativeX); // +y\r\n\r\n if (defined(normals)) {\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n if (defined(tangents)) {\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n if (defined(bitangents)) {\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n if (defined(st)) {\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: st,\r\n });\r\n }\r\n }\r\n\r\n var indices = new Uint16Array(6 * numberOfPlanes);\r\n for (var i = 0; i < numberOfPlanes; ++i) {\r\n var indexOffset = i * 6;\r\n var index = i * 4;\r\n\r\n indices[indexOffset] = index;\r\n indices[indexOffset + 1] = index + 1;\r\n indices[indexOffset + 2] = index + 2;\r\n indices[indexOffset + 3] = index;\r\n indices[indexOffset + 4] = index + 2;\r\n indices[indexOffset + 5] = index + 3;\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: BoundingSphere.fromVertices(positions),\r\n });\r\n};\r\nexport default FrustumGeometry;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport FrustumGeometry from \"./FrustumGeometry.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport OrthographicFrustum from \"./OrthographicFrustum.js\";\r\nimport PerspectiveFrustum from \"./PerspectiveFrustum.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\n\r\nvar PERSPECTIVE = 0;\r\nvar ORTHOGRAPHIC = 1;\r\n\r\n/**\r\n * A description of the outline of a frustum with the given the origin and orientation.\r\n *\r\n * @alias FrustumOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {PerspectiveFrustum|OrthographicFrustum} options.frustum The frustum.\r\n * @param {Cartesian3} options.origin The origin of the frustum.\r\n * @param {Quaternion} options.orientation The orientation of the frustum.\r\n */\r\nfunction FrustumOutlineGeometry(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.object(\"options.frustum\", options.frustum);\r\n Check.typeOf.object(\"options.origin\", options.origin);\r\n Check.typeOf.object(\"options.orientation\", options.orientation);\r\n //>>includeEnd('debug');\r\n\r\n var frustum = options.frustum;\r\n var orientation = options.orientation;\r\n var origin = options.origin;\r\n\r\n // This is private because it is used by DebugCameraPrimitive to draw a multi-frustum by\r\n // creating multiple FrustumOutlineGeometrys. This way the near plane of one frustum doesn't overlap\r\n // the far plane of another.\r\n var drawNearPlane = defaultValue(options._drawNearPlane, true);\r\n\r\n var frustumType;\r\n var frustumPackedLength;\r\n if (frustum instanceof PerspectiveFrustum) {\r\n frustumType = PERSPECTIVE;\r\n frustumPackedLength = PerspectiveFrustum.packedLength;\r\n } else if (frustum instanceof OrthographicFrustum) {\r\n frustumType = ORTHOGRAPHIC;\r\n frustumPackedLength = OrthographicFrustum.packedLength;\r\n }\r\n\r\n this._frustumType = frustumType;\r\n this._frustum = frustum.clone();\r\n this._origin = Cartesian3.clone(origin);\r\n this._orientation = Quaternion.clone(orientation);\r\n this._drawNearPlane = drawNearPlane;\r\n this._workerName = \"createFrustumOutlineGeometry\";\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n 2 + frustumPackedLength + Cartesian3.packedLength + Quaternion.packedLength;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {FrustumOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nFrustumOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var frustumType = value._frustumType;\r\n var frustum = value._frustum;\r\n\r\n array[startingIndex++] = frustumType;\r\n\r\n if (frustumType === PERSPECTIVE) {\r\n PerspectiveFrustum.pack(frustum, array, startingIndex);\r\n startingIndex += PerspectiveFrustum.packedLength;\r\n } else {\r\n OrthographicFrustum.pack(frustum, array, startingIndex);\r\n startingIndex += OrthographicFrustum.packedLength;\r\n }\r\n\r\n Cartesian3.pack(value._origin, array, startingIndex);\r\n startingIndex += Cartesian3.packedLength;\r\n Quaternion.pack(value._orientation, array, startingIndex);\r\n startingIndex += Quaternion.packedLength;\r\n array[startingIndex] = value._drawNearPlane ? 1.0 : 0.0;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchPackPerspective = new PerspectiveFrustum();\r\nvar scratchPackOrthographic = new OrthographicFrustum();\r\nvar scratchPackQuaternion = new Quaternion();\r\nvar scratchPackorigin = new Cartesian3();\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {FrustumOutlineGeometry} [result] The object into which to store the result.\r\n */\r\nFrustumOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var frustumType = array[startingIndex++];\r\n\r\n var frustum;\r\n if (frustumType === PERSPECTIVE) {\r\n frustum = PerspectiveFrustum.unpack(\r\n array,\r\n startingIndex,\r\n scratchPackPerspective\r\n );\r\n startingIndex += PerspectiveFrustum.packedLength;\r\n } else {\r\n frustum = OrthographicFrustum.unpack(\r\n array,\r\n startingIndex,\r\n scratchPackOrthographic\r\n );\r\n startingIndex += OrthographicFrustum.packedLength;\r\n }\r\n\r\n var origin = Cartesian3.unpack(array, startingIndex, scratchPackorigin);\r\n startingIndex += Cartesian3.packedLength;\r\n var orientation = Quaternion.unpack(\r\n array,\r\n startingIndex,\r\n scratchPackQuaternion\r\n );\r\n startingIndex += Quaternion.packedLength;\r\n var drawNearPlane = array[startingIndex] === 1.0;\r\n\r\n if (!defined(result)) {\r\n return new FrustumOutlineGeometry({\r\n frustum: frustum,\r\n origin: origin,\r\n orientation: orientation,\r\n _drawNearPlane: drawNearPlane,\r\n });\r\n }\r\n\r\n var frustumResult =\r\n frustumType === result._frustumType ? result._frustum : undefined;\r\n result._frustum = frustum.clone(frustumResult);\r\n\r\n result._frustumType = frustumType;\r\n result._origin = Cartesian3.clone(origin, result._origin);\r\n result._orientation = Quaternion.clone(orientation, result._orientation);\r\n result._drawNearPlane = drawNearPlane;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a frustum outline, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {FrustumOutlineGeometry} frustumGeometry A description of the frustum.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nFrustumOutlineGeometry.createGeometry = function (frustumGeometry) {\r\n var frustumType = frustumGeometry._frustumType;\r\n var frustum = frustumGeometry._frustum;\r\n var origin = frustumGeometry._origin;\r\n var orientation = frustumGeometry._orientation;\r\n var drawNearPlane = frustumGeometry._drawNearPlane;\r\n\r\n var positions = new Float64Array(3 * 4 * 2);\r\n FrustumGeometry._computeNearFarPlanes(\r\n origin,\r\n orientation,\r\n frustumType,\r\n frustum,\r\n positions\r\n );\r\n\r\n var attributes = new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n }),\r\n });\r\n\r\n var offset;\r\n var index;\r\n\r\n var numberOfPlanes = drawNearPlane ? 2 : 1;\r\n var indices = new Uint16Array(8 * (numberOfPlanes + 1));\r\n\r\n // Build the near/far planes\r\n var i = drawNearPlane ? 0 : 1;\r\n for (; i < 2; ++i) {\r\n offset = drawNearPlane ? i * 8 : 0;\r\n index = i * 4;\r\n\r\n indices[offset] = index;\r\n indices[offset + 1] = index + 1;\r\n indices[offset + 2] = index + 1;\r\n indices[offset + 3] = index + 2;\r\n indices[offset + 4] = index + 2;\r\n indices[offset + 5] = index + 3;\r\n indices[offset + 6] = index + 3;\r\n indices[offset + 7] = index;\r\n }\r\n\r\n // Build the sides of the frustums\r\n for (i = 0; i < 2; ++i) {\r\n offset = (numberOfPlanes + i) * 8;\r\n index = i * 4;\r\n\r\n indices[offset] = index;\r\n indices[offset + 1] = index + 4;\r\n indices[offset + 2] = index + 1;\r\n indices[offset + 3] = index + 5;\r\n indices[offset + 4] = index + 2;\r\n indices[offset + 5] = index + 6;\r\n indices[offset + 6] = index + 3;\r\n indices[offset + 7] = index + 7;\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: BoundingSphere.fromVertices(positions),\r\n });\r\n};\r\nexport default FrustumOutlineGeometry;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * @typedef {Object} GeocoderService.Result\r\n * @property {String} displayName The display name for a location\r\n * @property {Rectangle|Cartesian3} destination The bounding box for a location\r\n */\r\n\r\n/**\r\n * Provides geocoding through an external service. This type describes an interface and\r\n * is not intended to be used.\r\n * @alias GeocoderService\r\n * @constructor\r\n *\r\n * @see BingMapsGeocoderService\r\n * @see PeliasGeocoderService\r\n * @see OpenCageGeocoderService\r\n */\r\nfunction GeocoderService() {}\r\n\r\n/**\r\n * @function\r\n *\r\n * @param {String} query The query to be sent to the geocoder service\r\n * @param {GeocodeType} [type=GeocodeType.SEARCH] The type of geocode to perform.\r\n * @returns {Promise}\r\n */\r\nGeocoderService.prototype.geocode = DeveloperError.throwInstantiationError;\r\nexport default GeocoderService;\r\n","/**\r\n * The type of geocoding to be performed by a {@link GeocoderService}.\r\n * @enum {Number}\r\n * @see Geocoder\r\n */\r\nvar GeocodeType = {\r\n /**\r\n * Perform a search where the input is considered complete.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SEARCH: 0,\r\n\r\n /**\r\n * Perform an auto-complete using partial input, typically\r\n * reserved for providing possible results as a user is typing.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n AUTOCOMPLETE: 1,\r\n};\r\nexport default Object.freeze(GeocodeType);\r\n","import DeveloperError from \"../Core/DeveloperError.js\";\r\n\r\n/**\r\n * Base class for all geometry creation utility classes that can be passed to {@link GeometryInstance}\r\n * for asynchronous geometry creation.\r\n *\r\n * @constructor\r\n * @class\r\n * @abstract\r\n */\r\nfunction GeometryFactory() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\n/**\r\n * Returns a geometry.\r\n *\r\n * @param {GeometryFactory} geometryFactory A description of the circle.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nGeometryFactory.createGeometry = function (geometryFactory) {\r\n DeveloperError.throwInstantiationError();\r\n};\r\n\r\nexport default GeometryFactory;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Values and type information for per-instance geometry attributes.\r\n *\r\n * @alias GeometryInstanceAttribute\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {ComponentDatatype} options.componentDatatype The datatype of each component in the attribute, e.g., individual elements in values.\r\n * @param {Number} options.componentsPerAttribute A number between 1 and 4 that defines the number of components in an attributes.\r\n * @param {Boolean} [options.normalize=false] When true and componentDatatype is an integer format, indicate that the components should be mapped to the range [0, 1] (unsigned) or [-1, 1] (signed) when they are accessed as floating-point for rendering.\r\n * @param {Number[]} options.value The value for the attribute.\r\n *\r\n * @exception {DeveloperError} options.componentsPerAttribute must be between 1 and 4.\r\n *\r\n *\r\n * @example\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : Cesium.BoxGeometry.fromDimensions({\r\n * dimensions : new Cesium.Cartesian3(1000000.0, 1000000.0, 500000.0)\r\n * }),\r\n * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(\r\n * Cesium.Cartesian3.fromDegrees(0.0, 0.0)), new Cesium.Cartesian3(0.0, 0.0, 1000000.0), new Cesium.Matrix4()),\r\n * id : 'box',\r\n * attributes : {\r\n * color : new Cesium.GeometryInstanceAttribute({\r\n * componentDatatype : Cesium.ComponentDatatype.UNSIGNED_BYTE,\r\n * componentsPerAttribute : 4,\r\n * normalize : true,\r\n * value : [255, 255, 0, 255]\r\n * })\r\n * }\r\n * });\r\n *\r\n * @see ColorGeometryInstanceAttribute\r\n * @see ShowGeometryInstanceAttribute\r\n * @see DistanceDisplayConditionGeometryInstanceAttribute\r\n */\r\nfunction GeometryInstanceAttribute(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options.componentDatatype)) {\r\n throw new DeveloperError(\"options.componentDatatype is required.\");\r\n }\r\n if (!defined(options.componentsPerAttribute)) {\r\n throw new DeveloperError(\"options.componentsPerAttribute is required.\");\r\n }\r\n if (\r\n options.componentsPerAttribute < 1 ||\r\n options.componentsPerAttribute > 4\r\n ) {\r\n throw new DeveloperError(\r\n \"options.componentsPerAttribute must be between 1 and 4.\"\r\n );\r\n }\r\n if (!defined(options.value)) {\r\n throw new DeveloperError(\"options.value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * The datatype of each component in the attribute, e.g., individual elements in\r\n * {@link GeometryInstanceAttribute#value}.\r\n *\r\n * @type ComponentDatatype\r\n *\r\n * @default undefined\r\n */\r\n this.componentDatatype = options.componentDatatype;\r\n\r\n /**\r\n * A number between 1 and 4 that defines the number of components in an attributes.\r\n * For example, a position attribute with x, y, and z components would have 3 as\r\n * shown in the code example.\r\n *\r\n * @type Number\r\n *\r\n * @default undefined\r\n *\r\n * @example\r\n * show : new Cesium.GeometryInstanceAttribute({\r\n * componentDatatype : Cesium.ComponentDatatype.UNSIGNED_BYTE,\r\n * componentsPerAttribute : 1,\r\n * normalize : true,\r\n * value : [1.0]\r\n * })\r\n */\r\n this.componentsPerAttribute = options.componentsPerAttribute;\r\n\r\n /**\r\n * When true and componentDatatype is an integer format,\r\n * indicate that the components should be mapped to the range [0, 1] (unsigned)\r\n * or [-1, 1] (signed) when they are accessed as floating-point for rendering.\r\n *

\r\n * This is commonly used when storing colors using {@link ComponentDatatype.UNSIGNED_BYTE}.\r\n *

\r\n *\r\n * @type Boolean\r\n *\r\n * @default false\r\n *\r\n * @example\r\n * attribute.componentDatatype = Cesium.ComponentDatatype.UNSIGNED_BYTE;\r\n * attribute.componentsPerAttribute = 4;\r\n * attribute.normalize = true;\r\n * attribute.value = [\r\n * Cesium.Color.floatToByte(color.red),\r\n * Cesium.Color.floatToByte(color.green),\r\n * Cesium.Color.floatToByte(color.blue),\r\n * Cesium.Color.floatToByte(color.alpha)\r\n * ];\r\n */\r\n this.normalize = defaultValue(options.normalize, false);\r\n\r\n /**\r\n * The values for the attributes stored in a typed array. In the code example,\r\n * every three elements in values defines one attributes since\r\n * componentsPerAttribute is 3.\r\n *\r\n * @type {Number[]}\r\n *\r\n * @default undefined\r\n *\r\n * @example\r\n * show : new Cesium.GeometryInstanceAttribute({\r\n * componentDatatype : Cesium.ComponentDatatype.UNSIGNED_BYTE,\r\n * componentsPerAttribute : 1,\r\n * normalize : true,\r\n * value : [1.0]\r\n * })\r\n */\r\n this.value = options.value;\r\n}\r\nexport default GeometryInstanceAttribute;\r\n","import Uri from \"../ThirdParty/Uri.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Given a URI, returns the last segment of the URI, removing any path or query information.\r\n * @function getFilenameFromUri\r\n *\r\n * @param {String} uri The Uri.\r\n * @returns {String} The last segment of the Uri.\r\n *\r\n * @example\r\n * //fileName will be\"simple.czml\";\r\n * var fileName = Cesium.getFilenameFromUri('/Gallery/simple.czml?value=true&example=false');\r\n */\r\nfunction getFilenameFromUri(uri) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(uri)) {\r\n throw new DeveloperError(\"uri is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var uriObject = new Uri(uri);\r\n uriObject.normalize();\r\n var path = uriObject.path;\r\n var index = path.lastIndexOf(\"/\");\r\n if (index !== -1) {\r\n path = path.substr(index + 1);\r\n }\r\n return path;\r\n}\r\nexport default getFilenameFromUri;\r\n","import defined from \"./defined.js\";\r\n\r\nvar context2DsByWidthAndHeight = {};\r\n\r\n/**\r\n * Extract a pixel array from a loaded image. Draws the image\r\n * into a canvas so it can read the pixels back.\r\n *\r\n * @function getImagePixels\r\n *\r\n * @param {HTMLImageElement} image The image to extract pixels from.\r\n * @param {Number} width The width of the image. If not defined, then image.width is assigned.\r\n * @param {Number} height The height of the image. If not defined, then image.height is assigned.\r\n * @returns {ImageData} The pixels of the image.\r\n */\r\nfunction getImagePixels(image, width, height) {\r\n if (!defined(width)) {\r\n width = image.width;\r\n }\r\n if (!defined(height)) {\r\n height = image.height;\r\n }\r\n\r\n var context2DsByHeight = context2DsByWidthAndHeight[width];\r\n if (!defined(context2DsByHeight)) {\r\n context2DsByHeight = {};\r\n context2DsByWidthAndHeight[width] = context2DsByHeight;\r\n }\r\n\r\n var context2d = context2DsByHeight[height];\r\n if (!defined(context2d)) {\r\n var canvas = document.createElement(\"canvas\");\r\n canvas.width = width;\r\n canvas.height = height;\r\n context2d = canvas.getContext(\"2d\");\r\n context2d.globalCompositeOperation = \"copy\";\r\n context2DsByHeight[height] = context2d;\r\n }\r\n\r\n context2d.drawImage(image, 0, 0, width, height);\r\n return context2d.getImageData(0, 0, width, height).data;\r\n}\r\nexport default getImagePixels;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport getStringFromTypedArray from \"./getStringFromTypedArray.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction getMagic(uint8Array, byteOffset) {\r\n byteOffset = defaultValue(byteOffset, 0);\r\n return getStringFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n Math.min(4, uint8Array.length)\r\n );\r\n}\r\nexport default getMagic;\r\n","var tmp = {};\r\n/*!\r\n * protobuf.js v6.7.0 (c) 2016, Daniel Wirtz\r\n * Compiled Wed, 22 Mar 2017 17:30:26 UTC\r\n * Licensed under the BSD-3-Clause License\r\n * see: https://github.com/dcodeIO/protobuf.js for details\r\n */\r\n(function(global,undefined){\"use strict\";(function prelude(modules, cache, entries) {\r\n\r\n // This is the prelude used to bundle protobuf.js for the browser. Wraps up the CommonJS\r\n // sources through a conflict-free require shim and is again wrapped within an iife that\r\n // provides a unified `global` and a minification-friendly `undefined` var plus a global\r\n // \"use strict\" directive so that minification can remove the directives of each module.\r\n\r\n function $require(name) {\r\n var $module = cache[name];\r\n if (!$module)\r\n modules[name][0].call($module = cache[name] = { exports: {} }, $require, $module, $module.exports);\r\n return $module.exports;\r\n }\r\n\r\n // Expose globally\r\n var protobuf = global.protobuf = $require(entries[0]);\r\n\r\n // Commented out to avoid polluing the global scope in Node.js\r\n // // Be nice to AMD\r\n // if (typeof define === \"function\" && define.amd)\r\n // define([], function() {\r\n // protobuf.configure();\r\n // return protobuf;\r\n // });\r\n\r\n // // Be nice to CommonJS\r\n // if (typeof module === \"object\" && module && module.exports)\r\n // module.exports = protobuf;\r\n\r\n})/* end of prelude */({1:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = asPromise;\r\n\r\n/**\r\n * Returns a promise from a node-style callback function.\r\n * @memberof util\r\n * @param {function(?Error, ...*)} fn Function to call\r\n * @param {*} ctx Function context\r\n * @param {...*} params Function arguments\r\n * @returns {Promise<*>} Promisified function\r\n */\r\nfunction asPromise(fn, ctx/*, varargs */) {\r\n var params = [];\r\n for (var i = 2; i < arguments.length;)\r\n params.push(arguments[i++]);\r\n var pending = true;\r\n return new Promise(function asPromiseExecutor(resolve, reject) {\r\n params.push(function asPromiseCallback(err/*, varargs */) {\r\n if (pending) {\r\n pending = false;\r\n if (err)\r\n reject(err);\r\n else {\r\n var args = [];\r\n for (var i = 1; i < arguments.length;)\r\n args.push(arguments[i++]);\r\n resolve.apply(null, args);\r\n }\r\n }\r\n });\r\n try {\r\n fn.apply(ctx || this, params); // eslint-disable-line no-invalid-this\r\n } catch (err) {\r\n if (pending) {\r\n pending = false;\r\n reject(err);\r\n }\r\n }\r\n });\r\n}\r\n\r\n},{}],2:[function(require,module,exports){\r\n\"use strict\";\r\n\r\n/**\r\n * A minimal base64 implementation for number arrays.\r\n * @memberof util\r\n * @namespace\r\n */\r\nvar base64 = exports;\r\n\r\n/**\r\n * Calculates the byte length of a base64 encoded string.\r\n * @param {string} string Base64 encoded string\r\n * @returns {number} Byte length\r\n */\r\nbase64.length = function length(string) {\r\n var p = string.length;\r\n if (!p)\r\n return 0;\r\n var n = 0;\r\n while (--p % 4 > 1 && string.charAt(p) === \"=\")\r\n ++n;\r\n return Math.ceil(string.length * 3) / 4 - n;\r\n};\r\n\r\n// Base64 encoding table\r\nvar b64 = new Array(64);\r\n\r\n// Base64 decoding table\r\nvar s64 = new Array(123);\r\n\r\n// 65..90, 97..122, 48..57, 43, 47\r\nfor (var i = 0; i < 64;)\r\n s64[b64[i] = i < 26 ? i + 65 : i < 52 ? i + 71 : i < 62 ? i - 4 : i - 59 | 43] = i++;\r\n\r\n/**\r\n * Encodes a buffer to a base64 encoded string.\r\n * @param {Uint8Array} buffer Source buffer\r\n * @param {number} start Source start\r\n * @param {number} end Source end\r\n * @returns {string} Base64 encoded string\r\n */\r\nbase64.encode = function encode(buffer, start, end) {\r\n var string = []; // alt: new Array(Math.ceil((end - start) / 3) * 4);\r\n var i = 0, // output index\r\n j = 0, // goto index\r\n t; // temporary\r\n while (start < end) {\r\n var b = buffer[start++];\r\n switch (j) {\r\n case 0:\r\n string[i++] = b64[b >> 2];\r\n t = (b & 3) << 4;\r\n j = 1;\r\n break;\r\n case 1:\r\n string[i++] = b64[t | b >> 4];\r\n t = (b & 15) << 2;\r\n j = 2;\r\n break;\r\n case 2:\r\n string[i++] = b64[t | b >> 6];\r\n string[i++] = b64[b & 63];\r\n j = 0;\r\n break;\r\n }\r\n }\r\n if (j) {\r\n string[i++] = b64[t];\r\n string[i ] = 61;\r\n if (j === 1)\r\n string[i + 1] = 61;\r\n }\r\n return String.fromCharCode.apply(String, string);\r\n};\r\n\r\nvar invalidEncoding = \"invalid encoding\";\r\n\r\n/**\r\n * Decodes a base64 encoded string to a buffer.\r\n * @param {string} string Source string\r\n * @param {Uint8Array} buffer Destination buffer\r\n * @param {number} offset Destination offset\r\n * @returns {number} Number of bytes written\r\n * @throws {Error} If encoding is invalid\r\n */\r\nbase64.decode = function decode(string, buffer, offset) {\r\n var start = offset;\r\n var j = 0, // goto index\r\n t; // temporary\r\n for (var i = 0; i < string.length;) {\r\n var c = string.charCodeAt(i++);\r\n if (c === 61 && j > 1)\r\n break;\r\n if ((c = s64[c]) === undefined)\r\n throw Error(invalidEncoding);\r\n switch (j) {\r\n case 0:\r\n t = c;\r\n j = 1;\r\n break;\r\n case 1:\r\n buffer[offset++] = t << 2 | (c & 48) >> 4;\r\n t = c;\r\n j = 2;\r\n break;\r\n case 2:\r\n buffer[offset++] = (t & 15) << 4 | (c & 60) >> 2;\r\n t = c;\r\n j = 3;\r\n break;\r\n case 3:\r\n buffer[offset++] = (t & 3) << 6 | c;\r\n j = 0;\r\n break;\r\n }\r\n }\r\n if (j === 1)\r\n throw Error(invalidEncoding);\r\n return offset - start;\r\n};\r\n\r\n/**\r\n * Tests if the specified string appears to be base64 encoded.\r\n * @param {string} string String to test\r\n * @returns {boolean} `true` if probably base64 encoded, otherwise false\r\n */\r\nbase64.test = function test(string) {\r\n return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(string);\r\n};\r\n\r\n},{}],3:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = EventEmitter;\r\n\r\n/**\r\n * Constructs a new event emitter instance.\r\n * @classdesc A minimal event emitter.\r\n * @memberof util\r\n * @constructor\r\n */\r\nfunction EventEmitter() {\r\n\r\n /**\r\n * Registered listeners.\r\n * @type {Object.}\r\n * @private\r\n */\r\n this._listeners = {};\r\n}\r\n\r\n/**\r\n * Registers an event listener.\r\n * @param {string} evt Event name\r\n * @param {function} fn Listener\r\n * @param {*} [ctx] Listener context\r\n * @returns {util.EventEmitter} `this`\r\n */\r\nEventEmitter.prototype.on = function on(evt, fn, ctx) {\r\n (this._listeners[evt] || (this._listeners[evt] = [])).push({\r\n fn : fn,\r\n ctx : ctx || this\r\n });\r\n return this;\r\n};\r\n\r\n/**\r\n * Removes an event listener or any matching listeners if arguments are omitted.\r\n * @param {string} [evt] Event name. Removes all listeners if omitted.\r\n * @param {function} [fn] Listener to remove. Removes all listeners of `evt` if omitted.\r\n * @returns {util.EventEmitter} `this`\r\n */\r\nEventEmitter.prototype.off = function off(evt, fn) {\r\n if (evt === undefined)\r\n this._listeners = {};\r\n else {\r\n if (fn === undefined)\r\n this._listeners[evt] = [];\r\n else {\r\n var listeners = this._listeners[evt];\r\n for (var i = 0; i < listeners.length;)\r\n if (listeners[i].fn === fn)\r\n listeners.splice(i, 1);\r\n else\r\n ++i;\r\n }\r\n }\r\n return this;\r\n};\r\n\r\n/**\r\n * Emits an event by calling its listeners with the specified arguments.\r\n * @param {string} evt Event name\r\n * @param {...*} args Arguments\r\n * @returns {util.EventEmitter} `this`\r\n */\r\nEventEmitter.prototype.emit = function emit(evt) {\r\n var listeners = this._listeners[evt];\r\n if (listeners) {\r\n var args = [],\r\n i = 1;\r\n for (; i < arguments.length;)\r\n args.push(arguments[i++]);\r\n for (i = 0; i < listeners.length;)\r\n listeners[i].fn.apply(listeners[i++].ctx, args);\r\n }\r\n return this;\r\n};\r\n\r\n},{}],4:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = inquire;\r\n\r\n/**\r\n * Requires a module only if available.\r\n * @memberof util\r\n * @param {string} moduleName Module to require\r\n * @returns {?Object} Required module if available and not empty, otherwise `null`\r\n */\r\nfunction inquire(moduleName) {\r\n try {\r\n var mod = eval(\"quire\".replace(/^/,\"re\"))(moduleName); // eslint-disable-line no-eval\r\n if (mod && (mod.length || Object.keys(mod).length))\r\n return mod;\r\n } catch (e) {} // eslint-disable-line no-empty\r\n return null;\r\n}\r\n\r\n},{}],5:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = pool;\r\n\r\n/**\r\n * An allocator as used by {@link util.pool}.\r\n * @typedef PoolAllocator\r\n * @type {function}\r\n * @param {number} size Buffer size\r\n * @returns {Uint8Array} Buffer\r\n */\r\n\r\n/**\r\n * A slicer as used by {@link util.pool}.\r\n * @typedef PoolSlicer\r\n * @type {function}\r\n * @param {number} start Start offset\r\n * @param {number} end End offset\r\n * @returns {Uint8Array} Buffer slice\r\n * @this {Uint8Array}\r\n */\r\n\r\n/**\r\n * A general purpose buffer pool.\r\n * @memberof util\r\n * @function\r\n * @param {PoolAllocator} alloc Allocator\r\n * @param {PoolSlicer} slice Slicer\r\n * @param {number} [size=8192] Slab size\r\n * @returns {PoolAllocator} Pooled allocator\r\n */\r\nfunction pool(alloc, slice, size) {\r\n var SIZE = size || 8192;\r\n var MAX = SIZE >>> 1;\r\n var slab = null;\r\n var offset = SIZE;\r\n return function pool_alloc(size) {\r\n if (size < 1 || size > MAX)\r\n return alloc(size);\r\n if (offset + size > SIZE) {\r\n slab = alloc(SIZE);\r\n offset = 0;\r\n }\r\n var buf = slice.call(slab, offset, offset += size);\r\n if (offset & 7) // align to 32 bit\r\n offset = (offset | 7) + 1;\r\n return buf;\r\n };\r\n}\r\n\r\n},{}],6:[function(require,module,exports){\r\n\"use strict\";\r\n\r\n/**\r\n * A minimal UTF8 implementation for number arrays.\r\n * @memberof util\r\n * @namespace\r\n */\r\nvar utf8 = exports;\r\n\r\n/**\r\n * Calculates the UTF8 byte length of a string.\r\n * @param {string} string String\r\n * @returns {number} Byte length\r\n */\r\nutf8.length = function utf8_length(string) {\r\n var len = 0,\r\n c = 0;\r\n for (var i = 0; i < string.length; ++i) {\r\n c = string.charCodeAt(i);\r\n if (c < 128)\r\n len += 1;\r\n else if (c < 2048)\r\n len += 2;\r\n else if ((c & 0xFC00) === 0xD800 && (string.charCodeAt(i + 1) & 0xFC00) === 0xDC00) {\r\n ++i;\r\n len += 4;\r\n } else\r\n len += 3;\r\n }\r\n return len;\r\n};\r\n\r\n/**\r\n * Reads UTF8 bytes as a string.\r\n * @param {Uint8Array} buffer Source buffer\r\n * @param {number} start Source start\r\n * @param {number} end Source end\r\n * @returns {string} String read\r\n */\r\nutf8.read = function utf8_read(buffer, start, end) {\r\n var len = end - start;\r\n if (len < 1)\r\n return \"\";\r\n var parts = null,\r\n chunk = [],\r\n i = 0, // char offset\r\n t; // temporary\r\n while (start < end) {\r\n t = buffer[start++];\r\n if (t < 128)\r\n chunk[i++] = t;\r\n else if (t > 191 && t < 224)\r\n chunk[i++] = (t & 31) << 6 | buffer[start++] & 63;\r\n else if (t > 239 && t < 365) {\r\n t = ((t & 7) << 18 | (buffer[start++] & 63) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63) - 0x10000;\r\n chunk[i++] = 0xD800 + (t >> 10);\r\n chunk[i++] = 0xDC00 + (t & 1023);\r\n } else\r\n chunk[i++] = (t & 15) << 12 | (buffer[start++] & 63) << 6 | buffer[start++] & 63;\r\n if (i > 8191) {\r\n (parts || (parts = [])).push(String.fromCharCode.apply(String, chunk));\r\n i = 0;\r\n }\r\n }\r\n if (parts) {\r\n if (i)\r\n parts.push(String.fromCharCode.apply(String, chunk.slice(0, i)));\r\n return parts.join(\"\");\r\n }\r\n return String.fromCharCode.apply(String, chunk.slice(0, i));\r\n};\r\n\r\n/**\r\n * Writes a string as UTF8 bytes.\r\n * @param {string} string Source string\r\n * @param {Uint8Array} buffer Destination buffer\r\n * @param {number} offset Destination offset\r\n * @returns {number} Bytes written\r\n */\r\nutf8.write = function utf8_write(string, buffer, offset) {\r\n var start = offset,\r\n c1, // character 1\r\n c2; // character 2\r\n for (var i = 0; i < string.length; ++i) {\r\n c1 = string.charCodeAt(i);\r\n if (c1 < 128) {\r\n buffer[offset++] = c1;\r\n } else if (c1 < 2048) {\r\n buffer[offset++] = c1 >> 6 | 192;\r\n buffer[offset++] = c1 & 63 | 128;\r\n } else if ((c1 & 0xFC00) === 0xD800 && ((c2 = string.charCodeAt(i + 1)) & 0xFC00) === 0xDC00) {\r\n c1 = 0x10000 + ((c1 & 0x03FF) << 10) + (c2 & 0x03FF);\r\n ++i;\r\n buffer[offset++] = c1 >> 18 | 240;\r\n buffer[offset++] = c1 >> 12 & 63 | 128;\r\n buffer[offset++] = c1 >> 6 & 63 | 128;\r\n buffer[offset++] = c1 & 63 | 128;\r\n } else {\r\n buffer[offset++] = c1 >> 12 | 224;\r\n buffer[offset++] = c1 >> 6 & 63 | 128;\r\n buffer[offset++] = c1 & 63 | 128;\r\n }\r\n }\r\n return offset - start;\r\n};\r\n\r\n},{}],7:[function(require,module,exports){\r\n\"use strict\";\r\nvar protobuf = exports;\r\n\r\n/**\r\n * Build type, one of `\"full\"`, `\"light\"` or `\"minimal\"`.\r\n * @name build\r\n * @type {string}\r\n * @const\r\n */\r\nprotobuf.build = \"minimal\";\r\n\r\n/**\r\n * Named roots.\r\n * This is where pbjs stores generated structures (the option `-r, --root` specifies a name).\r\n * Can also be used manually to make roots available accross modules.\r\n * @name roots\r\n * @type {Object.}\r\n * @example\r\n * // pbjs -r myroot -o compiled.js ...\r\n *\r\n * // in another module:\r\n * require(\"./compiled.js\");\r\n *\r\n * // in any subsequent module:\r\n * var root = protobuf.roots[\"myroot\"];\r\n */\r\nprotobuf.roots = {};\r\n\r\n// Serialization\r\nprotobuf.Writer = require(14);\r\nprotobuf.BufferWriter = require(15);\r\nprotobuf.Reader = require(8);\r\nprotobuf.BufferReader = require(9);\r\n\r\n// Utility\r\nprotobuf.util = require(13);\r\nprotobuf.rpc = require(10);\r\nprotobuf.configure = configure;\r\n\r\n/* istanbul ignore next */\r\n/**\r\n * Reconfigures the library according to the environment.\r\n * @returns {undefined}\r\n */\r\nfunction configure() {\r\n protobuf.Reader._configure(protobuf.BufferReader);\r\n protobuf.util._configure();\r\n}\r\n\r\n// Configure serialization\r\nprotobuf.Writer._configure(protobuf.BufferWriter);\r\nconfigure();\r\n\r\n},{\"10\":10,\"13\":13,\"14\":14,\"15\":15,\"8\":8,\"9\":9}],8:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = Reader;\r\n\r\nvar util = require(13);\r\n\r\nvar BufferReader; // cyclic\r\n\r\nvar LongBits = util.LongBits,\r\n utf8 = util.utf8;\r\n\r\n/* istanbul ignore next */\r\nfunction indexOutOfRange(reader, writeLength) {\r\n return RangeError(\"index out of range: \" + reader.pos + \" + \" + (writeLength || 1) + \" > \" + reader.len);\r\n}\r\n\r\n/**\r\n * Constructs a new reader instance using the specified buffer.\r\n * @classdesc Wire format reader using `Uint8Array` if available, otherwise `Array`.\r\n * @constructor\r\n * @param {Uint8Array} buffer Buffer to read from\r\n */\r\nfunction Reader(buffer) {\r\n\r\n /**\r\n * Read buffer.\r\n * @type {Uint8Array}\r\n */\r\n this.buf = buffer;\r\n\r\n /**\r\n * Read buffer position.\r\n * @type {number}\r\n */\r\n this.pos = 0;\r\n\r\n /**\r\n * Read buffer length.\r\n * @type {number}\r\n */\r\n this.len = buffer.length;\r\n}\r\n\r\nvar create_array = typeof Uint8Array !== \"undefined\"\r\n ? function create_typed_array(buffer) {\r\n if (buffer instanceof Uint8Array || Array.isArray(buffer))\r\n return new Reader(buffer);\r\n throw Error(\"illegal buffer\");\r\n }\r\n /* istanbul ignore next */\r\n : function create_array(buffer) {\r\n if (Array.isArray(buffer))\r\n return new Reader(buffer);\r\n throw Error(\"illegal buffer\");\r\n };\r\n\r\n/**\r\n * Creates a new reader using the specified buffer.\r\n * @function\r\n * @param {Uint8Array|Buffer} buffer Buffer to read from\r\n * @returns {Reader|BufferReader} A {@link BufferReader} if `buffer` is a Buffer, otherwise a {@link Reader}\r\n * @throws {Error} If `buffer` is not a valid buffer\r\n */\r\nReader.create = util.Buffer\r\n ? function create_buffer_setup(buffer) {\r\n return (Reader.create = function create_buffer(buffer) {\r\n return util.Buffer.isBuffer(buffer)\r\n ? new BufferReader(buffer)\r\n /* istanbul ignore next */\r\n : create_array(buffer);\r\n })(buffer);\r\n }\r\n /* istanbul ignore next */\r\n : create_array;\r\n\r\nReader.prototype._slice = util.Array.prototype.subarray || /* istanbul ignore next */ util.Array.prototype.slice;\r\n\r\n/**\r\n * Reads a varint as an unsigned 32 bit value.\r\n * @function\r\n * @returns {number} Value read\r\n */\r\nReader.prototype.uint32 = (function read_uint32_setup() {\r\n var value = 4294967295; // optimizer type-hint, tends to deopt otherwise (?!)\r\n return function read_uint32() {\r\n value = ( this.buf[this.pos] & 127 ) >>> 0; if (this.buf[this.pos++] < 128) return value;\r\n value = (value | (this.buf[this.pos] & 127) << 7) >>> 0; if (this.buf[this.pos++] < 128) return value;\r\n value = (value | (this.buf[this.pos] & 127) << 14) >>> 0; if (this.buf[this.pos++] < 128) return value;\r\n value = (value | (this.buf[this.pos] & 127) << 21) >>> 0; if (this.buf[this.pos++] < 128) return value;\r\n value = (value | (this.buf[this.pos] & 15) << 28) >>> 0; if (this.buf[this.pos++] < 128) return value;\r\n\r\n /* istanbul ignore next */\r\n if ((this.pos += 5) > this.len) {\r\n this.pos = this.len;\r\n throw indexOutOfRange(this, 10);\r\n }\r\n return value;\r\n };\r\n})();\r\n\r\n/**\r\n * Reads a varint as a signed 32 bit value.\r\n * @returns {number} Value read\r\n */\r\nReader.prototype.int32 = function read_int32() {\r\n return this.uint32() | 0;\r\n};\r\n\r\n/**\r\n * Reads a zig-zag encoded varint as a signed 32 bit value.\r\n * @returns {number} Value read\r\n */\r\nReader.prototype.sint32 = function read_sint32() {\r\n var value = this.uint32();\r\n return value >>> 1 ^ -(value & 1) | 0;\r\n};\r\n\r\n/* eslint-disable no-invalid-this */\r\n\r\nfunction readLongVarint() {\r\n // tends to deopt with local vars for octet etc.\r\n var bits = new LongBits(0, 0);\r\n var i = 0;\r\n if (this.len - this.pos > 4) { // fast route (lo)\r\n for (; i < 4; ++i) {\r\n // 1st..4th\r\n bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;\r\n if (this.buf[this.pos++] < 128)\r\n return bits;\r\n }\r\n // 5th\r\n bits.lo = (bits.lo | (this.buf[this.pos] & 127) << 28) >>> 0;\r\n bits.hi = (bits.hi | (this.buf[this.pos] & 127) >> 4) >>> 0;\r\n if (this.buf[this.pos++] < 128)\r\n return bits;\r\n i = 0;\r\n } else {\r\n for (; i < 3; ++i) {\r\n /* istanbul ignore next */\r\n if (this.pos >= this.len)\r\n throw indexOutOfRange(this);\r\n // 1st..3th\r\n bits.lo = (bits.lo | (this.buf[this.pos] & 127) << i * 7) >>> 0;\r\n if (this.buf[this.pos++] < 128)\r\n return bits;\r\n }\r\n // 4th\r\n bits.lo = (bits.lo | (this.buf[this.pos++] & 127) << i * 7) >>> 0;\r\n return bits;\r\n }\r\n if (this.len - this.pos > 4) { // fast route (hi)\r\n for (; i < 5; ++i) {\r\n // 6th..10th\r\n bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;\r\n if (this.buf[this.pos++] < 128)\r\n return bits;\r\n }\r\n } else {\r\n for (; i < 5; ++i) {\r\n /* istanbul ignore next */\r\n if (this.pos >= this.len)\r\n throw indexOutOfRange(this);\r\n // 6th..10th\r\n bits.hi = (bits.hi | (this.buf[this.pos] & 127) << i * 7 + 3) >>> 0;\r\n if (this.buf[this.pos++] < 128)\r\n return bits;\r\n }\r\n }\r\n /* istanbul ignore next */\r\n throw Error(\"invalid varint encoding\");\r\n}\r\n\r\n/* eslint-enable no-invalid-this */\r\n\r\n/**\r\n * Reads a varint as a signed 64 bit value.\r\n * @name Reader#int64\r\n * @function\r\n * @returns {Long|number} Value read\r\n */\r\n\r\n/**\r\n * Reads a varint as an unsigned 64 bit value.\r\n * @name Reader#uint64\r\n * @function\r\n * @returns {Long|number} Value read\r\n */\r\n\r\n/**\r\n * Reads a zig-zag encoded varint as a signed 64 bit value.\r\n * @name Reader#sint64\r\n * @function\r\n * @returns {Long|number} Value read\r\n */\r\n\r\n/**\r\n * Reads a varint as a boolean.\r\n * @returns {boolean} Value read\r\n */\r\nReader.prototype.bool = function read_bool() {\r\n return this.uint32() !== 0;\r\n};\r\n\r\nfunction readFixed32(buf, end) {\r\n return (buf[end - 4]\r\n | buf[end - 3] << 8\r\n | buf[end - 2] << 16\r\n | buf[end - 1] << 24) >>> 0;\r\n}\r\n\r\n/**\r\n * Reads fixed 32 bits as an unsigned 32 bit integer.\r\n * @returns {number} Value read\r\n */\r\nReader.prototype.fixed32 = function read_fixed32() {\r\n\r\n /* istanbul ignore next */\r\n if (this.pos + 4 > this.len)\r\n throw indexOutOfRange(this, 4);\r\n\r\n return readFixed32(this.buf, this.pos += 4);\r\n};\r\n\r\n/**\r\n * Reads fixed 32 bits as a signed 32 bit integer.\r\n * @returns {number} Value read\r\n */\r\nReader.prototype.sfixed32 = function read_sfixed32() {\r\n\r\n /* istanbul ignore next */\r\n if (this.pos + 4 > this.len)\r\n throw indexOutOfRange(this, 4);\r\n\r\n return readFixed32(this.buf, this.pos += 4) | 0;\r\n};\r\n\r\n/* eslint-disable no-invalid-this */\r\n\r\nfunction readFixed64(/* this: Reader */) {\r\n\r\n /* istanbul ignore next */\r\n if (this.pos + 8 > this.len)\r\n throw indexOutOfRange(this, 8);\r\n\r\n return new LongBits(readFixed32(this.buf, this.pos += 4), readFixed32(this.buf, this.pos += 4));\r\n}\r\n\r\n/* eslint-enable no-invalid-this */\r\n\r\n/**\r\n * Reads fixed 64 bits.\r\n * @name Reader#fixed64\r\n * @function\r\n * @returns {Long|number} Value read\r\n */\r\n\r\n/**\r\n * Reads zig-zag encoded fixed 64 bits.\r\n * @name Reader#sfixed64\r\n * @function\r\n * @returns {Long|number} Value read\r\n */\r\n\r\nvar readFloat = typeof Float32Array !== \"undefined\"\r\n ? (function() {\r\n var f32 = new Float32Array(1),\r\n f8b = new Uint8Array(f32.buffer);\r\n f32[0] = -0;\r\n return f8b[3] // already le?\r\n ? function readFloat_f32(buf, pos) {\r\n f8b[0] = buf[pos ];\r\n f8b[1] = buf[pos + 1];\r\n f8b[2] = buf[pos + 2];\r\n f8b[3] = buf[pos + 3];\r\n return f32[0];\r\n }\r\n /* istanbul ignore next */\r\n : function readFloat_f32_le(buf, pos) {\r\n f8b[0] = buf[pos + 3];\r\n f8b[1] = buf[pos + 2];\r\n f8b[2] = buf[pos + 1];\r\n f8b[3] = buf[pos ];\r\n return f32[0];\r\n };\r\n })()\r\n /* istanbul ignore next */\r\n : function readFloat_ieee754(buf, pos) {\r\n var uint = readFixed32(buf, pos + 4),\r\n sign = (uint >> 31) * 2 + 1,\r\n exponent = uint >>> 23 & 255,\r\n mantissa = uint & 8388607;\r\n return exponent === 255\r\n ? mantissa\r\n ? NaN\r\n : sign * Infinity\r\n : exponent === 0 // denormal\r\n ? sign * 1.401298464324817e-45 * mantissa\r\n : sign * Math.pow(2, exponent - 150) * (mantissa + 8388608);\r\n };\r\n\r\n/**\r\n * Reads a float (32 bit) as a number.\r\n * @function\r\n * @returns {number} Value read\r\n */\r\nReader.prototype.float = function read_float() {\r\n\r\n /* istanbul ignore next */\r\n if (this.pos + 4 > this.len)\r\n throw indexOutOfRange(this, 4);\r\n\r\n var value = readFloat(this.buf, this.pos);\r\n this.pos += 4;\r\n return value;\r\n};\r\n\r\nvar readDouble = typeof Float64Array !== \"undefined\"\r\n ? (function() {\r\n var f64 = new Float64Array(1),\r\n f8b = new Uint8Array(f64.buffer);\r\n f64[0] = -0;\r\n return f8b[7] // already le?\r\n ? function readDouble_f64(buf, pos) {\r\n f8b[0] = buf[pos ];\r\n f8b[1] = buf[pos + 1];\r\n f8b[2] = buf[pos + 2];\r\n f8b[3] = buf[pos + 3];\r\n f8b[4] = buf[pos + 4];\r\n f8b[5] = buf[pos + 5];\r\n f8b[6] = buf[pos + 6];\r\n f8b[7] = buf[pos + 7];\r\n return f64[0];\r\n }\r\n /* istanbul ignore next */\r\n : function readDouble_f64_le(buf, pos) {\r\n f8b[0] = buf[pos + 7];\r\n f8b[1] = buf[pos + 6];\r\n f8b[2] = buf[pos + 5];\r\n f8b[3] = buf[pos + 4];\r\n f8b[4] = buf[pos + 3];\r\n f8b[5] = buf[pos + 2];\r\n f8b[6] = buf[pos + 1];\r\n f8b[7] = buf[pos ];\r\n return f64[0];\r\n };\r\n })()\r\n /* istanbul ignore next */\r\n : function readDouble_ieee754(buf, pos) {\r\n var lo = readFixed32(buf, pos + 4),\r\n hi = readFixed32(buf, pos + 8);\r\n var sign = (hi >> 31) * 2 + 1,\r\n exponent = hi >>> 20 & 2047,\r\n mantissa = 4294967296 * (hi & 1048575) + lo;\r\n return exponent === 2047\r\n ? mantissa\r\n ? NaN\r\n : sign * Infinity\r\n : exponent === 0 // denormal\r\n ? sign * 5e-324 * mantissa\r\n : sign * Math.pow(2, exponent - 1075) * (mantissa + 4503599627370496);\r\n };\r\n\r\n/**\r\n * Reads a double (64 bit float) as a number.\r\n * @function\r\n * @returns {number} Value read\r\n */\r\nReader.prototype.double = function read_double() {\r\n\r\n /* istanbul ignore next */\r\n if (this.pos + 8 > this.len)\r\n throw indexOutOfRange(this, 4);\r\n\r\n var value = readDouble(this.buf, this.pos);\r\n this.pos += 8;\r\n return value;\r\n};\r\n\r\n/**\r\n * Reads a sequence of bytes preceeded by its length as a varint.\r\n * @returns {Uint8Array} Value read\r\n */\r\nReader.prototype.bytes = function read_bytes() {\r\n var length = this.uint32(),\r\n start = this.pos,\r\n end = this.pos + length;\r\n\r\n /* istanbul ignore next */\r\n if (end > this.len)\r\n throw indexOutOfRange(this, length);\r\n\r\n this.pos += length;\r\n return start === end // fix for IE 10/Win8 and others' subarray returning array of size 1\r\n ? new this.buf.constructor(0)\r\n : this._slice.call(this.buf, start, end);\r\n};\r\n\r\n/**\r\n * Reads a string preceeded by its byte length as a varint.\r\n * @returns {string} Value read\r\n */\r\nReader.prototype.string = function read_string() {\r\n var bytes = this.bytes();\r\n return utf8.read(bytes, 0, bytes.length);\r\n};\r\n\r\n/**\r\n * Skips the specified number of bytes if specified, otherwise skips a varint.\r\n * @param {number} [length] Length if known, otherwise a varint is assumed\r\n * @returns {Reader} `this`\r\n */\r\nReader.prototype.skip = function skip(length) {\r\n if (typeof length === \"number\") {\r\n /* istanbul ignore next */\r\n if (this.pos + length > this.len)\r\n throw indexOutOfRange(this, length);\r\n this.pos += length;\r\n } else {\r\n /* istanbul ignore next */\r\n do {\r\n if (this.pos >= this.len)\r\n throw indexOutOfRange(this);\r\n } while (this.buf[this.pos++] & 128);\r\n }\r\n return this;\r\n};\r\n\r\n/**\r\n * Skips the next element of the specified wire type.\r\n * @param {number} wireType Wire type received\r\n * @returns {Reader} `this`\r\n */\r\nReader.prototype.skipType = function(wireType) {\r\n switch (wireType) {\r\n case 0:\r\n this.skip();\r\n break;\r\n case 1:\r\n this.skip(8);\r\n break;\r\n case 2:\r\n this.skip(this.uint32());\r\n break;\r\n case 3:\r\n do { // eslint-disable-line no-constant-condition\r\n if ((wireType = this.uint32() & 7) === 4)\r\n break;\r\n this.skipType(wireType);\r\n } while (true);\r\n break;\r\n case 5:\r\n this.skip(4);\r\n break;\r\n\r\n /* istanbul ignore next */\r\n default:\r\n throw Error(\"invalid wire type \" + wireType + \" at offset \" + this.pos);\r\n }\r\n return this;\r\n};\r\n\r\nReader._configure = function(BufferReader_) {\r\n BufferReader = BufferReader_;\r\n\r\n var fn = util.Long ? \"toLong\" : /* istanbul ignore next */ \"toNumber\";\r\n util.merge(Reader.prototype, {\r\n\r\n int64: function read_int64() {\r\n return readLongVarint.call(this)[fn](false);\r\n },\r\n\r\n uint64: function read_uint64() {\r\n return readLongVarint.call(this)[fn](true);\r\n },\r\n\r\n sint64: function read_sint64() {\r\n return readLongVarint.call(this).zzDecode()[fn](false);\r\n },\r\n\r\n fixed64: function read_fixed64() {\r\n return readFixed64.call(this)[fn](true);\r\n },\r\n\r\n sfixed64: function read_sfixed64() {\r\n return readFixed64.call(this)[fn](false);\r\n }\r\n\r\n });\r\n};\r\n\r\n},{\"13\":13}],9:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = BufferReader;\r\n\r\n// extends Reader\r\nvar Reader = require(8);\r\n(BufferReader.prototype = Object.create(Reader.prototype)).constructor = BufferReader;\r\n\r\nvar util = require(13);\r\n\r\n/**\r\n * Constructs a new buffer reader instance.\r\n * @classdesc Wire format reader using node buffers.\r\n * @extends Reader\r\n * @constructor\r\n * @param {Buffer} buffer Buffer to read from\r\n */\r\nfunction BufferReader(buffer) {\r\n Reader.call(this, buffer);\r\n\r\n /**\r\n * Read buffer.\r\n * @name BufferReader#buf\r\n * @type {Buffer}\r\n */\r\n}\r\n\r\n/* istanbul ignore else */\r\nif (util.Buffer)\r\n BufferReader.prototype._slice = util.Buffer.prototype.slice;\r\n\r\n/**\r\n * @override\r\n */\r\nBufferReader.prototype.string = function read_string_buffer() {\r\n var len = this.uint32(); // modifies pos\r\n return this.buf.utf8Slice(this.pos, this.pos = Math.min(this.pos + len, this.len));\r\n};\r\n\r\n/**\r\n * Reads a sequence of bytes preceeded by its length as a varint.\r\n * @name BufferReader#bytes\r\n * @function\r\n * @returns {Buffer} Value read\r\n */\r\n\r\n},{\"13\":13,\"8\":8}],10:[function(require,module,exports){\r\n\"use strict\";\r\n\r\n/**\r\n * Streaming RPC helpers.\r\n * @namespace\r\n */\r\nvar rpc = exports;\r\n\r\n/**\r\n * RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets.\r\n * @typedef RPCImpl\r\n * @type {function}\r\n * @param {Method|rpc.ServiceMethod} method Reflected or static method being called\r\n * @param {Uint8Array} requestData Request data\r\n * @param {RPCImplCallback} callback Callback function\r\n * @returns {undefined}\r\n * @example\r\n * function rpcImpl(method, requestData, callback) {\r\n * if (protobuf.util.lcFirst(method.name) !== \"myMethod\") // compatible with static code\r\n * throw Error(\"no such method\");\r\n * asynchronouslyObtainAResponse(requestData, function(err, responseData) {\r\n * callback(err, responseData);\r\n * });\r\n * }\r\n */\r\n\r\n/**\r\n * Node-style callback as used by {@link RPCImpl}.\r\n * @typedef RPCImplCallback\r\n * @type {function}\r\n * @param {?Error} error Error, if any, otherwise `null`\r\n * @param {?Uint8Array} [response] Response data or `null` to signal end of stream, if there hasn't been an error\r\n * @returns {undefined}\r\n */\r\n\r\nrpc.Service = require(11);\r\n\r\n},{\"11\":11}],11:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = Service;\r\n\r\nvar util = require(13);\r\n\r\n// Extends EventEmitter\r\n(Service.prototype = Object.create(util.EventEmitter.prototype)).constructor = Service;\r\n\r\n/**\r\n * A service method callback as used by {@link rpc.ServiceMethod|ServiceMethod}.\r\n *\r\n * Differs from {@link RPCImplCallback} in that it is an actual callback of a service method which may not return `response = null`.\r\n * @typedef rpc.ServiceMethodCallback\r\n * @type {function}\r\n * @param {?Error} error Error, if any\r\n * @param {?Message} [response] Response message\r\n * @returns {undefined}\r\n */\r\n\r\n/**\r\n * A service method part of a {@link rpc.ServiceMethodMixin|ServiceMethodMixin} and thus {@link rpc.Service} as created by {@link Service.create}.\r\n * @typedef rpc.ServiceMethod\r\n * @type {function}\r\n * @param {Message|Object.} request Request message or plain object\r\n * @param {rpc.ServiceMethodCallback} [callback] Node-style callback called with the error, if any, and the response message\r\n * @returns {Promise} Promise if `callback` has been omitted, otherwise `undefined`\r\n */\r\n\r\n/**\r\n * A service method mixin.\r\n *\r\n * When using TypeScript, mixed in service methods are only supported directly with a type definition of a static module (used with reflection). Otherwise, explicit casting is required.\r\n * @typedef rpc.ServiceMethodMixin\r\n * @type {Object.}\r\n * @example\r\n * // Explicit casting with TypeScript\r\n * (myRpcService[\"myMethod\"] as protobuf.rpc.ServiceMethod)(...)\r\n */\r\n\r\n/**\r\n * Constructs a new RPC service instance.\r\n * @classdesc An RPC service as returned by {@link Service#create}.\r\n * @exports rpc.Service\r\n * @extends util.EventEmitter\r\n * @augments rpc.ServiceMethodMixin\r\n * @constructor\r\n * @param {RPCImpl} rpcImpl RPC implementation\r\n * @param {boolean} [requestDelimited=false] Whether requests are length-delimited\r\n * @param {boolean} [responseDelimited=false] Whether responses are length-delimited\r\n */\r\nfunction Service(rpcImpl, requestDelimited, responseDelimited) {\r\n\r\n if (typeof rpcImpl !== \"function\")\r\n throw TypeError(\"rpcImpl must be a function\");\r\n\r\n util.EventEmitter.call(this);\r\n\r\n /**\r\n * RPC implementation. Becomes `null` once the service is ended.\r\n * @type {?RPCImpl}\r\n */\r\n this.rpcImpl = rpcImpl;\r\n\r\n /**\r\n * Whether requests are length-delimited.\r\n * @type {boolean}\r\n */\r\n this.requestDelimited = Boolean(requestDelimited);\r\n\r\n /**\r\n * Whether responses are length-delimited.\r\n * @type {boolean}\r\n */\r\n this.responseDelimited = Boolean(responseDelimited);\r\n}\r\n\r\n/**\r\n * Calls a service method through {@link rpc.Service#rpcImpl|rpcImpl}.\r\n * @param {Method|rpc.ServiceMethod} method Reflected or static method\r\n * @param {function} requestCtor Request constructor\r\n * @param {function} responseCtor Response constructor\r\n * @param {Message|Object.} request Request message or plain object\r\n * @param {rpc.ServiceMethodCallback} callback Service callback\r\n * @returns {undefined}\r\n */\r\nService.prototype.rpcCall = function rpcCall(method, requestCtor, responseCtor, request, callback) {\r\n\r\n if (!request)\r\n throw TypeError(\"request must be specified\");\r\n\r\n var self = this;\r\n if (!callback)\r\n return util.asPromise(rpcCall, self, method, requestCtor, responseCtor, request);\r\n\r\n if (!self.rpcImpl) {\r\n setTimeout(function() { callback(Error(\"already ended\")); }, 0);\r\n return undefined;\r\n }\r\n\r\n try {\r\n return self.rpcImpl(\r\n method,\r\n requestCtor[self.requestDelimited ? \"encodeDelimited\" : \"encode\"](request).finish(),\r\n function rpcCallback(err, response) {\r\n\r\n if (err) {\r\n self.emit(\"error\", err, method);\r\n return callback(err);\r\n }\r\n\r\n if (response === null) {\r\n self.end(/* endedByRPC */ true);\r\n return undefined;\r\n }\r\n\r\n if (!(response instanceof responseCtor)) {\r\n try {\r\n response = responseCtor[self.responseDelimited ? \"decodeDelimited\" : \"decode\"](response);\r\n } catch (err) {\r\n self.emit(\"error\", err, method);\r\n return callback(err);\r\n }\r\n }\r\n\r\n self.emit(\"data\", response, method);\r\n return callback(null, response);\r\n }\r\n );\r\n } catch (err) {\r\n self.emit(\"error\", err, method);\r\n setTimeout(function() { callback(err); }, 0);\r\n return undefined;\r\n }\r\n};\r\n\r\n/**\r\n * Ends this service and emits the `end` event.\r\n * @param {boolean} [endedByRPC=false] Whether the service has been ended by the RPC implementation.\r\n * @returns {rpc.Service} `this`\r\n */\r\nService.prototype.end = function end(endedByRPC) {\r\n if (this.rpcImpl) {\r\n if (!endedByRPC) // signal end to rpcImpl\r\n this.rpcImpl(null, null, null);\r\n this.rpcImpl = null;\r\n this.emit(\"end\").off();\r\n }\r\n return this;\r\n};\r\n\r\n},{\"13\":13}],12:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = LongBits;\r\n\r\nvar util = require(13);\r\n\r\n/**\r\n * Any compatible Long instance.\r\n *\r\n * This is a minimal stand-alone definition of a Long instance. The actual type is that exported by long.js.\r\n * @typedef Long\r\n * @type {Object}\r\n * @property {number} low Low bits\r\n * @property {number} high High bits\r\n * @property {boolean} unsigned Whether unsigned or not\r\n */\r\n\r\n/**\r\n * Constructs new long bits.\r\n * @classdesc Helper class for working with the low and high bits of a 64 bit value.\r\n * @memberof util\r\n * @constructor\r\n * @param {number} lo Low 32 bits, unsigned\r\n * @param {number} hi High 32 bits, unsigned\r\n */\r\nfunction LongBits(lo, hi) {\r\n\r\n // note that the casts below are theoretically unnecessary as of today, but older statically\r\n // generated converter code might still call the ctor with signed 32bits. kept for compat.\r\n\r\n /**\r\n * Low bits.\r\n * @type {number}\r\n */\r\n this.lo = lo >>> 0;\r\n\r\n /**\r\n * High bits.\r\n * @type {number}\r\n */\r\n this.hi = hi >>> 0;\r\n}\r\n\r\n/**\r\n * Zero bits.\r\n * @memberof util.LongBits\r\n * @type {util.LongBits}\r\n */\r\nvar zero = LongBits.zero = new LongBits(0, 0);\r\n\r\nzero.toNumber = function() { return 0; };\r\nzero.zzEncode = zero.zzDecode = function() { return this; };\r\nzero.length = function() { return 1; };\r\n\r\n/**\r\n * Zero hash.\r\n * @memberof util.LongBits\r\n * @type {string}\r\n */\r\nvar zeroHash = LongBits.zeroHash = \"\\0\\0\\0\\0\\0\\0\\0\\0\";\r\n\r\n/**\r\n * Constructs new long bits from the specified number.\r\n * @param {number} value Value\r\n * @returns {util.LongBits} Instance\r\n */\r\nLongBits.fromNumber = function fromNumber(value) {\r\n if (value === 0)\r\n return zero;\r\n var sign = value < 0;\r\n if (sign)\r\n value = -value;\r\n var lo = value >>> 0,\r\n hi = (value - lo) / 4294967296 >>> 0;\r\n if (sign) {\r\n hi = ~hi >>> 0;\r\n lo = ~lo >>> 0;\r\n if (++lo > 4294967295) {\r\n lo = 0;\r\n if (++hi > 4294967295)\r\n hi = 0;\r\n }\r\n }\r\n return new LongBits(lo, hi);\r\n};\r\n\r\n/**\r\n * Constructs new long bits from a number, long or string.\r\n * @param {Long|number|string} value Value\r\n * @returns {util.LongBits} Instance\r\n */\r\nLongBits.from = function from(value) {\r\n if (typeof value === \"number\")\r\n return LongBits.fromNumber(value);\r\n if (util.isString(value)) {\r\n /* istanbul ignore else */\r\n if (util.Long)\r\n value = util.Long.fromString(value);\r\n else\r\n return LongBits.fromNumber(parseInt(value, 10));\r\n }\r\n return value.low || value.high ? new LongBits(value.low >>> 0, value.high >>> 0) : zero;\r\n};\r\n\r\n/**\r\n * Converts this long bits to a possibly unsafe JavaScript number.\r\n * @param {boolean} [unsigned=false] Whether unsigned or not\r\n * @returns {number} Possibly unsafe number\r\n */\r\nLongBits.prototype.toNumber = function toNumber(unsigned) {\r\n if (!unsigned && this.hi >>> 31) {\r\n var lo = ~this.lo + 1 >>> 0,\r\n hi = ~this.hi >>> 0;\r\n if (!lo)\r\n hi = hi + 1 >>> 0;\r\n return -(lo + hi * 4294967296);\r\n }\r\n return this.lo + this.hi * 4294967296;\r\n};\r\n\r\n/**\r\n * Converts this long bits to a long.\r\n * @param {boolean} [unsigned=false] Whether unsigned or not\r\n * @returns {Long} Long\r\n */\r\nLongBits.prototype.toLong = function toLong(unsigned) {\r\n return util.Long\r\n ? new util.Long(this.lo | 0, this.hi | 0, Boolean(unsigned))\r\n /* istanbul ignore next */\r\n : { low: this.lo | 0, high: this.hi | 0, unsigned: Boolean(unsigned) };\r\n};\r\n\r\nvar charCodeAt = String.prototype.charCodeAt;\r\n\r\n/**\r\n * Constructs new long bits from the specified 8 characters long hash.\r\n * @param {string} hash Hash\r\n * @returns {util.LongBits} Bits\r\n */\r\nLongBits.fromHash = function fromHash(hash) {\r\n if (hash === zeroHash)\r\n return zero;\r\n return new LongBits(\r\n ( charCodeAt.call(hash, 0)\r\n | charCodeAt.call(hash, 1) << 8\r\n | charCodeAt.call(hash, 2) << 16\r\n | charCodeAt.call(hash, 3) << 24) >>> 0\r\n ,\r\n ( charCodeAt.call(hash, 4)\r\n | charCodeAt.call(hash, 5) << 8\r\n | charCodeAt.call(hash, 6) << 16\r\n | charCodeAt.call(hash, 7) << 24) >>> 0\r\n );\r\n};\r\n\r\n/**\r\n * Converts this long bits to a 8 characters long hash.\r\n * @returns {string} Hash\r\n */\r\nLongBits.prototype.toHash = function toHash() {\r\n return String.fromCharCode(\r\n this.lo & 255,\r\n this.lo >>> 8 & 255,\r\n this.lo >>> 16 & 255,\r\n this.lo >>> 24 ,\r\n this.hi & 255,\r\n this.hi >>> 8 & 255,\r\n this.hi >>> 16 & 255,\r\n this.hi >>> 24\r\n );\r\n};\r\n\r\n/**\r\n * Zig-zag encodes this long bits.\r\n * @returns {util.LongBits} `this`\r\n */\r\nLongBits.prototype.zzEncode = function zzEncode() {\r\n var mask = this.hi >> 31;\r\n this.hi = ((this.hi << 1 | this.lo >>> 31) ^ mask) >>> 0;\r\n this.lo = ( this.lo << 1 ^ mask) >>> 0;\r\n return this;\r\n};\r\n\r\n/**\r\n * Zig-zag decodes this long bits.\r\n * @returns {util.LongBits} `this`\r\n */\r\nLongBits.prototype.zzDecode = function zzDecode() {\r\n var mask = -(this.lo & 1);\r\n this.lo = ((this.lo >>> 1 | this.hi << 31) ^ mask) >>> 0;\r\n this.hi = ( this.hi >>> 1 ^ mask) >>> 0;\r\n return this;\r\n};\r\n\r\n/**\r\n * Calculates the length of this longbits when encoded as a varint.\r\n * @returns {number} Length\r\n */\r\nLongBits.prototype.length = function length() {\r\n var part0 = this.lo,\r\n part1 = (this.lo >>> 28 | this.hi << 4) >>> 0,\r\n part2 = this.hi >>> 24;\r\n return part2 === 0\r\n ? part1 === 0\r\n ? part0 < 16384\r\n ? part0 < 128 ? 1 : 2\r\n : part0 < 2097152 ? 3 : 4\r\n : part1 < 16384\r\n ? part1 < 128 ? 5 : 6\r\n : part1 < 2097152 ? 7 : 8\r\n : part2 < 128 ? 9 : 10;\r\n};\r\n\r\n},{\"13\":13}],13:[function(require,module,exports){\r\n\"use strict\";\r\nvar util = exports;\r\n\r\n// used to return a Promise where callback is omitted\r\nutil.asPromise = require(1);\r\n\r\n// converts to / from base64 encoded strings\r\nutil.base64 = require(2);\r\n\r\n// base class of rpc.Service\r\nutil.EventEmitter = require(3);\r\n\r\n// requires modules optionally and hides the call from bundlers\r\nutil.inquire = require(4);\r\n\r\n// converts to / from utf8 encoded strings\r\nutil.utf8 = require(6);\r\n\r\n// provides a node-like buffer pool in the browser\r\nutil.pool = require(5);\r\n\r\n// utility to work with the low and high bits of a 64 bit value\r\nutil.LongBits = require(12);\r\n\r\n/**\r\n * An immuable empty array.\r\n * @memberof util\r\n * @type {Array.<*>}\r\n */\r\nutil.emptyArray = Object.freeze ? Object.freeze([]) : /* istanbul ignore next */ []; // used on prototypes\r\n\r\n/**\r\n * An immutable empty object.\r\n * @type {Object}\r\n */\r\nutil.emptyObject = Object.freeze ? Object.freeze({}) : /* istanbul ignore next */ {}; // used on prototypes\r\n\r\n/**\r\n * Whether running within node or not.\r\n * @memberof util\r\n * @type {boolean}\r\n */\r\nutil.isNode = Boolean(global.process && global.process.versions && global.process.versions.node);\r\n\r\n/**\r\n * Tests if the specified value is an integer.\r\n * @function\r\n * @param {*} value Value to test\r\n * @returns {boolean} `true` if the value is an integer\r\n */\r\nutil.isInteger = Number.isInteger || /* istanbul ignore next */ function isInteger(value) {\r\n return typeof value === \"number\" && isFinite(value) && Math.floor(value) === value;\r\n};\r\n\r\n/**\r\n * Tests if the specified value is a string.\r\n * @param {*} value Value to test\r\n * @returns {boolean} `true` if the value is a string\r\n */\r\nutil.isString = function isString(value) {\r\n return typeof value === \"string\" || value instanceof String;\r\n};\r\n\r\n/**\r\n * Tests if the specified value is a non-null object.\r\n * @param {*} value Value to test\r\n * @returns {boolean} `true` if the value is a non-null object\r\n */\r\nutil.isObject = function isObject(value) {\r\n return value && typeof value === \"object\";\r\n};\r\n\r\n/**\r\n * Node's Buffer class if available.\r\n * @type {?function(new: Buffer)}\r\n */\r\nutil.Buffer = (function() {\r\n try {\r\n var Buffer = util.inquire(\"buffer\").Buffer;\r\n // refuse to use non-node buffers if not explicitly assigned (perf reasons):\r\n return Buffer.prototype.utf8Write ? Buffer : /* istanbul ignore next */ null;\r\n } catch (e) {\r\n /* istanbul ignore next */\r\n return null;\r\n }\r\n})();\r\n\r\n/**\r\n * Internal alias of or polyfull for Buffer.from.\r\n * @type {?function}\r\n * @param {string|number[]} value Value\r\n * @param {string} [encoding] Encoding if value is a string\r\n * @returns {Uint8Array}\r\n * @private\r\n */\r\nutil._Buffer_from = null;\r\n\r\n/**\r\n * Internal alias of or polyfill for Buffer.allocUnsafe.\r\n * @type {?function}\r\n * @param {number} size Buffer size\r\n * @returns {Uint8Array}\r\n * @private\r\n */\r\nutil._Buffer_allocUnsafe = null;\r\n\r\n/**\r\n * Creates a new buffer of whatever type supported by the environment.\r\n * @param {number|number[]} [sizeOrArray=0] Buffer size or number array\r\n * @returns {Uint8Array|Buffer} Buffer\r\n */\r\nutil.newBuffer = function newBuffer(sizeOrArray) {\r\n /* istanbul ignore next */\r\n return typeof sizeOrArray === \"number\"\r\n ? util.Buffer\r\n ? util._Buffer_allocUnsafe(sizeOrArray)\r\n : new util.Array(sizeOrArray)\r\n : util.Buffer\r\n ? util._Buffer_from(sizeOrArray)\r\n : typeof Uint8Array === \"undefined\"\r\n ? sizeOrArray\r\n : new Uint8Array(sizeOrArray);\r\n};\r\n\r\n/**\r\n * Array implementation used in the browser. `Uint8Array` if supported, otherwise `Array`.\r\n * @type {?function(new: Uint8Array, *)}\r\n */\r\nutil.Array = typeof Uint8Array !== \"undefined\" ? Uint8Array /* istanbul ignore next */ : Array;\r\n\r\n/**\r\n * Long.js's Long class if available.\r\n * @type {?function(new: Long)}\r\n */\r\nutil.Long = /* istanbul ignore next */ global.dcodeIO && /* istanbul ignore next */ global.dcodeIO.Long || util.inquire(\"long\");\r\n\r\n/**\r\n * Regular expression used to verify 2 bit (`bool`) map keys.\r\n * @type {RegExp}\r\n */\r\nutil.key2Re = /^true|false|0|1$/;\r\n\r\n/**\r\n * Regular expression used to verify 32 bit (`int32` etc.) map keys.\r\n * @type {RegExp}\r\n */\r\nutil.key32Re = /^-?(?:0|[1-9][0-9]*)$/;\r\n\r\n/**\r\n * Regular expression used to verify 64 bit (`int64` etc.) map keys.\r\n * @type {RegExp}\r\n */\r\nutil.key64Re = /^(?:[\\\\x00-\\\\xff]{8}|-?(?:0|[1-9][0-9]*))$/;\r\n\r\n/**\r\n * Converts a number or long to an 8 characters long hash string.\r\n * @param {Long|number} value Value to convert\r\n * @returns {string} Hash\r\n */\r\nutil.longToHash = function longToHash(value) {\r\n return value\r\n ? util.LongBits.from(value).toHash()\r\n : util.LongBits.zeroHash;\r\n};\r\n\r\n/**\r\n * Converts an 8 characters long hash string to a long or number.\r\n * @param {string} hash Hash\r\n * @param {boolean} [unsigned=false] Whether unsigned or not\r\n * @returns {Long|number} Original value\r\n */\r\nutil.longFromHash = function longFromHash(hash, unsigned) {\r\n var bits = util.LongBits.fromHash(hash);\r\n if (util.Long)\r\n return util.Long.fromBits(bits.lo, bits.hi, unsigned);\r\n return bits.toNumber(Boolean(unsigned));\r\n};\r\n\r\n/**\r\n * Merges the properties of the source object into the destination object.\r\n * @memberof util\r\n * @param {Object.} dst Destination object\r\n * @param {Object.} src Source object\r\n * @param {boolean} [ifNotSet=false] Merges only if the key is not already set\r\n * @returns {Object.} Destination object\r\n */\r\nfunction merge(dst, src, ifNotSet) { // used by converters\r\n for (var keys = Object.keys(src), i = 0; i < keys.length; ++i)\r\n if (dst[keys[i]] === undefined || !ifNotSet)\r\n dst[keys[i]] = src[keys[i]];\r\n return dst;\r\n}\r\n\r\nutil.merge = merge;\r\n\r\n/**\r\n * Converts the first character of a string to lower case.\r\n * @param {string} str String to convert\r\n * @returns {string} Converted string\r\n */\r\nutil.lcFirst = function lcFirst(str) {\r\n return str.charAt(0).toLowerCase() + str.substring(1);\r\n};\r\n\r\n/**\r\n * Creates a custom error constructor.\r\n * @memberof util\r\n * @param {string} name Error name\r\n * @returns {function} Custom error constructor\r\n */\r\nfunction newError(name) {\r\n\r\n function CustomError(message, properties) {\r\n\r\n if (!(this instanceof CustomError))\r\n return new CustomError(message, properties);\r\n\r\n // Error.call(this, message);\r\n // ^ just returns a new error instance because the ctor can be called as a function\r\n\r\n Object.defineProperty(this, \"message\", { get: function() { return message; } });\r\n\r\n /* istanbul ignore next */\r\n if (Error.captureStackTrace) // node\r\n Error.captureStackTrace(this, CustomError);\r\n else\r\n Object.defineProperty(this, \"stack\", { value: (new Error()).stack || \"\" });\r\n\r\n if (properties)\r\n merge(this, properties);\r\n }\r\n\r\n (CustomError.prototype = Object.create(Error.prototype)).constructor = CustomError;\r\n\r\n Object.defineProperty(CustomError.prototype, \"name\", { get: function() { return name; } });\r\n\r\n CustomError.prototype.toString = function toString() {\r\n return this.name + \": \" + this.message;\r\n };\r\n\r\n return CustomError;\r\n}\r\n\r\nutil.newError = newError;\r\n\r\n/**\r\n * Constructs a new protocol error.\r\n * @classdesc Error subclass indicating a protocol specifc error.\r\n * @memberof util\r\n * @extends Error\r\n * @constructor\r\n * @param {string} message Error message\r\n * @param {Object.=} properties Additional properties\r\n * @example\r\n * try {\r\n * MyMessage.decode(someBuffer); // throws if required fields are missing\r\n * } catch (e) {\r\n * if (e instanceof ProtocolError && e.instance)\r\n * console.log(\"decoded so far: \" + JSON.stringify(e.instance));\r\n * }\r\n */\r\nutil.ProtocolError = newError(\"ProtocolError\");\r\n\r\n/**\r\n * So far decoded message instance.\r\n * @name util.ProtocolError#instance\r\n * @type {Message}\r\n */\r\n\r\n/**\r\n * Builds a getter for a oneof's present field name.\r\n * @param {string[]} fieldNames Field names\r\n * @returns {function():string|undefined} Unbound getter\r\n */\r\nutil.oneOfGetter = function getOneOf(fieldNames) {\r\n var fieldMap = {};\r\n for (var i = 0; i < fieldNames.length; ++i)\r\n fieldMap[fieldNames[i]] = 1;\r\n\r\n /**\r\n * @returns {string|undefined} Set field name, if any\r\n * @this Object\r\n * @ignore\r\n */\r\n return function() { // eslint-disable-line consistent-return\r\n for (var keys = Object.keys(this), i = keys.length - 1; i > -1; --i)\r\n if (fieldMap[keys[i]] === 1 && this[keys[i]] !== undefined && this[keys[i]] !== null)\r\n return keys[i];\r\n };\r\n};\r\n\r\n/**\r\n * Builds a setter for a oneof's present field name.\r\n * @param {string[]} fieldNames Field names\r\n * @returns {function(?string):undefined} Unbound setter\r\n */\r\nutil.oneOfSetter = function setOneOf(fieldNames) {\r\n\r\n /**\r\n * @param {string} name Field name\r\n * @returns {undefined}\r\n * @this Object\r\n * @ignore\r\n */\r\n return function(name) {\r\n for (var i = 0; i < fieldNames.length; ++i)\r\n if (fieldNames[i] !== name)\r\n delete this[fieldNames[i]];\r\n };\r\n};\r\n\r\n/**\r\n * Lazily resolves fully qualified type names against the specified root.\r\n * @param {Root} root Root instanceof\r\n * @param {Object.} lazyTypes Type names\r\n * @returns {undefined}\r\n */\r\nutil.lazyResolve = function lazyResolve(root, lazyTypes) {\r\n for (var i = 0; i < lazyTypes.length; ++i) {\r\n for (var keys = Object.keys(lazyTypes[i]), j = 0; j < keys.length; ++j) {\r\n var path = lazyTypes[i][keys[j]].split(\".\"),\r\n ptr = root;\r\n while (path.length)\r\n ptr = ptr[path.shift()];\r\n lazyTypes[i][keys[j]] = ptr;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Default conversion options used for {@link Message#toJSON} implementations. Longs, enums and bytes are converted to strings by default.\r\n * @type {ConversionOptions}\r\n */\r\nutil.toJSONOptions = {\r\n longs: String,\r\n enums: String,\r\n bytes: String\r\n};\r\n\r\nutil._configure = function() {\r\n var Buffer = util.Buffer;\r\n /* istanbul ignore if */\r\n if (!Buffer) {\r\n util._Buffer_from = util._Buffer_allocUnsafe = null;\r\n return;\r\n }\r\n // because node 4.x buffers are incompatible & immutable\r\n // see: https://github.com/dcodeIO/protobuf.js/pull/665\r\n util._Buffer_from = Buffer.from !== Uint8Array.from && Buffer.from ||\r\n /* istanbul ignore next */\r\n function Buffer_from(value, encoding) {\r\n return new Buffer(value, encoding);\r\n };\r\n util._Buffer_allocUnsafe = Buffer.allocUnsafe ||\r\n /* istanbul ignore next */\r\n function Buffer_allocUnsafe(size) {\r\n return new Buffer(size);\r\n };\r\n};\r\n\r\n},{\"1\":1,\"12\":12,\"2\":2,\"3\":3,\"4\":4,\"5\":5,\"6\":6}],14:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = Writer;\r\n\r\nvar util = require(13);\r\n\r\nvar BufferWriter; // cyclic\r\n\r\nvar LongBits = util.LongBits,\r\n base64 = util.base64,\r\n utf8 = util.utf8;\r\n\r\n/**\r\n * Constructs a new writer operation instance.\r\n * @classdesc Scheduled writer operation.\r\n * @constructor\r\n * @param {function(*, Uint8Array, number)} fn Function to call\r\n * @param {number} len Value byte length\r\n * @param {*} val Value to write\r\n * @ignore\r\n */\r\nfunction Op(fn, len, val) {\r\n\r\n /**\r\n * Function to call.\r\n * @type {function(Uint8Array, number, *)}\r\n */\r\n this.fn = fn;\r\n\r\n /**\r\n * Value byte length.\r\n * @type {number}\r\n */\r\n this.len = len;\r\n\r\n /**\r\n * Next operation.\r\n * @type {Writer.Op|undefined}\r\n */\r\n this.next = undefined;\r\n\r\n /**\r\n * Value to write.\r\n * @type {*}\r\n */\r\n this.val = val; // type varies\r\n}\r\n\r\n/* istanbul ignore next */\r\nfunction noop() {} // eslint-disable-line no-empty-function\r\n\r\n/**\r\n * Constructs a new writer state instance.\r\n * @classdesc Copied writer state.\r\n * @memberof Writer\r\n * @constructor\r\n * @param {Writer} writer Writer to copy state from\r\n * @private\r\n * @ignore\r\n */\r\nfunction State(writer) {\r\n\r\n /**\r\n * Current head.\r\n * @type {Writer.Op}\r\n */\r\n this.head = writer.head;\r\n\r\n /**\r\n * Current tail.\r\n * @type {Writer.Op}\r\n */\r\n this.tail = writer.tail;\r\n\r\n /**\r\n * Current buffer length.\r\n * @type {number}\r\n */\r\n this.len = writer.len;\r\n\r\n /**\r\n * Next state.\r\n * @type {?State}\r\n */\r\n this.next = writer.states;\r\n}\r\n\r\n/**\r\n * Constructs a new writer instance.\r\n * @classdesc Wire format writer using `Uint8Array` if available, otherwise `Array`.\r\n * @constructor\r\n */\r\nfunction Writer() {\r\n\r\n /**\r\n * Current length.\r\n * @type {number}\r\n */\r\n this.len = 0;\r\n\r\n /**\r\n * Operations head.\r\n * @type {Object}\r\n */\r\n this.head = new Op(noop, 0, 0);\r\n\r\n /**\r\n * Operations tail\r\n * @type {Object}\r\n */\r\n this.tail = this.head;\r\n\r\n /**\r\n * Linked forked states.\r\n * @type {?Object}\r\n */\r\n this.states = null;\r\n\r\n // When a value is written, the writer calculates its byte length and puts it into a linked\r\n // list of operations to perform when finish() is called. This both allows us to allocate\r\n // buffers of the exact required size and reduces the amount of work we have to do compared\r\n // to first calculating over objects and then encoding over objects. In our case, the encoding\r\n // part is just a linked list walk calling operations with already prepared values.\r\n}\r\n\r\n/**\r\n * Creates a new writer.\r\n * @function\r\n * @returns {BufferWriter|Writer} A {@link BufferWriter} when Buffers are supported, otherwise a {@link Writer}\r\n */\r\nWriter.create = util.Buffer\r\n ? function create_buffer_setup() {\r\n return (Writer.create = function create_buffer() {\r\n return new BufferWriter();\r\n })();\r\n }\r\n /* istanbul ignore next */\r\n : function create_array() {\r\n return new Writer();\r\n };\r\n\r\n/**\r\n * Allocates a buffer of the specified size.\r\n * @param {number} size Buffer size\r\n * @returns {Uint8Array} Buffer\r\n */\r\nWriter.alloc = function alloc(size) {\r\n return new util.Array(size);\r\n};\r\n\r\n// Use Uint8Array buffer pool in the browser, just like node does with buffers\r\n/* istanbul ignore else */\r\nif (util.Array !== Array)\r\n Writer.alloc = util.pool(Writer.alloc, util.Array.prototype.subarray);\r\n\r\n/**\r\n * Pushes a new operation to the queue.\r\n * @param {function(Uint8Array, number, *)} fn Function to call\r\n * @param {number} len Value byte length\r\n * @param {number} val Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.push = function push(fn, len, val) {\r\n this.tail = this.tail.next = new Op(fn, len, val);\r\n this.len += len;\r\n return this;\r\n};\r\n\r\nfunction writeByte(val, buf, pos) {\r\n buf[pos] = val & 255;\r\n}\r\n\r\nfunction writeVarint32(val, buf, pos) {\r\n while (val > 127) {\r\n buf[pos++] = val & 127 | 128;\r\n val >>>= 7;\r\n }\r\n buf[pos] = val;\r\n}\r\n\r\n/**\r\n * Constructs a new varint writer operation instance.\r\n * @classdesc Scheduled varint writer operation.\r\n * @extends Op\r\n * @constructor\r\n * @param {number} len Value byte length\r\n * @param {number} val Value to write\r\n * @ignore\r\n */\r\nfunction VarintOp(len, val) {\r\n this.len = len;\r\n this.next = undefined;\r\n this.val = val;\r\n}\r\n\r\nVarintOp.prototype = Object.create(Op.prototype);\r\nVarintOp.prototype.fn = writeVarint32;\r\n\r\n/**\r\n * Writes an unsigned 32 bit value as a varint.\r\n * @param {number} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.uint32 = function write_uint32(value) {\r\n // here, the call to this.push has been inlined and a varint specific Op subclass is used.\r\n // uint32 is by far the most frequently used operation and benefits significantly from this.\r\n this.len += (this.tail = this.tail.next = new VarintOp(\r\n (value = value >>> 0)\r\n < 128 ? 1\r\n : value < 16384 ? 2\r\n : value < 2097152 ? 3\r\n : value < 268435456 ? 4\r\n : 5,\r\n value)).len;\r\n return this;\r\n};\r\n\r\n/**\r\n * Writes a signed 32 bit value as a varint.\r\n * @function\r\n * @param {number} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.int32 = function write_int32(value) {\r\n return value < 0\r\n ? this.push(writeVarint64, 10, LongBits.fromNumber(value)) // 10 bytes per spec\r\n : this.uint32(value);\r\n};\r\n\r\n/**\r\n * Writes a 32 bit value as a varint, zig-zag encoded.\r\n * @param {number} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.sint32 = function write_sint32(value) {\r\n return this.uint32((value << 1 ^ value >> 31) >>> 0);\r\n};\r\n\r\nfunction writeVarint64(val, buf, pos) {\r\n while (val.hi) {\r\n buf[pos++] = val.lo & 127 | 128;\r\n val.lo = (val.lo >>> 7 | val.hi << 25) >>> 0;\r\n val.hi >>>= 7;\r\n }\r\n while (val.lo > 127) {\r\n buf[pos++] = val.lo & 127 | 128;\r\n val.lo = val.lo >>> 7;\r\n }\r\n buf[pos++] = val.lo;\r\n}\r\n\r\n/**\r\n * Writes an unsigned 64 bit value as a varint.\r\n * @param {Long|number|string} value Value to write\r\n * @returns {Writer} `this`\r\n * @throws {TypeError} If `value` is a string and no long library is present.\r\n */\r\nWriter.prototype.uint64 = function write_uint64(value) {\r\n var bits = LongBits.from(value);\r\n return this.push(writeVarint64, bits.length(), bits);\r\n};\r\n\r\n/**\r\n * Writes a signed 64 bit value as a varint.\r\n * @function\r\n * @param {Long|number|string} value Value to write\r\n * @returns {Writer} `this`\r\n * @throws {TypeError} If `value` is a string and no long library is present.\r\n */\r\nWriter.prototype.int64 = Writer.prototype.uint64;\r\n\r\n/**\r\n * Writes a signed 64 bit value as a varint, zig-zag encoded.\r\n * @param {Long|number|string} value Value to write\r\n * @returns {Writer} `this`\r\n * @throws {TypeError} If `value` is a string and no long library is present.\r\n */\r\nWriter.prototype.sint64 = function write_sint64(value) {\r\n var bits = LongBits.from(value).zzEncode();\r\n return this.push(writeVarint64, bits.length(), bits);\r\n};\r\n\r\n/**\r\n * Writes a boolish value as a varint.\r\n * @param {boolean} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.bool = function write_bool(value) {\r\n return this.push(writeByte, 1, value ? 1 : 0);\r\n};\r\n\r\nfunction writeFixed32(val, buf, pos) {\r\n buf[pos++] = val & 255;\r\n buf[pos++] = val >>> 8 & 255;\r\n buf[pos++] = val >>> 16 & 255;\r\n buf[pos ] = val >>> 24;\r\n}\r\n\r\n/**\r\n * Writes an unsigned 32 bit value as fixed 32 bits.\r\n * @param {number} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.fixed32 = function write_fixed32(value) {\r\n return this.push(writeFixed32, 4, value >>> 0);\r\n};\r\n\r\n/**\r\n * Writes a signed 32 bit value as fixed 32 bits.\r\n * @function\r\n * @param {number} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.sfixed32 = Writer.prototype.fixed32;\r\n\r\n/**\r\n * Writes an unsigned 64 bit value as fixed 64 bits.\r\n * @param {Long|number|string} value Value to write\r\n * @returns {Writer} `this`\r\n * @throws {TypeError} If `value` is a string and no long library is present.\r\n */\r\nWriter.prototype.fixed64 = function write_fixed64(value) {\r\n var bits = LongBits.from(value);\r\n return this.push(writeFixed32, 4, bits.lo).push(writeFixed32, 4, bits.hi);\r\n};\r\n\r\n/**\r\n * Writes a signed 64 bit value as fixed 64 bits.\r\n * @function\r\n * @param {Long|number|string} value Value to write\r\n * @returns {Writer} `this`\r\n * @throws {TypeError} If `value` is a string and no long library is present.\r\n */\r\nWriter.prototype.sfixed64 = Writer.prototype.fixed64;\r\n\r\nvar writeFloat = typeof Float32Array !== \"undefined\"\r\n ? (function() {\r\n var f32 = new Float32Array(1),\r\n f8b = new Uint8Array(f32.buffer);\r\n f32[0] = -0;\r\n return f8b[3] // already le?\r\n ? function writeFloat_f32(val, buf, pos) {\r\n f32[0] = val;\r\n buf[pos++] = f8b[0];\r\n buf[pos++] = f8b[1];\r\n buf[pos++] = f8b[2];\r\n buf[pos ] = f8b[3];\r\n }\r\n /* istanbul ignore next */\r\n : function writeFloat_f32_le(val, buf, pos) {\r\n f32[0] = val;\r\n buf[pos++] = f8b[3];\r\n buf[pos++] = f8b[2];\r\n buf[pos++] = f8b[1];\r\n buf[pos ] = f8b[0];\r\n };\r\n })()\r\n /* istanbul ignore next */\r\n : function writeFloat_ieee754(value, buf, pos) {\r\n var sign = value < 0 ? 1 : 0;\r\n if (sign)\r\n value = -value;\r\n if (value === 0)\r\n writeFixed32(1 / value > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos);\r\n else if (isNaN(value))\r\n writeFixed32(2147483647, buf, pos);\r\n else if (value > 3.4028234663852886e+38) // +-Infinity\r\n writeFixed32((sign << 31 | 2139095040) >>> 0, buf, pos);\r\n else if (value < 1.1754943508222875e-38) // denormal\r\n writeFixed32((sign << 31 | Math.round(value / 1.401298464324817e-45)) >>> 0, buf, pos);\r\n else {\r\n var exponent = Math.floor(Math.log(value) / Math.LN2),\r\n mantissa = Math.round(value * Math.pow(2, -exponent) * 8388608) & 8388607;\r\n writeFixed32((sign << 31 | exponent + 127 << 23 | mantissa) >>> 0, buf, pos);\r\n }\r\n };\r\n\r\n/**\r\n * Writes a float (32 bit).\r\n * @function\r\n * @param {number} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.float = function write_float(value) {\r\n return this.push(writeFloat, 4, value);\r\n};\r\n\r\nvar writeDouble = typeof Float64Array !== \"undefined\"\r\n ? (function() {\r\n var f64 = new Float64Array(1),\r\n f8b = new Uint8Array(f64.buffer);\r\n f64[0] = -0;\r\n return f8b[7] // already le?\r\n ? function writeDouble_f64(val, buf, pos) {\r\n f64[0] = val;\r\n buf[pos++] = f8b[0];\r\n buf[pos++] = f8b[1];\r\n buf[pos++] = f8b[2];\r\n buf[pos++] = f8b[3];\r\n buf[pos++] = f8b[4];\r\n buf[pos++] = f8b[5];\r\n buf[pos++] = f8b[6];\r\n buf[pos ] = f8b[7];\r\n }\r\n /* istanbul ignore next */\r\n : function writeDouble_f64_le(val, buf, pos) {\r\n f64[0] = val;\r\n buf[pos++] = f8b[7];\r\n buf[pos++] = f8b[6];\r\n buf[pos++] = f8b[5];\r\n buf[pos++] = f8b[4];\r\n buf[pos++] = f8b[3];\r\n buf[pos++] = f8b[2];\r\n buf[pos++] = f8b[1];\r\n buf[pos ] = f8b[0];\r\n };\r\n })()\r\n /* istanbul ignore next */\r\n : function writeDouble_ieee754(value, buf, pos) {\r\n var sign = value < 0 ? 1 : 0;\r\n if (sign)\r\n value = -value;\r\n if (value === 0) {\r\n writeFixed32(0, buf, pos);\r\n writeFixed32(1 / value > 0 ? /* positive */ 0 : /* negative 0 */ 2147483648, buf, pos + 4);\r\n } else if (isNaN(value)) {\r\n writeFixed32(4294967295, buf, pos);\r\n writeFixed32(2147483647, buf, pos + 4);\r\n } else if (value > 1.7976931348623157e+308) { // +-Infinity\r\n writeFixed32(0, buf, pos);\r\n writeFixed32((sign << 31 | 2146435072) >>> 0, buf, pos + 4);\r\n } else {\r\n var mantissa;\r\n if (value < 2.2250738585072014e-308) { // denormal\r\n mantissa = value / 5e-324;\r\n writeFixed32(mantissa >>> 0, buf, pos);\r\n writeFixed32((sign << 31 | mantissa / 4294967296) >>> 0, buf, pos + 4);\r\n } else {\r\n var exponent = Math.floor(Math.log(value) / Math.LN2);\r\n if (exponent === 1024)\r\n exponent = 1023;\r\n mantissa = value * Math.pow(2, -exponent);\r\n writeFixed32(mantissa * 4503599627370496 >>> 0, buf, pos);\r\n writeFixed32((sign << 31 | exponent + 1023 << 20 | mantissa * 1048576 & 1048575) >>> 0, buf, pos + 4);\r\n }\r\n }\r\n };\r\n\r\n/**\r\n * Writes a double (64 bit float).\r\n * @function\r\n * @param {number} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.double = function write_double(value) {\r\n return this.push(writeDouble, 8, value);\r\n};\r\n\r\nvar writeBytes = util.Array.prototype.set\r\n ? function writeBytes_set(val, buf, pos) {\r\n buf.set(val, pos); // also works for plain array values\r\n }\r\n /* istanbul ignore next */\r\n : function writeBytes_for(val, buf, pos) {\r\n for (var i = 0; i < val.length; ++i)\r\n buf[pos + i] = val[i];\r\n };\r\n\r\n/**\r\n * Writes a sequence of bytes.\r\n * @param {Uint8Array|string} value Buffer or base64 encoded string to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.bytes = function write_bytes(value) {\r\n var len = value.length >>> 0;\r\n if (!len)\r\n return this.push(writeByte, 1, 0);\r\n if (util.isString(value)) {\r\n var buf = Writer.alloc(len = base64.length(value));\r\n base64.decode(value, buf, 0);\r\n value = buf;\r\n }\r\n return this.uint32(len).push(writeBytes, len, value);\r\n};\r\n\r\n/**\r\n * Writes a string.\r\n * @param {string} value Value to write\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.string = function write_string(value) {\r\n var len = utf8.length(value);\r\n return len\r\n ? this.uint32(len).push(utf8.write, len, value)\r\n : this.push(writeByte, 1, 0);\r\n};\r\n\r\n/**\r\n * Forks this writer's state by pushing it to a stack.\r\n * Calling {@link Writer#reset|reset} or {@link Writer#ldelim|ldelim} resets the writer to the previous state.\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.fork = function fork() {\r\n this.states = new State(this);\r\n this.head = this.tail = new Op(noop, 0, 0);\r\n this.len = 0;\r\n return this;\r\n};\r\n\r\n/**\r\n * Resets this instance to the last state.\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.reset = function reset() {\r\n if (this.states) {\r\n this.head = this.states.head;\r\n this.tail = this.states.tail;\r\n this.len = this.states.len;\r\n this.states = this.states.next;\r\n } else {\r\n this.head = this.tail = new Op(noop, 0, 0);\r\n this.len = 0;\r\n }\r\n return this;\r\n};\r\n\r\n/**\r\n * Resets to the last state and appends the fork state's current write length as a varint followed by its operations.\r\n * @returns {Writer} `this`\r\n */\r\nWriter.prototype.ldelim = function ldelim() {\r\n var head = this.head,\r\n tail = this.tail,\r\n len = this.len;\r\n this.reset().uint32(len);\r\n if (len) {\r\n this.tail.next = head.next; // skip noop\r\n this.tail = tail;\r\n this.len += len;\r\n }\r\n return this;\r\n};\r\n\r\n/**\r\n * Finishes the write operation.\r\n * @returns {Uint8Array} Finished buffer\r\n */\r\nWriter.prototype.finish = function finish() {\r\n var head = this.head.next, // skip noop\r\n buf = this.constructor.alloc(this.len),\r\n pos = 0;\r\n while (head) {\r\n head.fn(head.val, buf, pos);\r\n pos += head.len;\r\n head = head.next;\r\n }\r\n // this.head = this.tail = null;\r\n return buf;\r\n};\r\n\r\nWriter._configure = function(BufferWriter_) {\r\n BufferWriter = BufferWriter_;\r\n};\r\n\r\n},{\"13\":13}],15:[function(require,module,exports){\r\n\"use strict\";\r\nmodule.exports = BufferWriter;\r\n\r\n// extends Writer\r\nvar Writer = require(14);\r\n(BufferWriter.prototype = Object.create(Writer.prototype)).constructor = BufferWriter;\r\n\r\nvar util = require(13);\r\n\r\nvar Buffer = util.Buffer;\r\n\r\n/**\r\n * Constructs a new buffer writer instance.\r\n * @classdesc Wire format writer using node buffers.\r\n * @extends Writer\r\n * @constructor\r\n */\r\nfunction BufferWriter() {\r\n Writer.call(this);\r\n}\r\n\r\n/**\r\n * Allocates a buffer of the specified size.\r\n * @param {number} size Buffer size\r\n * @returns {Buffer} Buffer\r\n */\r\nBufferWriter.alloc = function alloc_buffer(size) {\r\n return (BufferWriter.alloc = util._Buffer_allocUnsafe)(size);\r\n};\r\n\r\nvar writeBytesBuffer = Buffer && Buffer.prototype instanceof Uint8Array && Buffer.prototype.set.name === \"set\"\r\n ? function writeBytesBuffer_set(val, buf, pos) {\r\n buf.set(val, pos); // faster than copy (requires node >= 4 where Buffers extend Uint8Array and set is properly inherited)\r\n // also works for plain array values\r\n }\r\n /* istanbul ignore next */\r\n : function writeBytesBuffer_copy(val, buf, pos) {\r\n if (val.copy) // Buffer values\r\n val.copy(buf, pos, 0, val.length);\r\n else for (var i = 0; i < val.length;) // plain array values\r\n buf[pos++] = val[i++];\r\n };\r\n\r\n/**\r\n * @override\r\n */\r\nBufferWriter.prototype.bytes = function write_bytes_buffer(value) {\r\n if (util.isString(value))\r\n value = util._Buffer_from(value, \"base64\");\r\n var len = value.length >>> 0;\r\n this.uint32(len);\r\n if (len)\r\n this.push(writeBytesBuffer, len, value);\r\n return this;\r\n};\r\n\r\nfunction writeStringBuffer(val, buf, pos) {\r\n if (val.length < 40) // plain js is faster for short strings (probably due to redundant assertions)\r\n util.utf8.write(val, buf, pos);\r\n else\r\n buf.utf8Write(val, pos);\r\n}\r\n\r\n/**\r\n * @override\r\n */\r\nBufferWriter.prototype.string = function write_string_buffer(value) {\r\n var len = Buffer.byteLength(value);\r\n this.uint32(len);\r\n if (len)\r\n this.push(writeStringBuffer, len, value);\r\n return this;\r\n};\r\n\r\n\r\n/**\r\n * Finishes the write operation.\r\n * @name BufferWriter#finish\r\n * @function\r\n * @returns {Buffer} Finished buffer\r\n */\r\n\r\n},{\"13\":13,\"14\":14}]},{},[7])\r\n\r\n})(tmp);\r\n//# sourceMappingURL=protobuf.js.map\r\n\r\nexport default tmp.protobuf;\r\n","/**\r\n * @private\r\n */\r\nfunction isBitSet(bits, mask) {\r\n return (bits & mask) !== 0;\r\n}\r\nexport default isBitSet;\r\n","import defined from \"./defined.js\";\r\nimport isBitSet from \"./isBitSet.js\";\r\n\r\n// Bitmask for checking tile properties\r\nvar childrenBitmasks = [0x01, 0x02, 0x04, 0x08];\r\nvar anyChildBitmask = 0x0f;\r\nvar cacheFlagBitmask = 0x10; // True if there is a child subtree\r\nvar imageBitmask = 0x40;\r\nvar terrainBitmask = 0x80;\r\n\r\n/**\r\n * Contains information about each tile from a Google Earth Enterprise server\r\n *\r\n * @param {Number} bits Bitmask that contains the type of data and available children for each tile.\r\n * @param {Number} cnodeVersion Version of the request for subtree metadata.\r\n * @param {Number} imageryVersion Version of the request for imagery tile.\r\n * @param {Number} terrainVersion Version of the request for terrain tile.\r\n * @param {Number} imageryProvider Id of imagery provider.\r\n * @param {Number} terrainProvider Id of terrain provider.\r\n *\r\n * @private\r\n */\r\nfunction GoogleEarthEnterpriseTileInformation(\r\n bits,\r\n cnodeVersion,\r\n imageryVersion,\r\n terrainVersion,\r\n imageryProvider,\r\n terrainProvider\r\n) {\r\n this._bits = bits;\r\n this.cnodeVersion = cnodeVersion;\r\n this.imageryVersion = imageryVersion;\r\n this.terrainVersion = terrainVersion;\r\n this.imageryProvider = imageryProvider;\r\n this.terrainProvider = terrainProvider;\r\n this.ancestorHasTerrain = false; // Set it later once we find its parent\r\n this.terrainState = undefined;\r\n}\r\n\r\n/**\r\n * Creates GoogleEarthEnterpriseTileInformation from an object\r\n *\r\n * @param {Object} info Object to be cloned\r\n * @param {GoogleEarthEnterpriseTileInformation} [result] The object onto which to store the result.\r\n * @returns {GoogleEarthEnterpriseTileInformation} The modified result parameter or a new GoogleEarthEnterpriseTileInformation instance if none was provided.\r\n */\r\nGoogleEarthEnterpriseTileInformation.clone = function (info, result) {\r\n if (!defined(result)) {\r\n result = new GoogleEarthEnterpriseTileInformation(\r\n info._bits,\r\n info.cnodeVersion,\r\n info.imageryVersion,\r\n info.terrainVersion,\r\n info.imageryProvider,\r\n info.terrainProvider\r\n );\r\n } else {\r\n result._bits = info._bits;\r\n result.cnodeVersion = info.cnodeVersion;\r\n result.imageryVersion = info.imageryVersion;\r\n result.terrainVersion = info.terrainVersion;\r\n result.imageryProvider = info.imageryProvider;\r\n result.terrainProvider = info.terrainProvider;\r\n }\r\n result.ancestorHasTerrain = info.ancestorHasTerrain;\r\n result.terrainState = info.terrainState;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Sets the parent for the tile\r\n *\r\n * @param {GoogleEarthEnterpriseTileInformation} parent Parent tile\r\n */\r\nGoogleEarthEnterpriseTileInformation.prototype.setParent = function (parent) {\r\n this.ancestorHasTerrain = parent.ancestorHasTerrain || this.hasTerrain();\r\n};\r\n\r\n/**\r\n * Gets whether a subtree is available\r\n *\r\n * @returns {Boolean} true if subtree is available, false otherwise.\r\n */\r\nGoogleEarthEnterpriseTileInformation.prototype.hasSubtree = function () {\r\n return isBitSet(this._bits, cacheFlagBitmask);\r\n};\r\n\r\n/**\r\n * Gets whether imagery is available\r\n *\r\n * @returns {Boolean} true if imagery is available, false otherwise.\r\n */\r\nGoogleEarthEnterpriseTileInformation.prototype.hasImagery = function () {\r\n return isBitSet(this._bits, imageBitmask);\r\n};\r\n\r\n/**\r\n * Gets whether terrain is available\r\n *\r\n * @returns {Boolean} true if terrain is available, false otherwise.\r\n */\r\nGoogleEarthEnterpriseTileInformation.prototype.hasTerrain = function () {\r\n return isBitSet(this._bits, terrainBitmask);\r\n};\r\n\r\n/**\r\n * Gets whether any children are present\r\n *\r\n * @returns {Boolean} true if any children are available, false otherwise.\r\n */\r\nGoogleEarthEnterpriseTileInformation.prototype.hasChildren = function () {\r\n return isBitSet(this._bits, anyChildBitmask);\r\n};\r\n\r\n/**\r\n * Gets whether a specified child is available\r\n *\r\n * @param {Number} index Index of child tile\r\n *\r\n * @returns {Boolean} true if child is available, false otherwise\r\n */\r\nGoogleEarthEnterpriseTileInformation.prototype.hasChild = function (index) {\r\n return isBitSet(this._bits, childrenBitmasks[index]);\r\n};\r\n\r\n/**\r\n * Gets bitmask containing children\r\n *\r\n * @returns {Number} Children bitmask\r\n */\r\nGoogleEarthEnterpriseTileInformation.prototype.getChildBitmask = function () {\r\n return this._bits & anyChildBitmask;\r\n};\r\nexport default GoogleEarthEnterpriseTileInformation;\r\n","import protobufMinimal from \"../ThirdParty/protobuf-minimal.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport buildModuleUrl from \"./buildModuleUrl.js\";\r\nimport Check from \"./Check.js\";\r\nimport Credit from \"./Credit.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport GoogleEarthEnterpriseTileInformation from \"./GoogleEarthEnterpriseTileInformation.js\";\r\nimport isBitSet from \"./isBitSet.js\";\r\nimport loadAndExecuteScript from \"./loadAndExecuteScript.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Request from \"./Request.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\nimport TaskProcessor from \"./TaskProcessor.js\";\r\n\r\nfunction stringToBuffer(str) {\r\n var len = str.length;\r\n var buffer = new ArrayBuffer(len);\r\n var ui8 = new Uint8Array(buffer);\r\n for (var i = 0; i < len; ++i) {\r\n ui8[i] = str.charCodeAt(i);\r\n }\r\n\r\n return buffer;\r\n}\r\n\r\n// Decodes packet with a key that has been around since the beginning of Google Earth Enterprise\r\nvar defaultKey = stringToBuffer(\r\n \"\\x45\\xf4\\xbd\\x0b\\x79\\xe2\\x6a\\x45\\x22\\x05\\x92\\x2c\\x17\\xcd\\x06\\x71\\xf8\\x49\\x10\\x46\\x67\\x51\\x00\\x42\\x25\\xc6\\xe8\\x61\\x2c\\x66\\x29\\x08\\xc6\\x34\\xdc\\x6a\\x62\\x25\\x79\\x0a\\x77\\x1d\\x6d\\x69\\xd6\\xf0\\x9c\\x6b\\x93\\xa1\\xbd\\x4e\\x75\\xe0\\x41\\x04\\x5b\\xdf\\x40\\x56\\x0c\\xd9\\xbb\\x72\\x9b\\x81\\x7c\\x10\\x33\\x53\\xee\\x4f\\x6c\\xd4\\x71\\x05\\xb0\\x7b\\xc0\\x7f\\x45\\x03\\x56\\x5a\\xad\\x77\\x55\\x65\\x0b\\x33\\x92\\x2a\\xac\\x19\\x6c\\x35\\x14\\xc5\\x1d\\x30\\x73\\xf8\\x33\\x3e\\x6d\\x46\\x38\\x4a\\xb4\\xdd\\xf0\\x2e\\xdd\\x17\\x75\\x16\\xda\\x8c\\x44\\x74\\x22\\x06\\xfa\\x61\\x22\\x0c\\x33\\x22\\x53\\x6f\\xaf\\x39\\x44\\x0b\\x8c\\x0e\\x39\\xd9\\x39\\x13\\x4c\\xb9\\xbf\\x7f\\xab\\x5c\\x8c\\x50\\x5f\\x9f\\x22\\x75\\x78\\x1f\\xe9\\x07\\x71\\x91\\x68\\x3b\\xc1\\xc4\\x9b\\x7f\\xf0\\x3c\\x56\\x71\\x48\\x82\\x05\\x27\\x55\\x66\\x59\\x4e\\x65\\x1d\\x98\\x75\\xa3\\x61\\x46\\x7d\\x61\\x3f\\x15\\x41\\x00\\x9f\\x14\\x06\\xd7\\xb4\\x34\\x4d\\xce\\x13\\x87\\x46\\xb0\\x1a\\xd5\\x05\\x1c\\xb8\\x8a\\x27\\x7b\\x8b\\xdc\\x2b\\xbb\\x4d\\x67\\x30\\xc8\\xd1\\xf6\\x5c\\x8f\\x50\\xfa\\x5b\\x2f\\x46\\x9b\\x6e\\x35\\x18\\x2f\\x27\\x43\\x2e\\xeb\\x0a\\x0c\\x5e\\x10\\x05\\x10\\xa5\\x73\\x1b\\x65\\x34\\xe5\\x6c\\x2e\\x6a\\x43\\x27\\x63\\x14\\x23\\x55\\xa9\\x3f\\x71\\x7b\\x67\\x43\\x7d\\x3a\\xaf\\xcd\\xe2\\x54\\x55\\x9c\\xfd\\x4b\\xc6\\xe2\\x9f\\x2f\\x28\\xed\\xcb\\x5c\\xc6\\x2d\\x66\\x07\\x88\\xa7\\x3b\\x2f\\x18\\x2a\\x22\\x4e\\x0e\\xb0\\x6b\\x2e\\xdd\\x0d\\x95\\x7d\\x7d\\x47\\xba\\x43\\xb2\\x11\\xb2\\x2b\\x3e\\x4d\\xaa\\x3e\\x7d\\xe6\\xce\\x49\\x89\\xc6\\xe6\\x78\\x0c\\x61\\x31\\x05\\x2d\\x01\\xa4\\x4f\\xa5\\x7e\\x71\\x20\\x88\\xec\\x0d\\x31\\xe8\\x4e\\x0b\\x00\\x6e\\x50\\x68\\x7d\\x17\\x3d\\x08\\x0d\\x17\\x95\\xa6\\x6e\\xa3\\x68\\x97\\x24\\x5b\\x6b\\xf3\\x17\\x23\\xf3\\xb6\\x73\\xb3\\x0d\\x0b\\x40\\xc0\\x9f\\xd8\\x04\\x51\\x5d\\xfa\\x1a\\x17\\x22\\x2e\\x15\\x6a\\xdf\\x49\\x00\\xb9\\xa0\\x77\\x55\\xc6\\xef\\x10\\x6a\\xbf\\x7b\\x47\\x4c\\x7f\\x83\\x17\\x05\\xee\\xdc\\xdc\\x46\\x85\\xa9\\xad\\x53\\x07\\x2b\\x53\\x34\\x06\\x07\\xff\\x14\\x94\\x59\\x19\\x02\\xe4\\x38\\xe8\\x31\\x83\\x4e\\xb9\\x58\\x46\\x6b\\xcb\\x2d\\x23\\x86\\x92\\x70\\x00\\x35\\x88\\x22\\xcf\\x31\\xb2\\x26\\x2f\\xe7\\xc3\\x75\\x2d\\x36\\x2c\\x72\\x74\\xb0\\x23\\x47\\xb7\\xd3\\xd1\\x26\\x16\\x85\\x37\\x72\\xe2\\x00\\x8c\\x44\\xcf\\x10\\xda\\x33\\x2d\\x1a\\xde\\x60\\x86\\x69\\x23\\x69\\x2a\\x7c\\xcd\\x4b\\x51\\x0d\\x95\\x54\\x39\\x77\\x2e\\x29\\xea\\x1b\\xa6\\x50\\xa2\\x6a\\x8f\\x6f\\x50\\x99\\x5c\\x3e\\x54\\xfb\\xef\\x50\\x5b\\x0b\\x07\\x45\\x17\\x89\\x6d\\x28\\x13\\x77\\x37\\x1d\\xdb\\x8e\\x1e\\x4a\\x05\\x66\\x4a\\x6f\\x99\\x20\\xe5\\x70\\xe2\\xb9\\x71\\x7e\\x0c\\x6d\\x49\\x04\\x2d\\x7a\\xfe\\x72\\xc7\\xf2\\x59\\x30\\x8f\\xbb\\x02\\x5d\\x73\\xe5\\xc9\\x20\\xea\\x78\\xec\\x20\\x90\\xf0\\x8a\\x7f\\x42\\x17\\x7c\\x47\\x19\\x60\\xb0\\x16\\xbd\\x26\\xb7\\x71\\xb6\\xc7\\x9f\\x0e\\xd1\\x33\\x82\\x3d\\xd3\\xab\\xee\\x63\\x99\\xc8\\x2b\\x53\\xa0\\x44\\x5c\\x71\\x01\\xc6\\xcc\\x44\\x1f\\x32\\x4f\\x3c\\xca\\xc0\\x29\\x3d\\x52\\xd3\\x61\\x19\\x58\\xa9\\x7d\\x65\\xb4\\xdc\\xcf\\x0d\\xf4\\x3d\\xf1\\x08\\xa9\\x42\\xda\\x23\\x09\\xd8\\xbf\\x5e\\x50\\x49\\xf8\\x4d\\xc0\\xcb\\x47\\x4c\\x1c\\x4f\\xf7\\x7b\\x2b\\xd8\\x16\\x18\\xc5\\x31\\x92\\x3b\\xb5\\x6f\\xdc\\x6c\\x0d\\x92\\x88\\x16\\xd1\\x9e\\xdb\\x3f\\xe2\\xe9\\xda\\x5f\\xd4\\x84\\xe2\\x46\\x61\\x5a\\xde\\x1c\\x55\\xcf\\xa4\\x00\\xbe\\xfd\\xce\\x67\\xf1\\x4a\\x69\\x1c\\x97\\xe6\\x20\\x48\\xd8\\x5d\\x7f\\x7e\\xae\\x71\\x20\\x0e\\x4e\\xae\\xc0\\x56\\xa9\\x91\\x01\\x3c\\x82\\x1d\\x0f\\x72\\xe7\\x76\\xec\\x29\\x49\\xd6\\x5d\\x2d\\x83\\xe3\\xdb\\x36\\x06\\xa9\\x3b\\x66\\x13\\x97\\x87\\x6a\\xd5\\xb6\\x3d\\x50\\x5e\\x52\\xb9\\x4b\\xc7\\x73\\x57\\x78\\xc9\\xf4\\x2e\\x59\\x07\\x95\\x93\\x6f\\xd0\\x4b\\x17\\x57\\x19\\x3e\\x27\\x27\\xc7\\x60\\xdb\\x3b\\xed\\x9a\\x0e\\x53\\x44\\x16\\x3e\\x3f\\x8d\\x92\\x6d\\x77\\xa2\\x0a\\xeb\\x3f\\x52\\xa8\\xc6\\x55\\x5e\\x31\\x49\\x37\\x85\\xf4\\xc5\\x1f\\x26\\x2d\\xa9\\x1c\\xbf\\x8b\\x27\\x54\\xda\\xc3\\x6a\\x20\\xe5\\x2a\\x78\\x04\\xb0\\xd6\\x90\\x70\\x72\\xaa\\x8b\\x68\\xbd\\x88\\xf7\\x02\\x5f\\x48\\xb1\\x7e\\xc0\\x58\\x4c\\x3f\\x66\\x1a\\xf9\\x3e\\xe1\\x65\\xc0\\x70\\xa7\\xcf\\x38\\x69\\xaf\\xf0\\x56\\x6c\\x64\\x49\\x9c\\x27\\xad\\x78\\x74\\x4f\\xc2\\x87\\xde\\x56\\x39\\x00\\xda\\x77\\x0b\\xcb\\x2d\\x1b\\x89\\xfb\\x35\\x4f\\x02\\xf5\\x08\\x51\\x13\\x60\\xc1\\x0a\\x5a\\x47\\x4d\\x26\\x1c\\x33\\x30\\x78\\xda\\xc0\\x9c\\x46\\x47\\xe2\\x5b\\x79\\x60\\x49\\x6e\\x37\\x67\\x53\\x0a\\x3e\\xe9\\xec\\x46\\x39\\xb2\\xf1\\x34\\x0d\\xc6\\x84\\x53\\x75\\x6e\\xe1\\x0c\\x59\\xd9\\x1e\\xde\\x29\\x85\\x10\\x7b\\x49\\x49\\xa5\\x77\\x79\\xbe\\x49\\x56\\x2e\\x36\\xe7\\x0b\\x3a\\xbb\\x4f\\x03\\x62\\x7b\\xd2\\x4d\\x31\\x95\\x2f\\xbd\\x38\\x7b\\xa8\\x4f\\x21\\xe1\\xec\\x46\\x70\\x76\\x95\\x7d\\x29\\x22\\x78\\x88\\x0a\\x90\\xdd\\x9d\\x5c\\xda\\xde\\x19\\x51\\xcf\\xf0\\xfc\\x59\\x52\\x65\\x7c\\x33\\x13\\xdf\\xf3\\x48\\xda\\xbb\\x2a\\x75\\xdb\\x60\\xb2\\x02\\x15\\xd4\\xfc\\x19\\xed\\x1b\\xec\\x7f\\x35\\xa8\\xff\\x28\\x31\\x07\\x2d\\x12\\xc8\\xdc\\x88\\x46\\x7c\\x8a\\x5b\\x22\"\r\n);\r\n\r\n/**\r\n * Provides metadata using the Google Earth Enterprise REST API. This is used by the GoogleEarthEnterpriseImageryProvider\r\n * and GoogleEarthEnterpriseTerrainProvider to share metadata requests.\r\n *\r\n * @alias GoogleEarthEnterpriseMetadata\r\n * @constructor\r\n *\r\n * @param {Resource|String} resourceOrUrl The url of the Google Earth Enterprise server hosting the imagery\r\n *\r\n * @see GoogleEarthEnterpriseImageryProvider\r\n * @see GoogleEarthEnterpriseTerrainProvider\r\n *\r\n */\r\nfunction GoogleEarthEnterpriseMetadata(resourceOrUrl) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"resourceOrUrl\", resourceOrUrl);\r\n //>>includeEnd('debug');\r\n\r\n var url = resourceOrUrl;\r\n\r\n if (typeof url !== \"string\" && !(url instanceof Resource)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"resourceOrUrl.url\", resourceOrUrl.url);\r\n //>>includeEnd('debug');\r\n\r\n url = resourceOrUrl.url;\r\n }\r\n\r\n var resource = Resource.createIfNeeded(url);\r\n resource.appendForwardSlash();\r\n this._resource = resource;\r\n\r\n /**\r\n * True if imagery is available.\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.imageryPresent = true;\r\n\r\n /**\r\n * True if imagery is sent as a protocol buffer, false if sent as plain images. If undefined we will try both.\r\n * @type {Boolean}\r\n * @default undefined\r\n */\r\n this.protoImagery = undefined;\r\n\r\n /**\r\n * True if terrain is available.\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.terrainPresent = true;\r\n\r\n /**\r\n * Exponent used to compute constant to calculate negative height values.\r\n * @type {Number}\r\n * @default 32\r\n */\r\n this.negativeAltitudeExponentBias = 32;\r\n\r\n /**\r\n * Threshold where any numbers smaller are actually negative values. They are multiplied by -2^negativeAltitudeExponentBias.\r\n * @type {Number}\r\n * @default EPSILON12\r\n */\r\n this.negativeAltitudeThreshold = CesiumMath.EPSILON12;\r\n\r\n /**\r\n * Dictionary of provider id to copyright strings.\r\n * @type {Object}\r\n * @default {}\r\n */\r\n this.providers = {};\r\n\r\n /**\r\n * Key used to decode packets\r\n * @type {ArrayBuffer}\r\n */\r\n this.key = undefined;\r\n\r\n this._quadPacketVersion = 1;\r\n\r\n this._tileInfo = {};\r\n this._subtreePromises = {};\r\n\r\n var that = this;\r\n this._readyPromise = requestDbRoot(this)\r\n .then(function () {\r\n return that.getQuadTreePacket(\"\", that._quadPacketVersion);\r\n })\r\n .then(function () {\r\n return true;\r\n })\r\n .otherwise(function (e) {\r\n var message =\r\n \"An error occurred while accessing \" +\r\n getMetadataResource(that, \"\", 1).url +\r\n \".\";\r\n return when.reject(new RuntimeError(message));\r\n });\r\n}\r\n\r\nObject.defineProperties(GoogleEarthEnterpriseMetadata.prototype, {\r\n /**\r\n * Gets the name of the Google Earth Enterprise server.\r\n * @memberof GoogleEarthEnterpriseMetadata.prototype\r\n * @type {String}\r\n * @readonly\r\n */\r\n url: {\r\n get: function () {\r\n return this._resource.url;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the proxy used for metadata requests.\r\n * @memberof GoogleEarthEnterpriseMetadata.prototype\r\n * @type {Proxy}\r\n * @readonly\r\n */\r\n proxy: {\r\n get: function () {\r\n return this._resource.proxy;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the resource used for metadata requests.\r\n * @memberof GoogleEarthEnterpriseMetadata.prototype\r\n * @type {Resource}\r\n * @readonly\r\n */\r\n resource: {\r\n get: function () {\r\n return this._resource;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves to true when the metadata is ready for use.\r\n * @memberof GoogleEarthEnterpriseMetadata.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Converts a tiles (x, y, level) position into a quadkey used to request an image\r\n * from a Google Earth Enterprise server.\r\n *\r\n * @param {Number} x The tile's x coordinate.\r\n * @param {Number} y The tile's y coordinate.\r\n * @param {Number} level The tile's zoom level.\r\n *\r\n * @see GoogleEarthEnterpriseMetadata#quadKeyToTileXY\r\n */\r\nGoogleEarthEnterpriseMetadata.tileXYToQuadKey = function (x, y, level) {\r\n var quadkey = \"\";\r\n for (var i = level; i >= 0; --i) {\r\n var bitmask = 1 << i;\r\n var digit = 0;\r\n\r\n // Tile Layout\r\n // ___ ___\r\n //| | |\r\n //| 3 | 2 |\r\n //|-------|\r\n //| 0 | 1 |\r\n //|___|___|\r\n //\r\n\r\n if (!isBitSet(y, bitmask)) {\r\n // Top Row\r\n digit |= 2;\r\n if (!isBitSet(x, bitmask)) {\r\n // Right to left\r\n digit |= 1;\r\n }\r\n } else if (isBitSet(x, bitmask)) {\r\n // Left to right\r\n digit |= 1;\r\n }\r\n\r\n quadkey += digit;\r\n }\r\n return quadkey;\r\n};\r\n\r\n/**\r\n * Converts a tile's quadkey used to request an image from a Google Earth Enterprise server into the\r\n * (x, y, level) position.\r\n *\r\n * @param {String} quadkey The tile's quad key\r\n *\r\n * @see GoogleEarthEnterpriseMetadata#tileXYToQuadKey\r\n */\r\nGoogleEarthEnterpriseMetadata.quadKeyToTileXY = function (quadkey) {\r\n var x = 0;\r\n var y = 0;\r\n var level = quadkey.length - 1;\r\n for (var i = level; i >= 0; --i) {\r\n var bitmask = 1 << i;\r\n var digit = +quadkey[level - i];\r\n\r\n if (isBitSet(digit, 2)) {\r\n // Top Row\r\n if (!isBitSet(digit, 1)) {\r\n // // Right to left\r\n x |= bitmask;\r\n }\r\n } else {\r\n y |= bitmask;\r\n if (isBitSet(digit, 1)) {\r\n // Left to right\r\n x |= bitmask;\r\n }\r\n }\r\n }\r\n return {\r\n x: x,\r\n y: y,\r\n level: level,\r\n };\r\n};\r\n\r\nGoogleEarthEnterpriseMetadata.prototype.isValid = function (quadKey) {\r\n var info = this.getTileInformationFromQuadKey(quadKey);\r\n if (defined(info)) {\r\n return info !== null;\r\n }\r\n\r\n var valid = true;\r\n var q = quadKey;\r\n var last;\r\n while (q.length > 1) {\r\n last = q.substring(q.length - 1);\r\n q = q.substring(0, q.length - 1);\r\n info = this.getTileInformationFromQuadKey(q);\r\n if (defined(info)) {\r\n if (!info.hasSubtree() && !info.hasChild(parseInt(last))) {\r\n // We have no subtree or child available at some point in this node's ancestry\r\n valid = false;\r\n }\r\n\r\n break;\r\n } else if (info === null) {\r\n // Some node in the ancestry was loaded and said there wasn't a subtree\r\n valid = false;\r\n break;\r\n }\r\n }\r\n\r\n return valid;\r\n};\r\n\r\nvar taskProcessor = new TaskProcessor(\"decodeGoogleEarthEnterprisePacket\");\r\n\r\n/**\r\n * Retrieves a Google Earth Enterprise quadtree packet.\r\n *\r\n * @param {String} [quadKey=''] The quadkey to retrieve the packet for.\r\n * @param {Number} [version=1] The cnode version to be used in the request.\r\n * @param {Request} [request] The request object. Intended for internal use only.\r\n *\r\n * @private\r\n */\r\nGoogleEarthEnterpriseMetadata.prototype.getQuadTreePacket = function (\r\n quadKey,\r\n version,\r\n request\r\n) {\r\n version = defaultValue(version, 1);\r\n quadKey = defaultValue(quadKey, \"\");\r\n var resource = getMetadataResource(this, quadKey, version, request);\r\n\r\n var promise = resource.fetchArrayBuffer();\r\n\r\n if (!defined(promise)) {\r\n return undefined; // Throttled\r\n }\r\n\r\n var tileInfo = this._tileInfo;\r\n var key = this.key;\r\n return promise.then(function (metadata) {\r\n var decodePromise = taskProcessor.scheduleTask(\r\n {\r\n buffer: metadata,\r\n quadKey: quadKey,\r\n type: \"Metadata\",\r\n key: key,\r\n },\r\n [metadata]\r\n );\r\n\r\n return decodePromise.then(function (result) {\r\n var root;\r\n var topLevelKeyLength = -1;\r\n if (quadKey !== \"\") {\r\n // Root tile has no data except children bits, so put them into the tile info\r\n topLevelKeyLength = quadKey.length + 1;\r\n var top = result[quadKey];\r\n root = tileInfo[quadKey];\r\n root._bits |= top._bits;\r\n\r\n delete result[quadKey];\r\n }\r\n\r\n // Copy the resulting objects into tileInfo\r\n // Make sure we start with shorter quadkeys first, so we know the parents have\r\n // already been processed. Otherwise we can lose ancestorHasTerrain along the way.\r\n var keys = Object.keys(result);\r\n keys.sort(function (a, b) {\r\n return a.length - b.length;\r\n });\r\n var keysLength = keys.length;\r\n for (var i = 0; i < keysLength; ++i) {\r\n var key = keys[i];\r\n var r = result[key];\r\n if (r !== null) {\r\n var info = GoogleEarthEnterpriseTileInformation.clone(result[key]);\r\n var keyLength = key.length;\r\n if (keyLength === topLevelKeyLength) {\r\n info.setParent(root);\r\n } else if (keyLength > 1) {\r\n var parent = tileInfo[key.substring(0, key.length - 1)];\r\n info.setParent(parent);\r\n }\r\n tileInfo[key] = info;\r\n } else {\r\n tileInfo[key] = null;\r\n }\r\n }\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Populates the metadata subtree down to the specified tile.\r\n *\r\n * @param {Number} x The tile X coordinate.\r\n * @param {Number} y The tile Y coordinate.\r\n * @param {Number} level The tile level.\r\n * @param {Request} [request] The request object. Intended for internal use only.\r\n *\r\n * @returns {Promise} A promise that resolves to the tile info for the requested quad key\r\n *\r\n * @private\r\n */\r\nGoogleEarthEnterpriseMetadata.prototype.populateSubtree = function (\r\n x,\r\n y,\r\n level,\r\n request\r\n) {\r\n var quadkey = GoogleEarthEnterpriseMetadata.tileXYToQuadKey(x, y, level);\r\n return populateSubtree(this, quadkey, request);\r\n};\r\n\r\nfunction populateSubtree(that, quadKey, request) {\r\n var tileInfo = that._tileInfo;\r\n var q = quadKey;\r\n var t = tileInfo[q];\r\n // If we have tileInfo make sure sure it is not a node with a subtree that's not loaded\r\n if (defined(t) && (!t.hasSubtree() || t.hasChildren())) {\r\n return t;\r\n }\r\n\r\n while (t === undefined && q.length > 1) {\r\n q = q.substring(0, q.length - 1);\r\n t = tileInfo[q];\r\n }\r\n\r\n var subtreeRequest;\r\n var subtreePromises = that._subtreePromises;\r\n var promise = subtreePromises[q];\r\n if (defined(promise)) {\r\n return promise.then(function () {\r\n // Recursively call this in case we need multiple subtree requests\r\n subtreeRequest = new Request({\r\n throttle: request.throttle,\r\n throttleByServer: request.throttleByServer,\r\n type: request.type,\r\n priorityFunction: request.priorityFunction,\r\n });\r\n return populateSubtree(that, quadKey, subtreeRequest);\r\n });\r\n }\r\n\r\n // t is either\r\n // null so one of its parents was a leaf node, so this tile doesn't exist\r\n // exists but doesn't have a subtree to request\r\n // undefined so no parent exists - this shouldn't ever happen once the provider is ready\r\n if (!defined(t) || !t.hasSubtree()) {\r\n return when.reject(\r\n new RuntimeError(\"Couldn't load metadata for tile \" + quadKey)\r\n );\r\n }\r\n\r\n // We need to split up the promise here because when will execute syncronously if getQuadTreePacket\r\n // is already resolved (like in the tests), so subtreePromises will never get cleared out.\r\n // Only the initial request will also remove the promise from subtreePromises.\r\n promise = that.getQuadTreePacket(q, t.cnodeVersion, request);\r\n if (!defined(promise)) {\r\n return undefined;\r\n }\r\n subtreePromises[q] = promise;\r\n\r\n return promise\r\n .then(function () {\r\n // Recursively call this in case we need multiple subtree requests\r\n subtreeRequest = new Request({\r\n throttle: request.throttle,\r\n throttleByServer: request.throttleByServer,\r\n type: request.type,\r\n priorityFunction: request.priorityFunction,\r\n });\r\n return populateSubtree(that, quadKey, subtreeRequest);\r\n })\r\n .always(function () {\r\n delete subtreePromises[q];\r\n });\r\n}\r\n\r\n/**\r\n * Gets information about a tile\r\n *\r\n * @param {Number} x The tile X coordinate.\r\n * @param {Number} y The tile Y coordinate.\r\n * @param {Number} level The tile level.\r\n * @returns {GoogleEarthEnterpriseTileInformation|undefined} Information about the tile or undefined if it isn't loaded.\r\n *\r\n * @private\r\n */\r\nGoogleEarthEnterpriseMetadata.prototype.getTileInformation = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n var quadkey = GoogleEarthEnterpriseMetadata.tileXYToQuadKey(x, y, level);\r\n return this._tileInfo[quadkey];\r\n};\r\n\r\n/**\r\n * Gets information about a tile from a quadKey\r\n *\r\n * @param {String} quadkey The quadkey for the tile\r\n * @returns {GoogleEarthEnterpriseTileInformation|undefined} Information about the tile or undefined if it isn't loaded.\r\n *\r\n * @private\r\n */\r\nGoogleEarthEnterpriseMetadata.prototype.getTileInformationFromQuadKey = function (\r\n quadkey\r\n) {\r\n return this._tileInfo[quadkey];\r\n};\r\n\r\nfunction getMetadataResource(that, quadKey, version, request) {\r\n return that._resource.getDerivedResource({\r\n url: \"flatfile?q2-0\" + quadKey + \"-q.\" + version.toString(),\r\n request: request,\r\n });\r\n}\r\n\r\nvar dbrootParser;\r\nvar dbrootParserPromise;\r\nfunction requestDbRoot(that) {\r\n var resource = that._resource.getDerivedResource({\r\n url: \"dbRoot.v5\",\r\n queryParameters: {\r\n output: \"proto\",\r\n },\r\n });\r\n\r\n if (!defined(dbrootParserPromise)) {\r\n var url = buildModuleUrl(\"ThirdParty/google-earth-dbroot-parser.js\");\r\n var oldValue = window.cesiumGoogleEarthDbRootParser;\r\n dbrootParserPromise = loadAndExecuteScript(url).then(function () {\r\n dbrootParser = window.cesiumGoogleEarthDbRootParser(protobufMinimal);\r\n if (defined(oldValue)) {\r\n window.cesiumGoogleEarthDbRootParser = oldValue;\r\n } else {\r\n delete window.cesiumGoogleEarthDbRootParser;\r\n }\r\n });\r\n }\r\n\r\n return dbrootParserPromise\r\n .then(function () {\r\n return resource.fetchArrayBuffer();\r\n })\r\n .then(function (buf) {\r\n var encryptedDbRootProto = dbrootParser.EncryptedDbRootProto.decode(\r\n new Uint8Array(buf)\r\n );\r\n\r\n var byteArray = encryptedDbRootProto.encryptionData;\r\n var offset = byteArray.byteOffset;\r\n var end = offset + byteArray.byteLength;\r\n var key = (that.key = byteArray.buffer.slice(offset, end));\r\n\r\n byteArray = encryptedDbRootProto.dbrootData;\r\n offset = byteArray.byteOffset;\r\n end = offset + byteArray.byteLength;\r\n var dbRootCompressed = byteArray.buffer.slice(offset, end);\r\n return taskProcessor.scheduleTask(\r\n {\r\n buffer: dbRootCompressed,\r\n type: \"DbRoot\",\r\n key: key,\r\n },\r\n [dbRootCompressed]\r\n );\r\n })\r\n .then(function (result) {\r\n var dbRoot = dbrootParser.DbRootProto.decode(\r\n new Uint8Array(result.buffer)\r\n );\r\n that.imageryPresent = defaultValue(\r\n dbRoot.imageryPresent,\r\n that.imageryPresent\r\n );\r\n that.protoImagery = dbRoot.protoImagery;\r\n that.terrainPresent = defaultValue(\r\n dbRoot.terrainPresent,\r\n that.terrainPresent\r\n );\r\n if (defined(dbRoot.endSnippet) && defined(dbRoot.endSnippet.model)) {\r\n var model = dbRoot.endSnippet.model;\r\n that.negativeAltitudeExponentBias = defaultValue(\r\n model.negativeAltitudeExponentBias,\r\n that.negativeAltitudeExponentBias\r\n );\r\n that.negativeAltitudeThreshold = defaultValue(\r\n model.compressedNegativeAltitudeThreshold,\r\n that.negativeAltitudeThreshold\r\n );\r\n }\r\n if (defined(dbRoot.databaseVersion)) {\r\n that._quadPacketVersion = defaultValue(\r\n dbRoot.databaseVersion.quadtreeVersion,\r\n that._quadPacketVersion\r\n );\r\n }\r\n var providers = that.providers;\r\n var providerInfo = defaultValue(dbRoot.providerInfo, []);\r\n var count = providerInfo.length;\r\n for (var i = 0; i < count; ++i) {\r\n var provider = providerInfo[i];\r\n var copyrightString = provider.copyrightString;\r\n if (defined(copyrightString)) {\r\n providers[provider.providerId] = new Credit(copyrightString.value);\r\n }\r\n }\r\n })\r\n .otherwise(function () {\r\n // Just eat the error and use the default values.\r\n console.log(\"Failed to retrieve \" + resource.url + \". Using defaults.\");\r\n that.key = defaultKey;\r\n });\r\n}\r\nexport default GoogleEarthEnterpriseMetadata;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport Intersections2D from \"./Intersections2D.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport OrientedBoundingBox from \"./OrientedBoundingBox.js\";\r\nimport QuantizedMeshTerrainData from \"./QuantizedMeshTerrainData.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport TaskProcessor from \"./TaskProcessor.js\";\r\nimport TerrainData from \"./TerrainData.js\";\r\nimport TerrainEncoding from \"./TerrainEncoding.js\";\r\nimport TerrainMesh from \"./TerrainMesh.js\";\r\n\r\n/**\r\n * Terrain data for a single tile from a Google Earth Enterprise server.\r\n *\r\n * @alias GoogleEarthEnterpriseTerrainData\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {ArrayBuffer} options.buffer The buffer containing terrain data.\r\n * @param {Number} options.negativeAltitudeExponentBias Multiplier for negative terrain heights that are encoded as very small positive values.\r\n * @param {Number} options.negativeElevationThreshold Threshold for negative values\r\n * @param {Number} [options.childTileMask=15] A bit mask indicating which of this tile's four children exist.\r\n * If a child's bit is set, geometry will be requested for that tile as well when it\r\n * is needed. If the bit is cleared, the child tile is not requested and geometry is\r\n * instead upsampled from the parent. The bit values are as follows:\r\n * \r\n * \r\n * \r\n * \r\n * \r\n * \r\n *
Bit PositionBit ValueChild Tile
01Southwest
12Southeast
24Northeast
38Northwest
\r\n * @param {Boolean} [options.createdByUpsampling=false] True if this instance was created by upsampling another instance;\r\n * otherwise, false.\r\n * @param {Credit[]} [options.credits] Array of credits for this tile.\r\n *\r\n *\r\n * @example\r\n * var buffer = ...\r\n * var childTileMask = ...\r\n * var terrainData = new Cesium.GoogleEarthEnterpriseTerrainData({\r\n * buffer : heightBuffer,\r\n * childTileMask : childTileMask\r\n * });\r\n *\r\n * @see TerrainData\r\n * @see HeightmapTerrainData\r\n * @see QuantizedMeshTerrainData\r\n */\r\nfunction GoogleEarthEnterpriseTerrainData(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options.buffer\", options.buffer);\r\n Check.typeOf.number(\r\n \"options.negativeAltitudeExponentBias\",\r\n options.negativeAltitudeExponentBias\r\n );\r\n Check.typeOf.number(\r\n \"options.negativeElevationThreshold\",\r\n options.negativeElevationThreshold\r\n );\r\n //>>includeEnd('debug');\r\n\r\n this._buffer = options.buffer;\r\n this._credits = options.credits;\r\n this._negativeAltitudeExponentBias = options.negativeAltitudeExponentBias;\r\n this._negativeElevationThreshold = options.negativeElevationThreshold;\r\n\r\n // Convert from google layout to layout of other providers\r\n // 3 2 -> 2 3\r\n // 0 1 -> 0 1\r\n var googleChildTileMask = defaultValue(options.childTileMask, 15);\r\n var childTileMask = googleChildTileMask & 3; // Bottom row is identical\r\n childTileMask |= googleChildTileMask & 4 ? 8 : 0; // NE\r\n childTileMask |= googleChildTileMask & 8 ? 4 : 0; // NW\r\n\r\n this._childTileMask = childTileMask;\r\n\r\n this._createdByUpsampling = defaultValue(options.createdByUpsampling, false);\r\n\r\n this._skirtHeight = undefined;\r\n this._bufferType = this._buffer.constructor;\r\n this._mesh = undefined;\r\n this._minimumHeight = undefined;\r\n this._maximumHeight = undefined;\r\n}\r\n\r\nObject.defineProperties(GoogleEarthEnterpriseTerrainData.prototype, {\r\n /**\r\n * An array of credits for this tile\r\n * @memberof GoogleEarthEnterpriseTerrainData.prototype\r\n * @type {Credit[]}\r\n */\r\n credits: {\r\n get: function () {\r\n return this._credits;\r\n },\r\n },\r\n /**\r\n * The water mask included in this terrain data, if any. A water mask is a rectangular\r\n * Uint8Array or image where a value of 255 indicates water and a value of 0 indicates land.\r\n * Values in between 0 and 255 are allowed as well to smoothly blend between land and water.\r\n * @memberof GoogleEarthEnterpriseTerrainData.prototype\r\n * @type {Uint8Array|HTMLImageElement|HTMLCanvasElement}\r\n */\r\n waterMask: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n});\r\n\r\nvar createMeshTaskName = \"createVerticesFromGoogleEarthEnterpriseBuffer\";\r\nvar createMeshTaskProcessorNoThrottle = new TaskProcessor(createMeshTaskName);\r\nvar createMeshTaskProcessorThrottle = new TaskProcessor(\r\n createMeshTaskName,\r\n TerrainData.maximumAsynchronousTasks\r\n);\r\n\r\nvar nativeRectangleScratch = new Rectangle();\r\nvar rectangleScratch = new Rectangle();\r\n\r\n/**\r\n * Creates a {@link TerrainMesh} from this terrain data.\r\n *\r\n * @private\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {TilingScheme} options.tilingScheme The tiling scheme to which this tile belongs.\r\n * @param {Number} options.x The X coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.y The Y coordinate of the tile for which to create the terrain data.\r\n * @param {Number} options.level The level of the tile for which to create the terrain data.\r\n * @param {Number} [options.exaggeration=1.0] The scale used to exaggerate the terrain.\r\n * @param {Boolean} [options.throttle=true] If true, indicates that this operation will need to be retried if too many asynchronous mesh creations are already in progress.\r\n * @returns {Promise.|undefined} A promise for the terrain mesh, or undefined if too many\r\n * asynchronous mesh creations are already in progress and the operation should\r\n * be retried later.\r\n */\r\nGoogleEarthEnterpriseTerrainData.prototype.createMesh = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options.tilingScheme\", options.tilingScheme);\r\n Check.typeOf.number(\"options.x\", options.x);\r\n Check.typeOf.number(\"options.y\", options.y);\r\n Check.typeOf.number(\"options.level\", options.level);\r\n //>>includeEnd('debug');\r\n\r\n var tilingScheme = options.tilingScheme;\r\n var x = options.x;\r\n var y = options.y;\r\n var level = options.level;\r\n var exaggeration = defaultValue(options.exaggeration, 1.0);\r\n var throttle = defaultValue(options.throttle, true);\r\n\r\n var ellipsoid = tilingScheme.ellipsoid;\r\n tilingScheme.tileXYToNativeRectangle(x, y, level, nativeRectangleScratch);\r\n tilingScheme.tileXYToRectangle(x, y, level, rectangleScratch);\r\n\r\n // Compute the center of the tile for RTC rendering.\r\n var center = ellipsoid.cartographicToCartesian(\r\n Rectangle.center(rectangleScratch)\r\n );\r\n\r\n var levelZeroMaxError = 40075.16; // From Google's Doc\r\n var thisLevelMaxError = levelZeroMaxError / (1 << level);\r\n this._skirtHeight = Math.min(thisLevelMaxError * 8.0, 1000.0);\r\n\r\n var createMeshTaskProcessor = throttle\r\n ? createMeshTaskProcessorThrottle\r\n : createMeshTaskProcessorNoThrottle;\r\n\r\n var verticesPromise = createMeshTaskProcessor.scheduleTask({\r\n buffer: this._buffer,\r\n nativeRectangle: nativeRectangleScratch,\r\n rectangle: rectangleScratch,\r\n relativeToCenter: center,\r\n ellipsoid: ellipsoid,\r\n skirtHeight: this._skirtHeight,\r\n exaggeration: exaggeration,\r\n includeWebMercatorT: true,\r\n negativeAltitudeExponentBias: this._negativeAltitudeExponentBias,\r\n negativeElevationThreshold: this._negativeElevationThreshold,\r\n });\r\n\r\n if (!defined(verticesPromise)) {\r\n // Postponed\r\n return undefined;\r\n }\r\n\r\n var that = this;\r\n return verticesPromise.then(function (result) {\r\n // Clone complex result objects because the transfer from the web worker\r\n // has stripped them down to JSON-style objects.\r\n that._mesh = new TerrainMesh(\r\n center,\r\n new Float32Array(result.vertices),\r\n new Uint16Array(result.indices),\r\n result.indexCountWithoutSkirts,\r\n result.vertexCountWithoutSkirts,\r\n result.minimumHeight,\r\n result.maximumHeight,\r\n BoundingSphere.clone(result.boundingSphere3D),\r\n Cartesian3.clone(result.occludeePointInScaledSpace),\r\n result.numberOfAttributes,\r\n OrientedBoundingBox.clone(result.orientedBoundingBox),\r\n TerrainEncoding.clone(result.encoding),\r\n exaggeration,\r\n result.westIndicesSouthToNorth,\r\n result.southIndicesEastToWest,\r\n result.eastIndicesNorthToSouth,\r\n result.northIndicesWestToEast\r\n );\r\n\r\n that._minimumHeight = result.minimumHeight;\r\n that._maximumHeight = result.maximumHeight;\r\n\r\n // Free memory received from server after mesh is created.\r\n that._buffer = undefined;\r\n return that._mesh;\r\n });\r\n};\r\n\r\n/**\r\n * Computes the terrain height at a specified longitude and latitude.\r\n *\r\n * @param {Rectangle} rectangle The rectangle covered by this terrain data.\r\n * @param {Number} longitude The longitude in radians.\r\n * @param {Number} latitude The latitude in radians.\r\n * @returns {Number} The terrain height at the specified position. If the position\r\n * is outside the rectangle, this method will extrapolate the height, which is likely to be wildly\r\n * incorrect for positions far outside the rectangle.\r\n */\r\nGoogleEarthEnterpriseTerrainData.prototype.interpolateHeight = function (\r\n rectangle,\r\n longitude,\r\n latitude\r\n) {\r\n var u = CesiumMath.clamp(\r\n (longitude - rectangle.west) / rectangle.width,\r\n 0.0,\r\n 1.0\r\n );\r\n var v = CesiumMath.clamp(\r\n (latitude - rectangle.south) / rectangle.height,\r\n 0.0,\r\n 1.0\r\n );\r\n\r\n if (!defined(this._mesh)) {\r\n return interpolateHeight(this, u, v, rectangle);\r\n }\r\n\r\n return interpolateMeshHeight(this, u, v);\r\n};\r\n\r\nvar upsampleTaskProcessor = new TaskProcessor(\r\n \"upsampleQuantizedTerrainMesh\",\r\n TerrainData.maximumAsynchronousTasks\r\n);\r\n\r\n/**\r\n * Upsamples this terrain data for use by a descendant tile. The resulting instance will contain a subset of the\r\n * height samples in this instance, interpolated if necessary.\r\n *\r\n * @param {TilingScheme} tilingScheme The tiling scheme of this terrain data.\r\n * @param {Number} thisX The X coordinate of this tile in the tiling scheme.\r\n * @param {Number} thisY The Y coordinate of this tile in the tiling scheme.\r\n * @param {Number} thisLevel The level of this tile in the tiling scheme.\r\n * @param {Number} descendantX The X coordinate within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @param {Number} descendantY The Y coordinate within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @param {Number} descendantLevel The level within the tiling scheme of the descendant tile for which we are upsampling.\r\n * @returns {Promise.|undefined} A promise for upsampled heightmap terrain data for the descendant tile,\r\n * or undefined if too many asynchronous upsample operations are in progress and the request has been\r\n * deferred.\r\n */\r\nGoogleEarthEnterpriseTerrainData.prototype.upsample = function (\r\n tilingScheme,\r\n thisX,\r\n thisY,\r\n thisLevel,\r\n descendantX,\r\n descendantY,\r\n descendantLevel\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"tilingScheme\", tilingScheme);\r\n Check.typeOf.number(\"thisX\", thisX);\r\n Check.typeOf.number(\"thisY\", thisY);\r\n Check.typeOf.number(\"thisLevel\", thisLevel);\r\n Check.typeOf.number(\"descendantX\", descendantX);\r\n Check.typeOf.number(\"descendantY\", descendantY);\r\n Check.typeOf.number(\"descendantLevel\", descendantLevel);\r\n var levelDifference = descendantLevel - thisLevel;\r\n if (levelDifference > 1) {\r\n throw new DeveloperError(\r\n \"Upsampling through more than one level at a time is not currently supported.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var mesh = this._mesh;\r\n if (!defined(this._mesh)) {\r\n return undefined;\r\n }\r\n\r\n var isEastChild = thisX * 2 !== descendantX;\r\n var isNorthChild = thisY * 2 === descendantY;\r\n\r\n var ellipsoid = tilingScheme.ellipsoid;\r\n var childRectangle = tilingScheme.tileXYToRectangle(\r\n descendantX,\r\n descendantY,\r\n descendantLevel\r\n );\r\n\r\n var upsamplePromise = upsampleTaskProcessor.scheduleTask({\r\n vertices: mesh.vertices,\r\n indices: mesh.indices,\r\n indexCountWithoutSkirts: mesh.indexCountWithoutSkirts,\r\n vertexCountWithoutSkirts: mesh.vertexCountWithoutSkirts,\r\n encoding: mesh.encoding,\r\n minimumHeight: this._minimumHeight,\r\n maximumHeight: this._maximumHeight,\r\n isEastChild: isEastChild,\r\n isNorthChild: isNorthChild,\r\n childRectangle: childRectangle,\r\n ellipsoid: ellipsoid,\r\n exaggeration: mesh.exaggeration,\r\n });\r\n\r\n if (!defined(upsamplePromise)) {\r\n // Postponed\r\n return undefined;\r\n }\r\n\r\n var that = this;\r\n return upsamplePromise.then(function (result) {\r\n var quantizedVertices = new Uint16Array(result.vertices);\r\n var indicesTypedArray = IndexDatatype.createTypedArray(\r\n quantizedVertices.length / 3,\r\n result.indices\r\n );\r\n\r\n var skirtHeight = that._skirtHeight;\r\n\r\n // Use QuantizedMeshTerrainData since we have what we need already parsed\r\n return new QuantizedMeshTerrainData({\r\n quantizedVertices: quantizedVertices,\r\n indices: indicesTypedArray,\r\n minimumHeight: result.minimumHeight,\r\n maximumHeight: result.maximumHeight,\r\n boundingSphere: BoundingSphere.clone(result.boundingSphere),\r\n orientedBoundingBox: OrientedBoundingBox.clone(\r\n result.orientedBoundingBox\r\n ),\r\n horizonOcclusionPoint: Cartesian3.clone(result.horizonOcclusionPoint),\r\n westIndices: result.westIndices,\r\n southIndices: result.southIndices,\r\n eastIndices: result.eastIndices,\r\n northIndices: result.northIndices,\r\n westSkirtHeight: skirtHeight,\r\n southSkirtHeight: skirtHeight,\r\n eastSkirtHeight: skirtHeight,\r\n northSkirtHeight: skirtHeight,\r\n childTileMask: 0,\r\n createdByUpsampling: true,\r\n credits: that._credits,\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Determines if a given child tile is available, based on the\r\n * {@link HeightmapTerrainData.childTileMask}. The given child tile coordinates are assumed\r\n * to be one of the four children of this tile. If non-child tile coordinates are\r\n * given, the availability of the southeast child tile is returned.\r\n *\r\n * @param {Number} thisX The tile X coordinate of this (the parent) tile.\r\n * @param {Number} thisY The tile Y coordinate of this (the parent) tile.\r\n * @param {Number} childX The tile X coordinate of the child tile to check for availability.\r\n * @param {Number} childY The tile Y coordinate of the child tile to check for availability.\r\n * @returns {Boolean} True if the child tile is available; otherwise, false.\r\n */\r\nGoogleEarthEnterpriseTerrainData.prototype.isChildAvailable = function (\r\n thisX,\r\n thisY,\r\n childX,\r\n childY\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"thisX\", thisX);\r\n Check.typeOf.number(\"thisY\", thisY);\r\n Check.typeOf.number(\"childX\", childX);\r\n Check.typeOf.number(\"childY\", childY);\r\n //>>includeEnd('debug');\r\n\r\n var bitNumber = 2; // northwest child\r\n if (childX !== thisX * 2) {\r\n ++bitNumber; // east child\r\n }\r\n if (childY !== thisY * 2) {\r\n bitNumber -= 2; // south child\r\n }\r\n\r\n return (this._childTileMask & (1 << bitNumber)) !== 0;\r\n};\r\n\r\n/**\r\n * Gets a value indicating whether or not this terrain data was created by upsampling lower resolution\r\n * terrain data. If this value is false, the data was obtained from some other source, such\r\n * as by downloading it from a remote server. This method should return true for instances\r\n * returned from a call to {@link HeightmapTerrainData#upsample}.\r\n *\r\n * @returns {Boolean} True if this instance was created by upsampling; otherwise, false.\r\n */\r\nGoogleEarthEnterpriseTerrainData.prototype.wasCreatedByUpsampling = function () {\r\n return this._createdByUpsampling;\r\n};\r\n\r\nvar texCoordScratch0 = new Cartesian2();\r\nvar texCoordScratch1 = new Cartesian2();\r\nvar texCoordScratch2 = new Cartesian2();\r\nvar barycentricCoordinateScratch = new Cartesian3();\r\n\r\nfunction interpolateMeshHeight(terrainData, u, v) {\r\n var mesh = terrainData._mesh;\r\n var vertices = mesh.vertices;\r\n var encoding = mesh.encoding;\r\n var indices = mesh.indices;\r\n\r\n for (var i = 0, len = indices.length; i < len; i += 3) {\r\n var i0 = indices[i];\r\n var i1 = indices[i + 1];\r\n var i2 = indices[i + 2];\r\n\r\n var uv0 = encoding.decodeTextureCoordinates(vertices, i0, texCoordScratch0);\r\n var uv1 = encoding.decodeTextureCoordinates(vertices, i1, texCoordScratch1);\r\n var uv2 = encoding.decodeTextureCoordinates(vertices, i2, texCoordScratch2);\r\n\r\n var barycentric = Intersections2D.computeBarycentricCoordinates(\r\n u,\r\n v,\r\n uv0.x,\r\n uv0.y,\r\n uv1.x,\r\n uv1.y,\r\n uv2.x,\r\n uv2.y,\r\n barycentricCoordinateScratch\r\n );\r\n if (\r\n barycentric.x >= -1e-15 &&\r\n barycentric.y >= -1e-15 &&\r\n barycentric.z >= -1e-15\r\n ) {\r\n var h0 = encoding.decodeHeight(vertices, i0);\r\n var h1 = encoding.decodeHeight(vertices, i1);\r\n var h2 = encoding.decodeHeight(vertices, i2);\r\n return barycentric.x * h0 + barycentric.y * h1 + barycentric.z * h2;\r\n }\r\n }\r\n\r\n // Position does not lie in any triangle in this mesh.\r\n return undefined;\r\n}\r\n\r\nvar sizeOfUint16 = Uint16Array.BYTES_PER_ELEMENT;\r\nvar sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;\r\nvar sizeOfInt32 = Int32Array.BYTES_PER_ELEMENT;\r\nvar sizeOfFloat = Float32Array.BYTES_PER_ELEMENT;\r\nvar sizeOfDouble = Float64Array.BYTES_PER_ELEMENT;\r\n\r\nfunction interpolateHeight(terrainData, u, v, rectangle) {\r\n var buffer = terrainData._buffer;\r\n var quad = 0; // SW\r\n var uStart = 0.0;\r\n var vStart = 0.0;\r\n if (v > 0.5) {\r\n // Upper row\r\n if (u > 0.5) {\r\n // NE\r\n quad = 2;\r\n uStart = 0.5;\r\n } else {\r\n // NW\r\n quad = 3;\r\n }\r\n vStart = 0.5;\r\n } else if (u > 0.5) {\r\n // SE\r\n quad = 1;\r\n uStart = 0.5;\r\n }\r\n\r\n var dv = new DataView(buffer);\r\n var offset = 0;\r\n for (var q = 0; q < quad; ++q) {\r\n offset += dv.getUint32(offset, true);\r\n offset += sizeOfUint32;\r\n }\r\n offset += sizeOfUint32; // Skip length of quad\r\n offset += 2 * sizeOfDouble; // Skip origin\r\n\r\n // Read sizes\r\n var xSize = CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);\r\n offset += sizeOfDouble;\r\n var ySize = CesiumMath.toRadians(dv.getFloat64(offset, true) * 180.0);\r\n offset += sizeOfDouble;\r\n\r\n // Samples per quad\r\n var xScale = rectangle.width / xSize / 2;\r\n var yScale = rectangle.height / ySize / 2;\r\n\r\n // Number of points\r\n var numPoints = dv.getInt32(offset, true);\r\n offset += sizeOfInt32;\r\n\r\n // Number of faces\r\n var numIndices = dv.getInt32(offset, true) * 3;\r\n offset += sizeOfInt32;\r\n\r\n offset += sizeOfInt32; // Skip Level\r\n\r\n var uBuffer = new Array(numPoints);\r\n var vBuffer = new Array(numPoints);\r\n var heights = new Array(numPoints);\r\n var i;\r\n for (i = 0; i < numPoints; ++i) {\r\n uBuffer[i] = uStart + dv.getUint8(offset++) * xScale;\r\n vBuffer[i] = vStart + dv.getUint8(offset++) * yScale;\r\n\r\n // Height is stored in units of (1/EarthRadius) or (1/6371010.0)\r\n heights[i] = dv.getFloat32(offset, true) * 6371010.0;\r\n offset += sizeOfFloat;\r\n }\r\n\r\n var indices = new Array(numIndices);\r\n for (i = 0; i < numIndices; ++i) {\r\n indices[i] = dv.getUint16(offset, true);\r\n offset += sizeOfUint16;\r\n }\r\n\r\n for (i = 0; i < numIndices; i += 3) {\r\n var i0 = indices[i];\r\n var i1 = indices[i + 1];\r\n var i2 = indices[i + 2];\r\n\r\n var u0 = uBuffer[i0];\r\n var u1 = uBuffer[i1];\r\n var u2 = uBuffer[i2];\r\n\r\n var v0 = vBuffer[i0];\r\n var v1 = vBuffer[i1];\r\n var v2 = vBuffer[i2];\r\n\r\n var barycentric = Intersections2D.computeBarycentricCoordinates(\r\n u,\r\n v,\r\n u0,\r\n v0,\r\n u1,\r\n v1,\r\n u2,\r\n v2,\r\n barycentricCoordinateScratch\r\n );\r\n if (\r\n barycentric.x >= -1e-15 &&\r\n barycentric.y >= -1e-15 &&\r\n barycentric.z >= -1e-15\r\n ) {\r\n return (\r\n barycentric.x * heights[i0] +\r\n barycentric.y * heights[i1] +\r\n barycentric.z * heights[i2]\r\n );\r\n }\r\n }\r\n\r\n // Position does not lie in any triangle in this mesh.\r\n return undefined;\r\n}\r\nexport default GoogleEarthEnterpriseTerrainData;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Credit from \"./Credit.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Event from \"./Event.js\";\r\nimport GeographicTilingScheme from \"./GeographicTilingScheme.js\";\r\nimport GoogleEarthEnterpriseMetadata from \"./GoogleEarthEnterpriseMetadata.js\";\r\nimport GoogleEarthEnterpriseTerrainData from \"./GoogleEarthEnterpriseTerrainData.js\";\r\nimport HeightmapTerrainData from \"./HeightmapTerrainData.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Request from \"./Request.js\";\r\nimport RequestState from \"./RequestState.js\";\r\nimport RequestType from \"./RequestType.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\nimport TaskProcessor from \"./TaskProcessor.js\";\r\nimport TileProviderError from \"./TileProviderError.js\";\r\n\r\nvar TerrainState = {\r\n UNKNOWN: 0,\r\n NONE: 1,\r\n SELF: 2,\r\n PARENT: 3,\r\n};\r\n\r\nvar julianDateScratch = new JulianDate();\r\n\r\nfunction TerrainCache() {\r\n this._terrainCache = {};\r\n this._lastTidy = JulianDate.now();\r\n}\r\n\r\nTerrainCache.prototype.add = function (quadKey, buffer) {\r\n this._terrainCache[quadKey] = {\r\n buffer: buffer,\r\n timestamp: JulianDate.now(),\r\n };\r\n};\r\n\r\nTerrainCache.prototype.get = function (quadKey) {\r\n var terrainCache = this._terrainCache;\r\n var result = terrainCache[quadKey];\r\n if (defined(result)) {\r\n delete this._terrainCache[quadKey];\r\n return result.buffer;\r\n }\r\n};\r\n\r\nTerrainCache.prototype.tidy = function () {\r\n JulianDate.now(julianDateScratch);\r\n if (JulianDate.secondsDifference(julianDateScratch, this._lastTidy) > 10) {\r\n var terrainCache = this._terrainCache;\r\n var keys = Object.keys(terrainCache);\r\n var count = keys.length;\r\n for (var i = 0; i < count; ++i) {\r\n var k = keys[i];\r\n var e = terrainCache[k];\r\n if (JulianDate.secondsDifference(julianDateScratch, e.timestamp) > 10) {\r\n delete terrainCache[k];\r\n }\r\n }\r\n\r\n JulianDate.clone(julianDateScratch, this._lastTidy);\r\n }\r\n};\r\n\r\n/**\r\n * Provides tiled terrain using the Google Earth Enterprise REST API.\r\n *\r\n * @alias GoogleEarthEnterpriseTerrainProvider\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Resource|String} options.url The url of the Google Earth Enterprise server hosting the imagery.\r\n * @param {GoogleEarthEnterpriseMetadata} options.metadata A metadata object that can be used to share metadata requests with a GoogleEarthEnterpriseImageryProvider.\r\n * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used.\r\n * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas.\r\n *\r\n * @see GoogleEarthEnterpriseImageryProvider\r\n * @see CesiumTerrainProvider\r\n *\r\n * @example\r\n * var geeMetadata = new GoogleEarthEnterpriseMetadata('http://www.earthenterprise.org/3d');\r\n * var gee = new Cesium.GoogleEarthEnterpriseTerrainProvider({\r\n * metadata : geeMetadata\r\n * });\r\n *\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n */\r\nfunction GoogleEarthEnterpriseTerrainProvider(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!(defined(options.url) || defined(options.metadata))) {\r\n throw new DeveloperError(\"options.url or options.metadata is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var metadata;\r\n if (defined(options.metadata)) {\r\n metadata = options.metadata;\r\n } else {\r\n var resource = Resource.createIfNeeded(options.url);\r\n metadata = new GoogleEarthEnterpriseMetadata(resource);\r\n }\r\n\r\n this._metadata = metadata;\r\n this._tilingScheme = new GeographicTilingScheme({\r\n numberOfLevelZeroTilesX: 2,\r\n numberOfLevelZeroTilesY: 2,\r\n rectangle: new Rectangle(\r\n -CesiumMath.PI,\r\n -CesiumMath.PI,\r\n CesiumMath.PI,\r\n CesiumMath.PI\r\n ),\r\n ellipsoid: options.ellipsoid,\r\n });\r\n\r\n var credit = options.credit;\r\n if (typeof credit === \"string\") {\r\n credit = new Credit(credit);\r\n }\r\n this._credit = credit;\r\n\r\n // Pulled from Google's documentation\r\n this._levelZeroMaximumGeometricError = 40075.16;\r\n\r\n this._terrainCache = new TerrainCache();\r\n this._terrainPromises = {};\r\n this._terrainRequests = {};\r\n\r\n this._errorEvent = new Event();\r\n\r\n this._ready = false;\r\n var that = this;\r\n var metadataError;\r\n this._readyPromise = metadata.readyPromise\r\n .then(function (result) {\r\n if (!metadata.terrainPresent) {\r\n var e = new RuntimeError(\r\n \"The server \" + metadata.url + \" doesn't have terrain\"\r\n );\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n e.message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n e\r\n );\r\n return when.reject(e);\r\n }\r\n\r\n TileProviderError.handleSuccess(metadataError);\r\n that._ready = result;\r\n return result;\r\n })\r\n .otherwise(function (e) {\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n e.message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n e\r\n );\r\n return when.reject(e);\r\n });\r\n}\r\n\r\nObject.defineProperties(GoogleEarthEnterpriseTerrainProvider.prototype, {\r\n /**\r\n * Gets the name of the Google Earth Enterprise server url hosting the imagery.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {String}\r\n * @readonly\r\n */\r\n url: {\r\n get: function () {\r\n return this._metadata.url;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the proxy used by this provider.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {Proxy}\r\n * @readonly\r\n */\r\n proxy: {\r\n get: function () {\r\n return this._metadata.proxy;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tiling scheme used by this provider. This function should\r\n * not be called before {@link GoogleEarthEnterpriseTerrainProvider#ready} returns true.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {TilingScheme}\r\n * @readonly\r\n */\r\n tilingScheme: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"tilingScheme must not be called before the imagery provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._tilingScheme;\r\n },\r\n },\r\n\r\n /**\r\n * Gets an event that is raised when the imagery provider encounters an asynchronous error. By subscribing\r\n * to the event, you will be notified of the error and can potentially recover from it. Event listeners\r\n * are passed an instance of {@link TileProviderError}.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n errorEvent: {\r\n get: function () {\r\n return this._errorEvent;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider is ready for use.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves to true when the provider is ready for use.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the credit to display when this terrain provider is active. Typically this is used to credit\r\n * the source of the terrain. This function should not be called before {@link GoogleEarthEnterpriseTerrainProvider#ready} returns true.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {Credit}\r\n * @readonly\r\n */\r\n credit: {\r\n get: function () {\r\n return this._credit;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider includes a water mask. The water mask\r\n * indicates which areas of the globe are water rather than land, so they can be rendered\r\n * as a reflective surface with animated waves. This function should not be\r\n * called before {@link GoogleEarthEnterpriseTerrainProvider#ready} returns true.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasWaterMask: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the requested tiles include vertex normals.\r\n * This function should not be called before {@link GoogleEarthEnterpriseTerrainProvider#ready} returns true.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasVertexNormals: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n\r\n /**\r\n * Gets an object that can be used to determine availability of terrain from this provider, such as\r\n * at points and in rectangles. This function should not be called before\r\n * {@link GoogleEarthEnterpriseTerrainProvider#ready} returns true. This property may be undefined if availability\r\n * information is not available.\r\n * @memberof GoogleEarthEnterpriseTerrainProvider.prototype\r\n * @type {TileAvailability}\r\n */\r\n availability: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n});\r\n\r\nvar taskProcessor = new TaskProcessor(\"decodeGoogleEarthEnterprisePacket\");\r\n\r\n// If the tile has its own terrain, then you can just use its child bitmask. If it was requested using it's parent\r\n// then you need to check all of its children to see if they have terrain.\r\nfunction computeChildMask(quadKey, info, metadata) {\r\n var childMask = info.getChildBitmask();\r\n if (info.terrainState === TerrainState.PARENT) {\r\n childMask = 0;\r\n for (var i = 0; i < 4; ++i) {\r\n var child = metadata.getTileInformationFromQuadKey(\r\n quadKey + i.toString()\r\n );\r\n if (defined(child) && child.hasTerrain()) {\r\n childMask |= 1 << i;\r\n }\r\n }\r\n }\r\n\r\n return childMask;\r\n}\r\n\r\n/**\r\n * Requests the geometry for a given tile. This function should not be called before\r\n * {@link GoogleEarthEnterpriseTerrainProvider#ready} returns true. The result must include terrain data and\r\n * may optionally include a water mask and an indication of which child tiles are available.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @param {Request} [request] The request object. Intended for internal use only.\r\n * @returns {Promise.|undefined} A promise for the requested geometry. If this method\r\n * returns undefined instead of a promise, it is an indication that too many requests are already\r\n * pending and the request will be retried later.\r\n *\r\n * @exception {DeveloperError} This function must not be called before {@link GoogleEarthEnterpriseTerrainProvider#ready}\r\n * returns true.\r\n */\r\nGoogleEarthEnterpriseTerrainProvider.prototype.requestTileGeometry = function (\r\n x,\r\n y,\r\n level,\r\n request\r\n) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!this._ready) {\r\n throw new DeveloperError(\r\n \"requestTileGeometry must not be called before the terrain provider is ready.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var quadKey = GoogleEarthEnterpriseMetadata.tileXYToQuadKey(x, y, level);\r\n var terrainCache = this._terrainCache;\r\n var metadata = this._metadata;\r\n var info = metadata.getTileInformationFromQuadKey(quadKey);\r\n\r\n // Check if this tile is even possibly available\r\n if (!defined(info)) {\r\n return when.reject(new RuntimeError(\"Terrain tile doesn't exist\"));\r\n }\r\n\r\n var terrainState = info.terrainState;\r\n if (!defined(terrainState)) {\r\n // First time we have tried to load this tile, so set terrain state to UNKNOWN\r\n terrainState = info.terrainState = TerrainState.UNKNOWN;\r\n }\r\n\r\n // If its in the cache, return it\r\n var buffer = terrainCache.get(quadKey);\r\n if (defined(buffer)) {\r\n var credit = metadata.providers[info.terrainProvider];\r\n return when.resolve(\r\n new GoogleEarthEnterpriseTerrainData({\r\n buffer: buffer,\r\n childTileMask: computeChildMask(quadKey, info, metadata),\r\n credits: defined(credit) ? [credit] : undefined,\r\n negativeAltitudeExponentBias: metadata.negativeAltitudeExponentBias,\r\n negativeElevationThreshold: metadata.negativeAltitudeThreshold,\r\n })\r\n );\r\n }\r\n\r\n // Clean up the cache\r\n terrainCache.tidy();\r\n\r\n // We have a tile, check to see if no ancestors have terrain or that we know for sure it doesn't\r\n if (!info.ancestorHasTerrain) {\r\n // We haven't reached a level with terrain, so return the ellipsoid\r\n return when.resolve(\r\n new HeightmapTerrainData({\r\n buffer: new Uint8Array(16 * 16),\r\n width: 16,\r\n height: 16,\r\n })\r\n );\r\n } else if (terrainState === TerrainState.NONE) {\r\n // Already have info and there isn't any terrain here\r\n return when.reject(new RuntimeError(\"Terrain tile doesn't exist\"));\r\n }\r\n\r\n // Figure out where we are getting the terrain and what version\r\n var parentInfo;\r\n var q = quadKey;\r\n var terrainVersion = -1;\r\n switch (terrainState) {\r\n case TerrainState.SELF: // We have terrain and have retrieved it before\r\n terrainVersion = info.terrainVersion;\r\n break;\r\n case TerrainState.PARENT: // We have terrain in our parent\r\n q = q.substring(0, q.length - 1);\r\n parentInfo = metadata.getTileInformationFromQuadKey(q);\r\n terrainVersion = parentInfo.terrainVersion;\r\n break;\r\n case TerrainState.UNKNOWN: // We haven't tried to retrieve terrain yet\r\n if (info.hasTerrain()) {\r\n terrainVersion = info.terrainVersion; // We should have terrain\r\n } else {\r\n q = q.substring(0, q.length - 1);\r\n parentInfo = metadata.getTileInformationFromQuadKey(q);\r\n if (defined(parentInfo) && parentInfo.hasTerrain()) {\r\n terrainVersion = parentInfo.terrainVersion; // Try checking in the parent\r\n }\r\n }\r\n break;\r\n }\r\n\r\n // We can't figure out where to get the terrain\r\n if (terrainVersion < 0) {\r\n return when.reject(new RuntimeError(\"Terrain tile doesn't exist\"));\r\n }\r\n\r\n // Load that terrain\r\n var terrainPromises = this._terrainPromises;\r\n var terrainRequests = this._terrainRequests;\r\n var sharedPromise;\r\n var sharedRequest;\r\n if (defined(terrainPromises[q])) {\r\n // Already being loaded possibly from another child, so return existing promise\r\n sharedPromise = terrainPromises[q];\r\n sharedRequest = terrainRequests[q];\r\n } else {\r\n // Create new request for terrain\r\n sharedRequest = request;\r\n var requestPromise = buildTerrainResource(\r\n this,\r\n q,\r\n terrainVersion,\r\n sharedRequest\r\n ).fetchArrayBuffer();\r\n\r\n if (!defined(requestPromise)) {\r\n return undefined; // Throttled\r\n }\r\n\r\n sharedPromise = requestPromise.then(function (terrain) {\r\n if (defined(terrain)) {\r\n return taskProcessor\r\n .scheduleTask(\r\n {\r\n buffer: terrain,\r\n type: \"Terrain\",\r\n key: metadata.key,\r\n },\r\n [terrain]\r\n )\r\n .then(function (terrainTiles) {\r\n // Add requested tile and mark it as SELF\r\n var requestedInfo = metadata.getTileInformationFromQuadKey(q);\r\n requestedInfo.terrainState = TerrainState.SELF;\r\n terrainCache.add(q, terrainTiles[0]);\r\n var provider = requestedInfo.terrainProvider;\r\n\r\n // Add children to cache\r\n var count = terrainTiles.length - 1;\r\n for (var j = 0; j < count; ++j) {\r\n var childKey = q + j.toString();\r\n var child = metadata.getTileInformationFromQuadKey(childKey);\r\n if (defined(child)) {\r\n terrainCache.add(childKey, terrainTiles[j + 1]);\r\n child.terrainState = TerrainState.PARENT;\r\n if (child.terrainProvider === 0) {\r\n child.terrainProvider = provider;\r\n }\r\n }\r\n }\r\n });\r\n }\r\n\r\n return when.reject(new RuntimeError(\"Failed to load terrain.\"));\r\n });\r\n\r\n terrainPromises[q] = sharedPromise; // Store promise without delete from terrainPromises\r\n terrainRequests[q] = sharedRequest;\r\n\r\n // Set promise so we remove from terrainPromises just one time\r\n sharedPromise = sharedPromise.always(function () {\r\n delete terrainPromises[q];\r\n delete terrainRequests[q];\r\n });\r\n }\r\n\r\n return sharedPromise\r\n .then(function () {\r\n var buffer = terrainCache.get(quadKey);\r\n if (defined(buffer)) {\r\n var credit = metadata.providers[info.terrainProvider];\r\n return new GoogleEarthEnterpriseTerrainData({\r\n buffer: buffer,\r\n childTileMask: computeChildMask(quadKey, info, metadata),\r\n credits: defined(credit) ? [credit] : undefined,\r\n negativeAltitudeExponentBias: metadata.negativeAltitudeExponentBias,\r\n negativeElevationThreshold: metadata.negativeAltitudeThreshold,\r\n });\r\n }\r\n\r\n return when.reject(new RuntimeError(\"Failed to load terrain.\"));\r\n })\r\n .otherwise(function (error) {\r\n if (sharedRequest.state === RequestState.CANCELLED) {\r\n request.state = sharedRequest.state;\r\n return when.reject(error);\r\n }\r\n info.terrainState = TerrainState.NONE;\r\n return when.reject(error);\r\n });\r\n};\r\n\r\n/**\r\n * Gets the maximum geometric error allowed in a tile at a given level.\r\n *\r\n * @param {Number} level The tile level for which to get the maximum geometric error.\r\n * @returns {Number} The maximum geometric error.\r\n */\r\nGoogleEarthEnterpriseTerrainProvider.prototype.getLevelMaximumGeometricError = function (\r\n level\r\n) {\r\n return this._levelZeroMaximumGeometricError / (1 << level);\r\n};\r\n\r\n/**\r\n * Determines whether data for a tile is available to be loaded.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {Boolean} Undefined if not supported, otherwise true or false.\r\n */\r\nGoogleEarthEnterpriseTerrainProvider.prototype.getTileDataAvailable = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n var metadata = this._metadata;\r\n var quadKey = GoogleEarthEnterpriseMetadata.tileXYToQuadKey(x, y, level);\r\n\r\n var info = metadata.getTileInformation(x, y, level);\r\n if (info === null) {\r\n return false;\r\n }\r\n\r\n if (defined(info)) {\r\n if (!info.ancestorHasTerrain) {\r\n return true; // We'll just return the ellipsoid\r\n }\r\n\r\n var terrainState = info.terrainState;\r\n if (terrainState === TerrainState.NONE) {\r\n return false; // Terrain is not available\r\n }\r\n\r\n if (!defined(terrainState) || terrainState === TerrainState.UNKNOWN) {\r\n info.terrainState = TerrainState.UNKNOWN;\r\n if (!info.hasTerrain()) {\r\n quadKey = quadKey.substring(0, quadKey.length - 1);\r\n var parentInfo = metadata.getTileInformationFromQuadKey(quadKey);\r\n if (!defined(parentInfo) || !parentInfo.hasTerrain()) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n if (metadata.isValid(quadKey)) {\r\n // We will need this tile, so request metadata and return false for now\r\n var request = new Request({\r\n throttle: false,\r\n throttleByServer: true,\r\n type: RequestType.TERRAIN,\r\n });\r\n metadata.populateSubtree(x, y, level, request);\r\n }\r\n return false;\r\n};\r\n\r\n/**\r\n * Makes sure we load availability data for a tile\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {undefined|Promise} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded\r\n */\r\nGoogleEarthEnterpriseTerrainProvider.prototype.loadTileDataAvailability = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n return undefined;\r\n};\r\n\r\n//\r\n// Functions to handle imagery packets\r\n//\r\nfunction buildTerrainResource(terrainProvider, quadKey, version, request) {\r\n version = defined(version) && version > 0 ? version : 1;\r\n return terrainProvider._metadata.resource.getDerivedResource({\r\n url: \"flatfile?f1c-0\" + quadKey + \"-t.\" + version.toString(),\r\n request: request,\r\n });\r\n}\r\nexport default GoogleEarthEnterpriseTerrainProvider;\r\n","import ApproximateTerrainHeights from \"./ApproximateTerrainHeights.js\";\r\nimport ArcType from \"./ArcType.js\";\r\nimport arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport EllipsoidGeodesic from \"./EllipsoidGeodesic.js\";\r\nimport EllipsoidRhumbLine from \"./EllipsoidRhumbLine.js\";\r\nimport EncodedCartesian3 from \"./EncodedCartesian3.js\";\r\nimport GeographicProjection from \"./GeographicProjection.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport IntersectionTests from \"./IntersectionTests.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Plane from \"./Plane.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport WebMercatorProjection from \"./WebMercatorProjection.js\";\r\n\r\nvar PROJECTIONS = [GeographicProjection, WebMercatorProjection];\r\nvar PROJECTION_COUNT = PROJECTIONS.length;\r\n\r\nvar MITER_BREAK_SMALL = Math.cos(CesiumMath.toRadians(30.0));\r\nvar MITER_BREAK_LARGE = Math.cos(CesiumMath.toRadians(150.0));\r\n\r\n// Initial heights for constructing the wall.\r\n// Keeping WALL_INITIAL_MIN_HEIGHT near the ellipsoid surface helps\r\n// prevent precision problems with planes in the shader.\r\n// Putting the start point of a plane at ApproximateTerrainHeights._defaultMinTerrainHeight,\r\n// which is a highly conservative bound, usually puts the plane origin several thousands\r\n// of meters away from the actual terrain, causing floating point problems when checking\r\n// fragments on terrain against the plane.\r\n// Ellipsoid height is generally much closer.\r\n// The initial max height is arbitrary.\r\n// Both heights are corrected using ApproximateTerrainHeights for computing the actual volume geometry.\r\nvar WALL_INITIAL_MIN_HEIGHT = 0.0;\r\nvar WALL_INITIAL_MAX_HEIGHT = 1000.0;\r\n\r\n/**\r\n * A description of a polyline on terrain or 3D Tiles. Only to be used with {@link GroundPolylinePrimitive}.\r\n *\r\n * @alias GroundPolylineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Options with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of {@link Cartesian3} defining the polyline's points. Heights above the ellipsoid will be ignored.\r\n * @param {Number} [options.width=1.0] The screen space width in pixels.\r\n * @param {Number} [options.granularity=9999.0] The distance interval in meters used for interpolating options.points. Defaults to 9999.0 meters. Zero indicates no interpolation.\r\n * @param {Boolean} [options.loop=false] Whether during geometry creation a line segment will be added between the last and first line positions to make this Polyline a loop.\r\n * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polyline segments must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.\r\n *\r\n * @exception {DeveloperError} At least two positions are required.\r\n *\r\n * @see GroundPolylinePrimitive\r\n *\r\n * @example\r\n * var positions = Cesium.Cartesian3.fromDegreesArray([\r\n * -112.1340164450331, 36.05494287836128,\r\n * -112.08821010582645, 36.097804071380715,\r\n * -112.13296079730024, 36.168769146801104\r\n * ]);\r\n *\r\n * var geometry = new Cesium.GroundPolylineGeometry({\r\n * positions : positions\r\n * });\r\n */\r\nfunction GroundPolylineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.positions;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions) || positions.length < 2) {\r\n throw new DeveloperError(\"At least two positions are required.\");\r\n }\r\n if (\r\n defined(options.arcType) &&\r\n options.arcType !== ArcType.GEODESIC &&\r\n options.arcType !== ArcType.RHUMB\r\n ) {\r\n throw new DeveloperError(\r\n \"Valid options for arcType are ArcType.GEODESIC and ArcType.RHUMB.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * The screen space width in pixels.\r\n * @type {Number}\r\n */\r\n this.width = defaultValue(options.width, 1.0); // Doesn't get packed, not necessary for computing geometry.\r\n\r\n this._positions = positions;\r\n\r\n /**\r\n * The distance interval used for interpolating options.points. Zero indicates no interpolation.\r\n * Default of 9999.0 allows centimeter accuracy with 32 bit floating point.\r\n * @type {Boolean}\r\n * @default 9999.0\r\n */\r\n this.granularity = defaultValue(options.granularity, 9999.0);\r\n\r\n /**\r\n * Whether during geometry creation a line segment will be added between the last and first line positions to make this Polyline a loop.\r\n * If the geometry has two positions this parameter will be ignored.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.loop = defaultValue(options.loop, false);\r\n\r\n /**\r\n * The type of path the polyline must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.\r\n * @type {ArcType}\r\n * @default ArcType.GEODESIC\r\n */\r\n this.arcType = defaultValue(options.arcType, ArcType.GEODESIC);\r\n\r\n this._ellipsoid = Ellipsoid.WGS84;\r\n\r\n // MapProjections can't be packed, so store the index to a known MapProjection.\r\n this._projectionIndex = 0;\r\n this._workerName = \"createGroundPolylineGeometry\";\r\n\r\n // Used by GroundPolylinePrimitive to signal worker that scenemode is 3D only.\r\n this._scene3DOnly = false;\r\n}\r\n\r\nObject.defineProperties(GroundPolylineGeometry.prototype, {\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @memberof GroundPolylineGeometry.prototype\r\n * @type {Number}\r\n * @readonly\r\n * @private\r\n */\r\n packedLength: {\r\n get: function () {\r\n return (\r\n 1.0 +\r\n this._positions.length * 3 +\r\n 1.0 +\r\n 1.0 +\r\n 1.0 +\r\n Ellipsoid.packedLength +\r\n 1.0 +\r\n 1.0\r\n );\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Set the GroundPolylineGeometry's projection and ellipsoid.\r\n * Used by GroundPolylinePrimitive to signal scene information to the geometry for generating 2D attributes.\r\n *\r\n * @param {GroundPolylineGeometry} groundPolylineGeometry GroundPolylinGeometry describing a polyline on terrain or 3D Tiles.\r\n * @param {Projection} mapProjection A MapProjection used for projecting cartographic coordinates to 2D.\r\n * @private\r\n */\r\nGroundPolylineGeometry.setProjectionAndEllipsoid = function (\r\n groundPolylineGeometry,\r\n mapProjection\r\n) {\r\n var projectionIndex = 0;\r\n for (var i = 0; i < PROJECTION_COUNT; i++) {\r\n if (mapProjection instanceof PROJECTIONS[i]) {\r\n projectionIndex = i;\r\n break;\r\n }\r\n }\r\n\r\n groundPolylineGeometry._projectionIndex = projectionIndex;\r\n groundPolylineGeometry._ellipsoid = mapProjection.ellipsoid;\r\n};\r\n\r\nvar cart3Scratch1 = new Cartesian3();\r\nvar cart3Scratch2 = new Cartesian3();\r\nvar cart3Scratch3 = new Cartesian3();\r\nfunction computeRightNormal(start, end, maxHeight, ellipsoid, result) {\r\n var startBottom = getPosition(ellipsoid, start, 0.0, cart3Scratch1);\r\n var startTop = getPosition(ellipsoid, start, maxHeight, cart3Scratch2);\r\n var endBottom = getPosition(ellipsoid, end, 0.0, cart3Scratch3);\r\n\r\n var up = direction(startTop, startBottom, cart3Scratch2);\r\n var forward = direction(endBottom, startBottom, cart3Scratch3);\r\n\r\n Cartesian3.cross(forward, up, result);\r\n return Cartesian3.normalize(result, result);\r\n}\r\n\r\nvar interpolatedCartographicScratch = new Cartographic();\r\nvar interpolatedBottomScratch = new Cartesian3();\r\nvar interpolatedTopScratch = new Cartesian3();\r\nvar interpolatedNormalScratch = new Cartesian3();\r\nfunction interpolateSegment(\r\n start,\r\n end,\r\n minHeight,\r\n maxHeight,\r\n granularity,\r\n arcType,\r\n ellipsoid,\r\n normalsArray,\r\n bottomPositionsArray,\r\n topPositionsArray,\r\n cartographicsArray\r\n) {\r\n if (granularity === 0.0) {\r\n return;\r\n }\r\n\r\n var ellipsoidLine;\r\n if (arcType === ArcType.GEODESIC) {\r\n ellipsoidLine = new EllipsoidGeodesic(start, end, ellipsoid);\r\n } else if (arcType === ArcType.RHUMB) {\r\n ellipsoidLine = new EllipsoidRhumbLine(start, end, ellipsoid);\r\n }\r\n\r\n var surfaceDistance = ellipsoidLine.surfaceDistance;\r\n if (surfaceDistance < granularity) {\r\n return;\r\n }\r\n\r\n // Compute rightwards normal applicable at all interpolated points\r\n var interpolatedNormal = computeRightNormal(\r\n start,\r\n end,\r\n maxHeight,\r\n ellipsoid,\r\n interpolatedNormalScratch\r\n );\r\n\r\n var segments = Math.ceil(surfaceDistance / granularity);\r\n var interpointDistance = surfaceDistance / segments;\r\n var distanceFromStart = interpointDistance;\r\n var pointsToAdd = segments - 1;\r\n var packIndex = normalsArray.length;\r\n for (var i = 0; i < pointsToAdd; i++) {\r\n var interpolatedCartographic = ellipsoidLine.interpolateUsingSurfaceDistance(\r\n distanceFromStart,\r\n interpolatedCartographicScratch\r\n );\r\n var interpolatedBottom = getPosition(\r\n ellipsoid,\r\n interpolatedCartographic,\r\n minHeight,\r\n interpolatedBottomScratch\r\n );\r\n var interpolatedTop = getPosition(\r\n ellipsoid,\r\n interpolatedCartographic,\r\n maxHeight,\r\n interpolatedTopScratch\r\n );\r\n\r\n Cartesian3.pack(interpolatedNormal, normalsArray, packIndex);\r\n Cartesian3.pack(interpolatedBottom, bottomPositionsArray, packIndex);\r\n Cartesian3.pack(interpolatedTop, topPositionsArray, packIndex);\r\n cartographicsArray.push(interpolatedCartographic.latitude);\r\n cartographicsArray.push(interpolatedCartographic.longitude);\r\n\r\n packIndex += 3;\r\n distanceFromStart += interpointDistance;\r\n }\r\n}\r\n\r\nvar heightlessCartographicScratch = new Cartographic();\r\nfunction getPosition(ellipsoid, cartographic, height, result) {\r\n Cartographic.clone(cartographic, heightlessCartographicScratch);\r\n heightlessCartographicScratch.height = height;\r\n return Cartographic.toCartesian(\r\n heightlessCartographicScratch,\r\n ellipsoid,\r\n result\r\n );\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PolygonGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nGroundPolylineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n var index = defaultValue(startingIndex, 0);\r\n\r\n var positions = value._positions;\r\n var positionsLength = positions.length;\r\n\r\n array[index++] = positionsLength;\r\n\r\n for (var i = 0; i < positionsLength; ++i) {\r\n var cartesian = positions[i];\r\n Cartesian3.pack(cartesian, array, index);\r\n index += 3;\r\n }\r\n\r\n array[index++] = value.granularity;\r\n array[index++] = value.loop ? 1.0 : 0.0;\r\n array[index++] = value.arcType;\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, index);\r\n index += Ellipsoid.packedLength;\r\n\r\n array[index++] = value._projectionIndex;\r\n array[index++] = value._scene3DOnly ? 1.0 : 0.0;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PolygonGeometry} [result] The object into which to store the result.\r\n */\r\nGroundPolylineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n var index = defaultValue(startingIndex, 0);\r\n var positionsLength = array[index++];\r\n var positions = new Array(positionsLength);\r\n\r\n for (var i = 0; i < positionsLength; i++) {\r\n positions[i] = Cartesian3.unpack(array, index);\r\n index += 3;\r\n }\r\n\r\n var granularity = array[index++];\r\n var loop = array[index++] === 1.0;\r\n var arcType = array[index++];\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, index);\r\n index += Ellipsoid.packedLength;\r\n\r\n var projectionIndex = array[index++];\r\n var scene3DOnly = array[index++] === 1.0;\r\n\r\n if (!defined(result)) {\r\n result = new GroundPolylineGeometry({\r\n positions: positions,\r\n });\r\n }\r\n\r\n result._positions = positions;\r\n result.granularity = granularity;\r\n result.loop = loop;\r\n result.arcType = arcType;\r\n result._ellipsoid = ellipsoid;\r\n result._projectionIndex = projectionIndex;\r\n result._scene3DOnly = scene3DOnly;\r\n\r\n return result;\r\n};\r\n\r\nfunction direction(target, origin, result) {\r\n Cartesian3.subtract(target, origin, result);\r\n Cartesian3.normalize(result, result);\r\n return result;\r\n}\r\n\r\nfunction tangentDirection(target, origin, up, result) {\r\n result = direction(target, origin, result);\r\n\r\n // orthogonalize\r\n result = Cartesian3.cross(result, up, result);\r\n result = Cartesian3.normalize(result, result);\r\n result = Cartesian3.cross(up, result, result);\r\n return result;\r\n}\r\n\r\nvar toPreviousScratch = new Cartesian3();\r\nvar toNextScratch = new Cartesian3();\r\nvar forwardScratch = new Cartesian3();\r\nvar vertexUpScratch = new Cartesian3();\r\nvar cosine90 = 0.0;\r\nvar cosine180 = -1.0;\r\nfunction computeVertexMiterNormal(\r\n previousBottom,\r\n vertexBottom,\r\n vertexTop,\r\n nextBottom,\r\n result\r\n) {\r\n var up = direction(vertexTop, vertexBottom, vertexUpScratch);\r\n\r\n // Compute vectors pointing towards neighboring points but tangent to this point on the ellipsoid\r\n var toPrevious = tangentDirection(\r\n previousBottom,\r\n vertexBottom,\r\n up,\r\n toPreviousScratch\r\n );\r\n var toNext = tangentDirection(nextBottom, vertexBottom, up, toNextScratch);\r\n\r\n // Check if tangents are almost opposite - if so, no need to miter.\r\n if (\r\n CesiumMath.equalsEpsilon(\r\n Cartesian3.dot(toPrevious, toNext),\r\n cosine180,\r\n CesiumMath.EPSILON5\r\n )\r\n ) {\r\n result = Cartesian3.cross(up, toPrevious, result);\r\n result = Cartesian3.normalize(result, result);\r\n return result;\r\n }\r\n\r\n // Average directions to previous and to next in the plane of Up\r\n result = Cartesian3.add(toNext, toPrevious, result);\r\n result = Cartesian3.normalize(result, result);\r\n\r\n // Flip the normal if it isn't pointing roughly bound right (aka if forward is pointing more \"backwards\")\r\n var forward = Cartesian3.cross(up, result, forwardScratch);\r\n if (Cartesian3.dot(toNext, forward) < cosine90) {\r\n result = Cartesian3.negate(result, result);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nvar XZ_PLANE = Plane.fromPointNormal(Cartesian3.ZERO, Cartesian3.UNIT_Y);\r\n\r\nvar previousBottomScratch = new Cartesian3();\r\nvar vertexBottomScratch = new Cartesian3();\r\nvar vertexTopScratch = new Cartesian3();\r\nvar nextBottomScratch = new Cartesian3();\r\nvar vertexNormalScratch = new Cartesian3();\r\nvar intersectionScratch = new Cartesian3();\r\nvar cartographicScratch0 = new Cartographic();\r\nvar cartographicScratch1 = new Cartographic();\r\nvar cartographicIntersectionScratch = new Cartographic();\r\n/**\r\n * Computes shadow volumes for the ground polyline, consisting of its vertices, indices, and a bounding sphere.\r\n * Vertices are \"fat,\" packing all the data needed in each volume to describe a line on terrain or 3D Tiles.\r\n * Should not be called independent of {@link GroundPolylinePrimitive}.\r\n *\r\n * @param {GroundPolylineGeometry} groundPolylineGeometry\r\n * @private\r\n */\r\nGroundPolylineGeometry.createGeometry = function (groundPolylineGeometry) {\r\n var compute2dAttributes = !groundPolylineGeometry._scene3DOnly;\r\n var loop = groundPolylineGeometry.loop;\r\n var ellipsoid = groundPolylineGeometry._ellipsoid;\r\n var granularity = groundPolylineGeometry.granularity;\r\n var arcType = groundPolylineGeometry.arcType;\r\n var projection = new PROJECTIONS[groundPolylineGeometry._projectionIndex](\r\n ellipsoid\r\n );\r\n\r\n var minHeight = WALL_INITIAL_MIN_HEIGHT;\r\n var maxHeight = WALL_INITIAL_MAX_HEIGHT;\r\n\r\n var index;\r\n var i;\r\n\r\n var positions = groundPolylineGeometry._positions;\r\n var positionsLength = positions.length;\r\n\r\n if (positionsLength === 2) {\r\n loop = false;\r\n }\r\n\r\n // Split positions across the IDL and the Prime Meridian as well.\r\n // Split across prime meridian because very large geometries crossing the Prime Meridian but not the IDL\r\n // may get split by the plane of IDL + Prime Meridian.\r\n var p0;\r\n var p1;\r\n var c0;\r\n var c1;\r\n var rhumbLine = new EllipsoidRhumbLine(undefined, undefined, ellipsoid);\r\n var intersection;\r\n var intersectionCartographic;\r\n var intersectionLongitude;\r\n var splitPositions = [positions[0]];\r\n for (i = 0; i < positionsLength - 1; i++) {\r\n p0 = positions[i];\r\n p1 = positions[i + 1];\r\n intersection = IntersectionTests.lineSegmentPlane(\r\n p0,\r\n p1,\r\n XZ_PLANE,\r\n intersectionScratch\r\n );\r\n if (\r\n defined(intersection) &&\r\n !Cartesian3.equalsEpsilon(intersection, p0, CesiumMath.EPSILON7) &&\r\n !Cartesian3.equalsEpsilon(intersection, p1, CesiumMath.EPSILON7)\r\n ) {\r\n if (groundPolylineGeometry.arcType === ArcType.GEODESIC) {\r\n splitPositions.push(Cartesian3.clone(intersection));\r\n } else if (groundPolylineGeometry.arcType === ArcType.RHUMB) {\r\n intersectionLongitude = ellipsoid.cartesianToCartographic(\r\n intersection,\r\n cartographicScratch0\r\n ).longitude;\r\n c0 = ellipsoid.cartesianToCartographic(p0, cartographicScratch0);\r\n c1 = ellipsoid.cartesianToCartographic(p1, cartographicScratch1);\r\n rhumbLine.setEndPoints(c0, c1);\r\n intersectionCartographic = rhumbLine.findIntersectionWithLongitude(\r\n intersectionLongitude,\r\n cartographicIntersectionScratch\r\n );\r\n intersection = ellipsoid.cartographicToCartesian(\r\n intersectionCartographic,\r\n intersectionScratch\r\n );\r\n if (\r\n defined(intersection) &&\r\n !Cartesian3.equalsEpsilon(intersection, p0, CesiumMath.EPSILON7) &&\r\n !Cartesian3.equalsEpsilon(intersection, p1, CesiumMath.EPSILON7)\r\n ) {\r\n splitPositions.push(Cartesian3.clone(intersection));\r\n }\r\n }\r\n }\r\n splitPositions.push(p1);\r\n }\r\n\r\n if (loop) {\r\n p0 = positions[positionsLength - 1];\r\n p1 = positions[0];\r\n intersection = IntersectionTests.lineSegmentPlane(\r\n p0,\r\n p1,\r\n XZ_PLANE,\r\n intersectionScratch\r\n );\r\n if (\r\n defined(intersection) &&\r\n !Cartesian3.equalsEpsilon(intersection, p0, CesiumMath.EPSILON7) &&\r\n !Cartesian3.equalsEpsilon(intersection, p1, CesiumMath.EPSILON7)\r\n ) {\r\n if (groundPolylineGeometry.arcType === ArcType.GEODESIC) {\r\n splitPositions.push(Cartesian3.clone(intersection));\r\n } else if (groundPolylineGeometry.arcType === ArcType.RHUMB) {\r\n intersectionLongitude = ellipsoid.cartesianToCartographic(\r\n intersection,\r\n cartographicScratch0\r\n ).longitude;\r\n c0 = ellipsoid.cartesianToCartographic(p0, cartographicScratch0);\r\n c1 = ellipsoid.cartesianToCartographic(p1, cartographicScratch1);\r\n rhumbLine.setEndPoints(c0, c1);\r\n intersectionCartographic = rhumbLine.findIntersectionWithLongitude(\r\n intersectionLongitude,\r\n cartographicIntersectionScratch\r\n );\r\n intersection = ellipsoid.cartographicToCartesian(\r\n intersectionCartographic,\r\n intersectionScratch\r\n );\r\n if (\r\n defined(intersection) &&\r\n !Cartesian3.equalsEpsilon(intersection, p0, CesiumMath.EPSILON7) &&\r\n !Cartesian3.equalsEpsilon(intersection, p1, CesiumMath.EPSILON7)\r\n ) {\r\n splitPositions.push(Cartesian3.clone(intersection));\r\n }\r\n }\r\n }\r\n }\r\n var cartographicsLength = splitPositions.length;\r\n\r\n var cartographics = new Array(cartographicsLength);\r\n for (i = 0; i < cartographicsLength; i++) {\r\n var cartographic = Cartographic.fromCartesian(splitPositions[i], ellipsoid);\r\n cartographic.height = 0.0;\r\n cartographics[i] = cartographic;\r\n }\r\n\r\n cartographics = arrayRemoveDuplicates(\r\n cartographics,\r\n Cartographic.equalsEpsilon\r\n );\r\n cartographicsLength = cartographics.length;\r\n\r\n if (cartographicsLength < 2) {\r\n return undefined;\r\n }\r\n\r\n /**** Build heap-side arrays for positions, interpolated cartographics, and normals from which to compute vertices ****/\r\n // We build a \"wall\" and then decompose it into separately connected component \"volumes\" because we need a lot\r\n // of information about the wall. Also, this simplifies interpolation.\r\n // Convention: \"next\" and \"end\" are locally forward to each segment of the wall,\r\n // and we are computing normals pointing towards the local right side of the vertices in each segment.\r\n var cartographicsArray = [];\r\n var normalsArray = [];\r\n var bottomPositionsArray = [];\r\n var topPositionsArray = [];\r\n\r\n var previousBottom = previousBottomScratch;\r\n var vertexBottom = vertexBottomScratch;\r\n var vertexTop = vertexTopScratch;\r\n var nextBottom = nextBottomScratch;\r\n var vertexNormal = vertexNormalScratch;\r\n\r\n // First point - either loop or attach a \"perpendicular\" normal\r\n var startCartographic = cartographics[0];\r\n var nextCartographic = cartographics[1];\r\n\r\n var prestartCartographic = cartographics[cartographicsLength - 1];\r\n previousBottom = getPosition(\r\n ellipsoid,\r\n prestartCartographic,\r\n minHeight,\r\n previousBottom\r\n );\r\n nextBottom = getPosition(ellipsoid, nextCartographic, minHeight, nextBottom);\r\n vertexBottom = getPosition(\r\n ellipsoid,\r\n startCartographic,\r\n minHeight,\r\n vertexBottom\r\n );\r\n vertexTop = getPosition(ellipsoid, startCartographic, maxHeight, vertexTop);\r\n\r\n if (loop) {\r\n vertexNormal = computeVertexMiterNormal(\r\n previousBottom,\r\n vertexBottom,\r\n vertexTop,\r\n nextBottom,\r\n vertexNormal\r\n );\r\n } else {\r\n vertexNormal = computeRightNormal(\r\n startCartographic,\r\n nextCartographic,\r\n maxHeight,\r\n ellipsoid,\r\n vertexNormal\r\n );\r\n }\r\n\r\n Cartesian3.pack(vertexNormal, normalsArray, 0);\r\n Cartesian3.pack(vertexBottom, bottomPositionsArray, 0);\r\n Cartesian3.pack(vertexTop, topPositionsArray, 0);\r\n cartographicsArray.push(startCartographic.latitude);\r\n cartographicsArray.push(startCartographic.longitude);\r\n\r\n interpolateSegment(\r\n startCartographic,\r\n nextCartographic,\r\n minHeight,\r\n maxHeight,\r\n granularity,\r\n arcType,\r\n ellipsoid,\r\n normalsArray,\r\n bottomPositionsArray,\r\n topPositionsArray,\r\n cartographicsArray\r\n );\r\n\r\n // All inbetween points\r\n for (i = 1; i < cartographicsLength - 1; ++i) {\r\n previousBottom = Cartesian3.clone(vertexBottom, previousBottom);\r\n vertexBottom = Cartesian3.clone(nextBottom, vertexBottom);\r\n var vertexCartographic = cartographics[i];\r\n getPosition(ellipsoid, vertexCartographic, maxHeight, vertexTop);\r\n getPosition(ellipsoid, cartographics[i + 1], minHeight, nextBottom);\r\n\r\n computeVertexMiterNormal(\r\n previousBottom,\r\n vertexBottom,\r\n vertexTop,\r\n nextBottom,\r\n vertexNormal\r\n );\r\n\r\n index = normalsArray.length;\r\n Cartesian3.pack(vertexNormal, normalsArray, index);\r\n Cartesian3.pack(vertexBottom, bottomPositionsArray, index);\r\n Cartesian3.pack(vertexTop, topPositionsArray, index);\r\n cartographicsArray.push(vertexCartographic.latitude);\r\n cartographicsArray.push(vertexCartographic.longitude);\r\n\r\n interpolateSegment(\r\n cartographics[i],\r\n cartographics[i + 1],\r\n minHeight,\r\n maxHeight,\r\n granularity,\r\n arcType,\r\n ellipsoid,\r\n normalsArray,\r\n bottomPositionsArray,\r\n topPositionsArray,\r\n cartographicsArray\r\n );\r\n }\r\n\r\n // Last point - either loop or attach a normal \"perpendicular\" to the wall.\r\n var endCartographic = cartographics[cartographicsLength - 1];\r\n var preEndCartographic = cartographics[cartographicsLength - 2];\r\n\r\n vertexBottom = getPosition(\r\n ellipsoid,\r\n endCartographic,\r\n minHeight,\r\n vertexBottom\r\n );\r\n vertexTop = getPosition(ellipsoid, endCartographic, maxHeight, vertexTop);\r\n\r\n if (loop) {\r\n var postEndCartographic = cartographics[0];\r\n previousBottom = getPosition(\r\n ellipsoid,\r\n preEndCartographic,\r\n minHeight,\r\n previousBottom\r\n );\r\n nextBottom = getPosition(\r\n ellipsoid,\r\n postEndCartographic,\r\n minHeight,\r\n nextBottom\r\n );\r\n\r\n vertexNormal = computeVertexMiterNormal(\r\n previousBottom,\r\n vertexBottom,\r\n vertexTop,\r\n nextBottom,\r\n vertexNormal\r\n );\r\n } else {\r\n vertexNormal = computeRightNormal(\r\n preEndCartographic,\r\n endCartographic,\r\n maxHeight,\r\n ellipsoid,\r\n vertexNormal\r\n );\r\n }\r\n\r\n index = normalsArray.length;\r\n Cartesian3.pack(vertexNormal, normalsArray, index);\r\n Cartesian3.pack(vertexBottom, bottomPositionsArray, index);\r\n Cartesian3.pack(vertexTop, topPositionsArray, index);\r\n cartographicsArray.push(endCartographic.latitude);\r\n cartographicsArray.push(endCartographic.longitude);\r\n\r\n if (loop) {\r\n interpolateSegment(\r\n endCartographic,\r\n startCartographic,\r\n minHeight,\r\n maxHeight,\r\n granularity,\r\n arcType,\r\n ellipsoid,\r\n normalsArray,\r\n bottomPositionsArray,\r\n topPositionsArray,\r\n cartographicsArray\r\n );\r\n index = normalsArray.length;\r\n for (i = 0; i < 3; ++i) {\r\n normalsArray[index + i] = normalsArray[i];\r\n bottomPositionsArray[index + i] = bottomPositionsArray[i];\r\n topPositionsArray[index + i] = topPositionsArray[i];\r\n }\r\n cartographicsArray.push(startCartographic.latitude);\r\n cartographicsArray.push(startCartographic.longitude);\r\n }\r\n\r\n return generateGeometryAttributes(\r\n loop,\r\n projection,\r\n bottomPositionsArray,\r\n topPositionsArray,\r\n normalsArray,\r\n cartographicsArray,\r\n compute2dAttributes\r\n );\r\n};\r\n\r\n// If the end normal angle is too steep compared to the direction of the line segment,\r\n// \"break\" the miter by rotating the normal 90 degrees around the \"up\" direction at the point\r\n// For ultra precision we would want to project into a plane, but in practice this is sufficient.\r\nvar lineDirectionScratch = new Cartesian3();\r\nvar matrix3Scratch = new Matrix3();\r\nvar quaternionScratch = new Quaternion();\r\nfunction breakMiter(endGeometryNormal, startBottom, endBottom, endTop) {\r\n var lineDirection = direction(endBottom, startBottom, lineDirectionScratch);\r\n\r\n var dot = Cartesian3.dot(lineDirection, endGeometryNormal);\r\n if (dot > MITER_BREAK_SMALL || dot < MITER_BREAK_LARGE) {\r\n var vertexUp = direction(endTop, endBottom, vertexUpScratch);\r\n var angle =\r\n dot < MITER_BREAK_LARGE\r\n ? CesiumMath.PI_OVER_TWO\r\n : -CesiumMath.PI_OVER_TWO;\r\n var quaternion = Quaternion.fromAxisAngle(\r\n vertexUp,\r\n angle,\r\n quaternionScratch\r\n );\r\n var rotationMatrix = Matrix3.fromQuaternion(quaternion, matrix3Scratch);\r\n Matrix3.multiplyByVector(\r\n rotationMatrix,\r\n endGeometryNormal,\r\n endGeometryNormal\r\n );\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\nvar endPosCartographicScratch = new Cartographic();\r\nvar normalStartpointScratch = new Cartesian3();\r\nvar normalEndpointScratch = new Cartesian3();\r\nfunction projectNormal(\r\n projection,\r\n cartographic,\r\n normal,\r\n projectedPosition,\r\n result\r\n) {\r\n var position = Cartographic.toCartesian(\r\n cartographic,\r\n projection._ellipsoid,\r\n normalStartpointScratch\r\n );\r\n var normalEndpoint = Cartesian3.add(position, normal, normalEndpointScratch);\r\n var flipNormal = false;\r\n\r\n var ellipsoid = projection._ellipsoid;\r\n var normalEndpointCartographic = ellipsoid.cartesianToCartographic(\r\n normalEndpoint,\r\n endPosCartographicScratch\r\n );\r\n // If normal crosses the IDL, go the other way and flip the result.\r\n // In practice this almost never happens because the cartographic start\r\n // and end points of each segment are \"nudged\" to be on the same side\r\n // of the IDL and slightly away from the IDL.\r\n if (\r\n Math.abs(cartographic.longitude - normalEndpointCartographic.longitude) >\r\n CesiumMath.PI_OVER_TWO\r\n ) {\r\n flipNormal = true;\r\n normalEndpoint = Cartesian3.subtract(\r\n position,\r\n normal,\r\n normalEndpointScratch\r\n );\r\n normalEndpointCartographic = ellipsoid.cartesianToCartographic(\r\n normalEndpoint,\r\n endPosCartographicScratch\r\n );\r\n }\r\n\r\n normalEndpointCartographic.height = 0.0;\r\n var normalEndpointProjected = projection.project(\r\n normalEndpointCartographic,\r\n result\r\n );\r\n result = Cartesian3.subtract(\r\n normalEndpointProjected,\r\n projectedPosition,\r\n result\r\n );\r\n result.z = 0.0;\r\n result = Cartesian3.normalize(result, result);\r\n if (flipNormal) {\r\n Cartesian3.negate(result, result);\r\n }\r\n return result;\r\n}\r\n\r\nvar adjustHeightNormalScratch = new Cartesian3();\r\nvar adjustHeightOffsetScratch = new Cartesian3();\r\nfunction adjustHeights(\r\n bottom,\r\n top,\r\n minHeight,\r\n maxHeight,\r\n adjustHeightBottom,\r\n adjustHeightTop\r\n) {\r\n // bottom and top should be at WALL_INITIAL_MIN_HEIGHT and WALL_INITIAL_MAX_HEIGHT, respectively\r\n var adjustHeightNormal = Cartesian3.subtract(\r\n top,\r\n bottom,\r\n adjustHeightNormalScratch\r\n );\r\n Cartesian3.normalize(adjustHeightNormal, adjustHeightNormal);\r\n\r\n var distanceForBottom = minHeight - WALL_INITIAL_MIN_HEIGHT;\r\n var adjustHeightOffset = Cartesian3.multiplyByScalar(\r\n adjustHeightNormal,\r\n distanceForBottom,\r\n adjustHeightOffsetScratch\r\n );\r\n Cartesian3.add(bottom, adjustHeightOffset, adjustHeightBottom);\r\n\r\n var distanceForTop = maxHeight - WALL_INITIAL_MAX_HEIGHT;\r\n adjustHeightOffset = Cartesian3.multiplyByScalar(\r\n adjustHeightNormal,\r\n distanceForTop,\r\n adjustHeightOffsetScratch\r\n );\r\n Cartesian3.add(top, adjustHeightOffset, adjustHeightTop);\r\n}\r\n\r\nvar nudgeDirectionScratch = new Cartesian3();\r\nfunction nudgeXZ(start, end) {\r\n var startToXZdistance = Plane.getPointDistance(XZ_PLANE, start);\r\n var endToXZdistance = Plane.getPointDistance(XZ_PLANE, end);\r\n var offset = nudgeDirectionScratch;\r\n // Larger epsilon than what's used in GeometryPipeline, a centimeter in world space\r\n if (CesiumMath.equalsEpsilon(startToXZdistance, 0.0, CesiumMath.EPSILON2)) {\r\n offset = direction(end, start, offset);\r\n Cartesian3.multiplyByScalar(offset, CesiumMath.EPSILON2, offset);\r\n Cartesian3.add(start, offset, start);\r\n } else if (\r\n CesiumMath.equalsEpsilon(endToXZdistance, 0.0, CesiumMath.EPSILON2)\r\n ) {\r\n offset = direction(start, end, offset);\r\n Cartesian3.multiplyByScalar(offset, CesiumMath.EPSILON2, offset);\r\n Cartesian3.add(end, offset, end);\r\n }\r\n}\r\n\r\n// \"Nudge\" cartographic coordinates so start and end are on the same side of the IDL.\r\n// Nudge amounts are tiny, basically just an IDL flip.\r\n// Only used for 2D/CV.\r\nfunction nudgeCartographic(start, end) {\r\n var absStartLon = Math.abs(start.longitude);\r\n var absEndLon = Math.abs(end.longitude);\r\n if (\r\n CesiumMath.equalsEpsilon(absStartLon, CesiumMath.PI, CesiumMath.EPSILON11)\r\n ) {\r\n var endSign = CesiumMath.sign(end.longitude);\r\n start.longitude = endSign * (absStartLon - CesiumMath.EPSILON11);\r\n return 1;\r\n } else if (\r\n CesiumMath.equalsEpsilon(absEndLon, CesiumMath.PI, CesiumMath.EPSILON11)\r\n ) {\r\n var startSign = CesiumMath.sign(start.longitude);\r\n end.longitude = startSign * (absEndLon - CesiumMath.EPSILON11);\r\n return 2;\r\n }\r\n return 0;\r\n}\r\n\r\nvar startCartographicScratch = new Cartographic();\r\nvar endCartographicScratch = new Cartographic();\r\n\r\nvar segmentStartTopScratch = new Cartesian3();\r\nvar segmentEndTopScratch = new Cartesian3();\r\nvar segmentStartBottomScratch = new Cartesian3();\r\nvar segmentEndBottomScratch = new Cartesian3();\r\nvar segmentStartNormalScratch = new Cartesian3();\r\nvar segmentEndNormalScratch = new Cartesian3();\r\n\r\nvar getHeightCartographics = [startCartographicScratch, endCartographicScratch];\r\nvar getHeightRectangleScratch = new Rectangle();\r\n\r\nvar adjustHeightStartTopScratch = new Cartesian3();\r\nvar adjustHeightEndTopScratch = new Cartesian3();\r\nvar adjustHeightStartBottomScratch = new Cartesian3();\r\nvar adjustHeightEndBottomScratch = new Cartesian3();\r\n\r\nvar segmentStart2DScratch = new Cartesian3();\r\nvar segmentEnd2DScratch = new Cartesian3();\r\nvar segmentStartNormal2DScratch = new Cartesian3();\r\nvar segmentEndNormal2DScratch = new Cartesian3();\r\n\r\nvar offsetScratch = new Cartesian3();\r\nvar startUpScratch = new Cartesian3();\r\nvar endUpScratch = new Cartesian3();\r\nvar rightScratch = new Cartesian3();\r\nvar startPlaneNormalScratch = new Cartesian3();\r\nvar endPlaneNormalScratch = new Cartesian3();\r\nvar encodeScratch = new EncodedCartesian3();\r\n\r\nvar encodeScratch2D = new EncodedCartesian3();\r\nvar forwardOffset2DScratch = new Cartesian3();\r\nvar right2DScratch = new Cartesian3();\r\n\r\nvar normalNudgeScratch = new Cartesian3();\r\n\r\nvar scratchBoundingSpheres = [new BoundingSphere(), new BoundingSphere()];\r\n\r\n// Winding order is reversed so each segment's volume is inside-out\r\nvar REFERENCE_INDICES = [\r\n 0,\r\n 2,\r\n 1,\r\n 0,\r\n 3,\r\n 2, // right\r\n 0,\r\n 7,\r\n 3,\r\n 0,\r\n 4,\r\n 7, // start\r\n 0,\r\n 5,\r\n 4,\r\n 0,\r\n 1,\r\n 5, // bottom\r\n 5,\r\n 7,\r\n 4,\r\n 5,\r\n 6,\r\n 7, // left\r\n 5,\r\n 2,\r\n 6,\r\n 5,\r\n 1,\r\n 2, // end\r\n 3,\r\n 6,\r\n 2,\r\n 3,\r\n 7,\r\n 6, // top\r\n];\r\nvar REFERENCE_INDICES_LENGTH = REFERENCE_INDICES.length;\r\n\r\n// Decompose the \"wall\" into a series of shadow volumes.\r\n// Each shadow volume's vertices encode a description of the line it contains,\r\n// including mitering planes at the end points, a plane along the line itself,\r\n// and attributes for computing length-wise texture coordinates.\r\nfunction generateGeometryAttributes(\r\n loop,\r\n projection,\r\n bottomPositionsArray,\r\n topPositionsArray,\r\n normalsArray,\r\n cartographicsArray,\r\n compute2dAttributes\r\n) {\r\n var i;\r\n var index;\r\n var ellipsoid = projection._ellipsoid;\r\n\r\n // Each segment will have 8 vertices\r\n var segmentCount = bottomPositionsArray.length / 3 - 1;\r\n var vertexCount = segmentCount * 8;\r\n var arraySizeVec4 = vertexCount * 4;\r\n var indexCount = segmentCount * 36;\r\n\r\n var indices =\r\n vertexCount > 65535\r\n ? new Uint32Array(indexCount)\r\n : new Uint16Array(indexCount);\r\n var positionsArray = new Float64Array(vertexCount * 3);\r\n\r\n var startHiAndForwardOffsetX = new Float32Array(arraySizeVec4);\r\n var startLoAndForwardOffsetY = new Float32Array(arraySizeVec4);\r\n var startNormalAndForwardOffsetZ = new Float32Array(arraySizeVec4);\r\n var endNormalAndTextureCoordinateNormalizationX = new Float32Array(\r\n arraySizeVec4\r\n );\r\n var rightNormalAndTextureCoordinateNormalizationY = new Float32Array(\r\n arraySizeVec4\r\n );\r\n\r\n var startHiLo2D;\r\n var offsetAndRight2D;\r\n var startEndNormals2D;\r\n var texcoordNormalization2D;\r\n\r\n if (compute2dAttributes) {\r\n startHiLo2D = new Float32Array(arraySizeVec4);\r\n offsetAndRight2D = new Float32Array(arraySizeVec4);\r\n startEndNormals2D = new Float32Array(arraySizeVec4);\r\n texcoordNormalization2D = new Float32Array(vertexCount * 2);\r\n }\r\n\r\n /*** Compute total lengths for texture coordinate normalization ***/\r\n // 2D\r\n var cartographicsLength = cartographicsArray.length / 2;\r\n var length2D = 0.0;\r\n\r\n var startCartographic = startCartographicScratch;\r\n startCartographic.height = 0.0;\r\n var endCartographic = endCartographicScratch;\r\n endCartographic.height = 0.0;\r\n\r\n var segmentStartCartesian = segmentStartTopScratch;\r\n var segmentEndCartesian = segmentEndTopScratch;\r\n\r\n if (compute2dAttributes) {\r\n index = 0;\r\n for (i = 1; i < cartographicsLength; i++) {\r\n // Don't clone anything from previous segment b/c possible IDL touch\r\n startCartographic.latitude = cartographicsArray[index];\r\n startCartographic.longitude = cartographicsArray[index + 1];\r\n endCartographic.latitude = cartographicsArray[index + 2];\r\n endCartographic.longitude = cartographicsArray[index + 3];\r\n\r\n segmentStartCartesian = projection.project(\r\n startCartographic,\r\n segmentStartCartesian\r\n );\r\n segmentEndCartesian = projection.project(\r\n endCartographic,\r\n segmentEndCartesian\r\n );\r\n length2D += Cartesian3.distance(\r\n segmentStartCartesian,\r\n segmentEndCartesian\r\n );\r\n index += 2;\r\n }\r\n }\r\n\r\n // 3D\r\n var positionsLength = topPositionsArray.length / 3;\r\n segmentEndCartesian = Cartesian3.unpack(\r\n topPositionsArray,\r\n 0,\r\n segmentEndCartesian\r\n );\r\n var length3D = 0.0;\r\n\r\n index = 3;\r\n for (i = 1; i < positionsLength; i++) {\r\n segmentStartCartesian = Cartesian3.clone(\r\n segmentEndCartesian,\r\n segmentStartCartesian\r\n );\r\n segmentEndCartesian = Cartesian3.unpack(\r\n topPositionsArray,\r\n index,\r\n segmentEndCartesian\r\n );\r\n length3D += Cartesian3.distance(segmentStartCartesian, segmentEndCartesian);\r\n index += 3;\r\n }\r\n\r\n /*** Generate segments ***/\r\n var j;\r\n index = 3;\r\n var cartographicsIndex = 0;\r\n var vec2sWriteIndex = 0;\r\n var vec3sWriteIndex = 0;\r\n var vec4sWriteIndex = 0;\r\n var miterBroken = false;\r\n\r\n var endBottom = Cartesian3.unpack(\r\n bottomPositionsArray,\r\n 0,\r\n segmentEndBottomScratch\r\n );\r\n var endTop = Cartesian3.unpack(topPositionsArray, 0, segmentEndTopScratch);\r\n var endGeometryNormal = Cartesian3.unpack(\r\n normalsArray,\r\n 0,\r\n segmentEndNormalScratch\r\n );\r\n\r\n if (loop) {\r\n var preEndBottom = Cartesian3.unpack(\r\n bottomPositionsArray,\r\n bottomPositionsArray.length - 6,\r\n segmentStartBottomScratch\r\n );\r\n if (breakMiter(endGeometryNormal, preEndBottom, endBottom, endTop)) {\r\n // Miter broken as if for the last point in the loop, needs to be inverted for first point (clone of endBottom)\r\n endGeometryNormal = Cartesian3.negate(\r\n endGeometryNormal,\r\n endGeometryNormal\r\n );\r\n }\r\n }\r\n\r\n var lengthSoFar3D = 0.0;\r\n var lengthSoFar2D = 0.0;\r\n\r\n // For translating bounding volume\r\n var sumHeights = 0.0;\r\n\r\n for (i = 0; i < segmentCount; i++) {\r\n var startBottom = Cartesian3.clone(endBottom, segmentStartBottomScratch);\r\n var startTop = Cartesian3.clone(endTop, segmentStartTopScratch);\r\n var startGeometryNormal = Cartesian3.clone(\r\n endGeometryNormal,\r\n segmentStartNormalScratch\r\n );\r\n\r\n if (miterBroken) {\r\n startGeometryNormal = Cartesian3.negate(\r\n startGeometryNormal,\r\n startGeometryNormal\r\n );\r\n }\r\n\r\n endBottom = Cartesian3.unpack(\r\n bottomPositionsArray,\r\n index,\r\n segmentEndBottomScratch\r\n );\r\n endTop = Cartesian3.unpack(topPositionsArray, index, segmentEndTopScratch);\r\n endGeometryNormal = Cartesian3.unpack(\r\n normalsArray,\r\n index,\r\n segmentEndNormalScratch\r\n );\r\n\r\n miterBroken = breakMiter(endGeometryNormal, startBottom, endBottom, endTop);\r\n\r\n // 2D - don't clone anything from previous segment b/c possible IDL touch\r\n startCartographic.latitude = cartographicsArray[cartographicsIndex];\r\n startCartographic.longitude = cartographicsArray[cartographicsIndex + 1];\r\n endCartographic.latitude = cartographicsArray[cartographicsIndex + 2];\r\n endCartographic.longitude = cartographicsArray[cartographicsIndex + 3];\r\n var start2D;\r\n var end2D;\r\n var startGeometryNormal2D;\r\n var endGeometryNormal2D;\r\n\r\n if (compute2dAttributes) {\r\n var nudgeResult = nudgeCartographic(startCartographic, endCartographic);\r\n start2D = projection.project(startCartographic, segmentStart2DScratch);\r\n end2D = projection.project(endCartographic, segmentEnd2DScratch);\r\n var direction2D = direction(end2D, start2D, forwardOffset2DScratch);\r\n direction2D.y = Math.abs(direction2D.y);\r\n\r\n startGeometryNormal2D = segmentStartNormal2DScratch;\r\n endGeometryNormal2D = segmentEndNormal2DScratch;\r\n if (\r\n nudgeResult === 0 ||\r\n Cartesian3.dot(direction2D, Cartesian3.UNIT_Y) > MITER_BREAK_SMALL\r\n ) {\r\n // No nudge - project the original normal\r\n // Or, if the line's angle relative to the IDL is very acute,\r\n // in which case snapping will produce oddly shaped volumes.\r\n startGeometryNormal2D = projectNormal(\r\n projection,\r\n startCartographic,\r\n startGeometryNormal,\r\n start2D,\r\n segmentStartNormal2DScratch\r\n );\r\n endGeometryNormal2D = projectNormal(\r\n projection,\r\n endCartographic,\r\n endGeometryNormal,\r\n end2D,\r\n segmentEndNormal2DScratch\r\n );\r\n } else if (nudgeResult === 1) {\r\n // Start is close to IDL - snap start normal to align with IDL\r\n endGeometryNormal2D = projectNormal(\r\n projection,\r\n endCartographic,\r\n endGeometryNormal,\r\n end2D,\r\n segmentEndNormal2DScratch\r\n );\r\n startGeometryNormal2D.x = 0.0;\r\n // If start longitude is negative and end longitude is less negative, relative right is unit -Y\r\n // If start longitude is positive and end longitude is less positive, relative right is unit +Y\r\n startGeometryNormal2D.y = CesiumMath.sign(\r\n startCartographic.longitude - Math.abs(endCartographic.longitude)\r\n );\r\n startGeometryNormal2D.z = 0.0;\r\n } else {\r\n // End is close to IDL - snap end normal to align with IDL\r\n startGeometryNormal2D = projectNormal(\r\n projection,\r\n startCartographic,\r\n startGeometryNormal,\r\n start2D,\r\n segmentStartNormal2DScratch\r\n );\r\n endGeometryNormal2D.x = 0.0;\r\n // If end longitude is negative and start longitude is less negative, relative right is unit Y\r\n // If end longitude is positive and start longitude is less positive, relative right is unit -Y\r\n endGeometryNormal2D.y = CesiumMath.sign(\r\n startCartographic.longitude - endCartographic.longitude\r\n );\r\n endGeometryNormal2D.z = 0.0;\r\n }\r\n }\r\n\r\n /****************************************\r\n * Geometry descriptors of a \"line on terrain,\"\r\n * as opposed to the \"shadow volume used to draw\r\n * the line on terrain\":\r\n * - position of start + offset to end\r\n * - start, end, and right-facing planes\r\n * - encoded texture coordinate offsets\r\n ****************************************/\r\n\r\n /* 3D */\r\n var segmentLength3D = Cartesian3.distance(startTop, endTop);\r\n\r\n var encodedStart = EncodedCartesian3.fromCartesian(\r\n startBottom,\r\n encodeScratch\r\n );\r\n var forwardOffset = Cartesian3.subtract(\r\n endBottom,\r\n startBottom,\r\n offsetScratch\r\n );\r\n var forward = Cartesian3.normalize(forwardOffset, rightScratch);\r\n\r\n var startUp = Cartesian3.subtract(startTop, startBottom, startUpScratch);\r\n startUp = Cartesian3.normalize(startUp, startUp);\r\n var rightNormal = Cartesian3.cross(forward, startUp, rightScratch);\r\n rightNormal = Cartesian3.normalize(rightNormal, rightNormal);\r\n\r\n var startPlaneNormal = Cartesian3.cross(\r\n startUp,\r\n startGeometryNormal,\r\n startPlaneNormalScratch\r\n );\r\n startPlaneNormal = Cartesian3.normalize(startPlaneNormal, startPlaneNormal);\r\n\r\n var endUp = Cartesian3.subtract(endTop, endBottom, endUpScratch);\r\n endUp = Cartesian3.normalize(endUp, endUp);\r\n var endPlaneNormal = Cartesian3.cross(\r\n endGeometryNormal,\r\n endUp,\r\n endPlaneNormalScratch\r\n );\r\n endPlaneNormal = Cartesian3.normalize(endPlaneNormal, endPlaneNormal);\r\n\r\n var texcoordNormalization3DX = segmentLength3D / length3D;\r\n var texcoordNormalization3DY = lengthSoFar3D / length3D;\r\n\r\n /* 2D */\r\n var segmentLength2D = 0.0;\r\n var encodedStart2D;\r\n var forwardOffset2D;\r\n var right2D;\r\n var texcoordNormalization2DX = 0.0;\r\n var texcoordNormalization2DY = 0.0;\r\n if (compute2dAttributes) {\r\n segmentLength2D = Cartesian3.distance(start2D, end2D);\r\n\r\n encodedStart2D = EncodedCartesian3.fromCartesian(\r\n start2D,\r\n encodeScratch2D\r\n );\r\n forwardOffset2D = Cartesian3.subtract(\r\n end2D,\r\n start2D,\r\n forwardOffset2DScratch\r\n );\r\n\r\n // Right direction is just forward direction rotated by -90 degrees around Z\r\n // Similarly with plane normals\r\n right2D = Cartesian3.normalize(forwardOffset2D, right2DScratch);\r\n var swap = right2D.x;\r\n right2D.x = right2D.y;\r\n right2D.y = -swap;\r\n\r\n texcoordNormalization2DX = segmentLength2D / length2D;\r\n texcoordNormalization2DY = lengthSoFar2D / length2D;\r\n }\r\n /** Pack **/\r\n for (j = 0; j < 8; j++) {\r\n var vec4Index = vec4sWriteIndex + j * 4;\r\n var vec2Index = vec2sWriteIndex + j * 2;\r\n var wIndex = vec4Index + 3;\r\n\r\n // Encode sidedness of vertex relative to right plane in texture coordinate normalization X,\r\n // whether vertex is top or bottom of volume in sign/magnitude of normalization Y.\r\n var rightPlaneSide = j < 4 ? 1.0 : -1.0;\r\n var topBottomSide = j === 2 || j === 3 || j === 6 || j === 7 ? 1.0 : -1.0;\r\n\r\n // 3D\r\n Cartesian3.pack(encodedStart.high, startHiAndForwardOffsetX, vec4Index);\r\n startHiAndForwardOffsetX[wIndex] = forwardOffset.x;\r\n\r\n Cartesian3.pack(encodedStart.low, startLoAndForwardOffsetY, vec4Index);\r\n startLoAndForwardOffsetY[wIndex] = forwardOffset.y;\r\n\r\n Cartesian3.pack(\r\n startPlaneNormal,\r\n startNormalAndForwardOffsetZ,\r\n vec4Index\r\n );\r\n startNormalAndForwardOffsetZ[wIndex] = forwardOffset.z;\r\n\r\n Cartesian3.pack(\r\n endPlaneNormal,\r\n endNormalAndTextureCoordinateNormalizationX,\r\n vec4Index\r\n );\r\n endNormalAndTextureCoordinateNormalizationX[wIndex] =\r\n texcoordNormalization3DX * rightPlaneSide;\r\n\r\n Cartesian3.pack(\r\n rightNormal,\r\n rightNormalAndTextureCoordinateNormalizationY,\r\n vec4Index\r\n );\r\n\r\n var texcoordNormalization = texcoordNormalization3DY * topBottomSide;\r\n if (texcoordNormalization === 0.0 && topBottomSide < 0.0) {\r\n texcoordNormalization = 9.0; // some value greater than 1.0\r\n }\r\n rightNormalAndTextureCoordinateNormalizationY[\r\n wIndex\r\n ] = texcoordNormalization;\r\n\r\n // 2D\r\n if (compute2dAttributes) {\r\n startHiLo2D[vec4Index] = encodedStart2D.high.x;\r\n startHiLo2D[vec4Index + 1] = encodedStart2D.high.y;\r\n startHiLo2D[vec4Index + 2] = encodedStart2D.low.x;\r\n startHiLo2D[vec4Index + 3] = encodedStart2D.low.y;\r\n\r\n startEndNormals2D[vec4Index] = -startGeometryNormal2D.y;\r\n startEndNormals2D[vec4Index + 1] = startGeometryNormal2D.x;\r\n startEndNormals2D[vec4Index + 2] = endGeometryNormal2D.y;\r\n startEndNormals2D[vec4Index + 3] = -endGeometryNormal2D.x;\r\n\r\n offsetAndRight2D[vec4Index] = forwardOffset2D.x;\r\n offsetAndRight2D[vec4Index + 1] = forwardOffset2D.y;\r\n offsetAndRight2D[vec4Index + 2] = right2D.x;\r\n offsetAndRight2D[vec4Index + 3] = right2D.y;\r\n\r\n texcoordNormalization2D[vec2Index] =\r\n texcoordNormalization2DX * rightPlaneSide;\r\n\r\n texcoordNormalization = texcoordNormalization2DY * topBottomSide;\r\n if (texcoordNormalization === 0.0 && topBottomSide < 0.0) {\r\n texcoordNormalization = 9.0; // some value greater than 1.0\r\n }\r\n texcoordNormalization2D[vec2Index + 1] = texcoordNormalization;\r\n }\r\n }\r\n\r\n // Adjust height of volume in 3D\r\n var adjustHeightStartBottom = adjustHeightStartBottomScratch;\r\n var adjustHeightEndBottom = adjustHeightEndBottomScratch;\r\n var adjustHeightStartTop = adjustHeightStartTopScratch;\r\n var adjustHeightEndTop = adjustHeightEndTopScratch;\r\n\r\n var getHeightsRectangle = Rectangle.fromCartographicArray(\r\n getHeightCartographics,\r\n getHeightRectangleScratch\r\n );\r\n var minMaxHeights = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n getHeightsRectangle,\r\n ellipsoid\r\n );\r\n var minHeight = minMaxHeights.minimumTerrainHeight;\r\n var maxHeight = minMaxHeights.maximumTerrainHeight;\r\n\r\n sumHeights += minHeight;\r\n sumHeights += maxHeight;\r\n\r\n adjustHeights(\r\n startBottom,\r\n startTop,\r\n minHeight,\r\n maxHeight,\r\n adjustHeightStartBottom,\r\n adjustHeightStartTop\r\n );\r\n adjustHeights(\r\n endBottom,\r\n endTop,\r\n minHeight,\r\n maxHeight,\r\n adjustHeightEndBottom,\r\n adjustHeightEndTop\r\n );\r\n\r\n // Nudge the positions away from the \"polyline\" a little bit to prevent errors in GeometryPipeline\r\n var normalNudge = Cartesian3.multiplyByScalar(\r\n rightNormal,\r\n CesiumMath.EPSILON5,\r\n normalNudgeScratch\r\n );\r\n Cartesian3.add(\r\n adjustHeightStartBottom,\r\n normalNudge,\r\n adjustHeightStartBottom\r\n );\r\n Cartesian3.add(adjustHeightEndBottom, normalNudge, adjustHeightEndBottom);\r\n Cartesian3.add(adjustHeightStartTop, normalNudge, adjustHeightStartTop);\r\n Cartesian3.add(adjustHeightEndTop, normalNudge, adjustHeightEndTop);\r\n\r\n // If the segment is very close to the XZ plane, nudge the vertices slightly to avoid touching it.\r\n nudgeXZ(adjustHeightStartBottom, adjustHeightEndBottom);\r\n nudgeXZ(adjustHeightStartTop, adjustHeightEndTop);\r\n\r\n Cartesian3.pack(adjustHeightStartBottom, positionsArray, vec3sWriteIndex);\r\n Cartesian3.pack(adjustHeightEndBottom, positionsArray, vec3sWriteIndex + 3);\r\n Cartesian3.pack(adjustHeightEndTop, positionsArray, vec3sWriteIndex + 6);\r\n Cartesian3.pack(adjustHeightStartTop, positionsArray, vec3sWriteIndex + 9);\r\n\r\n normalNudge = Cartesian3.multiplyByScalar(\r\n rightNormal,\r\n -2.0 * CesiumMath.EPSILON5,\r\n normalNudgeScratch\r\n );\r\n Cartesian3.add(\r\n adjustHeightStartBottom,\r\n normalNudge,\r\n adjustHeightStartBottom\r\n );\r\n Cartesian3.add(adjustHeightEndBottom, normalNudge, adjustHeightEndBottom);\r\n Cartesian3.add(adjustHeightStartTop, normalNudge, adjustHeightStartTop);\r\n Cartesian3.add(adjustHeightEndTop, normalNudge, adjustHeightEndTop);\r\n\r\n nudgeXZ(adjustHeightStartBottom, adjustHeightEndBottom);\r\n nudgeXZ(adjustHeightStartTop, adjustHeightEndTop);\r\n\r\n Cartesian3.pack(\r\n adjustHeightStartBottom,\r\n positionsArray,\r\n vec3sWriteIndex + 12\r\n );\r\n Cartesian3.pack(\r\n adjustHeightEndBottom,\r\n positionsArray,\r\n vec3sWriteIndex + 15\r\n );\r\n Cartesian3.pack(adjustHeightEndTop, positionsArray, vec3sWriteIndex + 18);\r\n Cartesian3.pack(adjustHeightStartTop, positionsArray, vec3sWriteIndex + 21);\r\n\r\n cartographicsIndex += 2;\r\n index += 3;\r\n\r\n vec2sWriteIndex += 16;\r\n vec3sWriteIndex += 24;\r\n vec4sWriteIndex += 32;\r\n\r\n lengthSoFar3D += segmentLength3D;\r\n lengthSoFar2D += segmentLength2D;\r\n }\r\n\r\n index = 0;\r\n var indexOffset = 0;\r\n for (i = 0; i < segmentCount; i++) {\r\n for (j = 0; j < REFERENCE_INDICES_LENGTH; j++) {\r\n indices[index + j] = REFERENCE_INDICES[j] + indexOffset;\r\n }\r\n indexOffset += 8;\r\n index += REFERENCE_INDICES_LENGTH;\r\n }\r\n\r\n var boundingSpheres = scratchBoundingSpheres;\r\n BoundingSphere.fromVertices(\r\n bottomPositionsArray,\r\n Cartesian3.ZERO,\r\n 3,\r\n boundingSpheres[0]\r\n );\r\n BoundingSphere.fromVertices(\r\n topPositionsArray,\r\n Cartesian3.ZERO,\r\n 3,\r\n boundingSpheres[1]\r\n );\r\n var boundingSphere = BoundingSphere.fromBoundingSpheres(boundingSpheres);\r\n\r\n // Adjust bounding sphere height and radius to cover more of the volume\r\n boundingSphere.radius += sumHeights / (segmentCount * 2.0);\r\n\r\n var attributes = {\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n normalize: false,\r\n values: positionsArray,\r\n }),\r\n startHiAndForwardOffsetX: getVec4GeometryAttribute(\r\n startHiAndForwardOffsetX\r\n ),\r\n startLoAndForwardOffsetY: getVec4GeometryAttribute(\r\n startLoAndForwardOffsetY\r\n ),\r\n startNormalAndForwardOffsetZ: getVec4GeometryAttribute(\r\n startNormalAndForwardOffsetZ\r\n ),\r\n endNormalAndTextureCoordinateNormalizationX: getVec4GeometryAttribute(\r\n endNormalAndTextureCoordinateNormalizationX\r\n ),\r\n rightNormalAndTextureCoordinateNormalizationY: getVec4GeometryAttribute(\r\n rightNormalAndTextureCoordinateNormalizationY\r\n ),\r\n };\r\n\r\n if (compute2dAttributes) {\r\n attributes.startHiLo2D = getVec4GeometryAttribute(startHiLo2D);\r\n attributes.offsetAndRight2D = getVec4GeometryAttribute(offsetAndRight2D);\r\n attributes.startEndNormals2D = getVec4GeometryAttribute(startEndNormals2D);\r\n attributes.texcoordNormalization2D = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n normalize: false,\r\n values: texcoordNormalization2D,\r\n });\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n boundingSphere: boundingSphere,\r\n });\r\n}\r\n\r\nfunction getVec4GeometryAttribute(typedArray) {\r\n return new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n normalize: false,\r\n values: typedArray,\r\n });\r\n}\r\n\r\n/**\r\n * Approximates an ellipsoid-tangent vector in 2D by projecting the end point into 2D.\r\n * Exposed for testing.\r\n *\r\n * @param {MapProjection} projection Map Projection for projecting coordinates to 2D.\r\n * @param {Cartographic} cartographic The cartographic origin point of the normal.\r\n * Used to check if the normal crosses the IDL during projection.\r\n * @param {Cartesian3} normal The normal in 3D.\r\n * @param {Cartesian3} projectedPosition The projected origin point of the normal in 2D.\r\n * @param {Cartesian3} result Result parameter on which to store the projected normal.\r\n * @private\r\n */\r\nGroundPolylineGeometry._projectNormal = projectNormal;\r\nexport default GroundPolylineGeometry;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * Defines a heading angle, pitch angle, and range in a local frame.\r\n * Heading is the rotation from the local north direction where a positive angle is increasing eastward.\r\n * Pitch is the rotation from the local xy-plane. Positive pitch angles are above the plane. Negative pitch\r\n * angles are below the plane. Range is the distance from the center of the frame.\r\n * @alias HeadingPitchRange\r\n * @constructor\r\n *\r\n * @param {Number} [heading=0.0] The heading angle in radians.\r\n * @param {Number} [pitch=0.0] The pitch angle in radians.\r\n * @param {Number} [range=0.0] The distance from the center in meters.\r\n */\r\nfunction HeadingPitchRange(heading, pitch, range) {\r\n /**\r\n * Heading is the rotation from the local north direction where a positive angle is increasing eastward.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.heading = defaultValue(heading, 0.0);\r\n\r\n /**\r\n * Pitch is the rotation from the local xy-plane. Positive pitch angles\r\n * are above the plane. Negative pitch angles are below the plane.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.pitch = defaultValue(pitch, 0.0);\r\n\r\n /**\r\n * Range is the distance from the center of the local frame.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.range = defaultValue(range, 0.0);\r\n}\r\n\r\n/**\r\n * Duplicates a HeadingPitchRange instance.\r\n *\r\n * @param {HeadingPitchRange} hpr The HeadingPitchRange to duplicate.\r\n * @param {HeadingPitchRange} [result] The object onto which to store the result.\r\n * @returns {HeadingPitchRange} The modified result parameter or a new HeadingPitchRange instance if one was not provided. (Returns undefined if hpr is undefined)\r\n */\r\nHeadingPitchRange.clone = function (hpr, result) {\r\n if (!defined(hpr)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n result = new HeadingPitchRange();\r\n }\r\n\r\n result.heading = hpr.heading;\r\n result.pitch = hpr.pitch;\r\n result.range = hpr.range;\r\n return result;\r\n};\r\nexport default HeadingPitchRange;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport CesiumMath from \"./Math.js\";\r\n\r\nvar factorial = CesiumMath.factorial;\r\n\r\nfunction calculateCoefficientTerm(\r\n x,\r\n zIndices,\r\n xTable,\r\n derivOrder,\r\n termOrder,\r\n reservedIndices\r\n) {\r\n var result = 0;\r\n var reserved;\r\n var i;\r\n var j;\r\n\r\n if (derivOrder > 0) {\r\n for (i = 0; i < termOrder; i++) {\r\n reserved = false;\r\n for (j = 0; j < reservedIndices.length && !reserved; j++) {\r\n if (i === reservedIndices[j]) {\r\n reserved = true;\r\n }\r\n }\r\n\r\n if (!reserved) {\r\n reservedIndices.push(i);\r\n result += calculateCoefficientTerm(\r\n x,\r\n zIndices,\r\n xTable,\r\n derivOrder - 1,\r\n termOrder,\r\n reservedIndices\r\n );\r\n reservedIndices.splice(reservedIndices.length - 1, 1);\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n result = 1;\r\n for (i = 0; i < termOrder; i++) {\r\n reserved = false;\r\n for (j = 0; j < reservedIndices.length && !reserved; j++) {\r\n if (i === reservedIndices[j]) {\r\n reserved = true;\r\n }\r\n }\r\n\r\n if (!reserved) {\r\n result *= x - xTable[zIndices[i]];\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * An {@link InterpolationAlgorithm} for performing Hermite interpolation.\r\n *\r\n * @namespace HermitePolynomialApproximation\r\n */\r\nvar HermitePolynomialApproximation = {\r\n type: \"Hermite\",\r\n};\r\n\r\n/**\r\n * Given the desired degree, returns the number of data points required for interpolation.\r\n *\r\n * @param {Number} degree The desired degree of interpolation.\r\n * @param {Number} [inputOrder=0] The order of the inputs (0 means just the data, 1 means the data and its derivative, etc).\r\n * @returns {Number} The number of required data points needed for the desired degree of interpolation.\r\n * @exception {DeveloperError} degree must be 0 or greater.\r\n * @exception {DeveloperError} inputOrder must be 0 or greater.\r\n */\r\nHermitePolynomialApproximation.getRequiredDataPoints = function (\r\n degree,\r\n inputOrder\r\n) {\r\n inputOrder = defaultValue(inputOrder, 0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(degree)) {\r\n throw new DeveloperError(\"degree is required.\");\r\n }\r\n if (degree < 0) {\r\n throw new DeveloperError(\"degree must be 0 or greater.\");\r\n }\r\n if (inputOrder < 0) {\r\n throw new DeveloperError(\"inputOrder must be 0 or greater.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return Math.max(Math.floor((degree + 1) / (inputOrder + 1)), 2);\r\n};\r\n\r\n/**\r\n * Interpolates values using Hermite Polynomial Approximation.\r\n *\r\n * @param {Number} x The independent variable for which the dependent variables will be interpolated.\r\n * @param {Number[]} xTable The array of independent variables to use to interpolate. The values\r\n * in this array must be in increasing order and the same value must not occur twice in the array.\r\n * @param {Number[]} yTable The array of dependent variables to use to interpolate. For a set of three\r\n * dependent values (p,q,w) at time 1 and time 2 this should be as follows: {p1, q1, w1, p2, q2, w2}.\r\n * @param {Number} yStride The number of dependent variable values in yTable corresponding to\r\n * each independent variable value in xTable.\r\n * @param {Number[]} [result] An existing array into which to store the result.\r\n * @returns {Number[]} The array of interpolated values, or the result parameter if one was provided.\r\n */\r\nHermitePolynomialApproximation.interpolateOrderZero = function (\r\n x,\r\n xTable,\r\n yTable,\r\n yStride,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new Array(yStride);\r\n }\r\n\r\n var i;\r\n var j;\r\n var d;\r\n var s;\r\n var len;\r\n var index;\r\n var length = xTable.length;\r\n var coefficients = new Array(yStride);\r\n\r\n for (i = 0; i < yStride; i++) {\r\n result[i] = 0;\r\n\r\n var l = new Array(length);\r\n coefficients[i] = l;\r\n for (j = 0; j < length; j++) {\r\n l[j] = [];\r\n }\r\n }\r\n\r\n var zIndicesLength = length,\r\n zIndices = new Array(zIndicesLength);\r\n\r\n for (i = 0; i < zIndicesLength; i++) {\r\n zIndices[i] = i;\r\n }\r\n\r\n var highestNonZeroCoef = length - 1;\r\n for (s = 0; s < yStride; s++) {\r\n for (j = 0; j < zIndicesLength; j++) {\r\n index = zIndices[j] * yStride + s;\r\n coefficients[s][0].push(yTable[index]);\r\n }\r\n\r\n for (i = 1; i < zIndicesLength; i++) {\r\n var nonZeroCoefficients = false;\r\n for (j = 0; j < zIndicesLength - i; j++) {\r\n var zj = xTable[zIndices[j]];\r\n var zn = xTable[zIndices[j + i]];\r\n\r\n var numerator;\r\n if (zn - zj <= 0) {\r\n index = zIndices[j] * yStride + yStride * i + s;\r\n numerator = yTable[index];\r\n coefficients[s][i].push(numerator / factorial(i));\r\n } else {\r\n numerator = coefficients[s][i - 1][j + 1] - coefficients[s][i - 1][j];\r\n coefficients[s][i].push(numerator / (zn - zj));\r\n }\r\n nonZeroCoefficients = nonZeroCoefficients || numerator !== 0;\r\n }\r\n\r\n if (!nonZeroCoefficients) {\r\n highestNonZeroCoef = i - 1;\r\n }\r\n }\r\n }\r\n\r\n for (d = 0, len = 0; d <= len; d++) {\r\n for (i = d; i <= highestNonZeroCoef; i++) {\r\n var tempTerm = calculateCoefficientTerm(x, zIndices, xTable, d, i, []);\r\n for (s = 0; s < yStride; s++) {\r\n var coeff = coefficients[s][i][0];\r\n result[s + d * yStride] += coeff * tempTerm;\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n\r\nvar arrayScratch = [];\r\n\r\n/**\r\n * Interpolates values using Hermite Polynomial Approximation.\r\n *\r\n * @param {Number} x The independent variable for which the dependent variables will be interpolated.\r\n * @param {Number[]} xTable The array of independent variables to use to interpolate. The values\r\n * in this array must be in increasing order and the same value must not occur twice in the array.\r\n * @param {Number[]} yTable The array of dependent variables to use to interpolate. For a set of three\r\n * dependent values (p,q,w) at time 1 and time 2 this should be as follows: {p1, q1, w1, p2, q2, w2}.\r\n * @param {Number} yStride The number of dependent variable values in yTable corresponding to\r\n * each independent variable value in xTable.\r\n * @param {Number} inputOrder The number of derivatives supplied for input.\r\n * @param {Number} outputOrder The number of derivatives desired for output.\r\n * @param {Number[]} [result] An existing array into which to store the result.\r\n *\r\n * @returns {Number[]} The array of interpolated values, or the result parameter if one was provided.\r\n */\r\nHermitePolynomialApproximation.interpolate = function (\r\n x,\r\n xTable,\r\n yTable,\r\n yStride,\r\n inputOrder,\r\n outputOrder,\r\n result\r\n) {\r\n var resultLength = yStride * (outputOrder + 1);\r\n if (!defined(result)) {\r\n result = new Array(resultLength);\r\n }\r\n for (var r = 0; r < resultLength; r++) {\r\n result[r] = 0;\r\n }\r\n\r\n var length = xTable.length;\r\n // The zIndices array holds copies of the addresses of the xTable values\r\n // in the range we're looking at. Even though this just holds information already\r\n // available in xTable this is a much more convenient format.\r\n var zIndices = new Array(length * (inputOrder + 1));\r\n var i;\r\n for (i = 0; i < length; i++) {\r\n for (var j = 0; j < inputOrder + 1; j++) {\r\n zIndices[i * (inputOrder + 1) + j] = i;\r\n }\r\n }\r\n\r\n var zIndiceslength = zIndices.length;\r\n var coefficients = arrayScratch;\r\n var highestNonZeroCoef = fillCoefficientList(\r\n coefficients,\r\n zIndices,\r\n xTable,\r\n yTable,\r\n yStride,\r\n inputOrder\r\n );\r\n var reservedIndices = [];\r\n\r\n var tmp = (zIndiceslength * (zIndiceslength + 1)) / 2;\r\n var loopStop = Math.min(highestNonZeroCoef, outputOrder);\r\n for (var d = 0; d <= loopStop; d++) {\r\n for (i = d; i <= highestNonZeroCoef; i++) {\r\n reservedIndices.length = 0;\r\n var tempTerm = calculateCoefficientTerm(\r\n x,\r\n zIndices,\r\n xTable,\r\n d,\r\n i,\r\n reservedIndices\r\n );\r\n var dimTwo = Math.floor((i * (1 - i)) / 2) + zIndiceslength * i;\r\n\r\n for (var s = 0; s < yStride; s++) {\r\n var dimOne = Math.floor(s * tmp);\r\n var coef = coefficients[dimOne + dimTwo];\r\n result[s + d * yStride] += coef * tempTerm;\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n};\r\n\r\nfunction fillCoefficientList(\r\n coefficients,\r\n zIndices,\r\n xTable,\r\n yTable,\r\n yStride,\r\n inputOrder\r\n) {\r\n var j;\r\n var index;\r\n var highestNonZero = -1;\r\n var zIndiceslength = zIndices.length;\r\n var tmp = (zIndiceslength * (zIndiceslength + 1)) / 2;\r\n\r\n for (var s = 0; s < yStride; s++) {\r\n var dimOne = Math.floor(s * tmp);\r\n\r\n for (j = 0; j < zIndiceslength; j++) {\r\n index = zIndices[j] * yStride * (inputOrder + 1) + s;\r\n coefficients[dimOne + j] = yTable[index];\r\n }\r\n\r\n for (var i = 1; i < zIndiceslength; i++) {\r\n var coefIndex = 0;\r\n var dimTwo = Math.floor((i * (1 - i)) / 2) + zIndiceslength * i;\r\n var nonZeroCoefficients = false;\r\n\r\n for (j = 0; j < zIndiceslength - i; j++) {\r\n var zj = xTable[zIndices[j]];\r\n var zn = xTable[zIndices[j + i]];\r\n\r\n var numerator;\r\n var coefficient;\r\n if (zn - zj <= 0) {\r\n index = zIndices[j] * yStride * (inputOrder + 1) + yStride * i + s;\r\n numerator = yTable[index];\r\n coefficient = numerator / CesiumMath.factorial(i);\r\n coefficients[dimOne + dimTwo + coefIndex] = coefficient;\r\n coefIndex++;\r\n } else {\r\n var dimTwoMinusOne =\r\n Math.floor(((i - 1) * (2 - i)) / 2) + zIndiceslength * (i - 1);\r\n numerator =\r\n coefficients[dimOne + dimTwoMinusOne + j + 1] -\r\n coefficients[dimOne + dimTwoMinusOne + j];\r\n coefficient = numerator / (zn - zj);\r\n coefficients[dimOne + dimTwo + coefIndex] = coefficient;\r\n coefIndex++;\r\n }\r\n nonZeroCoefficients = nonZeroCoefficients || numerator !== 0.0;\r\n }\r\n\r\n if (nonZeroCoefficients) {\r\n highestNonZero = Math.max(highestNonZero, i);\r\n }\r\n }\r\n }\r\n\r\n return highestNonZero;\r\n}\r\nexport default HermitePolynomialApproximation;\r\n","/**\r\n * A structure containing the orientation data computed at a particular time. The data\r\n * represents the direction of the pole of rotation and the rotation about that pole.\r\n *

\r\n * These parameters correspond to the parameters in the Report from the IAU/IAG Working Group\r\n * except that they are expressed in radians.\r\n *

\r\n *\r\n * @namespace IauOrientationParameters\r\n *\r\n * @private\r\n */\r\nfunction IauOrientationParameters(\r\n rightAscension,\r\n declination,\r\n rotation,\r\n rotationRate\r\n) {\r\n /**\r\n * The right ascension of the north pole of the body with respect to\r\n * the International Celestial Reference Frame, in radians.\r\n * @type {Number}\r\n *\r\n * @private\r\n */\r\n this.rightAscension = rightAscension;\r\n\r\n /**\r\n * The declination of the north pole of the body with respect to\r\n * the International Celestial Reference Frame, in radians.\r\n * @type {Number}\r\n *\r\n * @private\r\n */\r\n this.declination = declination;\r\n\r\n /**\r\n * The rotation about the north pole used to align a set of axes with\r\n * the meridian defined by the IAU report, in radians.\r\n * @type {Number}\r\n *\r\n * @private\r\n */\r\n this.rotation = rotation;\r\n\r\n /**\r\n * The instantaneous rotation rate about the north pole, in radians per second.\r\n * @type {Number}\r\n *\r\n * @private\r\n */\r\n this.rotationRate = rotationRate;\r\n}\r\nexport default IauOrientationParameters;\r\n","import defined from \"./defined.js\";\r\nimport IauOrientationParameters from \"./IauOrientationParameters.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport TimeConstants from \"./TimeConstants.js\";\r\n\r\n/**\r\n * This is a collection of the orientation information available for central bodies.\r\n * The data comes from the Report of the IAU/IAG Working Group on Cartographic\r\n * Coordinates and Rotational Elements: 2000.\r\n *\r\n * @namespace Iau2000Orientation\r\n *\r\n * @private\r\n */\r\nvar Iau2000Orientation = {};\r\n\r\nvar TdtMinusTai = 32.184;\r\nvar J2000d = 2451545.0;\r\n\r\nvar c1 = -0.0529921;\r\nvar c2 = -0.1059842;\r\nvar c3 = 13.0120009;\r\nvar c4 = 13.3407154;\r\nvar c5 = 0.9856003;\r\nvar c6 = 26.4057084;\r\nvar c7 = 13.064993;\r\nvar c8 = 0.3287146;\r\nvar c9 = 1.7484877;\r\nvar c10 = -0.1589763;\r\nvar c11 = 0.0036096;\r\nvar c12 = 0.1643573;\r\nvar c13 = 12.9590088;\r\nvar dateTT = new JulianDate();\r\n\r\n/**\r\n * Compute the orientation parameters for the Moon.\r\n *\r\n * @param {JulianDate} [date=JulianDate.now()] The date to evaluate the parameters.\r\n * @param {IauOrientationParameters} [result] The object onto which to store the result.\r\n * @returns {IauOrientationParameters} The modified result parameter or a new instance representing the orientation of the Earth's Moon.\r\n * @private\r\n */\r\nIau2000Orientation.ComputeMoon = function (date, result) {\r\n if (!defined(date)) {\r\n date = JulianDate.now();\r\n }\r\n\r\n dateTT = JulianDate.addSeconds(date, TdtMinusTai, dateTT);\r\n var d = JulianDate.totalDays(dateTT) - J2000d;\r\n var T = d / TimeConstants.DAYS_PER_JULIAN_CENTURY;\r\n\r\n var E1 = (125.045 + c1 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E2 = (250.089 + c2 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E3 = (260.008 + c3 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E4 = (176.625 + c4 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E5 = (357.529 + c5 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E6 = (311.589 + c6 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E7 = (134.963 + c7 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E8 = (276.617 + c8 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E9 = (34.226 + c9 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E10 = (15.134 + c10 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E11 = (119.743 + c11 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E12 = (239.961 + c12 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n var E13 = (25.053 + c13 * d) * CesiumMath.RADIANS_PER_DEGREE;\r\n\r\n var sinE1 = Math.sin(E1);\r\n var sinE2 = Math.sin(E2);\r\n var sinE3 = Math.sin(E3);\r\n var sinE4 = Math.sin(E4);\r\n var sinE5 = Math.sin(E5);\r\n var sinE6 = Math.sin(E6);\r\n var sinE7 = Math.sin(E7);\r\n var sinE8 = Math.sin(E8);\r\n var sinE9 = Math.sin(E9);\r\n var sinE10 = Math.sin(E10);\r\n var sinE11 = Math.sin(E11);\r\n var sinE12 = Math.sin(E12);\r\n var sinE13 = Math.sin(E13);\r\n\r\n var cosE1 = Math.cos(E1);\r\n var cosE2 = Math.cos(E2);\r\n var cosE3 = Math.cos(E3);\r\n var cosE4 = Math.cos(E4);\r\n var cosE5 = Math.cos(E5);\r\n var cosE6 = Math.cos(E6);\r\n var cosE7 = Math.cos(E7);\r\n var cosE8 = Math.cos(E8);\r\n var cosE9 = Math.cos(E9);\r\n var cosE10 = Math.cos(E10);\r\n var cosE11 = Math.cos(E11);\r\n var cosE12 = Math.cos(E12);\r\n var cosE13 = Math.cos(E13);\r\n\r\n var rightAscension =\r\n (269.9949 +\r\n 0.0031 * T -\r\n 3.8787 * sinE1 -\r\n 0.1204 * sinE2 +\r\n 0.07 * sinE3 -\r\n 0.0172 * sinE4 +\r\n 0.0072 * sinE6 -\r\n 0.0052 * sinE10 +\r\n 0.0043 * sinE13) *\r\n CesiumMath.RADIANS_PER_DEGREE;\r\n var declination =\r\n (66.5392 +\r\n 0.013 * T +\r\n 1.5419 * cosE1 +\r\n 0.0239 * cosE2 -\r\n 0.0278 * cosE3 +\r\n 0.0068 * cosE4 -\r\n 0.0029 * cosE6 +\r\n 0.0009 * cosE7 +\r\n 0.0008 * cosE10 -\r\n 0.0009 * cosE13) *\r\n CesiumMath.RADIANS_PER_DEGREE;\r\n var rotation =\r\n (38.3213 +\r\n 13.17635815 * d -\r\n 1.4e-12 * d * d +\r\n 3.561 * sinE1 +\r\n 0.1208 * sinE2 -\r\n 0.0642 * sinE3 +\r\n 0.0158 * sinE4 +\r\n 0.0252 * sinE5 -\r\n 0.0066 * sinE6 -\r\n 0.0047 * sinE7 -\r\n 0.0046 * sinE8 +\r\n 0.0028 * sinE9 +\r\n 0.0052 * sinE10 +\r\n 0.004 * sinE11 +\r\n 0.0019 * sinE12 -\r\n 0.0044 * sinE13) *\r\n CesiumMath.RADIANS_PER_DEGREE;\r\n\r\n var rotationRate =\r\n ((13.17635815 -\r\n 1.4e-12 * (2.0 * d) +\r\n 3.561 * cosE1 * c1 +\r\n 0.1208 * cosE2 * c2 -\r\n 0.0642 * cosE3 * c3 +\r\n 0.0158 * cosE4 * c4 +\r\n 0.0252 * cosE5 * c5 -\r\n 0.0066 * cosE6 * c6 -\r\n 0.0047 * cosE7 * c7 -\r\n 0.0046 * cosE8 * c8 +\r\n 0.0028 * cosE9 * c9 +\r\n 0.0052 * cosE10 * c10 +\r\n 0.004 * cosE11 * c11 +\r\n 0.0019 * cosE12 * c12 -\r\n 0.0044 * cosE13 * c13) /\r\n 86400.0) *\r\n CesiumMath.RADIANS_PER_DEGREE;\r\n\r\n if (!defined(result)) {\r\n result = new IauOrientationParameters();\r\n }\r\n\r\n result.rightAscension = rightAscension;\r\n result.declination = declination;\r\n result.rotation = rotation;\r\n result.rotationRate = rotationRate;\r\n\r\n return result;\r\n};\r\nexport default Iau2000Orientation;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport defined from \"./defined.js\";\r\nimport Iau2000Orientation from \"./Iau2000Orientation.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\n\r\n/**\r\n * The Axes representing the orientation of a Globe as represented by the data\r\n * from the IAU/IAG Working Group reports on rotational elements.\r\n * @alias IauOrientationAxes\r\n * @constructor\r\n *\r\n * @param {IauOrientationAxes.ComputeFunction} [computeFunction] The function that computes the {@link IauOrientationParameters} given a {@link JulianDate}.\r\n *\r\n * @see Iau2000Orientation\r\n *\r\n * @private\r\n */\r\nfunction IauOrientationAxes(computeFunction) {\r\n if (!defined(computeFunction) || typeof computeFunction !== \"function\") {\r\n computeFunction = Iau2000Orientation.ComputeMoon;\r\n }\r\n\r\n this._computeFunction = computeFunction;\r\n}\r\n\r\nvar xAxisScratch = new Cartesian3();\r\nvar yAxisScratch = new Cartesian3();\r\nvar zAxisScratch = new Cartesian3();\r\n\r\nfunction computeRotationMatrix(alpha, delta, result) {\r\n var xAxis = xAxisScratch;\r\n xAxis.x = Math.cos(alpha + CesiumMath.PI_OVER_TWO);\r\n xAxis.y = Math.sin(alpha + CesiumMath.PI_OVER_TWO);\r\n xAxis.z = 0.0;\r\n\r\n var cosDec = Math.cos(delta);\r\n\r\n var zAxis = zAxisScratch;\r\n zAxis.x = cosDec * Math.cos(alpha);\r\n zAxis.y = cosDec * Math.sin(alpha);\r\n zAxis.z = Math.sin(delta);\r\n\r\n var yAxis = Cartesian3.cross(zAxis, xAxis, yAxisScratch);\r\n\r\n if (!defined(result)) {\r\n result = new Matrix3();\r\n }\r\n\r\n result[0] = xAxis.x;\r\n result[1] = yAxis.x;\r\n result[2] = zAxis.x;\r\n result[3] = xAxis.y;\r\n result[4] = yAxis.y;\r\n result[5] = zAxis.y;\r\n result[6] = xAxis.z;\r\n result[7] = yAxis.z;\r\n result[8] = zAxis.z;\r\n\r\n return result;\r\n}\r\n\r\nvar rotMtxScratch = new Matrix3();\r\nvar quatScratch = new Quaternion();\r\n\r\n/**\r\n * Computes a rotation from ICRF to a Globe's Fixed axes.\r\n *\r\n * @param {JulianDate} date The date to evaluate the matrix.\r\n * @param {Matrix3} result The object onto which to store the result.\r\n * @returns {Matrix3} The modified result parameter or a new instance of the rotation from ICRF to Fixed.\r\n */\r\nIauOrientationAxes.prototype.evaluate = function (date, result) {\r\n if (!defined(date)) {\r\n date = JulianDate.now();\r\n }\r\n\r\n var alphaDeltaW = this._computeFunction(date);\r\n var precMtx = computeRotationMatrix(\r\n alphaDeltaW.rightAscension,\r\n alphaDeltaW.declination,\r\n result\r\n );\r\n\r\n var rot = CesiumMath.zeroToTwoPi(alphaDeltaW.rotation);\r\n var quat = Quaternion.fromAxisAngle(Cartesian3.UNIT_Z, rot, quatScratch);\r\n var rotMtx = Matrix3.fromQuaternion(\r\n Quaternion.conjugate(quat, quat),\r\n rotMtxScratch\r\n );\r\n\r\n var cbi2cbf = Matrix3.multiply(rotMtx, precMtx, precMtx);\r\n return cbi2cbf;\r\n};\r\n\r\n/**\r\n * A function that computes the {@link IauOrientationParameters} for a {@link JulianDate}.\r\n * @callback IauOrientationAxes.ComputeFunction\r\n * @param {JulianDate} date The date to evaluate the parameters.\r\n * @returns {IauOrientationParameters} The orientation parameters.\r\n * @private\r\n */\r\nexport default IauOrientationAxes;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * The interface for interpolation algorithms.\r\n *\r\n * @interface InterpolationAlgorithm\r\n *\r\n * @see LagrangePolynomialApproximation\r\n * @see LinearApproximation\r\n * @see HermitePolynomialApproximation\r\n */\r\nvar InterpolationAlgorithm = {};\r\n\r\n/**\r\n * Gets the name of this interpolation algorithm.\r\n * @type {String}\r\n */\r\nInterpolationAlgorithm.type = undefined;\r\n\r\n/**\r\n * Given the desired degree, returns the number of data points required for interpolation.\r\n * @function\r\n *\r\n * @param {Number} degree The desired degree of interpolation.\r\n * @returns {Number} The number of required data points needed for the desired degree of interpolation.\r\n */\r\nInterpolationAlgorithm.getRequiredDataPoints =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Performs zero order interpolation.\r\n * @function\r\n *\r\n * @param {Number} x The independent variable for which the dependent variables will be interpolated.\r\n * @param {Number[]} xTable The array of independent variables to use to interpolate. The values\r\n * in this array must be in increasing order and the same value must not occur twice in the array.\r\n * @param {Number[]} yTable The array of dependent variables to use to interpolate. For a set of three\r\n * dependent values (p,q,w) at time 1 and time 2 this should be as follows: {p1, q1, w1, p2, q2, w2}.\r\n * @param {Number} yStride The number of dependent variable values in yTable corresponding to\r\n * each independent variable value in xTable.\r\n * @param {Number[]} [result] An existing array into which to store the result.\r\n *\r\n * @returns {Number[]} The array of interpolated values, or the result parameter if one was provided.\r\n */\r\nInterpolationAlgorithm.interpolateOrderZero =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Performs higher order interpolation. Not all interpolators need to support high-order interpolation,\r\n * if this function remains undefined on implementing objects, interpolateOrderZero will be used instead.\r\n * @function\r\n * @param {Number} x The independent variable for which the dependent variables will be interpolated.\r\n * @param {Number[]} xTable The array of independent variables to use to interpolate. The values\r\n * in this array must be in increasing order and the same value must not occur twice in the array.\r\n * @param {Number[]} yTable The array of dependent variables to use to interpolate. For a set of three\r\n * dependent values (p,q,w) at time 1 and time 2 this should be as follows: {p1, q1, w1, p2, q2, w2}.\r\n * @param {Number} yStride The number of dependent variable values in yTable corresponding to\r\n * each independent variable value in xTable.\r\n * @param {Number} inputOrder The number of derivatives supplied for input.\r\n * @param {Number} outputOrder The number of derivatives desired for output.\r\n * @param {Number[]} [result] An existing array into which to store the result.\r\n * @returns {Number[]} The array of interpolated values, or the result parameter if one was provided.\r\n */\r\nInterpolationAlgorithm.interpolate = DeveloperError.throwInstantiationError;\r\nexport default InterpolationAlgorithm;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defined from \"./defined.js\";\r\nimport GeocodeType from \"./GeocodeType.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Resource from \"./Resource.js\";\r\n\r\n/**\r\n * Provides geocoding via a {@link https://pelias.io/|Pelias} server.\r\n * @alias PeliasGeocoderService\r\n * @constructor\r\n *\r\n * @param {Resource|String} url The endpoint to the Pelias server.\r\n *\r\n * @example\r\n * // Configure a Viewer to use the Pelias server hosted by https://geocode.earth/\r\n * var viewer = new Cesium.Viewer('cesiumContainer', {\r\n * geocoder: new Cesium.PeliasGeocoderService(new Cesium.Resource({\r\n * url: 'https://api.geocode.earth/v1/',\r\n * queryParameters: {\r\n * api_key: ''\r\n * }\r\n * }))\r\n * });\r\n */\r\nfunction PeliasGeocoderService(url) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"url\", url);\r\n //>>includeEnd('debug');\r\n\r\n this._url = Resource.createIfNeeded(url);\r\n this._url.appendForwardSlash();\r\n}\r\n\r\nObject.defineProperties(PeliasGeocoderService.prototype, {\r\n /**\r\n * The Resource used to access the Pelias endpoint.\r\n * @type {Resource}\r\n * @memberof PeliasGeocoderService.prototype\r\n * @readonly\r\n */\r\n url: {\r\n get: function () {\r\n return this._url;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @function\r\n *\r\n * @param {String} query The query to be sent to the geocoder service\r\n * @param {GeocodeType} [type=GeocodeType.SEARCH] The type of geocode to perform.\r\n * @returns {Promise}\r\n */\r\nPeliasGeocoderService.prototype.geocode = function (query, type) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"query\", query);\r\n //>>includeEnd('debug');\r\n\r\n var resource = this._url.getDerivedResource({\r\n url: type === GeocodeType.AUTOCOMPLETE ? \"autocomplete\" : \"search\",\r\n queryParameters: {\r\n text: query,\r\n },\r\n });\r\n\r\n return resource.fetchJson().then(function (results) {\r\n return results.features.map(function (resultObject) {\r\n var destination;\r\n var bboxDegrees = resultObject.bbox;\r\n\r\n if (defined(bboxDegrees)) {\r\n destination = Rectangle.fromDegrees(\r\n bboxDegrees[0],\r\n bboxDegrees[1],\r\n bboxDegrees[2],\r\n bboxDegrees[3]\r\n );\r\n } else {\r\n var lon = resultObject.geometry.coordinates[0];\r\n var lat = resultObject.geometry.coordinates[1];\r\n destination = Cartesian3.fromDegrees(lon, lat);\r\n }\r\n\r\n return {\r\n displayName: resultObject.properties.label,\r\n destination: destination,\r\n };\r\n });\r\n });\r\n};\r\nexport default PeliasGeocoderService;\r\n","import Check from \"./Check.js\";\r\nimport Credit from \"./Credit.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Ion from \"./Ion.js\";\r\nimport PeliasGeocoderService from \"./PeliasGeocoderService.js\";\r\nimport Resource from \"./Resource.js\";\r\n\r\n/**\r\n * Provides geocoding through Cesium ion.\r\n * @alias IonGeocoderService\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Scene} options.scene The scene\r\n * @param {String} [options.accessToken=Ion.defaultAccessToken] The access token to use.\r\n * @param {String|Resource} [options.server=Ion.defaultServer] The resource to the Cesium ion API server.\r\n *\r\n * @see Ion\r\n */\r\nfunction IonGeocoderService(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options.scene\", options.scene);\r\n //>>includeEnd('debug');\r\n\r\n var accessToken = defaultValue(options.accessToken, Ion.defaultAccessToken);\r\n var server = Resource.createIfNeeded(\r\n defaultValue(options.server, Ion.defaultServer)\r\n );\r\n server.appendForwardSlash();\r\n\r\n var defaultTokenCredit = Ion.getDefaultTokenCredit(accessToken);\r\n if (defined(defaultTokenCredit)) {\r\n options.scene.frameState.creditDisplay.addDefaultCredit(\r\n Credit.clone(defaultTokenCredit)\r\n );\r\n }\r\n\r\n var searchEndpoint = server.getDerivedResource({\r\n url: \"v1/geocode\",\r\n });\r\n\r\n if (defined(accessToken)) {\r\n searchEndpoint.appendQueryParameters({ access_token: accessToken });\r\n }\r\n\r\n this._accessToken = accessToken;\r\n this._server = server;\r\n this._pelias = new PeliasGeocoderService(searchEndpoint);\r\n}\r\n\r\n/**\r\n * @function\r\n *\r\n * @param {String} query The query to be sent to the geocoder service\r\n * @param {GeocodeType} [type=GeocodeType.SEARCH] The type of geocode to perform.\r\n * @returns {Promise}\r\n */\r\nIonGeocoderService.prototype.geocode = function (query, geocodeType) {\r\n return this._pelias.geocode(query, geocodeType);\r\n};\r\nexport default IonGeocoderService;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\n\r\n/**\r\n * An interval defined by a start and a stop time; optionally including those times as part of the interval.\r\n * Arbitrary data can optionally be associated with each instance for used with {@link TimeIntervalCollection}.\r\n *\r\n * @alias TimeInterval\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {JulianDate} [options.start=new JulianDate()] The start time of the interval.\r\n * @param {JulianDate} [options.stop=new JulianDate()] The stop time of the interval.\r\n * @param {Boolean} [options.isStartIncluded=true] true if options.start is included in the interval, false otherwise.\r\n * @param {Boolean} [options.isStopIncluded=true] true if options.stop is included in the interval, false otherwise.\r\n * @param {Object} [options.data] Arbitrary data associated with this interval.\r\n *\r\n * @example\r\n * // Create an instance that spans August 1st, 1980 and is associated\r\n * // with a Cartesian position.\r\n * var timeInterval = new Cesium.TimeInterval({\r\n * start : Cesium.JulianDate.fromIso8601('1980-08-01T00:00:00Z'),\r\n * stop : Cesium.JulianDate.fromIso8601('1980-08-02T00:00:00Z'),\r\n * isStartIncluded : true,\r\n * isStopIncluded : false,\r\n * data : Cesium.Cartesian3.fromDegrees(39.921037, -75.170082)\r\n * });\r\n *\r\n * @example\r\n * // Create two instances from ISO 8601 intervals with associated numeric data\r\n * // then compute their intersection, summing the data they contain.\r\n * var left = Cesium.TimeInterval.fromIso8601({\r\n * iso8601 : '2000/2010',\r\n * data : 2\r\n * });\r\n *\r\n * var right = Cesium.TimeInterval.fromIso8601({\r\n * iso8601 : '1995/2005',\r\n * data : 3\r\n * });\r\n *\r\n * //The result of the below intersection will be an interval equivalent to\r\n * //var intersection = Cesium.TimeInterval.fromIso8601({\r\n * // iso8601 : '2000/2005',\r\n * // data : 5\r\n * //});\r\n * var intersection = new Cesium.TimeInterval();\r\n * Cesium.TimeInterval.intersect(left, right, intersection, function(leftData, rightData) {\r\n * return leftData + rightData;\r\n * });\r\n *\r\n * @example\r\n * // Check if an interval contains a specific time.\r\n * var dateToCheck = Cesium.JulianDate.fromIso8601('1982-09-08T11:30:00Z');\r\n * var containsDate = Cesium.TimeInterval.contains(timeInterval, dateToCheck);\r\n */\r\nfunction TimeInterval(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n /**\r\n * Gets or sets the start time of this interval.\r\n * @type {JulianDate}\r\n */\r\n this.start = defined(options.start)\r\n ? JulianDate.clone(options.start)\r\n : new JulianDate();\r\n\r\n /**\r\n * Gets or sets the stop time of this interval.\r\n * @type {JulianDate}\r\n */\r\n this.stop = defined(options.stop)\r\n ? JulianDate.clone(options.stop)\r\n : new JulianDate();\r\n\r\n /**\r\n * Gets or sets the data associated with this interval.\r\n * @type {*}\r\n */\r\n this.data = options.data;\r\n\r\n /**\r\n * Gets or sets whether or not the start time is included in this interval.\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.isStartIncluded = defaultValue(options.isStartIncluded, true);\r\n\r\n /**\r\n * Gets or sets whether or not the stop time is included in this interval.\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.isStopIncluded = defaultValue(options.isStopIncluded, true);\r\n}\r\n\r\nObject.defineProperties(TimeInterval.prototype, {\r\n /**\r\n * Gets whether or not this interval is empty.\r\n * @memberof TimeInterval.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isEmpty: {\r\n get: function () {\r\n var stopComparedToStart = JulianDate.compare(this.stop, this.start);\r\n return (\r\n stopComparedToStart < 0 ||\r\n (stopComparedToStart === 0 &&\r\n (!this.isStartIncluded || !this.isStopIncluded))\r\n );\r\n },\r\n },\r\n});\r\n\r\nvar scratchInterval = {\r\n start: undefined,\r\n stop: undefined,\r\n isStartIncluded: undefined,\r\n isStopIncluded: undefined,\r\n data: undefined,\r\n};\r\n\r\n/**\r\n * Creates a new instance from a {@link http://en.wikipedia.org/wiki/ISO_8601|ISO 8601} interval.\r\n *\r\n * @throws DeveloperError if options.iso8601 does not match proper formatting.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {String} options.iso8601 An ISO 8601 interval.\r\n * @param {Boolean} [options.isStartIncluded=true] true if options.start is included in the interval, false otherwise.\r\n * @param {Boolean} [options.isStopIncluded=true] true if options.stop is included in the interval, false otherwise.\r\n * @param {Object} [options.data] Arbitrary data associated with this interval.\r\n * @param {TimeInterval} [result] An existing instance to use for the result.\r\n * @returns {TimeInterval} The modified result parameter or a new instance if none was provided.\r\n */\r\nTimeInterval.fromIso8601 = function (options, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.string(\"options.iso8601\", options.iso8601);\r\n //>>includeEnd('debug');\r\n\r\n var dates = options.iso8601.split(\"/\");\r\n if (dates.length !== 2) {\r\n throw new DeveloperError(\r\n \"options.iso8601 is an invalid ISO 8601 interval.\"\r\n );\r\n }\r\n var start = JulianDate.fromIso8601(dates[0]);\r\n var stop = JulianDate.fromIso8601(dates[1]);\r\n var isStartIncluded = defaultValue(options.isStartIncluded, true);\r\n var isStopIncluded = defaultValue(options.isStopIncluded, true);\r\n var data = options.data;\r\n\r\n if (!defined(result)) {\r\n scratchInterval.start = start;\r\n scratchInterval.stop = stop;\r\n scratchInterval.isStartIncluded = isStartIncluded;\r\n scratchInterval.isStopIncluded = isStopIncluded;\r\n scratchInterval.data = data;\r\n return new TimeInterval(scratchInterval);\r\n }\r\n\r\n result.start = start;\r\n result.stop = stop;\r\n result.isStartIncluded = isStartIncluded;\r\n result.isStopIncluded = isStopIncluded;\r\n result.data = data;\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates an ISO8601 representation of the provided interval.\r\n *\r\n * @param {TimeInterval} timeInterval The interval to be converted.\r\n * @param {Number} [precision] The number of fractional digits used to represent the seconds component. By default, the most precise representation is used.\r\n * @returns {String} The ISO8601 representation of the provided interval.\r\n */\r\nTimeInterval.toIso8601 = function (timeInterval, precision) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"timeInterval\", timeInterval);\r\n //>>includeEnd('debug');\r\n\r\n return (\r\n JulianDate.toIso8601(timeInterval.start, precision) +\r\n \"/\" +\r\n JulianDate.toIso8601(timeInterval.stop, precision)\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates the provided instance.\r\n *\r\n * @param {TimeInterval} [timeInterval] The instance to clone.\r\n * @param {TimeInterval} [result] An existing instance to use for the result.\r\n * @returns {TimeInterval} The modified result parameter or a new instance if none was provided.\r\n */\r\nTimeInterval.clone = function (timeInterval, result) {\r\n if (!defined(timeInterval)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n return new TimeInterval(timeInterval);\r\n }\r\n result.start = timeInterval.start;\r\n result.stop = timeInterval.stop;\r\n result.isStartIncluded = timeInterval.isStartIncluded;\r\n result.isStopIncluded = timeInterval.isStopIncluded;\r\n result.data = timeInterval.data;\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares two instances and returns true if they are equal, false otherwise.\r\n *\r\n * @param {TimeInterval} [left] The first instance.\r\n * @param {TimeInterval} [right] The second instance.\r\n * @param {TimeInterval.DataComparer} [dataComparer] A function which compares the data of the two intervals. If omitted, reference equality is used.\r\n * @returns {Boolean} true if the dates are equal; otherwise, false.\r\n */\r\nTimeInterval.equals = function (left, right, dataComparer) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n ((left.isEmpty && right.isEmpty) ||\r\n (left.isStartIncluded === right.isStartIncluded &&\r\n left.isStopIncluded === right.isStopIncluded &&\r\n JulianDate.equals(left.start, right.start) &&\r\n JulianDate.equals(left.stop, right.stop) &&\r\n (left.data === right.data ||\r\n (defined(dataComparer) && dataComparer(left.data, right.data))))))\r\n );\r\n};\r\n\r\n/**\r\n * Compares two instances and returns true if they are within epsilon seconds of\r\n * each other. That is, in order for the dates to be considered equal (and for\r\n * this function to return true), the absolute value of the difference between them, in\r\n * seconds, must be less than epsilon.\r\n *\r\n * @param {TimeInterval} [left] The first instance.\r\n * @param {TimeInterval} [right] The second instance.\r\n * @param {Number} [epsilon=0] The maximum number of seconds that should separate the two instances.\r\n * @param {TimeInterval.DataComparer} [dataComparer] A function which compares the data of the two intervals. If omitted, reference equality is used.\r\n * @returns {Boolean} true if the two dates are within epsilon seconds of each other; otherwise false.\r\n */\r\nTimeInterval.equalsEpsilon = function (left, right, epsilon, dataComparer) {\r\n epsilon = defaultValue(epsilon, 0);\r\n\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n ((left.isEmpty && right.isEmpty) ||\r\n (left.isStartIncluded === right.isStartIncluded &&\r\n left.isStopIncluded === right.isStopIncluded &&\r\n JulianDate.equalsEpsilon(left.start, right.start, epsilon) &&\r\n JulianDate.equalsEpsilon(left.stop, right.stop, epsilon) &&\r\n (left.data === right.data ||\r\n (defined(dataComparer) && dataComparer(left.data, right.data))))))\r\n );\r\n};\r\n\r\n/**\r\n * Computes the intersection of two intervals, optionally merging their data.\r\n *\r\n * @param {TimeInterval} left The first interval.\r\n * @param {TimeInterval} [right] The second interval.\r\n * @param {TimeInterval} [result] An existing instance to use for the result.\r\n * @param {TimeInterval.MergeCallback} [mergeCallback] A function which merges the data of the two intervals. If omitted, the data from the left interval will be used.\r\n * @returns {TimeInterval} The modified result parameter.\r\n */\r\nTimeInterval.intersect = function (left, right, result, mergeCallback) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"left\", left);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(right)) {\r\n return TimeInterval.clone(TimeInterval.EMPTY, result);\r\n }\r\n\r\n var leftStart = left.start;\r\n var leftStop = left.stop;\r\n\r\n var rightStart = right.start;\r\n var rightStop = right.stop;\r\n\r\n var intersectsStartRight =\r\n JulianDate.greaterThanOrEquals(rightStart, leftStart) &&\r\n JulianDate.greaterThanOrEquals(leftStop, rightStart);\r\n var intersectsStartLeft =\r\n !intersectsStartRight &&\r\n JulianDate.lessThanOrEquals(rightStart, leftStart) &&\r\n JulianDate.lessThanOrEquals(leftStart, rightStop);\r\n\r\n if (!intersectsStartRight && !intersectsStartLeft) {\r\n return TimeInterval.clone(TimeInterval.EMPTY, result);\r\n }\r\n\r\n var leftIsStartIncluded = left.isStartIncluded;\r\n var leftIsStopIncluded = left.isStopIncluded;\r\n var rightIsStartIncluded = right.isStartIncluded;\r\n var rightIsStopIncluded = right.isStopIncluded;\r\n var leftLessThanRight = JulianDate.lessThan(leftStop, rightStop);\r\n\r\n if (!defined(result)) {\r\n result = new TimeInterval();\r\n }\r\n\r\n result.start = intersectsStartRight ? rightStart : leftStart;\r\n result.isStartIncluded =\r\n (leftIsStartIncluded && rightIsStartIncluded) ||\r\n (!JulianDate.equals(rightStart, leftStart) &&\r\n ((intersectsStartRight && rightIsStartIncluded) ||\r\n (intersectsStartLeft && leftIsStartIncluded)));\r\n result.stop = leftLessThanRight ? leftStop : rightStop;\r\n result.isStopIncluded = leftLessThanRight\r\n ? leftIsStopIncluded\r\n : (leftIsStopIncluded && rightIsStopIncluded) ||\r\n (!JulianDate.equals(rightStop, leftStop) && rightIsStopIncluded);\r\n result.data = defined(mergeCallback)\r\n ? mergeCallback(left.data, right.data)\r\n : left.data;\r\n return result;\r\n};\r\n\r\n/**\r\n * Checks if the specified date is inside the provided interval.\r\n *\r\n * @param {TimeInterval} timeInterval The interval.\r\n * @param {JulianDate} julianDate The date to check.\r\n * @returns {Boolean} true if the interval contains the specified date, false otherwise.\r\n */\r\nTimeInterval.contains = function (timeInterval, julianDate) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"timeInterval\", timeInterval);\r\n Check.typeOf.object(\"julianDate\", julianDate);\r\n //>>includeEnd('debug');\r\n\r\n if (timeInterval.isEmpty) {\r\n return false;\r\n }\r\n\r\n var startComparedToDate = JulianDate.compare(timeInterval.start, julianDate);\r\n if (startComparedToDate === 0) {\r\n return timeInterval.isStartIncluded;\r\n }\r\n\r\n var dateComparedToStop = JulianDate.compare(julianDate, timeInterval.stop);\r\n if (dateComparedToStop === 0) {\r\n return timeInterval.isStopIncluded;\r\n }\r\n\r\n return startComparedToDate < 0 && dateComparedToStop < 0;\r\n};\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {TimeInterval} [result] An existing instance to use for the result.\r\n * @returns {TimeInterval} The modified result parameter or a new instance if none was provided.\r\n */\r\nTimeInterval.prototype.clone = function (result) {\r\n return TimeInterval.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this instance against the provided instance componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {TimeInterval} [right] The right hand side interval.\r\n * @param {TimeInterval.DataComparer} [dataComparer] A function which compares the data of the two intervals. If omitted, reference equality is used.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nTimeInterval.prototype.equals = function (right, dataComparer) {\r\n return TimeInterval.equals(this, right, dataComparer);\r\n};\r\n\r\n/**\r\n * Compares this instance against the provided instance componentwise and returns\r\n * true if they are within the provided epsilon,\r\n * false otherwise.\r\n *\r\n * @param {TimeInterval} [right] The right hand side interval.\r\n * @param {Number} [epsilon=0] The epsilon to use for equality testing.\r\n * @param {TimeInterval.DataComparer} [dataComparer] A function which compares the data of the two intervals. If omitted, reference equality is used.\r\n * @returns {Boolean} true if they are within the provided epsilon, false otherwise.\r\n */\r\nTimeInterval.prototype.equalsEpsilon = function (right, epsilon, dataComparer) {\r\n return TimeInterval.equalsEpsilon(this, right, epsilon, dataComparer);\r\n};\r\n\r\n/**\r\n * Creates a string representing this TimeInterval in ISO8601 format.\r\n *\r\n * @returns {String} A string representing this TimeInterval in ISO8601 format.\r\n */\r\nTimeInterval.prototype.toString = function () {\r\n return TimeInterval.toIso8601(this);\r\n};\r\n\r\n/**\r\n * An immutable empty interval.\r\n *\r\n * @type {TimeInterval}\r\n * @constant\r\n */\r\nTimeInterval.EMPTY = Object.freeze(\r\n new TimeInterval({\r\n start: new JulianDate(),\r\n stop: new JulianDate(),\r\n isStartIncluded: false,\r\n isStopIncluded: false,\r\n })\r\n);\r\n\r\n/**\r\n * Function interface for merging interval data.\r\n * @callback TimeInterval.MergeCallback\r\n *\r\n * @param {*} leftData The first data instance.\r\n * @param {*} rightData The second data instance.\r\n * @returns {*} The result of merging the two data instances.\r\n */\r\n\r\n/**\r\n * Function interface for comparing interval data.\r\n * @callback TimeInterval.DataComparer\r\n * @param {*} leftData The first data instance.\r\n * @param {*} rightData The second data instance.\r\n * @returns {Boolean} true if the provided instances are equal, false otherwise.\r\n */\r\nexport default TimeInterval;\r\n","import JulianDate from \"./JulianDate.js\";\r\nimport TimeInterval from \"./TimeInterval.js\";\r\n\r\nvar MINIMUM_VALUE = Object.freeze(\r\n JulianDate.fromIso8601(\"0000-01-01T00:00:00Z\")\r\n);\r\nvar MAXIMUM_VALUE = Object.freeze(\r\n JulianDate.fromIso8601(\"9999-12-31T24:00:00Z\")\r\n);\r\nvar MAXIMUM_INTERVAL = Object.freeze(\r\n new TimeInterval({\r\n start: MINIMUM_VALUE,\r\n stop: MAXIMUM_VALUE,\r\n })\r\n);\r\n\r\n/**\r\n * Constants related to ISO8601 support.\r\n *\r\n * @namespace\r\n *\r\n * @see {@link http://en.wikipedia.org/wiki/ISO_8601|ISO 8601 on Wikipedia}\r\n * @see JulianDate\r\n * @see TimeInterval\r\n */\r\nvar Iso8601 = {\r\n /**\r\n * A {@link JulianDate} representing the earliest time representable by an ISO8601 date.\r\n * This is equivalent to the date string '0000-01-01T00:00:00Z'\r\n *\r\n * @type {JulianDate}\r\n * @constant\r\n */\r\n MINIMUM_VALUE: MINIMUM_VALUE,\r\n\r\n /**\r\n * A {@link JulianDate} representing the latest time representable by an ISO8601 date.\r\n * This is equivalent to the date string '9999-12-31T24:00:00Z'\r\n *\r\n * @type {JulianDate}\r\n * @constant\r\n */\r\n MAXIMUM_VALUE: MAXIMUM_VALUE,\r\n\r\n /**\r\n * A {@link TimeInterval} representing the largest interval representable by an ISO8601 interval.\r\n * This is equivalent to the interval string '0000-01-01T00:00:00Z/9999-12-31T24:00:00Z'\r\n *\r\n * @type {JulianDate}\r\n * @constant\r\n */\r\n MAXIMUM_INTERVAL: MAXIMUM_INTERVAL,\r\n};\r\nexport default Iso8601;\r\n","/**\r\n * This enumerated type is for representing keyboard modifiers. These are keys\r\n * that are held down in addition to other event types.\r\n *\r\n * @enum {Number}\r\n */\r\nvar KeyboardEventModifier = {\r\n /**\r\n * Represents the shift key being held down.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SHIFT: 0,\r\n\r\n /**\r\n * Represents the control key being held down.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CTRL: 1,\r\n\r\n /**\r\n * Represents the alt key being held down.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ALT: 2,\r\n};\r\nexport default Object.freeze(KeyboardEventModifier);\r\n","import defined from \"./defined.js\";\r\n\r\n/**\r\n * An {@link InterpolationAlgorithm} for performing Lagrange interpolation.\r\n *\r\n * @namespace LagrangePolynomialApproximation\r\n */\r\nvar LagrangePolynomialApproximation = {\r\n type: \"Lagrange\",\r\n};\r\n\r\n/**\r\n * Given the desired degree, returns the number of data points required for interpolation.\r\n *\r\n * @param {Number} degree The desired degree of interpolation.\r\n * @returns {Number} The number of required data points needed for the desired degree of interpolation.\r\n */\r\nLagrangePolynomialApproximation.getRequiredDataPoints = function (degree) {\r\n return Math.max(degree + 1.0, 2);\r\n};\r\n\r\n/**\r\n * Interpolates values using Lagrange Polynomial Approximation.\r\n *\r\n * @param {Number} x The independent variable for which the dependent variables will be interpolated.\r\n * @param {Number[]} xTable The array of independent variables to use to interpolate. The values\r\n * in this array must be in increasing order and the same value must not occur twice in the array.\r\n * @param {Number[]} yTable The array of dependent variables to use to interpolate. For a set of three\r\n * dependent values (p,q,w) at time 1 and time 2 this should be as follows: {p1, q1, w1, p2, q2, w2}.\r\n * @param {Number} yStride The number of dependent variable values in yTable corresponding to\r\n * each independent variable value in xTable.\r\n * @param {Number[]} [result] An existing array into which to store the result.\r\n * @returns {Number[]} The array of interpolated values, or the result parameter if one was provided.\r\n */\r\nLagrangePolynomialApproximation.interpolateOrderZero = function (\r\n x,\r\n xTable,\r\n yTable,\r\n yStride,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = new Array(yStride);\r\n }\r\n\r\n var i;\r\n var j;\r\n var length = xTable.length;\r\n\r\n for (i = 0; i < yStride; i++) {\r\n result[i] = 0;\r\n }\r\n\r\n for (i = 0; i < length; i++) {\r\n var coefficient = 1;\r\n\r\n for (j = 0; j < length; j++) {\r\n if (j !== i) {\r\n var diffX = xTable[i] - xTable[j];\r\n coefficient *= (x - xTable[j]) / diffX;\r\n }\r\n }\r\n\r\n for (j = 0; j < yStride; j++) {\r\n result[j] += coefficient * yTable[i * yStride + j];\r\n }\r\n }\r\n\r\n return result;\r\n};\r\nexport default LagrangePolynomialApproximation;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * An {@link InterpolationAlgorithm} for performing linear interpolation.\r\n *\r\n * @namespace LinearApproximation\r\n */\r\nvar LinearApproximation = {\r\n type: \"Linear\",\r\n};\r\n\r\n/**\r\n * Given the desired degree, returns the number of data points required for interpolation.\r\n * Since linear interpolation can only generate a first degree polynomial, this function\r\n * always returns 2.\r\n * @param {Number} degree The desired degree of interpolation.\r\n * @returns {Number} This function always returns 2.\r\n *\r\n */\r\nLinearApproximation.getRequiredDataPoints = function (degree) {\r\n return 2;\r\n};\r\n\r\n/**\r\n * Interpolates values using linear approximation.\r\n *\r\n * @param {Number} x The independent variable for which the dependent variables will be interpolated.\r\n * @param {Number[]} xTable The array of independent variables to use to interpolate. The values\r\n * in this array must be in increasing order and the same value must not occur twice in the array.\r\n * @param {Number[]} yTable The array of dependent variables to use to interpolate. For a set of three\r\n * dependent values (p,q,w) at time 1 and time 2 this should be as follows: {p1, q1, w1, p2, q2, w2}.\r\n * @param {Number} yStride The number of dependent variable values in yTable corresponding to\r\n * each independent variable value in xTable.\r\n * @param {Number[]} [result] An existing array into which to store the result.\r\n * @returns {Number[]} The array of interpolated values, or the result parameter if one was provided.\r\n */\r\nLinearApproximation.interpolateOrderZero = function (\r\n x,\r\n xTable,\r\n yTable,\r\n yStride,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (xTable.length !== 2) {\r\n throw new DeveloperError(\r\n \"The xTable provided to the linear interpolator must have exactly two elements.\"\r\n );\r\n } else if (yStride <= 0) {\r\n throw new DeveloperError(\r\n \"There must be at least 1 dependent variable for each independent variable.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Array(yStride);\r\n }\r\n\r\n var i;\r\n var y0;\r\n var y1;\r\n var x0 = xTable[0];\r\n var x1 = xTable[1];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (x0 === x1) {\r\n throw new DeveloperError(\r\n \"Divide by zero error: xTable[0] and xTable[1] are equal\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n for (i = 0; i < yStride; i++) {\r\n y0 = yTable[i];\r\n y1 = yTable[i + yStride];\r\n result[i] = ((y1 - y0) * x + x1 * y0 - x0 * y1) / (x1 - x0);\r\n }\r\n\r\n return result;\r\n};\r\nexport default LinearApproximation;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport CompressedTextureBuffer from \"./CompressedTextureBuffer.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport TaskProcessor from \"./TaskProcessor.js\";\r\n\r\nvar transcodeTaskProcessor = new TaskProcessor(\"transcodeCRNToDXT\");\r\n\r\n/**\r\n * Asynchronously loads and parses the given URL to a CRN file or parses the raw binary data of a CRN file.\r\n * Returns a promise that will resolve to an object containing the image buffer, width, height and format once loaded,\r\n * or reject if the URL failed to load or failed to parse the data. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *\r\n * @function loadCRN\r\n *\r\n * @param {Resource|String|ArrayBuffer} resourceOrUrlOrBuffer The URL of the binary data or an ArrayBuffer.\r\n * @returns {Promise.|undefined} A promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n * @exception {RuntimeError} Unsupported compressed format.\r\n *\r\n * @example\r\n * // load a single URL asynchronously\r\n * Cesium.loadCRN('some/url').then(function(textureData) {\r\n * var width = textureData.width;\r\n * var height = textureData.height;\r\n * var format = textureData.internalFormat;\r\n * var arrayBufferView = textureData.bufferView;\r\n * // use the data to create a texture\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link https://github.com/BinomialLLC/crunch|crunch DXTc texture compression and transcoding library}\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nfunction loadCRN(resourceOrUrlOrBuffer) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(resourceOrUrlOrBuffer)) {\r\n throw new DeveloperError(\"resourceOrUrlOrBuffer is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var loadPromise;\r\n if (\r\n resourceOrUrlOrBuffer instanceof ArrayBuffer ||\r\n ArrayBuffer.isView(resourceOrUrlOrBuffer)\r\n ) {\r\n loadPromise = when.resolve(resourceOrUrlOrBuffer);\r\n } else {\r\n var resource = Resource.createIfNeeded(resourceOrUrlOrBuffer);\r\n loadPromise = resource.fetchArrayBuffer();\r\n }\r\n\r\n if (!defined(loadPromise)) {\r\n return undefined;\r\n }\r\n\r\n return loadPromise\r\n .then(function (data) {\r\n if (!defined(data)) {\r\n return;\r\n }\r\n var transferrableObjects = [];\r\n if (data instanceof ArrayBuffer) {\r\n transferrableObjects.push(data);\r\n } else if (\r\n data.byteOffset === 0 &&\r\n data.byteLength === data.buffer.byteLength\r\n ) {\r\n transferrableObjects.push(data.buffer);\r\n } else {\r\n // data is a view of an array buffer. need to copy so it is transferrable to web worker\r\n data = data.slice(0, data.length);\r\n transferrableObjects.push(data.buffer);\r\n }\r\n\r\n return transcodeTaskProcessor.scheduleTask(data, transferrableObjects);\r\n })\r\n .then(function (compressedTextureBuffer) {\r\n return CompressedTextureBuffer.clone(compressedTextureBuffer);\r\n });\r\n}\r\nexport default loadCRN;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Resource from \"./Resource.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction loadImageFromTypedArray(options) {\r\n var uint8Array = options.uint8Array;\r\n var format = options.format;\r\n var request = options.request;\r\n var flipY = defaultValue(options.flipY, false);\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"uint8Array\", uint8Array);\r\n Check.typeOf.string(\"format\", format);\r\n //>>includeEnd('debug');\r\n\r\n var blob = new Blob([uint8Array], {\r\n type: format,\r\n });\r\n\r\n var blobUrl;\r\n return Resource.supportsImageBitmapOptions()\r\n .then(function (result) {\r\n if (result) {\r\n return when(\r\n Resource.createImageBitmapFromBlob(blob, {\r\n flipY: flipY,\r\n premultiplyAlpha: false,\r\n })\r\n );\r\n }\r\n\r\n blobUrl = window.URL.createObjectURL(blob);\r\n var resource = new Resource({\r\n url: blobUrl,\r\n request: request,\r\n });\r\n\r\n return resource.fetchImage({\r\n flipY: flipY,\r\n });\r\n })\r\n .then(function (result) {\r\n if (defined(blobUrl)) {\r\n window.URL.revokeObjectURL(blobUrl);\r\n }\r\n return result;\r\n })\r\n .otherwise(function (error) {\r\n if (defined(blobUrl)) {\r\n window.URL.revokeObjectURL(blobUrl);\r\n }\r\n return when.reject(error);\r\n });\r\n}\r\nexport default loadImageFromTypedArray;\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * The data type of a pixel.\r\n *\r\n * @enum {Number}\r\n * @see PostProcessStage\r\n */\r\nvar PixelDatatype = {\r\n UNSIGNED_BYTE: WebGLConstants.UNSIGNED_BYTE,\r\n UNSIGNED_SHORT: WebGLConstants.UNSIGNED_SHORT,\r\n UNSIGNED_INT: WebGLConstants.UNSIGNED_INT,\r\n FLOAT: WebGLConstants.FLOAT,\r\n HALF_FLOAT: WebGLConstants.HALF_FLOAT_OES,\r\n UNSIGNED_INT_24_8: WebGLConstants.UNSIGNED_INT_24_8,\r\n UNSIGNED_SHORT_4_4_4_4: WebGLConstants.UNSIGNED_SHORT_4_4_4_4,\r\n UNSIGNED_SHORT_5_5_5_1: WebGLConstants.UNSIGNED_SHORT_5_5_5_1,\r\n UNSIGNED_SHORT_5_6_5: WebGLConstants.UNSIGNED_SHORT_5_6_5,\r\n};\r\n\r\n/**\r\n @private\r\n*/\r\nPixelDatatype.toWebGLConstant = function (pixelDatatype, context) {\r\n switch (pixelDatatype) {\r\n case PixelDatatype.UNSIGNED_BYTE:\r\n return WebGLConstants.UNSIGNED_BYTE;\r\n case PixelDatatype.UNSIGNED_SHORT:\r\n return WebGLConstants.UNSIGNED_SHORT;\r\n case PixelDatatype.UNSIGNED_INT:\r\n return WebGLConstants.UNSIGNED_INT;\r\n case PixelDatatype.FLOAT:\r\n return WebGLConstants.FLOAT;\r\n case PixelDatatype.HALF_FLOAT:\r\n return context.webgl2\r\n ? WebGLConstants.HALF_FLOAT\r\n : WebGLConstants.HALF_FLOAT_OES;\r\n case PixelDatatype.UNSIGNED_INT_24_8:\r\n return WebGLConstants.UNSIGNED_INT_24_8;\r\n case PixelDatatype.UNSIGNED_SHORT_4_4_4_4:\r\n return WebGLConstants.UNSIGNED_SHORT_4_4_4_4;\r\n case PixelDatatype.UNSIGNED_SHORT_5_5_5_1:\r\n return WebGLConstants.UNSIGNED_SHORT_5_5_5_1;\r\n case PixelDatatype.UNSIGNED_SHORT_5_6_5:\r\n return PixelDatatype.UNSIGNED_SHORT_5_6_5;\r\n }\r\n};\r\n\r\n/**\r\n @private\r\n*/\r\nPixelDatatype.isPacked = function (pixelDatatype) {\r\n return (\r\n pixelDatatype === PixelDatatype.UNSIGNED_INT_24_8 ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_SHORT_4_4_4_4 ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_SHORT_5_5_5_1 ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_SHORT_5_6_5\r\n );\r\n};\r\n\r\n/**\r\n @private\r\n*/\r\nPixelDatatype.sizeInBytes = function (pixelDatatype) {\r\n switch (pixelDatatype) {\r\n case PixelDatatype.UNSIGNED_BYTE:\r\n return 1;\r\n case PixelDatatype.UNSIGNED_SHORT:\r\n case PixelDatatype.UNSIGNED_SHORT_4_4_4_4:\r\n case PixelDatatype.UNSIGNED_SHORT_5_5_5_1:\r\n case PixelDatatype.UNSIGNED_SHORT_5_6_5:\r\n case PixelDatatype.HALF_FLOAT:\r\n return 2;\r\n case PixelDatatype.UNSIGNED_INT:\r\n case PixelDatatype.FLOAT:\r\n case PixelDatatype.UNSIGNED_INT_24_8:\r\n return 4;\r\n }\r\n};\r\n\r\n/**\r\n @private\r\n*/\r\nPixelDatatype.validate = function (pixelDatatype) {\r\n return (\r\n pixelDatatype === PixelDatatype.UNSIGNED_BYTE ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_SHORT ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_INT ||\r\n pixelDatatype === PixelDatatype.FLOAT ||\r\n pixelDatatype === PixelDatatype.HALF_FLOAT ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_INT_24_8 ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_SHORT_4_4_4_4 ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_SHORT_5_5_5_1 ||\r\n pixelDatatype === PixelDatatype.UNSIGNED_SHORT_5_6_5\r\n );\r\n};\r\n\r\nexport default Object.freeze(PixelDatatype);\r\n","import PixelDatatype from \"../Renderer/PixelDatatype.js\";\r\nimport WebGLConstants from \"./WebGLConstants.js\";\r\n\r\n/**\r\n * The format of a pixel, i.e., the number of components it has and what they represent.\r\n *\r\n * @enum {Number}\r\n */\r\nvar PixelFormat = {\r\n /**\r\n * A pixel format containing a depth value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n DEPTH_COMPONENT: WebGLConstants.DEPTH_COMPONENT,\r\n\r\n /**\r\n * A pixel format containing a depth and stencil value, most often used with {@link PixelDatatype.UNSIGNED_INT_24_8}.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n DEPTH_STENCIL: WebGLConstants.DEPTH_STENCIL,\r\n\r\n /**\r\n * A pixel format containing an alpha channel.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ALPHA: WebGLConstants.ALPHA,\r\n\r\n /**\r\n * A pixel format containing red, green, and blue channels.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGB: WebGLConstants.RGB,\r\n\r\n /**\r\n * A pixel format containing red, green, blue, and alpha channels.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGBA: WebGLConstants.RGBA,\r\n\r\n /**\r\n * A pixel format containing a luminance (intensity) channel.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LUMINANCE: WebGLConstants.LUMINANCE,\r\n\r\n /**\r\n * A pixel format containing luminance (intensity) and alpha channels.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LUMINANCE_ALPHA: WebGLConstants.LUMINANCE_ALPHA,\r\n\r\n /**\r\n * A pixel format containing red, green, and blue channels that is DXT1 compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGB_DXT1: WebGLConstants.COMPRESSED_RGB_S3TC_DXT1_EXT,\r\n\r\n /**\r\n * A pixel format containing red, green, blue, and alpha channels that is DXT1 compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGBA_DXT1: WebGLConstants.COMPRESSED_RGBA_S3TC_DXT1_EXT,\r\n\r\n /**\r\n * A pixel format containing red, green, blue, and alpha channels that is DXT3 compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGBA_DXT3: WebGLConstants.COMPRESSED_RGBA_S3TC_DXT3_EXT,\r\n\r\n /**\r\n * A pixel format containing red, green, blue, and alpha channels that is DXT5 compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGBA_DXT5: WebGLConstants.COMPRESSED_RGBA_S3TC_DXT5_EXT,\r\n\r\n /**\r\n * A pixel format containing red, green, and blue channels that is PVR 4bpp compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGB_PVRTC_4BPPV1: WebGLConstants.COMPRESSED_RGB_PVRTC_4BPPV1_IMG,\r\n\r\n /**\r\n * A pixel format containing red, green, and blue channels that is PVR 2bpp compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGB_PVRTC_2BPPV1: WebGLConstants.COMPRESSED_RGB_PVRTC_2BPPV1_IMG,\r\n\r\n /**\r\n * A pixel format containing red, green, blue, and alpha channels that is PVR 4bpp compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGBA_PVRTC_4BPPV1: WebGLConstants.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG,\r\n\r\n /**\r\n * A pixel format containing red, green, blue, and alpha channels that is PVR 2bpp compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGBA_PVRTC_2BPPV1: WebGLConstants.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG,\r\n\r\n /**\r\n * A pixel format containing red, green, and blue channels that is ETC1 compressed.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RGB_ETC1: WebGLConstants.COMPRESSED_RGB_ETC1_WEBGL,\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.componentsLength = function (pixelFormat) {\r\n switch (pixelFormat) {\r\n case PixelFormat.RGB:\r\n return 3;\r\n case PixelFormat.RGBA:\r\n return 4;\r\n case PixelFormat.LUMINANCE_ALPHA:\r\n return 2;\r\n case PixelFormat.ALPHA:\r\n case PixelFormat.LUMINANCE:\r\n return 1;\r\n default:\r\n return 1;\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.validate = function (pixelFormat) {\r\n return (\r\n pixelFormat === PixelFormat.DEPTH_COMPONENT ||\r\n pixelFormat === PixelFormat.DEPTH_STENCIL ||\r\n pixelFormat === PixelFormat.ALPHA ||\r\n pixelFormat === PixelFormat.RGB ||\r\n pixelFormat === PixelFormat.RGBA ||\r\n pixelFormat === PixelFormat.LUMINANCE ||\r\n pixelFormat === PixelFormat.LUMINANCE_ALPHA ||\r\n pixelFormat === PixelFormat.RGB_DXT1 ||\r\n pixelFormat === PixelFormat.RGBA_DXT1 ||\r\n pixelFormat === PixelFormat.RGBA_DXT3 ||\r\n pixelFormat === PixelFormat.RGBA_DXT5 ||\r\n pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 ||\r\n pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 ||\r\n pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 ||\r\n pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1 ||\r\n pixelFormat === PixelFormat.RGB_ETC1\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.isColorFormat = function (pixelFormat) {\r\n return (\r\n pixelFormat === PixelFormat.ALPHA ||\r\n pixelFormat === PixelFormat.RGB ||\r\n pixelFormat === PixelFormat.RGBA ||\r\n pixelFormat === PixelFormat.LUMINANCE ||\r\n pixelFormat === PixelFormat.LUMINANCE_ALPHA\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.isDepthFormat = function (pixelFormat) {\r\n return (\r\n pixelFormat === PixelFormat.DEPTH_COMPONENT ||\r\n pixelFormat === PixelFormat.DEPTH_STENCIL\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.isCompressedFormat = function (pixelFormat) {\r\n return (\r\n pixelFormat === PixelFormat.RGB_DXT1 ||\r\n pixelFormat === PixelFormat.RGBA_DXT1 ||\r\n pixelFormat === PixelFormat.RGBA_DXT3 ||\r\n pixelFormat === PixelFormat.RGBA_DXT5 ||\r\n pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 ||\r\n pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 ||\r\n pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 ||\r\n pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1 ||\r\n pixelFormat === PixelFormat.RGB_ETC1\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.isDXTFormat = function (pixelFormat) {\r\n return (\r\n pixelFormat === PixelFormat.RGB_DXT1 ||\r\n pixelFormat === PixelFormat.RGBA_DXT1 ||\r\n pixelFormat === PixelFormat.RGBA_DXT3 ||\r\n pixelFormat === PixelFormat.RGBA_DXT5\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.isPVRTCFormat = function (pixelFormat) {\r\n return (\r\n pixelFormat === PixelFormat.RGB_PVRTC_4BPPV1 ||\r\n pixelFormat === PixelFormat.RGB_PVRTC_2BPPV1 ||\r\n pixelFormat === PixelFormat.RGBA_PVRTC_4BPPV1 ||\r\n pixelFormat === PixelFormat.RGBA_PVRTC_2BPPV1\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.isETC1Format = function (pixelFormat) {\r\n return pixelFormat === PixelFormat.RGB_ETC1;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.compressedTextureSizeInBytes = function (\r\n pixelFormat,\r\n width,\r\n height\r\n) {\r\n switch (pixelFormat) {\r\n case PixelFormat.RGB_DXT1:\r\n case PixelFormat.RGBA_DXT1:\r\n case PixelFormat.RGB_ETC1:\r\n return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 8;\r\n\r\n case PixelFormat.RGBA_DXT3:\r\n case PixelFormat.RGBA_DXT5:\r\n return Math.floor((width + 3) / 4) * Math.floor((height + 3) / 4) * 16;\r\n\r\n case PixelFormat.RGB_PVRTC_4BPPV1:\r\n case PixelFormat.RGBA_PVRTC_4BPPV1:\r\n return Math.floor((Math.max(width, 8) * Math.max(height, 8) * 4 + 7) / 8);\r\n\r\n case PixelFormat.RGB_PVRTC_2BPPV1:\r\n case PixelFormat.RGBA_PVRTC_2BPPV1:\r\n return Math.floor(\r\n (Math.max(width, 16) * Math.max(height, 8) * 2 + 7) / 8\r\n );\r\n\r\n default:\r\n return 0;\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.textureSizeInBytes = function (\r\n pixelFormat,\r\n pixelDatatype,\r\n width,\r\n height\r\n) {\r\n var componentsLength = PixelFormat.componentsLength(pixelFormat);\r\n if (PixelDatatype.isPacked(pixelDatatype)) {\r\n componentsLength = 1;\r\n }\r\n return (\r\n componentsLength * PixelDatatype.sizeInBytes(pixelDatatype) * width * height\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.alignmentInBytes = function (pixelFormat, pixelDatatype, width) {\r\n var mod =\r\n PixelFormat.textureSizeInBytes(pixelFormat, pixelDatatype, width, 1) % 4;\r\n return mod === 0 ? 4 : mod === 2 ? 2 : 1;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.createTypedArray = function (\r\n pixelFormat,\r\n pixelDatatype,\r\n width,\r\n height\r\n) {\r\n var constructor;\r\n var sizeInBytes = PixelDatatype.sizeInBytes(pixelDatatype);\r\n if (sizeInBytes === Uint8Array.BYTES_PER_ELEMENT) {\r\n constructor = Uint8Array;\r\n } else if (sizeInBytes === Uint16Array.BYTES_PER_ELEMENT) {\r\n constructor = Uint16Array;\r\n } else if (\r\n sizeInBytes === Float32Array.BYTES_PER_ELEMENT &&\r\n pixelDatatype === PixelDatatype.FLOAT\r\n ) {\r\n constructor = Float32Array;\r\n } else {\r\n constructor = Uint32Array;\r\n }\r\n\r\n var size = PixelFormat.componentsLength(pixelFormat) * width * height;\r\n return new constructor(size);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.flipY = function (\r\n bufferView,\r\n pixelFormat,\r\n pixelDatatype,\r\n width,\r\n height\r\n) {\r\n if (height === 1) {\r\n return bufferView;\r\n }\r\n var flipped = PixelFormat.createTypedArray(\r\n pixelFormat,\r\n pixelDatatype,\r\n width,\r\n height\r\n );\r\n var numberOfComponents = PixelFormat.componentsLength(pixelFormat);\r\n var textureWidth = width * numberOfComponents;\r\n for (var i = 0; i < height; ++i) {\r\n var row = i * width * numberOfComponents;\r\n var flippedRow = (height - i - 1) * width * numberOfComponents;\r\n for (var j = 0; j < textureWidth; ++j) {\r\n flipped[flippedRow + j] = bufferView[row + j];\r\n }\r\n }\r\n return flipped;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPixelFormat.toInternalFormat = function (pixelFormat, pixelDatatype, context) {\r\n // WebGL 1 require internalFormat to be the same as PixelFormat\r\n if (!context.webgl2) {\r\n return pixelFormat;\r\n }\r\n\r\n // Convert pixelFormat to correct internalFormat for WebGL 2\r\n if (pixelFormat === PixelFormat.DEPTH_STENCIL) {\r\n return WebGLConstants.DEPTH24_STENCIL8;\r\n }\r\n\r\n if (pixelFormat === PixelFormat.DEPTH_COMPONENT) {\r\n if (pixelDatatype === PixelDatatype.UNSIGNED_SHORT) {\r\n return WebGLConstants.DEPTH_COMPONENT16;\r\n } else if (pixelDatatype === PixelDatatype.UNSIGNED_INT) {\r\n return WebGLConstants.DEPTH_COMPONENT24;\r\n }\r\n }\r\n\r\n if (pixelDatatype === PixelDatatype.FLOAT) {\r\n switch (pixelFormat) {\r\n case PixelFormat.RGBA:\r\n return WebGLConstants.RGBA32F;\r\n case PixelFormat.RGB:\r\n return WebGLConstants.RGB32F;\r\n case PixelFormat.RG:\r\n return WebGLConstants.RG32F;\r\n case PixelFormat.R:\r\n return WebGLConstants.R32F;\r\n }\r\n }\r\n\r\n if (pixelDatatype === PixelDatatype.HALF_FLOAT) {\r\n switch (pixelFormat) {\r\n case PixelFormat.RGBA:\r\n return WebGLConstants.RGBA16F;\r\n case PixelFormat.RGB:\r\n return WebGLConstants.RGB16F;\r\n case PixelFormat.RG:\r\n return WebGLConstants.RG16F;\r\n case PixelFormat.R:\r\n return WebGLConstants.R16F;\r\n }\r\n }\r\n\r\n return pixelFormat;\r\n};\r\n\r\nexport default Object.freeze(PixelFormat);\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Check from \"./Check.js\";\r\nimport CompressedTextureBuffer from \"./CompressedTextureBuffer.js\";\r\nimport defined from \"./defined.js\";\r\nimport PixelFormat from \"./PixelFormat.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport RuntimeError from \"./RuntimeError.js\";\r\nimport WebGLConstants from \"./WebGLConstants.js\";\r\n\r\n/**\r\n * Asynchronously loads and parses the given URL to a KTX file or parses the raw binary data of a KTX file.\r\n * Returns a promise that will resolve to an object containing the image buffer, width, height and format once loaded,\r\n * or reject if the URL failed to load or failed to parse the data. The data is loaded\r\n * using XMLHttpRequest, which means that in order to make requests to another origin,\r\n * the server must have Cross-Origin Resource Sharing (CORS) headers enabled.\r\n *

\r\n * The following are part of the KTX format specification but are not supported:\r\n *

    \r\n *
  • Big-endian files
  • \r\n *
  • Metadata
  • \r\n *
  • 3D textures
  • \r\n *
  • Texture Arrays
  • \r\n *
  • Cubemaps
  • \r\n *
  • Mipmaps
  • \r\n *
\r\n *

\r\n *\r\n * @function loadKTX\r\n *\r\n * @param {Resource|String|ArrayBuffer} resourceOrUrlOrBuffer The URL of the binary data or an ArrayBuffer.\r\n * @returns {Promise.|undefined} A promise that will resolve to the requested data when loaded. Returns undefined if request.throttle is true and the request does not have high enough priority.\r\n *\r\n * @exception {RuntimeError} Invalid KTX file.\r\n * @exception {RuntimeError} File is the wrong endianness.\r\n * @exception {RuntimeError} glInternalFormat is not a valid format.\r\n * @exception {RuntimeError} glType must be zero when the texture is compressed.\r\n * @exception {RuntimeError} The type size for compressed textures must be 1.\r\n * @exception {RuntimeError} glFormat must be zero when the texture is compressed.\r\n * @exception {RuntimeError} Generating mipmaps for a compressed texture is unsupported.\r\n * @exception {RuntimeError} The base internal format must be the same as the format for uncompressed textures.\r\n * @exception {RuntimeError} 3D textures are not supported.\r\n * @exception {RuntimeError} Texture arrays are not supported.\r\n * @exception {RuntimeError} Cubemaps are not supported.\r\n *\r\n * @example\r\n * // load a single URL asynchronously\r\n * Cesium.loadKTX('some/url').then(function(ktxData) {\r\n * var width = ktxData.width;\r\n * var height = ktxData.height;\r\n * var format = ktxData.internalFormat;\r\n * var arrayBufferView = ktxData.bufferView;\r\n * // use the data to create a texture\r\n * }).otherwise(function(error) {\r\n * // an error occurred\r\n * });\r\n *\r\n * @see {@link https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/|KTX file format}\r\n * @see {@link http://www.w3.org/TR/cors/|Cross-Origin Resource Sharing}\r\n * @see {@link http://wiki.commonjs.org/wiki/Promises/A|CommonJS Promises/A}\r\n */\r\nfunction loadKTX(resourceOrUrlOrBuffer) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"resourceOrUrlOrBuffer\", resourceOrUrlOrBuffer);\r\n //>>includeEnd('debug');\r\n\r\n var loadPromise;\r\n if (\r\n resourceOrUrlOrBuffer instanceof ArrayBuffer ||\r\n ArrayBuffer.isView(resourceOrUrlOrBuffer)\r\n ) {\r\n loadPromise = when.resolve(resourceOrUrlOrBuffer);\r\n } else {\r\n var resource = Resource.createIfNeeded(resourceOrUrlOrBuffer);\r\n loadPromise = resource.fetchArrayBuffer();\r\n }\r\n\r\n if (!defined(loadPromise)) {\r\n return undefined;\r\n }\r\n\r\n return loadPromise.then(function (data) {\r\n if (defined(data)) {\r\n return parseKTX(data);\r\n }\r\n });\r\n}\r\n\r\nvar fileIdentifier = [\r\n 0xab,\r\n 0x4b,\r\n 0x54,\r\n 0x58,\r\n 0x20,\r\n 0x31,\r\n 0x31,\r\n 0xbb,\r\n 0x0d,\r\n 0x0a,\r\n 0x1a,\r\n 0x0a,\r\n];\r\nvar endiannessTest = 0x04030201;\r\nvar faceOrder = [\r\n \"positiveX\",\r\n \"negativeX\",\r\n \"positiveY\",\r\n \"negativeY\",\r\n \"positiveZ\",\r\n \"negativeZ\",\r\n];\r\n\r\nvar sizeOfUint32 = 4;\r\n\r\nfunction parseKTX(data) {\r\n var byteBuffer = new Uint8Array(data);\r\n\r\n var isKTX = true;\r\n var i;\r\n for (i = 0; i < fileIdentifier.length; ++i) {\r\n if (fileIdentifier[i] !== byteBuffer[i]) {\r\n isKTX = false;\r\n break;\r\n }\r\n }\r\n\r\n if (!isKTX) {\r\n throw new RuntimeError(\"Invalid KTX file.\");\r\n }\r\n\r\n var view;\r\n var byteOffset;\r\n\r\n if (defined(data.buffer)) {\r\n view = new DataView(data.buffer);\r\n byteOffset = data.byteOffset;\r\n } else {\r\n view = new DataView(data);\r\n byteOffset = 0;\r\n }\r\n\r\n byteOffset += 12; // skip identifier\r\n\r\n var endianness = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n if (endianness !== endiannessTest) {\r\n throw new RuntimeError(\"File is the wrong endianness.\");\r\n }\r\n\r\n var glType = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var glTypeSize = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var glFormat = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var glInternalFormat = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var glBaseInternalFormat = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var pixelWidth = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var pixelHeight = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var pixelDepth = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var numberOfArrayElements = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var numberOfFaces = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var numberOfMipmapLevels = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var bytesOfKeyValueByteSize = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n // skip metadata\r\n byteOffset += bytesOfKeyValueByteSize;\r\n\r\n var imageSize = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var texture;\r\n if (defined(data.buffer)) {\r\n texture = new Uint8Array(data.buffer, byteOffset, imageSize);\r\n } else {\r\n texture = new Uint8Array(data, byteOffset, imageSize);\r\n }\r\n\r\n // Some tools use a sized internal format.\r\n // See table 2: https://www.opengl.org/sdk/docs/man/html/glTexImage2D.xhtml\r\n if (glInternalFormat === WebGLConstants.RGB8) {\r\n glInternalFormat = PixelFormat.RGB;\r\n } else if (glInternalFormat === WebGLConstants.RGBA8) {\r\n glInternalFormat = PixelFormat.RGBA;\r\n }\r\n\r\n if (!PixelFormat.validate(glInternalFormat)) {\r\n throw new RuntimeError(\"glInternalFormat is not a valid format.\");\r\n }\r\n\r\n if (PixelFormat.isCompressedFormat(glInternalFormat)) {\r\n if (glType !== 0) {\r\n throw new RuntimeError(\r\n \"glType must be zero when the texture is compressed.\"\r\n );\r\n }\r\n if (glTypeSize !== 1) {\r\n throw new RuntimeError(\r\n \"The type size for compressed textures must be 1.\"\r\n );\r\n }\r\n if (glFormat !== 0) {\r\n throw new RuntimeError(\r\n \"glFormat must be zero when the texture is compressed.\"\r\n );\r\n }\r\n } else if (glType !== WebGLConstants.UNSIGNED_BYTE) {\r\n throw new RuntimeError(\"Only unsigned byte buffers are supported.\");\r\n } else if (glBaseInternalFormat !== glFormat) {\r\n throw new RuntimeError(\r\n \"The base internal format must be the same as the format for uncompressed textures.\"\r\n );\r\n }\r\n\r\n if (pixelDepth !== 0) {\r\n throw new RuntimeError(\"3D textures are unsupported.\");\r\n }\r\n\r\n if (numberOfArrayElements !== 0) {\r\n throw new RuntimeError(\"Texture arrays are unsupported.\");\r\n }\r\n\r\n var offset = texture.byteOffset;\r\n var mipmaps = new Array(numberOfMipmapLevels);\r\n for (i = 0; i < numberOfMipmapLevels; ++i) {\r\n var level = (mipmaps[i] = {});\r\n for (var j = 0; j < numberOfFaces; ++j) {\r\n var width = pixelWidth >> i;\r\n var height = pixelHeight >> i;\r\n var levelSize = PixelFormat.isCompressedFormat(glInternalFormat)\r\n ? PixelFormat.compressedTextureSizeInBytes(\r\n glInternalFormat,\r\n width,\r\n height\r\n )\r\n : PixelFormat.textureSizeInBytes(\r\n glInternalFormat,\r\n glType,\r\n width,\r\n height\r\n );\r\n var levelBuffer = new Uint8Array(texture.buffer, offset, levelSize);\r\n level[faceOrder[j]] = new CompressedTextureBuffer(\r\n glInternalFormat,\r\n width,\r\n height,\r\n levelBuffer\r\n );\r\n offset += levelSize;\r\n }\r\n offset += 3 - ((offset + 3) % 4) + 4;\r\n }\r\n\r\n var result = mipmaps;\r\n if (numberOfFaces === 1) {\r\n for (i = 0; i < numberOfMipmapLevels; ++i) {\r\n result[i] = result[i][faceOrder[0]];\r\n }\r\n }\r\n if (numberOfMipmapLevels === 1) {\r\n result = result[0];\r\n }\r\n\r\n return result;\r\n}\r\nexport default loadKTX;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\n\r\n/**\r\n * A wrapper around arrays so that the internal length of the array can be manually managed.\r\n *\r\n * @alias ManagedArray\r\n * @constructor\r\n * @private\r\n *\r\n * @param {Number} [length=0] The initial length of the array.\r\n */\r\nfunction ManagedArray(length) {\r\n length = defaultValue(length, 0);\r\n this._array = new Array(length);\r\n this._length = length;\r\n}\r\n\r\nObject.defineProperties(ManagedArray.prototype, {\r\n /**\r\n * Gets or sets the length of the array.\r\n * If the set length is greater than the length of the internal array, the internal array is resized.\r\n *\r\n * @memberof ManagedArray.prototype\r\n * @type Number\r\n */\r\n length: {\r\n get: function () {\r\n return this._length;\r\n },\r\n set: function (length) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"length\", length, 0);\r\n //>>includeEnd('debug');\r\n var array = this._array;\r\n var originalLength = this._length;\r\n if (length < originalLength) {\r\n // Remove trailing references\r\n for (var i = length; i < originalLength; ++i) {\r\n array[i] = undefined;\r\n }\r\n } else if (length > array.length) {\r\n array.length = length;\r\n }\r\n this._length = length;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the internal array.\r\n *\r\n * @memberof ManagedArray.prototype\r\n * @type Array\r\n * @readonly\r\n */\r\n values: {\r\n get: function () {\r\n return this._array;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the element at an index.\r\n *\r\n * @param {Number} index The index to get.\r\n */\r\nManagedArray.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.lessThan(\"index\", index, this._array.length);\r\n //>>includeEnd('debug');\r\n\r\n return this._array[index];\r\n};\r\n\r\n/**\r\n * Sets the element at an index. Resizes the array if index is greater than the length of the array.\r\n *\r\n * @param {Number} index The index to set.\r\n * @param {*} element The element to set at index.\r\n */\r\nManagedArray.prototype.set = function (index, element) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"index\", index);\r\n //>>includeEnd('debug');\r\n\r\n if (index >= this._length) {\r\n this.length = index + 1;\r\n }\r\n this._array[index] = element;\r\n};\r\n\r\n/**\r\n * Returns the last element in the array without modifying the array.\r\n *\r\n * @returns {*} The last element in the array.\r\n */\r\nManagedArray.prototype.peek = function () {\r\n return this._array[this._length - 1];\r\n};\r\n\r\n/**\r\n * Push an element into the array.\r\n *\r\n * @param {*} element The element to push.\r\n */\r\nManagedArray.prototype.push = function (element) {\r\n var index = this.length++;\r\n this._array[index] = element;\r\n};\r\n\r\n/**\r\n * Pop an element from the array.\r\n *\r\n * @returns {*} The last element in the array.\r\n */\r\nManagedArray.prototype.pop = function () {\r\n if (this._length === 0) {\r\n return undefined;\r\n }\r\n var element = this._array[this._length - 1];\r\n --this.length;\r\n return element;\r\n};\r\n\r\n/**\r\n * Resize the internal array if length > _array.length.\r\n *\r\n * @param {Number} length The length.\r\n */\r\nManagedArray.prototype.reserve = function (length) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"length\", length, 0);\r\n //>>includeEnd('debug');\r\n\r\n if (length > this._array.length) {\r\n this._array.length = length;\r\n }\r\n};\r\n\r\n/**\r\n * Resize the array.\r\n *\r\n * @param {Number} length The length.\r\n */\r\nManagedArray.prototype.resize = function (length) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"length\", length, 0);\r\n //>>includeEnd('debug');\r\n\r\n this.length = length;\r\n};\r\n\r\n/**\r\n * Trim the internal array to the specified length. Defaults to the current length.\r\n *\r\n * @param {Number} [length] The length.\r\n */\r\nManagedArray.prototype.trim = function (length) {\r\n length = defaultValue(length, this._length);\r\n this._array.length = length;\r\n};\r\nexport default ManagedArray;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Defines how geodetic ellipsoid coordinates ({@link Cartographic}) project to a\r\n * flat map like Cesium's 2D and Columbus View modes.\r\n *\r\n * @alias MapProjection\r\n * @constructor\r\n * @abstract\r\n *\r\n * @see GeographicProjection\r\n * @see WebMercatorProjection\r\n */\r\nfunction MapProjection() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\nObject.defineProperties(MapProjection.prototype, {\r\n /**\r\n * Gets the {@link Ellipsoid}.\r\n *\r\n * @memberof MapProjection.prototype\r\n *\r\n * @type {Ellipsoid}\r\n * @readonly\r\n */\r\n ellipsoid: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n});\r\n\r\n/**\r\n * Projects {@link Cartographic} coordinates, in radians, to projection-specific map coordinates, in meters.\r\n *\r\n * @memberof MapProjection\r\n * @function\r\n *\r\n * @param {Cartographic} cartographic The coordinates to project.\r\n * @param {Cartesian3} [result] An instance into which to copy the result. If this parameter is\r\n * undefined, a new instance is created and returned.\r\n * @returns {Cartesian3} The projected coordinates. If the result parameter is not undefined, the\r\n * coordinates are copied there and that instance is returned. Otherwise, a new instance is\r\n * created and returned.\r\n */\r\nMapProjection.prototype.project = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Unprojects projection-specific map {@link Cartesian3} coordinates, in meters, to {@link Cartographic}\r\n * coordinates, in radians.\r\n *\r\n * @memberof MapProjection\r\n * @function\r\n *\r\n * @param {Cartesian3} cartesian The Cartesian position to unproject with height (z) in meters.\r\n * @param {Cartographic} [result] An instance into which to copy the result. If this parameter is\r\n * undefined, a new instance is created and returned.\r\n * @returns {Cartographic} The unprojected coordinates. If the result parameter is not undefined, the\r\n * coordinates are copied there and that instance is returned. Otherwise, a new instance is\r\n * created and returned.\r\n */\r\nMapProjection.prototype.unproject = DeveloperError.throwInstantiationError;\r\nexport default MapProjection;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\nvar leftScratchArray = [];\r\nvar rightScratchArray = [];\r\n\r\nfunction merge(array, compare, userDefinedObject, start, middle, end) {\r\n var leftLength = middle - start + 1;\r\n var rightLength = end - middle;\r\n\r\n var left = leftScratchArray;\r\n var right = rightScratchArray;\r\n\r\n var i;\r\n var j;\r\n\r\n for (i = 0; i < leftLength; ++i) {\r\n left[i] = array[start + i];\r\n }\r\n\r\n for (j = 0; j < rightLength; ++j) {\r\n right[j] = array[middle + j + 1];\r\n }\r\n\r\n i = 0;\r\n j = 0;\r\n for (var k = start; k <= end; ++k) {\r\n var leftElement = left[i];\r\n var rightElement = right[j];\r\n if (\r\n i < leftLength &&\r\n (j >= rightLength ||\r\n compare(leftElement, rightElement, userDefinedObject) <= 0)\r\n ) {\r\n array[k] = leftElement;\r\n ++i;\r\n } else if (j < rightLength) {\r\n array[k] = rightElement;\r\n ++j;\r\n }\r\n }\r\n}\r\n\r\nfunction sort(array, compare, userDefinedObject, start, end) {\r\n if (start >= end) {\r\n return;\r\n }\r\n\r\n var middle = Math.floor((start + end) * 0.5);\r\n sort(array, compare, userDefinedObject, start, middle);\r\n sort(array, compare, userDefinedObject, middle + 1, end);\r\n merge(array, compare, userDefinedObject, start, middle, end);\r\n}\r\n\r\n/**\r\n * A stable merge sort.\r\n *\r\n * @function mergeSort\r\n * @param {Array} array The array to sort.\r\n * @param {mergeSortComparator} comparator The function to use to compare elements in the array.\r\n * @param {*} [userDefinedObject] Any item to pass as the third parameter to comparator.\r\n *\r\n * @example\r\n * // Assume array contains BoundingSpheres in world coordinates.\r\n * // Sort them in ascending order of distance from the camera.\r\n * var position = camera.positionWC;\r\n * Cesium.mergeSort(array, function(a, b, position) {\r\n * return Cesium.BoundingSphere.distanceSquaredTo(b, position) - Cesium.BoundingSphere.distanceSquaredTo(a, position);\r\n * }, position);\r\n */\r\nfunction mergeSort(array, comparator, userDefinedObject) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required.\");\r\n }\r\n if (!defined(comparator)) {\r\n throw new DeveloperError(\"comparator is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var length = array.length;\r\n var scratchLength = Math.ceil(length * 0.5);\r\n\r\n // preallocate space in scratch arrays\r\n leftScratchArray.length = scratchLength;\r\n rightScratchArray.length = scratchLength;\r\n\r\n sort(array, comparator, userDefinedObject, 0, length - 1);\r\n\r\n // trim scratch arrays\r\n leftScratchArray.length = 0;\r\n rightScratchArray.length = 0;\r\n}\r\n\r\n/**\r\n * A function used to compare two items while performing a merge sort.\r\n * @callback mergeSortComparator\r\n *\r\n * @param {*} a An item in the array.\r\n * @param {*} b An item in the array.\r\n * @param {*} [userDefinedObject] An object that was passed to {@link mergeSort}.\r\n * @returns {Number} Returns a negative value if a is less than b,\r\n * a positive value if a is greater than b, or\r\n * 0 if a is equal to b.\r\n *\r\n * @example\r\n * function compareNumbers(a, b, userDefinedObject) {\r\n * return a - b;\r\n * }\r\n */\r\nexport default mergeSort;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Represents a scalar value's lower and upper bound at a near distance and far distance in eye space.\r\n * @alias NearFarScalar\r\n * @constructor\r\n *\r\n * @param {Number} [near=0.0] The lower bound of the camera range.\r\n * @param {Number} [nearValue=0.0] The value at the lower bound of the camera range.\r\n * @param {Number} [far=1.0] The upper bound of the camera range.\r\n * @param {Number} [farValue=0.0] The value at the upper bound of the camera range.\r\n *\r\n * @see Packable\r\n */\r\nfunction NearFarScalar(near, nearValue, far, farValue) {\r\n /**\r\n * The lower bound of the camera range.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.near = defaultValue(near, 0.0);\r\n /**\r\n * The value at the lower bound of the camera range.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.nearValue = defaultValue(nearValue, 0.0);\r\n /**\r\n * The upper bound of the camera range.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.far = defaultValue(far, 1.0);\r\n /**\r\n * The value at the upper bound of the camera range.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.farValue = defaultValue(farValue, 0.0);\r\n}\r\n\r\n/**\r\n * Duplicates a NearFarScalar instance.\r\n *\r\n * @param {NearFarScalar} nearFarScalar The NearFarScalar to duplicate.\r\n * @param {NearFarScalar} [result] The object onto which to store the result.\r\n * @returns {NearFarScalar} The modified result parameter or a new NearFarScalar instance if one was not provided. (Returns undefined if nearFarScalar is undefined)\r\n */\r\nNearFarScalar.clone = function (nearFarScalar, result) {\r\n if (!defined(nearFarScalar)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new NearFarScalar(\r\n nearFarScalar.near,\r\n nearFarScalar.nearValue,\r\n nearFarScalar.far,\r\n nearFarScalar.farValue\r\n );\r\n }\r\n\r\n result.near = nearFarScalar.near;\r\n result.nearValue = nearFarScalar.nearValue;\r\n result.far = nearFarScalar.far;\r\n result.farValue = nearFarScalar.farValue;\r\n return result;\r\n};\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nNearFarScalar.packedLength = 4;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {NearFarScalar} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nNearFarScalar.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n array[startingIndex++] = value.near;\r\n array[startingIndex++] = value.nearValue;\r\n array[startingIndex++] = value.far;\r\n array[startingIndex] = value.farValue;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {NearFarScalar} [result] The object into which to store the result.\r\n * @returns {NearFarScalar} The modified result parameter or a new NearFarScalar instance if one was not provided.\r\n */\r\nNearFarScalar.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n if (!defined(result)) {\r\n result = new NearFarScalar();\r\n }\r\n result.near = array[startingIndex++];\r\n result.nearValue = array[startingIndex++];\r\n result.far = array[startingIndex++];\r\n result.farValue = array[startingIndex];\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares the provided NearFarScalar and returns true if they are equal,\r\n * false otherwise.\r\n *\r\n * @param {NearFarScalar} [left] The first NearFarScalar.\r\n * @param {NearFarScalar} [right] The second NearFarScalar.\r\n * @returns {Boolean} true if left and right are equal; otherwise false.\r\n */\r\nNearFarScalar.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.near === right.near &&\r\n left.nearValue === right.nearValue &&\r\n left.far === right.far &&\r\n left.farValue === right.farValue)\r\n );\r\n};\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {NearFarScalar} [result] The object onto which to store the result.\r\n * @returns {NearFarScalar} The modified result parameter or a new NearFarScalar instance if one was not provided.\r\n */\r\nNearFarScalar.prototype.clone = function (result) {\r\n return NearFarScalar.clone(this, result);\r\n};\r\n\r\n/**\r\n * Compares this instance to the provided NearFarScalar and returns true if they are equal,\r\n * false otherwise.\r\n *\r\n * @param {NearFarScalar} [right] The right hand side NearFarScalar.\r\n * @returns {Boolean} true if left and right are equal; otherwise false.\r\n */\r\nNearFarScalar.prototype.equals = function (right) {\r\n return NearFarScalar.equals(this, right);\r\n};\r\nexport default NearFarScalar;\r\n","/**\r\n * This enumerated type is used in determining to what extent an object, the occludee,\r\n * is visible during horizon culling. An occluder may fully block an occludee, in which case\r\n * it has no visibility, may partially block an occludee from view, or may not block it at all,\r\n * leading to full visibility.\r\n *\r\n * @enum {Number}\r\n */\r\nvar Visibility = {\r\n /**\r\n * Represents that no part of an object is visible.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NONE: -1,\r\n\r\n /**\r\n * Represents that part, but not all, of an object is visible\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n PARTIAL: 0,\r\n\r\n /**\r\n * Represents that an object is visible in its entirety.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n FULL: 1,\r\n};\r\nexport default Object.freeze(Visibility);\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Visibility from \"./Visibility.js\";\r\n\r\n/**\r\n * Creates an Occluder derived from an object's position and radius, as well as the camera position.\r\n * The occluder can be used to determine whether or not other objects are visible or hidden behind the\r\n * visible horizon defined by the occluder and camera position.\r\n *\r\n * @alias Occluder\r\n *\r\n * @param {BoundingSphere} occluderBoundingSphere The bounding sphere surrounding the occluder.\r\n * @param {Cartesian3} cameraPosition The coordinate of the viewer/camera.\r\n *\r\n * @constructor\r\n *\r\n * @example\r\n * // Construct an occluder one unit away from the origin with a radius of one.\r\n * var cameraPosition = Cesium.Cartesian3.ZERO;\r\n * var occluderBoundingSphere = new Cesium.BoundingSphere(new Cesium.Cartesian3(0, 0, -1), 1);\r\n * var occluder = new Cesium.Occluder(occluderBoundingSphere, cameraPosition);\r\n */\r\nfunction Occluder(occluderBoundingSphere, cameraPosition) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(occluderBoundingSphere)) {\r\n throw new DeveloperError(\"occluderBoundingSphere is required.\");\r\n }\r\n if (!defined(cameraPosition)) {\r\n throw new DeveloperError(\"camera position is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._occluderPosition = Cartesian3.clone(occluderBoundingSphere.center);\r\n this._occluderRadius = occluderBoundingSphere.radius;\r\n\r\n this._horizonDistance = 0.0;\r\n this._horizonPlaneNormal = undefined;\r\n this._horizonPlanePosition = undefined;\r\n this._cameraPosition = undefined;\r\n\r\n // cameraPosition fills in the above values\r\n this.cameraPosition = cameraPosition;\r\n}\r\n\r\nvar scratchCartesian3 = new Cartesian3();\r\n\r\nObject.defineProperties(Occluder.prototype, {\r\n /**\r\n * The position of the occluder.\r\n * @memberof Occluder.prototype\r\n * @type {Cartesian3}\r\n */\r\n position: {\r\n get: function () {\r\n return this._occluderPosition;\r\n },\r\n },\r\n\r\n /**\r\n * The radius of the occluder.\r\n * @memberof Occluder.prototype\r\n * @type {Number}\r\n */\r\n radius: {\r\n get: function () {\r\n return this._occluderRadius;\r\n },\r\n },\r\n\r\n /**\r\n * The position of the camera.\r\n * @memberof Occluder.prototype\r\n * @type {Cartesian3}\r\n */\r\n cameraPosition: {\r\n set: function (cameraPosition) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(cameraPosition)) {\r\n throw new DeveloperError(\"cameraPosition is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n cameraPosition = Cartesian3.clone(cameraPosition, this._cameraPosition);\r\n\r\n var cameraToOccluderVec = Cartesian3.subtract(\r\n this._occluderPosition,\r\n cameraPosition,\r\n scratchCartesian3\r\n );\r\n var invCameraToOccluderDistance = Cartesian3.magnitudeSquared(\r\n cameraToOccluderVec\r\n );\r\n var occluderRadiusSqrd = this._occluderRadius * this._occluderRadius;\r\n\r\n var horizonDistance;\r\n var horizonPlaneNormal;\r\n var horizonPlanePosition;\r\n if (invCameraToOccluderDistance > occluderRadiusSqrd) {\r\n horizonDistance = Math.sqrt(\r\n invCameraToOccluderDistance - occluderRadiusSqrd\r\n );\r\n invCameraToOccluderDistance =\r\n 1.0 / Math.sqrt(invCameraToOccluderDistance);\r\n horizonPlaneNormal = Cartesian3.multiplyByScalar(\r\n cameraToOccluderVec,\r\n invCameraToOccluderDistance,\r\n scratchCartesian3\r\n );\r\n var nearPlaneDistance =\r\n horizonDistance * horizonDistance * invCameraToOccluderDistance;\r\n horizonPlanePosition = Cartesian3.add(\r\n cameraPosition,\r\n Cartesian3.multiplyByScalar(\r\n horizonPlaneNormal,\r\n nearPlaneDistance,\r\n scratchCartesian3\r\n ),\r\n scratchCartesian3\r\n );\r\n } else {\r\n horizonDistance = Number.MAX_VALUE;\r\n }\r\n\r\n this._horizonDistance = horizonDistance;\r\n this._horizonPlaneNormal = horizonPlaneNormal;\r\n this._horizonPlanePosition = horizonPlanePosition;\r\n this._cameraPosition = cameraPosition;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates an occluder from a bounding sphere and the camera position.\r\n *\r\n * @param {BoundingSphere} occluderBoundingSphere The bounding sphere surrounding the occluder.\r\n * @param {Cartesian3} cameraPosition The coordinate of the viewer/camera.\r\n * @param {Occluder} [result] The object onto which to store the result.\r\n * @returns {Occluder} The occluder derived from an object's position and radius, as well as the camera position.\r\n */\r\nOccluder.fromBoundingSphere = function (\r\n occluderBoundingSphere,\r\n cameraPosition,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(occluderBoundingSphere)) {\r\n throw new DeveloperError(\"occluderBoundingSphere is required.\");\r\n }\r\n\r\n if (!defined(cameraPosition)) {\r\n throw new DeveloperError(\"camera position is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Occluder(occluderBoundingSphere, cameraPosition);\r\n }\r\n\r\n Cartesian3.clone(occluderBoundingSphere.center, result._occluderPosition);\r\n result._occluderRadius = occluderBoundingSphere.radius;\r\n result.cameraPosition = cameraPosition;\r\n\r\n return result;\r\n};\r\n\r\nvar tempVecScratch = new Cartesian3();\r\n\r\n/**\r\n * Determines whether or not a point, the occludee, is hidden from view by the occluder.\r\n *\r\n * @param {Cartesian3} occludee The point surrounding the occludee object.\r\n * @returns {Boolean} true if the occludee is visible; otherwise false.\r\n *\r\n *\r\n * @example\r\n * var cameraPosition = new Cesium.Cartesian3(0, 0, 0);\r\n * var littleSphere = new Cesium.BoundingSphere(new Cesium.Cartesian3(0, 0, -1), 0.25);\r\n * var occluder = new Cesium.Occluder(littleSphere, cameraPosition);\r\n * var point = new Cesium.Cartesian3(0, 0, -3);\r\n * occluder.isPointVisible(point); //returns true\r\n *\r\n * @see Occluder#computeVisibility\r\n */\r\nOccluder.prototype.isPointVisible = function (occludee) {\r\n if (this._horizonDistance !== Number.MAX_VALUE) {\r\n var tempVec = Cartesian3.subtract(\r\n occludee,\r\n this._occluderPosition,\r\n tempVecScratch\r\n );\r\n var temp = this._occluderRadius;\r\n temp = Cartesian3.magnitudeSquared(tempVec) - temp * temp;\r\n if (temp > 0.0) {\r\n temp = Math.sqrt(temp) + this._horizonDistance;\r\n tempVec = Cartesian3.subtract(occludee, this._cameraPosition, tempVec);\r\n return temp * temp > Cartesian3.magnitudeSquared(tempVec);\r\n }\r\n }\r\n return false;\r\n};\r\n\r\nvar occludeePositionScratch = new Cartesian3();\r\n\r\n/**\r\n * Determines whether or not a sphere, the occludee, is hidden from view by the occluder.\r\n *\r\n * @param {BoundingSphere} occludee The bounding sphere surrounding the occludee object.\r\n * @returns {Boolean} true if the occludee is visible; otherwise false.\r\n *\r\n *\r\n * @example\r\n * var cameraPosition = new Cesium.Cartesian3(0, 0, 0);\r\n * var littleSphere = new Cesium.BoundingSphere(new Cesium.Cartesian3(0, 0, -1), 0.25);\r\n * var occluder = new Cesium.Occluder(littleSphere, cameraPosition);\r\n * var bigSphere = new Cesium.BoundingSphere(new Cesium.Cartesian3(0, 0, -3), 1);\r\n * occluder.isBoundingSphereVisible(bigSphere); //returns true\r\n *\r\n * @see Occluder#computeVisibility\r\n */\r\nOccluder.prototype.isBoundingSphereVisible = function (occludee) {\r\n var occludeePosition = Cartesian3.clone(\r\n occludee.center,\r\n occludeePositionScratch\r\n );\r\n var occludeeRadius = occludee.radius;\r\n\r\n if (this._horizonDistance !== Number.MAX_VALUE) {\r\n var tempVec = Cartesian3.subtract(\r\n occludeePosition,\r\n this._occluderPosition,\r\n tempVecScratch\r\n );\r\n var temp = this._occluderRadius - occludeeRadius;\r\n temp = Cartesian3.magnitudeSquared(tempVec) - temp * temp;\r\n if (occludeeRadius < this._occluderRadius) {\r\n if (temp > 0.0) {\r\n temp = Math.sqrt(temp) + this._horizonDistance;\r\n tempVec = Cartesian3.subtract(\r\n occludeePosition,\r\n this._cameraPosition,\r\n tempVec\r\n );\r\n return (\r\n temp * temp + occludeeRadius * occludeeRadius >\r\n Cartesian3.magnitudeSquared(tempVec)\r\n );\r\n }\r\n return false;\r\n }\r\n\r\n // Prevent against the case where the occludee radius is larger than the occluder's; since this is\r\n // an uncommon case, the following code should rarely execute.\r\n if (temp > 0.0) {\r\n tempVec = Cartesian3.subtract(\r\n occludeePosition,\r\n this._cameraPosition,\r\n tempVec\r\n );\r\n var tempVecMagnitudeSquared = Cartesian3.magnitudeSquared(tempVec);\r\n var occluderRadiusSquared = this._occluderRadius * this._occluderRadius;\r\n var occludeeRadiusSquared = occludeeRadius * occludeeRadius;\r\n if (\r\n (this._horizonDistance * this._horizonDistance +\r\n occluderRadiusSquared) *\r\n occludeeRadiusSquared >\r\n tempVecMagnitudeSquared * occluderRadiusSquared\r\n ) {\r\n // The occludee is close enough that the occluder cannot possible occlude the occludee\r\n return true;\r\n }\r\n temp = Math.sqrt(temp) + this._horizonDistance;\r\n return temp * temp + occludeeRadiusSquared > tempVecMagnitudeSquared;\r\n }\r\n\r\n // The occludee completely encompasses the occluder\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\nvar tempScratch = new Cartesian3();\r\n/**\r\n * Determine to what extent an occludee is visible (not visible, partially visible, or fully visible).\r\n *\r\n * @param {BoundingSphere} occludeeBS The bounding sphere of the occludee.\r\n * @returns {Visibility} Visibility.NONE if the occludee is not visible,\r\n * Visibility.PARTIAL if the occludee is partially visible, or\r\n * Visibility.FULL if the occludee is fully visible.\r\n *\r\n *\r\n * @example\r\n * var sphere1 = new Cesium.BoundingSphere(new Cesium.Cartesian3(0, 0, -1.5), 0.5);\r\n * var sphere2 = new Cesium.BoundingSphere(new Cesium.Cartesian3(0, 0, -2.5), 0.5);\r\n * var cameraPosition = new Cesium.Cartesian3(0, 0, 0);\r\n * var occluder = new Cesium.Occluder(sphere1, cameraPosition);\r\n * occluder.computeVisibility(sphere2); //returns Visibility.NONE\r\n *\r\n * @see Occluder#isVisible\r\n */\r\nOccluder.prototype.computeVisibility = function (occludeeBS) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(occludeeBS)) {\r\n throw new DeveloperError(\"occludeeBS is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // If the occludee radius is larger than the occluders, this will return that\r\n // the entire ocludee is visible, even though that may not be the case, though this should\r\n // not occur too often.\r\n var occludeePosition = Cartesian3.clone(occludeeBS.center);\r\n var occludeeRadius = occludeeBS.radius;\r\n\r\n if (occludeeRadius > this._occluderRadius) {\r\n return Visibility.FULL;\r\n }\r\n\r\n if (this._horizonDistance !== Number.MAX_VALUE) {\r\n // The camera is outside the occluder\r\n var tempVec = Cartesian3.subtract(\r\n occludeePosition,\r\n this._occluderPosition,\r\n tempScratch\r\n );\r\n var temp = this._occluderRadius - occludeeRadius;\r\n var occluderToOccludeeDistSqrd = Cartesian3.magnitudeSquared(tempVec);\r\n temp = occluderToOccludeeDistSqrd - temp * temp;\r\n if (temp > 0.0) {\r\n // The occludee is not completely inside the occluder\r\n // Check to see if the occluder completely hides the occludee\r\n temp = Math.sqrt(temp) + this._horizonDistance;\r\n tempVec = Cartesian3.subtract(\r\n occludeePosition,\r\n this._cameraPosition,\r\n tempVec\r\n );\r\n var cameraToOccludeeDistSqrd = Cartesian3.magnitudeSquared(tempVec);\r\n if (\r\n temp * temp + occludeeRadius * occludeeRadius <\r\n cameraToOccludeeDistSqrd\r\n ) {\r\n return Visibility.NONE;\r\n }\r\n\r\n // Check to see whether the occluder is fully or partially visible\r\n // when the occludee does not intersect the occluder\r\n temp = this._occluderRadius + occludeeRadius;\r\n temp = occluderToOccludeeDistSqrd - temp * temp;\r\n if (temp > 0.0) {\r\n // The occludee does not intersect the occluder.\r\n temp = Math.sqrt(temp) + this._horizonDistance;\r\n return cameraToOccludeeDistSqrd <\r\n temp * temp + occludeeRadius * occludeeRadius\r\n ? Visibility.FULL\r\n : Visibility.PARTIAL;\r\n }\r\n\r\n //Check to see if the occluder is fully or partially visible when the occludee DOES\r\n //intersect the occluder\r\n tempVec = Cartesian3.subtract(\r\n occludeePosition,\r\n this._horizonPlanePosition,\r\n tempVec\r\n );\r\n return Cartesian3.dot(tempVec, this._horizonPlaneNormal) > -occludeeRadius\r\n ? Visibility.PARTIAL\r\n : Visibility.FULL;\r\n }\r\n }\r\n return Visibility.NONE;\r\n};\r\n\r\nvar occludeePointScratch = new Cartesian3();\r\n/**\r\n * Computes a point that can be used as the occludee position to the visibility functions.\r\n * Use a radius of zero for the occludee radius. Typically, a user computes a bounding sphere around\r\n * an object that is used for visibility; however it is also possible to compute a point that if\r\n * seen/not seen would also indicate if an object is visible/not visible. This function is better\r\n * called for objects that do not move relative to the occluder and is large, such as a chunk of\r\n * terrain. You are better off not calling this and using the object's bounding sphere for objects\r\n * such as a satellite or ground vehicle.\r\n *\r\n * @param {BoundingSphere} occluderBoundingSphere The bounding sphere surrounding the occluder.\r\n * @param {Cartesian3} occludeePosition The point where the occludee (bounding sphere of radius 0) is located.\r\n * @param {Cartesian3[]} positions List of altitude points on the horizon near the surface of the occluder.\r\n * @returns {Object} An object containing two attributes: occludeePoint and valid\r\n * which is a boolean value.\r\n *\r\n * @exception {DeveloperError} positions must contain at least one element.\r\n * @exception {DeveloperError} occludeePosition must have a value other than occluderBoundingSphere.center.\r\n *\r\n * @example\r\n * var cameraPosition = new Cesium.Cartesian3(0, 0, 0);\r\n * var occluderBoundingSphere = new Cesium.BoundingSphere(new Cesium.Cartesian3(0, 0, -8), 2);\r\n * var occluder = new Cesium.Occluder(occluderBoundingSphere, cameraPosition);\r\n * var positions = [new Cesium.Cartesian3(-0.25, 0, -5.3), new Cesium.Cartesian3(0.25, 0, -5.3)];\r\n * var tileOccluderSphere = Cesium.BoundingSphere.fromPoints(positions);\r\n * var occludeePosition = tileOccluderSphere.center;\r\n * var occludeePt = Cesium.Occluder.computeOccludeePoint(occluderBoundingSphere, occludeePosition, positions);\r\n */\r\nOccluder.computeOccludeePoint = function (\r\n occluderBoundingSphere,\r\n occludeePosition,\r\n positions\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(occluderBoundingSphere)) {\r\n throw new DeveloperError(\"occluderBoundingSphere is required.\");\r\n }\r\n if (!defined(positions)) {\r\n throw new DeveloperError(\"positions is required.\");\r\n }\r\n if (positions.length === 0) {\r\n throw new DeveloperError(\"positions must contain at least one element\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var occludeePos = Cartesian3.clone(occludeePosition);\r\n var occluderPosition = Cartesian3.clone(occluderBoundingSphere.center);\r\n var occluderRadius = occluderBoundingSphere.radius;\r\n var numPositions = positions.length;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (Cartesian3.equals(occluderPosition, occludeePosition)) {\r\n throw new DeveloperError(\r\n \"occludeePosition must be different than occluderBoundingSphere.center\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Compute a plane with a normal from the occluder to the occludee position.\r\n var occluderPlaneNormal = Cartesian3.normalize(\r\n Cartesian3.subtract(occludeePos, occluderPosition, occludeePointScratch),\r\n occludeePointScratch\r\n );\r\n var occluderPlaneD = -Cartesian3.dot(occluderPlaneNormal, occluderPosition);\r\n\r\n //For each position, determine the horizon intersection. Choose the position and intersection\r\n //that results in the greatest angle with the occcluder plane.\r\n var aRotationVector = Occluder._anyRotationVector(\r\n occluderPosition,\r\n occluderPlaneNormal,\r\n occluderPlaneD\r\n );\r\n var dot = Occluder._horizonToPlaneNormalDotProduct(\r\n occluderBoundingSphere,\r\n occluderPlaneNormal,\r\n occluderPlaneD,\r\n aRotationVector,\r\n positions[0]\r\n );\r\n if (!dot) {\r\n //The position is inside the mimimum radius, which is invalid\r\n return undefined;\r\n }\r\n var tempDot;\r\n for (var i = 1; i < numPositions; ++i) {\r\n tempDot = Occluder._horizonToPlaneNormalDotProduct(\r\n occluderBoundingSphere,\r\n occluderPlaneNormal,\r\n occluderPlaneD,\r\n aRotationVector,\r\n positions[i]\r\n );\r\n if (!tempDot) {\r\n //The position is inside the minimum radius, which is invalid\r\n return undefined;\r\n }\r\n if (tempDot < dot) {\r\n dot = tempDot;\r\n }\r\n }\r\n //Verify that the dot is not near 90 degress\r\n if (dot < 0.00174532836589830883577820272085) {\r\n return undefined;\r\n }\r\n\r\n var distance = occluderRadius / dot;\r\n return Cartesian3.add(\r\n occluderPosition,\r\n Cartesian3.multiplyByScalar(\r\n occluderPlaneNormal,\r\n distance,\r\n occludeePointScratch\r\n ),\r\n occludeePointScratch\r\n );\r\n};\r\n\r\nvar computeOccludeePointFromRectangleScratch = [];\r\n/**\r\n * Computes a point that can be used as the occludee position to the visibility functions from a rectangle.\r\n *\r\n * @param {Rectangle} rectangle The rectangle used to create a bounding sphere.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid used to determine positions of the rectangle.\r\n * @returns {Object} An object containing two attributes: occludeePoint and valid\r\n * which is a boolean value.\r\n */\r\nOccluder.computeOccludeePointFromRectangle = function (rectangle, ellipsoid) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(rectangle)) {\r\n throw new DeveloperError(\"rectangle is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n var positions = Rectangle.subsample(\r\n rectangle,\r\n ellipsoid,\r\n 0.0,\r\n computeOccludeePointFromRectangleScratch\r\n );\r\n var bs = BoundingSphere.fromPoints(positions);\r\n\r\n // TODO: get correct ellipsoid center\r\n var ellipsoidCenter = Cartesian3.ZERO;\r\n if (!Cartesian3.equals(ellipsoidCenter, bs.center)) {\r\n return Occluder.computeOccludeePoint(\r\n new BoundingSphere(ellipsoidCenter, ellipsoid.minimumRadius),\r\n bs.center,\r\n positions\r\n );\r\n }\r\n\r\n return undefined;\r\n};\r\n\r\nvar tempVec0Scratch = new Cartesian3();\r\nOccluder._anyRotationVector = function (\r\n occluderPosition,\r\n occluderPlaneNormal,\r\n occluderPlaneD\r\n) {\r\n var tempVec0 = Cartesian3.abs(occluderPlaneNormal, tempVec0Scratch);\r\n var majorAxis = tempVec0.x > tempVec0.y ? 0 : 1;\r\n if (\r\n (majorAxis === 0 && tempVec0.z > tempVec0.x) ||\r\n (majorAxis === 1 && tempVec0.z > tempVec0.y)\r\n ) {\r\n majorAxis = 2;\r\n }\r\n var tempVec = new Cartesian3();\r\n var tempVec1;\r\n if (majorAxis === 0) {\r\n tempVec0.x = occluderPosition.x;\r\n tempVec0.y = occluderPosition.y + 1.0;\r\n tempVec0.z = occluderPosition.z + 1.0;\r\n tempVec1 = Cartesian3.UNIT_X;\r\n } else if (majorAxis === 1) {\r\n tempVec0.x = occluderPosition.x + 1.0;\r\n tempVec0.y = occluderPosition.y;\r\n tempVec0.z = occluderPosition.z + 1.0;\r\n tempVec1 = Cartesian3.UNIT_Y;\r\n } else {\r\n tempVec0.x = occluderPosition.x + 1.0;\r\n tempVec0.y = occluderPosition.y + 1.0;\r\n tempVec0.z = occluderPosition.z;\r\n tempVec1 = Cartesian3.UNIT_Z;\r\n }\r\n var u =\r\n (Cartesian3.dot(occluderPlaneNormal, tempVec0) + occluderPlaneD) /\r\n -Cartesian3.dot(occluderPlaneNormal, tempVec1);\r\n return Cartesian3.normalize(\r\n Cartesian3.subtract(\r\n Cartesian3.add(\r\n tempVec0,\r\n Cartesian3.multiplyByScalar(tempVec1, u, tempVec),\r\n tempVec0\r\n ),\r\n occluderPosition,\r\n tempVec0\r\n ),\r\n tempVec0\r\n );\r\n};\r\n\r\nvar posDirectionScratch = new Cartesian3();\r\nOccluder._rotationVector = function (\r\n occluderPosition,\r\n occluderPlaneNormal,\r\n occluderPlaneD,\r\n position,\r\n anyRotationVector\r\n) {\r\n //Determine the angle between the occluder plane normal and the position direction\r\n var positionDirection = Cartesian3.subtract(\r\n position,\r\n occluderPosition,\r\n posDirectionScratch\r\n );\r\n positionDirection = Cartesian3.normalize(\r\n positionDirection,\r\n positionDirection\r\n );\r\n if (\r\n Cartesian3.dot(occluderPlaneNormal, positionDirection) <\r\n 0.99999998476912904932780850903444\r\n ) {\r\n var crossProduct = Cartesian3.cross(\r\n occluderPlaneNormal,\r\n positionDirection,\r\n positionDirection\r\n );\r\n var length = Cartesian3.magnitude(crossProduct);\r\n if (length > CesiumMath.EPSILON13) {\r\n return Cartesian3.normalize(crossProduct, new Cartesian3());\r\n }\r\n }\r\n //The occluder plane normal and the position direction are colinear. Use any\r\n //vector in the occluder plane as the rotation vector\r\n return anyRotationVector;\r\n};\r\n\r\nvar posScratch1 = new Cartesian3();\r\nvar occluerPosScratch = new Cartesian3();\r\nvar posScratch2 = new Cartesian3();\r\nvar horizonPlanePosScratch = new Cartesian3();\r\nOccluder._horizonToPlaneNormalDotProduct = function (\r\n occluderBS,\r\n occluderPlaneNormal,\r\n occluderPlaneD,\r\n anyRotationVector,\r\n position\r\n) {\r\n var pos = Cartesian3.clone(position, posScratch1);\r\n var occluderPosition = Cartesian3.clone(occluderBS.center, occluerPosScratch);\r\n var occluderRadius = occluderBS.radius;\r\n\r\n //Verify that the position is outside the occluder\r\n var positionToOccluder = Cartesian3.subtract(\r\n occluderPosition,\r\n pos,\r\n posScratch2\r\n );\r\n var occluderToPositionDistanceSquared = Cartesian3.magnitudeSquared(\r\n positionToOccluder\r\n );\r\n var occluderRadiusSquared = occluderRadius * occluderRadius;\r\n if (occluderToPositionDistanceSquared < occluderRadiusSquared) {\r\n return false;\r\n }\r\n\r\n //Horizon parameters\r\n var horizonDistanceSquared =\r\n occluderToPositionDistanceSquared - occluderRadiusSquared;\r\n var horizonDistance = Math.sqrt(horizonDistanceSquared);\r\n var occluderToPositionDistance = Math.sqrt(occluderToPositionDistanceSquared);\r\n var invOccluderToPositionDistance = 1.0 / occluderToPositionDistance;\r\n var cosTheta = horizonDistance * invOccluderToPositionDistance;\r\n var horizonPlaneDistance = cosTheta * horizonDistance;\r\n positionToOccluder = Cartesian3.normalize(\r\n positionToOccluder,\r\n positionToOccluder\r\n );\r\n var horizonPlanePosition = Cartesian3.add(\r\n pos,\r\n Cartesian3.multiplyByScalar(\r\n positionToOccluder,\r\n horizonPlaneDistance,\r\n horizonPlanePosScratch\r\n ),\r\n horizonPlanePosScratch\r\n );\r\n var horizonCrossDistance = Math.sqrt(\r\n horizonDistanceSquared - horizonPlaneDistance * horizonPlaneDistance\r\n );\r\n\r\n //Rotate the position to occluder vector 90 degrees\r\n var tempVec = this._rotationVector(\r\n occluderPosition,\r\n occluderPlaneNormal,\r\n occluderPlaneD,\r\n pos,\r\n anyRotationVector\r\n );\r\n var horizonCrossDirection = Cartesian3.fromElements(\r\n tempVec.x * tempVec.x * positionToOccluder.x +\r\n (tempVec.x * tempVec.y - tempVec.z) * positionToOccluder.y +\r\n (tempVec.x * tempVec.z + tempVec.y) * positionToOccluder.z,\r\n (tempVec.x * tempVec.y + tempVec.z) * positionToOccluder.x +\r\n tempVec.y * tempVec.y * positionToOccluder.y +\r\n (tempVec.y * tempVec.z - tempVec.x) * positionToOccluder.z,\r\n (tempVec.x * tempVec.z - tempVec.y) * positionToOccluder.x +\r\n (tempVec.y * tempVec.z + tempVec.x) * positionToOccluder.y +\r\n tempVec.z * tempVec.z * positionToOccluder.z,\r\n posScratch1\r\n );\r\n horizonCrossDirection = Cartesian3.normalize(\r\n horizonCrossDirection,\r\n horizonCrossDirection\r\n );\r\n\r\n //Horizon positions\r\n var offset = Cartesian3.multiplyByScalar(\r\n horizonCrossDirection,\r\n horizonCrossDistance,\r\n posScratch1\r\n );\r\n tempVec = Cartesian3.normalize(\r\n Cartesian3.subtract(\r\n Cartesian3.add(horizonPlanePosition, offset, posScratch2),\r\n occluderPosition,\r\n posScratch2\r\n ),\r\n posScratch2\r\n );\r\n var dot0 = Cartesian3.dot(occluderPlaneNormal, tempVec);\r\n tempVec = Cartesian3.normalize(\r\n Cartesian3.subtract(\r\n Cartesian3.subtract(horizonPlanePosition, offset, tempVec),\r\n occluderPosition,\r\n tempVec\r\n ),\r\n tempVec\r\n );\r\n var dot1 = Cartesian3.dot(occluderPlaneNormal, tempVec);\r\n return dot0 < dot1 ? dot0 : dot1;\r\n};\r\nexport default Occluder;\r\n","import Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * Value and type information for per-instance geometry attribute that determines the geometry instance offset\r\n *\r\n * @alias OffsetGeometryInstanceAttribute\r\n * @constructor\r\n *\r\n * @param {Number} [x=0] The x translation\r\n * @param {Number} [y=0] The y translation\r\n * @param {Number} [z=0] The z translation\r\n *\r\n * @private\r\n *\r\n * @see GeometryInstance\r\n * @see GeometryInstanceAttribute\r\n */\r\nfunction OffsetGeometryInstanceAttribute(x, y, z) {\r\n x = defaultValue(x, 0);\r\n y = defaultValue(y, 0);\r\n z = defaultValue(z, 0);\r\n\r\n /**\r\n * The values for the attributes stored in a typed array.\r\n *\r\n * @type Float32Array\r\n */\r\n this.value = new Float32Array([x, y, z]);\r\n}\r\n\r\nObject.defineProperties(OffsetGeometryInstanceAttribute.prototype, {\r\n /**\r\n * The datatype of each component in the attribute, e.g., individual elements in\r\n * {@link OffsetGeometryInstanceAttribute#value}.\r\n *\r\n * @memberof OffsetGeometryInstanceAttribute.prototype\r\n *\r\n * @type {ComponentDatatype}\r\n * @readonly\r\n *\r\n * @default {@link ComponentDatatype.FLOAT}\r\n */\r\n componentDatatype: {\r\n get: function () {\r\n return ComponentDatatype.FLOAT;\r\n },\r\n },\r\n\r\n /**\r\n * The number of components in the attributes, i.e., {@link OffsetGeometryInstanceAttribute#value}.\r\n *\r\n * @memberof OffsetGeometryInstanceAttribute.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n *\r\n * @default 3\r\n */\r\n componentsPerAttribute: {\r\n get: function () {\r\n return 3;\r\n },\r\n },\r\n\r\n /**\r\n * When true and componentDatatype is an integer format,\r\n * indicate that the components should be mapped to the range [0, 1] (unsigned)\r\n * or [-1, 1] (signed) when they are accessed as floating-point for rendering.\r\n *\r\n * @memberof OffsetGeometryInstanceAttribute.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n normalize: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates a new {@link OffsetGeometryInstanceAttribute} instance given the provided an enabled flag and {@link DistanceDisplayCondition}.\r\n *\r\n * @param {Cartesian3} offset The cartesian offset\r\n * @returns {OffsetGeometryInstanceAttribute} The new {@link OffsetGeometryInstanceAttribute} instance.\r\n */\r\nOffsetGeometryInstanceAttribute.fromCartesian3 = function (offset) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"offset\", offset);\r\n //>>includeEnd('debug');\r\n\r\n return new OffsetGeometryInstanceAttribute(offset.x, offset.y, offset.z);\r\n};\r\n\r\n/**\r\n * Converts a distance display condition to a typed array that can be used to assign a distance display condition attribute.\r\n *\r\n * @param {Cartesian3} offset The cartesian offset\r\n * @param {Float32Array} [result] The array to store the result in, if undefined a new instance will be created.\r\n * @returns {Float32Array} The modified result parameter or a new instance if result was undefined.\r\n *\r\n * @example\r\n * var attributes = primitive.getGeometryInstanceAttributes('an id');\r\n * attributes.modelMatrix = Cesium.OffsetGeometryInstanceAttribute.toValue(modelMatrix, attributes.modelMatrix);\r\n */\r\nOffsetGeometryInstanceAttribute.toValue = function (offset, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"offset\", offset);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Float32Array([offset.x, offset.y, offset.z]);\r\n }\r\n\r\n result[0] = offset.x;\r\n result[1] = offset.y;\r\n result[2] = offset.z;\r\n return result;\r\n};\r\nexport default OffsetGeometryInstanceAttribute;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport combine from \"./combine.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Resource from \"./Resource.js\";\r\n\r\n/**\r\n * Provides geocoding via a {@link https://opencagedata.com/|OpenCage} server.\r\n * @alias OpenCageGeocoderService\r\n * @constructor\r\n *\r\n * @param {Resource|String} url The endpoint to the OpenCage server.\r\n * @param {String} apiKey The OpenCage API Key.\r\n * @param {Object} [params] An object with the following properties (See https://opencagedata.com/api#forward-opt):\r\n * @param {Number} [params.abbrv] When set to 1 we attempt to abbreviate and shorten the formatted string we return.\r\n * @param {Number} [options.add_request] When set to 1 the various request parameters are added to the response for ease of debugging.\r\n * @param {String} [options.bounds] Provides the geocoder with a hint to the region that the query resides in.\r\n * @param {String} [options.countrycode] Restricts the results to the specified country or countries (as defined by the ISO 3166-1 Alpha 2 standard).\r\n * @param {String} [options.jsonp] Wraps the returned JSON with a function name.\r\n * @param {String} [options.language] An IETF format language code.\r\n * @param {Number} [options.limit] The maximum number of results we should return.\r\n * @param {Number} [options.min_confidence] An integer from 1-10. Only results with at least this confidence will be returned.\r\n * @param {Number} [options.no_annotations] When set to 1 results will not contain annotations.\r\n * @param {Number} [options.no_dedupe] When set to 1 results will not be deduplicated.\r\n * @param {Number} [options.no_record] When set to 1 the query contents are not logged.\r\n * @param {Number} [options.pretty] When set to 1 results are 'pretty' printed for easier reading. Useful for debugging.\r\n * @param {String} [options.proximity] Provides the geocoder with a hint to bias results in favour of those closer to the specified location (For example: 41.40139,2.12870).\r\n *\r\n * @example\r\n * // Configure a Viewer to use the OpenCage Geocoder\r\n * var viewer = new Cesium.Viewer('cesiumContainer', {\r\n * geocoder: new Cesium.OpenCageGeocoderService('https://api.opencagedata.com/geocode/v1/', '')\r\n * });\r\n */\r\nfunction OpenCageGeocoderService(url, apiKey, params) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"url\", url);\r\n Check.defined(\"apiKey\", apiKey);\r\n if (defined(params)) {\r\n Check.typeOf.object(\"params\", params);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n url = Resource.createIfNeeded(url);\r\n url.appendForwardSlash();\r\n url.setQueryParameters({ key: apiKey });\r\n this._url = url;\r\n this._params = defaultValue(params, {});\r\n}\r\n\r\nObject.defineProperties(OpenCageGeocoderService.prototype, {\r\n /**\r\n * The Resource used to access the OpenCage endpoint.\r\n * @type {Resource}\r\n * @memberof OpenCageGeocoderService.prototype\r\n * @readonly\r\n */\r\n url: {\r\n get: function () {\r\n return this._url;\r\n },\r\n },\r\n /**\r\n * Optional params passed to OpenCage in order to customize geocoding\r\n * @type {Object}\r\n * @memberof OpenCageGeocoderService.prototype\r\n * @readonly\r\n */\r\n params: {\r\n get: function () {\r\n return this._params;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @function\r\n *\r\n * @param {String} query The query to be sent to the geocoder service\r\n * @returns {Promise}\r\n */\r\nOpenCageGeocoderService.prototype.geocode = function (query) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"query\", query);\r\n //>>includeEnd('debug');\r\n\r\n var resource = this._url.getDerivedResource({\r\n url: \"json\",\r\n queryParameters: combine(this._params, { q: query }),\r\n });\r\n return resource.fetchJson().then(function (response) {\r\n return response.results.map(function (resultObject) {\r\n var destination;\r\n var bounds = resultObject.bounds;\r\n\r\n if (defined(bounds)) {\r\n destination = Rectangle.fromDegrees(\r\n bounds.southwest.lng,\r\n bounds.southwest.lat,\r\n bounds.northeast.lng,\r\n bounds.northeast.lat\r\n );\r\n } else {\r\n var lon = resultObject.geometry.lat;\r\n var lat = resultObject.geometry.lng;\r\n destination = Cartesian3.fromDegrees(lon, lat);\r\n }\r\n\r\n return {\r\n displayName: resultObject.formatted,\r\n destination: destination,\r\n };\r\n });\r\n });\r\n};\r\nexport default OpenCageGeocoderService;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Static interface for types which can store their values as packed\r\n * elements in an array. These methods and properties are expected to be\r\n * defined on a constructor function.\r\n *\r\n * @interface Packable\r\n *\r\n * @see PackableForInterpolation\r\n */\r\nvar Packable = {\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n packedLength: undefined,\r\n\r\n /**\r\n * Stores the provided instance into the provided array.\r\n * @function\r\n *\r\n * @param {*} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n */\r\n pack: DeveloperError.throwInstantiationError,\r\n\r\n /**\r\n * Retrieves an instance from a packed array.\r\n * @function\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Object} [result] The object into which to store the result.\r\n * @returns {Object} The modified result parameter or a new Object instance if one was not provided.\r\n */\r\n unpack: DeveloperError.throwInstantiationError,\r\n};\r\nexport default Packable;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Static interface for {@link Packable} types which are interpolated in a\r\n * different representation than their packed value. These methods and\r\n * properties are expected to be defined on a constructor function.\r\n *\r\n * @namespace PackableForInterpolation\r\n *\r\n * @see Packable\r\n */\r\nvar PackableForInterpolation = {\r\n /**\r\n * The number of elements used to store the object into an array in its interpolatable form.\r\n * @type {Number}\r\n */\r\n packedInterpolationLength: undefined,\r\n\r\n /**\r\n * Converts a packed array into a form suitable for interpolation.\r\n * @function\r\n *\r\n * @param {Number[]} packedArray The packed array.\r\n * @param {Number} [startingIndex=0] The index of the first element to be converted.\r\n * @param {Number} [lastIndex=packedArray.length] The index of the last element to be converted.\r\n * @param {Number[]} [result] The object into which to store the result.\r\n */\r\n convertPackedArrayForInterpolation: DeveloperError.throwInstantiationError,\r\n\r\n /**\r\n * Retrieves an instance from a packed array converted with {@link PackableForInterpolation.convertPackedArrayForInterpolation}.\r\n * @function\r\n *\r\n * @param {Number[]} array The array previously packed for interpolation.\r\n * @param {Number[]} sourceArray The original packed array.\r\n * @param {Number} [startingIndex=0] The startingIndex used to convert the array.\r\n * @param {Number} [lastIndex=packedArray.length] The lastIndex used to convert the array.\r\n * @param {Object} [result] The object into which to store the result.\r\n * @returns {Object} The modified result parameter or a new Object instance if one was not provided.\r\n */\r\n unpackInterpolationResult: DeveloperError.throwInstantiationError,\r\n};\r\nexport default PackableForInterpolation;\r\n","/*\r\n This library rewrites the Canvas2D \"measureText\" function\r\n so that it returns a more complete metrics object.\r\n\r\n** -----------------------------------------------------------------------------\r\n\r\n CHANGELOG:\r\n\r\n 2012-01-21 - Whitespace handling added by Joe Turner\r\n (https://github.com/oampo)\r\n\r\n** -----------------------------------------------------------------------------\r\n*/\r\n/**\r\n @license\r\n fontmetrics.js - https://github.com/Pomax/fontmetrics.js\r\n\r\n Copyright (C) 2011 by Mike \"Pomax\" Kamermans\r\n\r\n Permission is hereby granted, free of charge, to any person obtaining a copy\r\n of this software and associated documentation files (the \"Software\"), to deal\r\n in the Software without restriction, including without limitation the rights\r\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\n copies of the Software, and to permit persons to whom the Software is\r\n furnished to do so, subject to the following conditions:\r\n\r\n The above copyright notice and this permission notice shall be included in\r\n all copies or substantial portions of the Software.\r\n\r\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r\n THE SOFTWARE.\r\n**/\r\n\r\n/*\r\n var NAME = \"FontMetrics Library\"\r\n var VERSION = \"1-2012.0121.1300\";\r\n\r\n // if there is no getComputedStyle, this library won't work.\r\n if(!document.defaultView.getComputedStyle) {\r\n throw(\"ERROR: 'document.defaultView.getComputedStyle' not found. This library only works in browsers that can report computed CSS values.\");\r\n }\r\n\r\n // store the old text metrics function on the Canvas2D prototype\r\n CanvasRenderingContext2D.prototype.measureTextWidth = CanvasRenderingContext2D.prototype.measureText;\r\n*/\r\n /**\r\n * shortcut function for getting computed CSS values\r\n */\r\n var getCSSValue = function(element, property) {\r\n return document.defaultView.getComputedStyle(element,null).getPropertyValue(property);\r\n };\r\n/*\r\n // debug function\r\n var show = function(canvas, ctx, xstart, w, h, metrics)\r\n {\r\n document.body.appendChild(canvas);\r\n ctx.strokeStyle = 'rgba(0, 0, 0, 0.5)';\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(xstart,0);\r\n ctx.lineTo(xstart,h);\r\n ctx.closePath();\r\n ctx.stroke();\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(xstart+metrics.bounds.maxx,0);\r\n ctx.lineTo(xstart+metrics.bounds.maxx,h);\r\n ctx.closePath();\r\n ctx.stroke();\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(0,h/2-metrics.ascent);\r\n ctx.lineTo(w,h/2-metrics.ascent);\r\n ctx.closePath();\r\n ctx.stroke();\r\n\r\n ctx.beginPath();\r\n ctx.moveTo(0,h/2+metrics.descent);\r\n ctx.lineTo(w,h/2+metrics.descent);\r\n ctx.closePath();\r\n ctx.stroke();\r\n }\r\n*/\r\n /**\r\n * The new text metrics function\r\n */\r\n var measureText = function(context2D, textstring, stroke, fill) {\r\n var metrics = context2D.measureText(textstring),\r\n fontFamily = getCSSValue(context2D.canvas,\"font-family\"),\r\n fontSize = getCSSValue(context2D.canvas,\"font-size\").replace(\"px\",\"\"),\r\n fontStyle = getCSSValue(context2D.canvas,\"font-style\"),\r\n fontWeight = getCSSValue(context2D.canvas,\"font-weight\"),\r\n isSpace = !(/\\S/.test(textstring));\r\n metrics.fontsize = fontSize;\r\n\r\n // for text lead values, we meaure a multiline text container.\r\n var leadDiv = document.createElement(\"div\");\r\n leadDiv.style.position = \"absolute\";\r\n leadDiv.style.opacity = 0;\r\n leadDiv.style.font = fontStyle + \" \" + fontWeight + \" \" + fontSize + \"px \" + fontFamily;\r\n leadDiv.innerHTML = textstring + \"
\" + textstring;\r\n document.body.appendChild(leadDiv);\r\n\r\n // make some initial guess at the text leading (using the standard TeX ratio)\r\n metrics.leading = 1.2 * fontSize;\r\n\r\n // then we try to get the real value from the browser\r\n var leadDivHeight = getCSSValue(leadDiv,\"height\");\r\n leadDivHeight = leadDivHeight.replace(\"px\",\"\");\r\n if (leadDivHeight >= fontSize * 2) { metrics.leading = (leadDivHeight/2) | 0; }\r\n document.body.removeChild(leadDiv);\r\n\r\n // if we're not dealing with white space, we can compute metrics\r\n if (!isSpace) {\r\n // Have characters, so measure the text\r\n var canvas = document.createElement(\"canvas\");\r\n var padding = 100;\r\n canvas.width = metrics.width + padding;\r\n canvas.height = 3*fontSize;\r\n canvas.style.opacity = 1;\r\n canvas.style.fontFamily = fontFamily;\r\n canvas.style.fontSize = fontSize;\r\n canvas.style.fontStyle = fontStyle;\r\n canvas.style.fontWeight = fontWeight;\r\n var ctx = canvas.getContext(\"2d\");\r\n ctx.font = fontStyle + \" \" + fontWeight + \" \" + fontSize + \"px \" + fontFamily;\r\n\r\n var w = canvas.width,\r\n h = canvas.height,\r\n baseline = h/2;\r\n\r\n // Set all canvas pixeldata values to 255, with all the content\r\n // data being 0. This lets us scan for data[i] != 255.\r\n ctx.fillStyle = \"white\";\r\n ctx.fillRect(-1, -1, w + 2, h + 2);\r\n\r\n if (stroke) {\r\n ctx.strokeStyle = \"black\";\r\n ctx.lineWidth = context2D.lineWidth;\r\n ctx.strokeText(textstring, (padding / 2), baseline);\r\n }\r\n\r\n if (fill) {\r\n ctx.fillStyle = \"black\";\r\n ctx.fillText(textstring, padding / 2, baseline);\r\n }\r\n\r\n var pixelData = ctx.getImageData(0, 0, w, h).data;\r\n\r\n // canvas pixel data is w*4 by h*4, because R, G, B and A are separate,\r\n // consecutive values in the array, rather than stored as 32 bit ints.\r\n var i = 0,\r\n w4 = w * 4,\r\n len = pixelData.length;\r\n\r\n // Finding the ascent uses a normal, forward scanline\r\n while (++i < len && pixelData[i] === 255) {}\r\n var ascent = (i/w4)|0;\r\n\r\n // Finding the descent uses a reverse scanline\r\n i = len - 1;\r\n while (--i > 0 && pixelData[i] === 255) {}\r\n var descent = (i/w4)|0;\r\n\r\n // find the min-x coordinate\r\n for(i = 0; i=len) { i = (i-len) + 4; }}\r\n var minx = ((i%w4)/4) | 0;\r\n\r\n // find the max-x coordinate\r\n var step = 1;\r\n for(i = len-3; i>=0 && pixelData[i] === 255; ) {\r\n i -= w4;\r\n if(i<0) { i = (len - 3) - (step++)*4; }}\r\n var maxx = ((i%w4)/4) + 1 | 0;\r\n\r\n // set font metrics\r\n metrics.ascent = (baseline - ascent);\r\n metrics.descent = (descent - baseline);\r\n metrics.bounds = { minx: minx - (padding/2),\r\n maxx: maxx - (padding/2),\r\n miny: 0,\r\n maxy: descent-ascent };\r\n metrics.height = 1+(descent - ascent);\r\n }\r\n\r\n // if we ARE dealing with whitespace, most values will just be zero.\r\n else {\r\n // Only whitespace, so we can't measure the text\r\n metrics.ascent = 0;\r\n metrics.descent = 0;\r\n metrics.bounds = { minx: 0,\r\n maxx: metrics.width, // Best guess\r\n miny: 0,\r\n maxy: 0 };\r\n metrics.height = 0;\r\n }\r\n return metrics;\r\n };\r\n\r\nexport default measureText;\r\n","import measureText from \"../ThirdParty/measureText.js\";\r\nimport Color from \"./Color.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\nvar imageSmoothingEnabledName;\r\n\r\n/**\r\n * Writes the given text into a new canvas. The canvas will be sized to fit the text.\r\n * If text is blank, returns undefined.\r\n *\r\n * @param {String} text The text to write.\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {String} [options.font='10px sans-serif'] The CSS font to use.\r\n * @param {String} [options.textBaseline='bottom'] The baseline of the text.\r\n * @param {Boolean} [options.fill=true] Whether to fill the text.\r\n * @param {Boolean} [options.stroke=false] Whether to stroke the text.\r\n * @param {Color} [options.fillColor=Color.WHITE] The fill color.\r\n * @param {Color} [options.strokeColor=Color.BLACK] The stroke color.\r\n * @param {Number} [options.strokeWidth=1] The stroke width.\r\n * @param {Color} [options.backgroundColor=Color.TRANSPARENT] The background color of the canvas.\r\n * @param {Number} [options.padding=0] The pixel size of the padding to add around the text.\r\n * @returns {HTMLCanvasElement|undefined} A new canvas with the given text drawn into it. The dimensions object\r\n * from measureText will also be added to the returned canvas. If text is\r\n * blank, returns undefined.\r\n * @function writeTextToCanvas\r\n */\r\nfunction writeTextToCanvas(text, options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(text)) {\r\n throw new DeveloperError(\"text is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n if (text === \"\") {\r\n return undefined;\r\n }\r\n\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var font = defaultValue(options.font, \"10px sans-serif\");\r\n var stroke = defaultValue(options.stroke, false);\r\n var fill = defaultValue(options.fill, true);\r\n var strokeWidth = defaultValue(options.strokeWidth, 1);\r\n var backgroundColor = defaultValue(\r\n options.backgroundColor,\r\n Color.TRANSPARENT\r\n );\r\n var padding = defaultValue(options.padding, 0);\r\n var doublePadding = padding * 2.0;\r\n\r\n var canvas = document.createElement(\"canvas\");\r\n canvas.width = 1;\r\n canvas.height = 1;\r\n canvas.style.font = font;\r\n\r\n var context2D = canvas.getContext(\"2d\");\r\n\r\n if (!defined(imageSmoothingEnabledName)) {\r\n if (defined(context2D.imageSmoothingEnabled)) {\r\n imageSmoothingEnabledName = \"imageSmoothingEnabled\";\r\n } else if (defined(context2D.mozImageSmoothingEnabled)) {\r\n imageSmoothingEnabledName = \"mozImageSmoothingEnabled\";\r\n } else if (defined(context2D.webkitImageSmoothingEnabled)) {\r\n imageSmoothingEnabledName = \"webkitImageSmoothingEnabled\";\r\n } else if (defined(context2D.msImageSmoothingEnabled)) {\r\n imageSmoothingEnabledName = \"msImageSmoothingEnabled\";\r\n }\r\n }\r\n\r\n context2D.font = font;\r\n context2D.lineJoin = \"round\";\r\n context2D.lineWidth = strokeWidth;\r\n context2D[imageSmoothingEnabledName] = false;\r\n\r\n // textBaseline needs to be set before the measureText call. It won't work otherwise.\r\n // It's magic.\r\n context2D.textBaseline = defaultValue(options.textBaseline, \"bottom\");\r\n\r\n // in order for measureText to calculate style, the canvas has to be\r\n // (temporarily) added to the DOM.\r\n canvas.style.visibility = \"hidden\";\r\n document.body.appendChild(canvas);\r\n\r\n var dimensions = measureText(context2D, text, stroke, fill);\r\n canvas.dimensions = dimensions;\r\n\r\n document.body.removeChild(canvas);\r\n canvas.style.visibility = \"\";\r\n\r\n //Some characters, such as the letter j, have a non-zero starting position.\r\n //This value is used for kerning later, but we need to take it into account\r\n //now in order to draw the text completely on the canvas\r\n var x = -dimensions.bounds.minx;\r\n\r\n //Expand the width to include the starting position.\r\n var width = Math.ceil(dimensions.width) + x + doublePadding;\r\n\r\n //While the height of the letter is correct, we need to adjust\r\n //where we start drawing it so that letters like j and y properly dip\r\n //below the line.\r\n\r\n var height = dimensions.height + doublePadding;\r\n var baseline = height - dimensions.ascent + padding;\r\n var y = height - baseline + doublePadding;\r\n\r\n canvas.width = width;\r\n canvas.height = height;\r\n\r\n // Properties must be explicitly set again after changing width and height\r\n context2D.font = font;\r\n context2D.lineJoin = \"round\";\r\n context2D.lineWidth = strokeWidth;\r\n context2D[imageSmoothingEnabledName] = false;\r\n\r\n // Draw background\r\n if (backgroundColor !== Color.TRANSPARENT) {\r\n context2D.fillStyle = backgroundColor.toCssColorString();\r\n context2D.fillRect(0, 0, canvas.width, canvas.height);\r\n }\r\n\r\n if (stroke) {\r\n var strokeColor = defaultValue(options.strokeColor, Color.BLACK);\r\n context2D.strokeStyle = strokeColor.toCssColorString();\r\n context2D.strokeText(text, x + padding, y);\r\n }\r\n\r\n if (fill) {\r\n var fillColor = defaultValue(options.fillColor, Color.WHITE);\r\n context2D.fillStyle = fillColor.toCssColorString();\r\n context2D.fillText(text, x + padding, y);\r\n }\r\n\r\n return canvas;\r\n}\r\nexport default writeTextToCanvas;\r\n","import buildModuleUrl from \"./buildModuleUrl.js\";\r\nimport Color from \"./Color.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport writeTextToCanvas from \"./writeTextToCanvas.js\";\r\n\r\n/**\r\n * A utility class for generating custom map pins as canvas elements.\r\n *

\r\n *
\r\n *
\r\n * Example pins generated using both the maki icon set, which ships with Cesium, and single character text.\r\n *
\r\n *\r\n * @alias PinBuilder\r\n * @constructor\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Map%20Pins.html|Cesium Sandcastle PinBuilder Demo}\r\n */\r\nfunction PinBuilder() {\r\n this._cache = {};\r\n}\r\n\r\n/**\r\n * Creates an empty pin of the specified color and size.\r\n *\r\n * @param {Color} color The color of the pin.\r\n * @param {Number} size The size of the pin, in pixels.\r\n * @returns {HTMLCanvasElement} The canvas element that represents the generated pin.\r\n */\r\nPinBuilder.prototype.fromColor = function (color, size) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(color)) {\r\n throw new DeveloperError(\"color is required\");\r\n }\r\n if (!defined(size)) {\r\n throw new DeveloperError(\"size is required\");\r\n }\r\n //>>includeEnd('debug');\r\n return createPin(undefined, undefined, color, size, this._cache);\r\n};\r\n\r\n/**\r\n * Creates a pin with the specified icon, color, and size.\r\n *\r\n * @param {Resource|String} url The url of the image to be stamped onto the pin.\r\n * @param {Color} color The color of the pin.\r\n * @param {Number} size The size of the pin, in pixels.\r\n * @returns {HTMLCanvasElement|Promise.} The canvas element or a Promise to the canvas element that represents the generated pin.\r\n */\r\nPinBuilder.prototype.fromUrl = function (url, color, size) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(url)) {\r\n throw new DeveloperError(\"url is required\");\r\n }\r\n if (!defined(color)) {\r\n throw new DeveloperError(\"color is required\");\r\n }\r\n if (!defined(size)) {\r\n throw new DeveloperError(\"size is required\");\r\n }\r\n //>>includeEnd('debug');\r\n return createPin(url, undefined, color, size, this._cache);\r\n};\r\n\r\n/**\r\n * Creates a pin with the specified {@link https://www.mapbox.com/maki/|maki} icon identifier, color, and size.\r\n *\r\n * @param {String} id The id of the maki icon to be stamped onto the pin.\r\n * @param {Color} color The color of the pin.\r\n * @param {Number} size The size of the pin, in pixels.\r\n * @returns {HTMLCanvasElement|Promise.} The canvas element or a Promise to the canvas element that represents the generated pin.\r\n */\r\nPinBuilder.prototype.fromMakiIconId = function (id, color, size) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(id)) {\r\n throw new DeveloperError(\"id is required\");\r\n }\r\n if (!defined(color)) {\r\n throw new DeveloperError(\"color is required\");\r\n }\r\n if (!defined(size)) {\r\n throw new DeveloperError(\"size is required\");\r\n }\r\n //>>includeEnd('debug');\r\n return createPin(\r\n buildModuleUrl(\"Assets/Textures/maki/\" + encodeURIComponent(id) + \".png\"),\r\n undefined,\r\n color,\r\n size,\r\n this._cache\r\n );\r\n};\r\n\r\n/**\r\n * Creates a pin with the specified text, color, and size. The text will be sized to be as large as possible\r\n * while still being contained completely within the pin.\r\n *\r\n * @param {String} text The text to be stamped onto the pin.\r\n * @param {Color} color The color of the pin.\r\n * @param {Number} size The size of the pin, in pixels.\r\n * @returns {HTMLCanvasElement} The canvas element that represents the generated pin.\r\n */\r\nPinBuilder.prototype.fromText = function (text, color, size) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(text)) {\r\n throw new DeveloperError(\"text is required\");\r\n }\r\n if (!defined(color)) {\r\n throw new DeveloperError(\"color is required\");\r\n }\r\n if (!defined(size)) {\r\n throw new DeveloperError(\"size is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return createPin(undefined, text, color, size, this._cache);\r\n};\r\n\r\nvar colorScratch = new Color();\r\n\r\n//This function (except for the 3 commented lines) was auto-generated from an online tool,\r\n//http://www.professorcloud.com/svg-to-canvas/, using Assets/Textures/pin.svg as input.\r\n//The reason we simply can't load and draw the SVG directly to the canvas is because\r\n//it taints the canvas in Internet Explorer (and possibly some other browsers); making\r\n//it impossible to create a WebGL texture from the result.\r\nfunction drawPin(context2D, color, size) {\r\n context2D.save();\r\n context2D.scale(size / 24, size / 24); //Added to auto-generated code to scale up to desired size.\r\n context2D.fillStyle = color.toCssColorString(); //Modified from auto-generated code.\r\n context2D.strokeStyle = color.brighten(0.6, colorScratch).toCssColorString(); //Modified from auto-generated code.\r\n context2D.lineWidth = 0.846;\r\n context2D.beginPath();\r\n context2D.moveTo(6.72, 0.422);\r\n context2D.lineTo(17.28, 0.422);\r\n context2D.bezierCurveTo(18.553, 0.422, 19.577, 1.758, 19.577, 3.415);\r\n context2D.lineTo(19.577, 10.973);\r\n context2D.bezierCurveTo(19.577, 12.63, 18.553, 13.966, 17.282, 13.966);\r\n context2D.lineTo(14.386, 14.008);\r\n context2D.lineTo(11.826, 23.578);\r\n context2D.lineTo(9.614, 14.008);\r\n context2D.lineTo(6.719, 13.965);\r\n context2D.bezierCurveTo(5.446, 13.983, 4.422, 12.629, 4.422, 10.972);\r\n context2D.lineTo(4.422, 3.416);\r\n context2D.bezierCurveTo(4.423, 1.76, 5.447, 0.423, 6.718, 0.423);\r\n context2D.closePath();\r\n context2D.fill();\r\n context2D.stroke();\r\n context2D.restore();\r\n}\r\n\r\n//This function takes an image or canvas and uses it as a template\r\n//to \"stamp\" the pin with a white image outlined in black. The color\r\n//values of the input image are ignored completely and only the alpha\r\n//values are used.\r\nfunction drawIcon(context2D, image, size) {\r\n //Size is the largest image that looks good inside of pin box.\r\n var imageSize = size / 2.5;\r\n var sizeX = imageSize;\r\n var sizeY = imageSize;\r\n\r\n if (image.width > image.height) {\r\n sizeY = imageSize * (image.height / image.width);\r\n } else if (image.width < image.height) {\r\n sizeX = imageSize * (image.width / image.height);\r\n }\r\n\r\n //x and y are the center of the pin box\r\n var x = Math.round((size - sizeX) / 2);\r\n var y = Math.round((7 / 24) * size - sizeY / 2);\r\n\r\n context2D.globalCompositeOperation = \"destination-out\";\r\n context2D.drawImage(image, x - 1, y, sizeX, sizeY);\r\n context2D.drawImage(image, x, y - 1, sizeX, sizeY);\r\n context2D.drawImage(image, x + 1, y, sizeX, sizeY);\r\n context2D.drawImage(image, x, y + 1, sizeX, sizeY);\r\n\r\n context2D.globalCompositeOperation = \"destination-over\";\r\n context2D.fillStyle = Color.BLACK.toCssColorString();\r\n context2D.fillRect(x - 1, y - 1, sizeX + 2, sizeY + 2);\r\n\r\n context2D.globalCompositeOperation = \"destination-out\";\r\n context2D.drawImage(image, x, y, sizeX, sizeY);\r\n\r\n context2D.globalCompositeOperation = \"destination-over\";\r\n context2D.fillStyle = Color.WHITE.toCssColorString();\r\n context2D.fillRect(x - 1, y - 2, sizeX + 2, sizeY + 2);\r\n}\r\n\r\nvar stringifyScratch = new Array(4);\r\nfunction createPin(url, label, color, size, cache) {\r\n //Use the parameters as a unique ID for caching.\r\n stringifyScratch[0] = url;\r\n stringifyScratch[1] = label;\r\n stringifyScratch[2] = color;\r\n stringifyScratch[3] = size;\r\n var id = JSON.stringify(stringifyScratch);\r\n\r\n var item = cache[id];\r\n if (defined(item)) {\r\n return item;\r\n }\r\n\r\n var canvas = document.createElement(\"canvas\");\r\n canvas.width = size;\r\n canvas.height = size;\r\n\r\n var context2D = canvas.getContext(\"2d\");\r\n drawPin(context2D, color, size);\r\n\r\n if (defined(url)) {\r\n var resource = Resource.createIfNeeded(url);\r\n\r\n //If we have an image url, load it and then stamp the pin.\r\n var promise = resource.fetchImage().then(function (image) {\r\n drawIcon(context2D, image, size);\r\n cache[id] = canvas;\r\n return canvas;\r\n });\r\n cache[id] = promise;\r\n return promise;\r\n } else if (defined(label)) {\r\n //If we have a label, write it to a canvas and then stamp the pin.\r\n var image = writeTextToCanvas(label, {\r\n font: \"bold \" + size + \"px sans-serif\",\r\n });\r\n drawIcon(context2D, image, size);\r\n }\r\n\r\n cache[id] = canvas;\r\n return canvas;\r\n}\r\nexport default PinBuilder;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\n/**\r\n * Describes geometry representing a plane centered at the origin, with a unit width and length.\r\n *\r\n * @alias PlaneGeometry\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n *\r\n * @example\r\n * var planeGeometry = new Cesium.PlaneGeometry({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_ONLY\r\n * });\r\n */\r\nfunction PlaneGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n\r\n this._vertexFormat = vertexFormat;\r\n this._workerName = \"createPlaneGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nPlaneGeometry.packedLength = VertexFormat.packedLength;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PlaneGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nPlaneGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n vertexFormat: scratchVertexFormat,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PlaneGeometry} [result] The object into which to store the result.\r\n * @returns {PlaneGeometry} The modified result parameter or a new PlaneGeometry instance if one was not provided.\r\n */\r\nPlaneGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n\r\n if (!defined(result)) {\r\n return new PlaneGeometry(scratchOptions);\r\n }\r\n\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n\r\n return result;\r\n};\r\n\r\nvar min = new Cartesian3(-0.5, -0.5, 0.0);\r\nvar max = new Cartesian3(0.5, 0.5, 0.0);\r\n\r\n/**\r\n * Computes the geometric representation of a plane, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {PlaneGeometry} planeGeometry A description of the plane.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nPlaneGeometry.createGeometry = function (planeGeometry) {\r\n var vertexFormat = planeGeometry._vertexFormat;\r\n\r\n var attributes = new GeometryAttributes();\r\n var indices;\r\n var positions;\r\n\r\n if (vertexFormat.position) {\r\n // 4 corner points. Duplicated 3 times each for each incident edge/face.\r\n positions = new Float64Array(4 * 3);\r\n\r\n // +z face\r\n positions[0] = min.x;\r\n positions[1] = min.y;\r\n positions[2] = 0.0;\r\n positions[3] = max.x;\r\n positions[4] = min.y;\r\n positions[5] = 0.0;\r\n positions[6] = max.x;\r\n positions[7] = max.y;\r\n positions[8] = 0.0;\r\n positions[9] = min.x;\r\n positions[10] = max.y;\r\n positions[11] = 0.0;\r\n\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n\r\n if (vertexFormat.normal) {\r\n var normals = new Float32Array(4 * 3);\r\n\r\n // +z face\r\n normals[0] = 0.0;\r\n normals[1] = 0.0;\r\n normals[2] = 1.0;\r\n normals[3] = 0.0;\r\n normals[4] = 0.0;\r\n normals[5] = 1.0;\r\n normals[6] = 0.0;\r\n normals[7] = 0.0;\r\n normals[8] = 1.0;\r\n normals[9] = 0.0;\r\n normals[10] = 0.0;\r\n normals[11] = 1.0;\r\n\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.st) {\r\n var texCoords = new Float32Array(4 * 2);\r\n\r\n // +z face\r\n texCoords[0] = 0.0;\r\n texCoords[1] = 0.0;\r\n texCoords[2] = 1.0;\r\n texCoords[3] = 0.0;\r\n texCoords[4] = 1.0;\r\n texCoords[5] = 1.0;\r\n texCoords[6] = 0.0;\r\n texCoords[7] = 1.0;\r\n\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: texCoords,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n var tangents = new Float32Array(4 * 3);\r\n\r\n // +z face\r\n tangents[0] = 1.0;\r\n tangents[1] = 0.0;\r\n tangents[2] = 0.0;\r\n tangents[3] = 1.0;\r\n tangents[4] = 0.0;\r\n tangents[5] = 0.0;\r\n tangents[6] = 1.0;\r\n tangents[7] = 0.0;\r\n tangents[8] = 0.0;\r\n tangents[9] = 1.0;\r\n tangents[10] = 0.0;\r\n tangents[11] = 0.0;\r\n\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n var bitangents = new Float32Array(4 * 3);\r\n\r\n // +z face\r\n bitangents[0] = 0.0;\r\n bitangents[1] = 1.0;\r\n bitangents[2] = 0.0;\r\n bitangents[3] = 0.0;\r\n bitangents[4] = 1.0;\r\n bitangents[5] = 0.0;\r\n bitangents[6] = 0.0;\r\n bitangents[7] = 1.0;\r\n bitangents[8] = 0.0;\r\n bitangents[9] = 0.0;\r\n bitangents[10] = 1.0;\r\n bitangents[11] = 0.0;\r\n\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n\r\n // 2 triangles\r\n indices = new Uint16Array(2 * 3);\r\n\r\n // +z face\r\n indices[0] = 0;\r\n indices[1] = 1;\r\n indices[2] = 2;\r\n indices[3] = 0;\r\n indices[4] = 2;\r\n indices[5] = 3;\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: new BoundingSphere(Cartesian3.ZERO, Math.sqrt(2.0)),\r\n });\r\n};\r\nexport default PlaneGeometry;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defined from \"./defined.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\n\r\n/**\r\n * Describes geometry representing the outline of a plane centered at the origin, with a unit width and length.\r\n *\r\n * @alias PlaneOutlineGeometry\r\n * @constructor\r\n *\r\n */\r\nfunction PlaneOutlineGeometry() {\r\n this._workerName = \"createPlaneOutlineGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nPlaneOutlineGeometry.packedLength = 0;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PlaneOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nPlaneOutlineGeometry.pack = function (value, array) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PlaneOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {PlaneOutlineGeometry} The modified result parameter or a new PlaneOutlineGeometry instance if one was not provided.\r\n */\r\nPlaneOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new PlaneOutlineGeometry();\r\n }\r\n\r\n return result;\r\n};\r\n\r\nvar min = new Cartesian3(-0.5, -0.5, 0.0);\r\nvar max = new Cartesian3(0.5, 0.5, 0.0);\r\n\r\n/**\r\n * Computes the geometric representation of an outline of a plane, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nPlaneOutlineGeometry.createGeometry = function () {\r\n var attributes = new GeometryAttributes();\r\n var indices = new Uint16Array(4 * 2);\r\n var positions = new Float64Array(4 * 3);\r\n\r\n positions[0] = min.x;\r\n positions[1] = min.y;\r\n positions[2] = min.z;\r\n positions[3] = max.x;\r\n positions[4] = min.y;\r\n positions[5] = min.z;\r\n positions[6] = max.x;\r\n positions[7] = max.y;\r\n positions[8] = min.z;\r\n positions[9] = min.x;\r\n positions[10] = max.y;\r\n positions[11] = min.z;\r\n\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n\r\n indices[0] = 0;\r\n indices[1] = 1;\r\n indices[2] = 1;\r\n indices[3] = 2;\r\n indices[4] = 2;\r\n indices[5] = 3;\r\n indices[6] = 3;\r\n indices[7] = 0;\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: new BoundingSphere(Cartesian3.ZERO, Math.sqrt(2.0)),\r\n });\r\n};\r\nexport default PlaneOutlineGeometry;\r\n","import barycentricCoordinates from \"./barycentricCoordinates.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\n\r\nvar coords = new Cartesian3();\r\n\r\n/**\r\n * Determines if a point is inside a triangle.\r\n *\r\n * @function pointInsideTriangle\r\n *\r\n * @param {Cartesian2|Cartesian3} point The point to test.\r\n * @param {Cartesian2|Cartesian3} p0 The first point of the triangle.\r\n * @param {Cartesian2|Cartesian3} p1 The second point of the triangle.\r\n * @param {Cartesian2|Cartesian3} p2 The third point of the triangle.\r\n * @returns {Boolean} true if the point is inside the triangle; otherwise, false.\r\n *\r\n * @example\r\n * // Returns true\r\n * var p = new Cesium.Cartesian2(0.25, 0.25);\r\n * var b = Cesium.pointInsideTriangle(p,\r\n * new Cesium.Cartesian2(0.0, 0.0),\r\n * new Cesium.Cartesian2(1.0, 0.0),\r\n * new Cesium.Cartesian2(0.0, 1.0));\r\n */\r\nfunction pointInsideTriangle(point, p0, p1, p2) {\r\n barycentricCoordinates(point, p0, p1, p2, coords);\r\n return coords.x > 0.0 && coords.y > 0.0 && coords.z > 0;\r\n}\r\nexport default pointInsideTriangle;\r\n","import ArcType from \"./ArcType.js\";\r\nimport arrayFill from \"./arrayFill.js\";\r\nimport BoundingRectangle from \"./BoundingRectangle.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport EllipsoidGeodesic from \"./EllipsoidGeodesic.js\";\r\nimport EllipsoidTangentPlane from \"./EllipsoidTangentPlane.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryInstance from \"./GeometryInstance.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport GeometryPipeline from \"./GeometryPipeline.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport PolygonGeometryLibrary from \"./PolygonGeometryLibrary.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\nimport WindingOrder from \"./WindingOrder.js\";\r\n\r\nvar scratchCarto1 = new Cartographic();\r\nvar scratchCarto2 = new Cartographic();\r\nfunction adjustPosHeightsForNormal(position, p1, p2, ellipsoid) {\r\n var carto1 = ellipsoid.cartesianToCartographic(position, scratchCarto1);\r\n var height = carto1.height;\r\n var p1Carto = ellipsoid.cartesianToCartographic(p1, scratchCarto2);\r\n p1Carto.height = height;\r\n ellipsoid.cartographicToCartesian(p1Carto, p1);\r\n\r\n var p2Carto = ellipsoid.cartesianToCartographic(p2, scratchCarto2);\r\n p2Carto.height = height - 100;\r\n ellipsoid.cartographicToCartesian(p2Carto, p2);\r\n}\r\n\r\nvar scratchBoundingRectangle = new BoundingRectangle();\r\nvar scratchPosition = new Cartesian3();\r\nvar scratchNormal = new Cartesian3();\r\nvar scratchTangent = new Cartesian3();\r\nvar scratchBitangent = new Cartesian3();\r\nvar p1Scratch = new Cartesian3();\r\nvar p2Scratch = new Cartesian3();\r\nvar scratchPerPosNormal = new Cartesian3();\r\nvar scratchPerPosTangent = new Cartesian3();\r\nvar scratchPerPosBitangent = new Cartesian3();\r\n\r\nvar appendTextureCoordinatesOrigin = new Cartesian2();\r\nvar appendTextureCoordinatesCartesian2 = new Cartesian2();\r\nvar appendTextureCoordinatesCartesian3 = new Cartesian3();\r\nvar appendTextureCoordinatesQuaternion = new Quaternion();\r\nvar appendTextureCoordinatesMatrix3 = new Matrix3();\r\nvar tangentMatrixScratch = new Matrix3();\r\n\r\nfunction computeAttributes(options) {\r\n var vertexFormat = options.vertexFormat;\r\n var geometry = options.geometry;\r\n var shadowVolume = options.shadowVolume;\r\n var flatPositions = geometry.attributes.position.values;\r\n var length = flatPositions.length;\r\n var wall = options.wall;\r\n var top = options.top || wall;\r\n var bottom = options.bottom || wall;\r\n if (\r\n vertexFormat.st ||\r\n vertexFormat.normal ||\r\n vertexFormat.tangent ||\r\n vertexFormat.bitangent ||\r\n shadowVolume\r\n ) {\r\n // PERFORMANCE_IDEA: Compute before subdivision, then just interpolate during subdivision.\r\n // PERFORMANCE_IDEA: Compute with createGeometryFromPositions() for fast path when there's no holes.\r\n var boundingRectangle = options.boundingRectangle;\r\n var tangentPlane = options.tangentPlane;\r\n var ellipsoid = options.ellipsoid;\r\n var stRotation = options.stRotation;\r\n var perPositionHeight = options.perPositionHeight;\r\n\r\n var origin = appendTextureCoordinatesOrigin;\r\n origin.x = boundingRectangle.x;\r\n origin.y = boundingRectangle.y;\r\n\r\n var textureCoordinates = vertexFormat.st\r\n ? new Float32Array(2 * (length / 3))\r\n : undefined;\r\n var normals;\r\n if (vertexFormat.normal) {\r\n if (perPositionHeight && top && !wall) {\r\n normals = geometry.attributes.normal.values;\r\n } else {\r\n normals = new Float32Array(length);\r\n }\r\n }\r\n var tangents = vertexFormat.tangent ? new Float32Array(length) : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(length)\r\n : undefined;\r\n var extrudeNormals = shadowVolume ? new Float32Array(length) : undefined;\r\n\r\n var textureCoordIndex = 0;\r\n var attrIndex = 0;\r\n\r\n var normal = scratchNormal;\r\n var tangent = scratchTangent;\r\n var bitangent = scratchBitangent;\r\n var recomputeNormal = true;\r\n\r\n var textureMatrix = appendTextureCoordinatesMatrix3;\r\n var tangentRotationMatrix = tangentMatrixScratch;\r\n if (stRotation !== 0.0) {\r\n var rotation = Quaternion.fromAxisAngle(\r\n tangentPlane._plane.normal,\r\n stRotation,\r\n appendTextureCoordinatesQuaternion\r\n );\r\n textureMatrix = Matrix3.fromQuaternion(rotation, textureMatrix);\r\n\r\n rotation = Quaternion.fromAxisAngle(\r\n tangentPlane._plane.normal,\r\n -stRotation,\r\n appendTextureCoordinatesQuaternion\r\n );\r\n tangentRotationMatrix = Matrix3.fromQuaternion(\r\n rotation,\r\n tangentRotationMatrix\r\n );\r\n } else {\r\n textureMatrix = Matrix3.clone(Matrix3.IDENTITY, textureMatrix);\r\n tangentRotationMatrix = Matrix3.clone(\r\n Matrix3.IDENTITY,\r\n tangentRotationMatrix\r\n );\r\n }\r\n\r\n var bottomOffset = 0;\r\n var bottomOffset2 = 0;\r\n\r\n if (top && bottom) {\r\n bottomOffset = length / 2;\r\n bottomOffset2 = length / 3;\r\n\r\n length /= 2;\r\n }\r\n\r\n for (var i = 0; i < length; i += 3) {\r\n var position = Cartesian3.fromArray(\r\n flatPositions,\r\n i,\r\n appendTextureCoordinatesCartesian3\r\n );\r\n\r\n if (vertexFormat.st) {\r\n var p = Matrix3.multiplyByVector(\r\n textureMatrix,\r\n position,\r\n scratchPosition\r\n );\r\n p = ellipsoid.scaleToGeodeticSurface(p, p);\r\n var st = tangentPlane.projectPointOntoPlane(\r\n p,\r\n appendTextureCoordinatesCartesian2\r\n );\r\n Cartesian2.subtract(st, origin, st);\r\n\r\n var stx = CesiumMath.clamp(st.x / boundingRectangle.width, 0, 1);\r\n var sty = CesiumMath.clamp(st.y / boundingRectangle.height, 0, 1);\r\n if (bottom) {\r\n textureCoordinates[textureCoordIndex + bottomOffset2] = stx;\r\n textureCoordinates[textureCoordIndex + 1 + bottomOffset2] = sty;\r\n }\r\n if (top) {\r\n textureCoordinates[textureCoordIndex] = stx;\r\n textureCoordinates[textureCoordIndex + 1] = sty;\r\n }\r\n\r\n textureCoordIndex += 2;\r\n }\r\n\r\n if (\r\n vertexFormat.normal ||\r\n vertexFormat.tangent ||\r\n vertexFormat.bitangent ||\r\n shadowVolume\r\n ) {\r\n var attrIndex1 = attrIndex + 1;\r\n var attrIndex2 = attrIndex + 2;\r\n\r\n if (wall) {\r\n if (i + 3 < length) {\r\n var p1 = Cartesian3.fromArray(flatPositions, i + 3, p1Scratch);\r\n\r\n if (recomputeNormal) {\r\n var p2 = Cartesian3.fromArray(\r\n flatPositions,\r\n i + length,\r\n p2Scratch\r\n );\r\n if (perPositionHeight) {\r\n adjustPosHeightsForNormal(position, p1, p2, ellipsoid);\r\n }\r\n Cartesian3.subtract(p1, position, p1);\r\n Cartesian3.subtract(p2, position, p2);\r\n normal = Cartesian3.normalize(\r\n Cartesian3.cross(p2, p1, normal),\r\n normal\r\n );\r\n recomputeNormal = false;\r\n }\r\n\r\n if (Cartesian3.equalsEpsilon(p1, position, CesiumMath.EPSILON10)) {\r\n // if we've reached a corner\r\n recomputeNormal = true;\r\n }\r\n }\r\n\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n bitangent = ellipsoid.geodeticSurfaceNormal(position, bitangent);\r\n if (vertexFormat.tangent) {\r\n tangent = Cartesian3.normalize(\r\n Cartesian3.cross(bitangent, normal, tangent),\r\n tangent\r\n );\r\n }\r\n }\r\n } else {\r\n normal = ellipsoid.geodeticSurfaceNormal(position, normal);\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n if (perPositionHeight) {\r\n scratchPerPosNormal = Cartesian3.fromArray(\r\n normals,\r\n attrIndex,\r\n scratchPerPosNormal\r\n );\r\n scratchPerPosTangent = Cartesian3.cross(\r\n Cartesian3.UNIT_Z,\r\n scratchPerPosNormal,\r\n scratchPerPosTangent\r\n );\r\n scratchPerPosTangent = Cartesian3.normalize(\r\n Matrix3.multiplyByVector(\r\n tangentRotationMatrix,\r\n scratchPerPosTangent,\r\n scratchPerPosTangent\r\n ),\r\n scratchPerPosTangent\r\n );\r\n if (vertexFormat.bitangent) {\r\n scratchPerPosBitangent = Cartesian3.normalize(\r\n Cartesian3.cross(\r\n scratchPerPosNormal,\r\n scratchPerPosTangent,\r\n scratchPerPosBitangent\r\n ),\r\n scratchPerPosBitangent\r\n );\r\n }\r\n }\r\n\r\n tangent = Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent);\r\n tangent = Cartesian3.normalize(\r\n Matrix3.multiplyByVector(tangentRotationMatrix, tangent, tangent),\r\n tangent\r\n );\r\n if (vertexFormat.bitangent) {\r\n bitangent = Cartesian3.normalize(\r\n Cartesian3.cross(normal, tangent, bitangent),\r\n bitangent\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n if (options.wall) {\r\n normals[attrIndex + bottomOffset] = normal.x;\r\n normals[attrIndex1 + bottomOffset] = normal.y;\r\n normals[attrIndex2 + bottomOffset] = normal.z;\r\n } else if (bottom) {\r\n normals[attrIndex + bottomOffset] = -normal.x;\r\n normals[attrIndex1 + bottomOffset] = -normal.y;\r\n normals[attrIndex2 + bottomOffset] = -normal.z;\r\n }\r\n\r\n if ((top && !perPositionHeight) || wall) {\r\n normals[attrIndex] = normal.x;\r\n normals[attrIndex1] = normal.y;\r\n normals[attrIndex2] = normal.z;\r\n }\r\n }\r\n\r\n if (shadowVolume) {\r\n if (wall) {\r\n normal = ellipsoid.geodeticSurfaceNormal(position, normal);\r\n }\r\n extrudeNormals[attrIndex + bottomOffset] = -normal.x;\r\n extrudeNormals[attrIndex1 + bottomOffset] = -normal.y;\r\n extrudeNormals[attrIndex2 + bottomOffset] = -normal.z;\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n if (options.wall) {\r\n tangents[attrIndex + bottomOffset] = tangent.x;\r\n tangents[attrIndex1 + bottomOffset] = tangent.y;\r\n tangents[attrIndex2 + bottomOffset] = tangent.z;\r\n } else if (bottom) {\r\n tangents[attrIndex + bottomOffset] = -tangent.x;\r\n tangents[attrIndex1 + bottomOffset] = -tangent.y;\r\n tangents[attrIndex2 + bottomOffset] = -tangent.z;\r\n }\r\n\r\n if (top) {\r\n if (perPositionHeight) {\r\n tangents[attrIndex] = scratchPerPosTangent.x;\r\n tangents[attrIndex1] = scratchPerPosTangent.y;\r\n tangents[attrIndex2] = scratchPerPosTangent.z;\r\n } else {\r\n tangents[attrIndex] = tangent.x;\r\n tangents[attrIndex1] = tangent.y;\r\n tangents[attrIndex2] = tangent.z;\r\n }\r\n }\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n if (bottom) {\r\n bitangents[attrIndex + bottomOffset] = bitangent.x;\r\n bitangents[attrIndex1 + bottomOffset] = bitangent.y;\r\n bitangents[attrIndex2 + bottomOffset] = bitangent.z;\r\n }\r\n if (top) {\r\n if (perPositionHeight) {\r\n bitangents[attrIndex] = scratchPerPosBitangent.x;\r\n bitangents[attrIndex1] = scratchPerPosBitangent.y;\r\n bitangents[attrIndex2] = scratchPerPosBitangent.z;\r\n } else {\r\n bitangents[attrIndex] = bitangent.x;\r\n bitangents[attrIndex1] = bitangent.y;\r\n bitangents[attrIndex2] = bitangent.z;\r\n }\r\n }\r\n }\r\n attrIndex += 3;\r\n }\r\n }\r\n\r\n if (vertexFormat.st) {\r\n geometry.attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: textureCoordinates,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n geometry.attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n geometry.attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n geometry.attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n\r\n if (shadowVolume) {\r\n geometry.attributes.extrudeDirection = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: extrudeNormals,\r\n });\r\n }\r\n }\r\n\r\n if (options.extrude && defined(options.offsetAttribute)) {\r\n var size = flatPositions.length / 3;\r\n var offsetAttribute = new Uint8Array(size);\r\n\r\n if (options.offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n if ((top && bottom) || wall) {\r\n offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);\r\n } else if (top) {\r\n offsetAttribute = arrayFill(offsetAttribute, 1);\r\n }\r\n } else {\r\n var offsetValue =\r\n options.offsetAttribute === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n offsetAttribute = arrayFill(offsetAttribute, offsetValue);\r\n }\r\n\r\n geometry.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: offsetAttribute,\r\n });\r\n }\r\n\r\n return geometry;\r\n}\r\n\r\nvar startCartographicScratch = new Cartographic();\r\nvar endCartographicScratch = new Cartographic();\r\nvar idlCross = {\r\n westOverIDL: 0.0,\r\n eastOverIDL: 0.0,\r\n};\r\nvar ellipsoidGeodesic = new EllipsoidGeodesic();\r\nfunction computeRectangle(positions, ellipsoid, arcType, granularity, result) {\r\n result = defaultValue(result, new Rectangle());\r\n if (!defined(positions) || positions.length < 3) {\r\n result.west = 0.0;\r\n result.north = 0.0;\r\n result.south = 0.0;\r\n result.east = 0.0;\r\n return result;\r\n }\r\n\r\n if (arcType === ArcType.RHUMB) {\r\n return Rectangle.fromCartesianArray(positions, ellipsoid, result);\r\n }\r\n\r\n if (!ellipsoidGeodesic.ellipsoid.equals(ellipsoid)) {\r\n ellipsoidGeodesic = new EllipsoidGeodesic(undefined, undefined, ellipsoid);\r\n }\r\n\r\n result.west = Number.POSITIVE_INFINITY;\r\n result.east = Number.NEGATIVE_INFINITY;\r\n result.south = Number.POSITIVE_INFINITY;\r\n result.north = Number.NEGATIVE_INFINITY;\r\n\r\n idlCross.westOverIDL = Number.POSITIVE_INFINITY;\r\n idlCross.eastOverIDL = Number.NEGATIVE_INFINITY;\r\n\r\n var inverseChordLength =\r\n 1.0 / CesiumMath.chordLength(granularity, ellipsoid.maximumRadius);\r\n var positionsLength = positions.length;\r\n var endCartographic = ellipsoid.cartesianToCartographic(\r\n positions[0],\r\n endCartographicScratch\r\n );\r\n var startCartographic = startCartographicScratch;\r\n var swap;\r\n\r\n for (var i = 1; i < positionsLength; i++) {\r\n swap = startCartographic;\r\n startCartographic = endCartographic;\r\n endCartographic = ellipsoid.cartesianToCartographic(positions[i], swap);\r\n ellipsoidGeodesic.setEndPoints(startCartographic, endCartographic);\r\n interpolateAndGrowRectangle(\r\n ellipsoidGeodesic,\r\n inverseChordLength,\r\n result,\r\n idlCross\r\n );\r\n }\r\n\r\n swap = startCartographic;\r\n startCartographic = endCartographic;\r\n endCartographic = ellipsoid.cartesianToCartographic(positions[0], swap);\r\n ellipsoidGeodesic.setEndPoints(startCartographic, endCartographic);\r\n interpolateAndGrowRectangle(\r\n ellipsoidGeodesic,\r\n inverseChordLength,\r\n result,\r\n idlCross\r\n );\r\n\r\n if (result.east - result.west > idlCross.eastOverIDL - idlCross.westOverIDL) {\r\n result.west = idlCross.westOverIDL;\r\n result.east = idlCross.eastOverIDL;\r\n\r\n if (result.east > CesiumMath.PI) {\r\n result.east = result.east - CesiumMath.TWO_PI;\r\n }\r\n if (result.west > CesiumMath.PI) {\r\n result.west = result.west - CesiumMath.TWO_PI;\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nvar interpolatedCartographicScratch = new Cartographic();\r\nfunction interpolateAndGrowRectangle(\r\n ellipsoidGeodesic,\r\n inverseChordLength,\r\n result,\r\n idlCross\r\n) {\r\n var segmentLength = ellipsoidGeodesic.surfaceDistance;\r\n\r\n var numPoints = Math.ceil(segmentLength * inverseChordLength);\r\n var subsegmentDistance =\r\n numPoints > 0 ? segmentLength / (numPoints - 1) : Number.POSITIVE_INFINITY;\r\n var interpolationDistance = 0.0;\r\n\r\n for (var i = 0; i < numPoints; i++) {\r\n var interpolatedCartographic = ellipsoidGeodesic.interpolateUsingSurfaceDistance(\r\n interpolationDistance,\r\n interpolatedCartographicScratch\r\n );\r\n interpolationDistance += subsegmentDistance;\r\n var longitude = interpolatedCartographic.longitude;\r\n var latitude = interpolatedCartographic.latitude;\r\n\r\n result.west = Math.min(result.west, longitude);\r\n result.east = Math.max(result.east, longitude);\r\n result.south = Math.min(result.south, latitude);\r\n result.north = Math.max(result.north, latitude);\r\n\r\n var lonAdjusted =\r\n longitude >= 0 ? longitude : longitude + CesiumMath.TWO_PI;\r\n idlCross.westOverIDL = Math.min(idlCross.westOverIDL, lonAdjusted);\r\n idlCross.eastOverIDL = Math.max(idlCross.eastOverIDL, lonAdjusted);\r\n }\r\n}\r\n\r\nvar createGeometryFromPositionsExtrudedPositions = [];\r\n\r\nfunction createGeometryFromPositionsExtruded(\r\n ellipsoid,\r\n polygon,\r\n granularity,\r\n hierarchy,\r\n perPositionHeight,\r\n closeTop,\r\n closeBottom,\r\n vertexFormat,\r\n arcType\r\n) {\r\n var geos = {\r\n walls: [],\r\n };\r\n var i;\r\n\r\n if (closeTop || closeBottom) {\r\n var topGeo = PolygonGeometryLibrary.createGeometryFromPositions(\r\n ellipsoid,\r\n polygon,\r\n granularity,\r\n perPositionHeight,\r\n vertexFormat,\r\n arcType\r\n );\r\n\r\n var edgePoints = topGeo.attributes.position.values;\r\n var indices = topGeo.indices;\r\n var numPositions;\r\n var newIndices;\r\n\r\n if (closeTop && closeBottom) {\r\n var topBottomPositions = edgePoints.concat(edgePoints);\r\n\r\n numPositions = topBottomPositions.length / 3;\r\n\r\n newIndices = IndexDatatype.createTypedArray(\r\n numPositions,\r\n indices.length * 2\r\n );\r\n newIndices.set(indices);\r\n var ilength = indices.length;\r\n\r\n var length = numPositions / 2;\r\n\r\n for (i = 0; i < ilength; i += 3) {\r\n var i0 = newIndices[i] + length;\r\n var i1 = newIndices[i + 1] + length;\r\n var i2 = newIndices[i + 2] + length;\r\n\r\n newIndices[i + ilength] = i2;\r\n newIndices[i + 1 + ilength] = i1;\r\n newIndices[i + 2 + ilength] = i0;\r\n }\r\n\r\n topGeo.attributes.position.values = topBottomPositions;\r\n if (perPositionHeight && vertexFormat.normal) {\r\n var normals = topGeo.attributes.normal.values;\r\n topGeo.attributes.normal.values = new Float32Array(\r\n topBottomPositions.length\r\n );\r\n topGeo.attributes.normal.values.set(normals);\r\n }\r\n topGeo.indices = newIndices;\r\n } else if (closeBottom) {\r\n numPositions = edgePoints.length / 3;\r\n newIndices = IndexDatatype.createTypedArray(numPositions, indices.length);\r\n\r\n for (i = 0; i < indices.length; i += 3) {\r\n newIndices[i] = indices[i + 2];\r\n newIndices[i + 1] = indices[i + 1];\r\n newIndices[i + 2] = indices[i];\r\n }\r\n\r\n topGeo.indices = newIndices;\r\n }\r\n\r\n geos.topAndBottom = new GeometryInstance({\r\n geometry: topGeo,\r\n });\r\n }\r\n\r\n var outerRing = hierarchy.outerRing;\r\n var tangentPlane = EllipsoidTangentPlane.fromPoints(outerRing, ellipsoid);\r\n var positions2D = tangentPlane.projectPointsOntoPlane(\r\n outerRing,\r\n createGeometryFromPositionsExtrudedPositions\r\n );\r\n\r\n var windingOrder = PolygonPipeline.computeWindingOrder2D(positions2D);\r\n if (windingOrder === WindingOrder.CLOCKWISE) {\r\n outerRing = outerRing.slice().reverse();\r\n }\r\n\r\n var wallGeo = PolygonGeometryLibrary.computeWallGeometry(\r\n outerRing,\r\n ellipsoid,\r\n granularity,\r\n perPositionHeight,\r\n arcType\r\n );\r\n geos.walls.push(\r\n new GeometryInstance({\r\n geometry: wallGeo,\r\n })\r\n );\r\n\r\n var holes = hierarchy.holes;\r\n for (i = 0; i < holes.length; i++) {\r\n var hole = holes[i];\r\n\r\n tangentPlane = EllipsoidTangentPlane.fromPoints(hole, ellipsoid);\r\n positions2D = tangentPlane.projectPointsOntoPlane(\r\n hole,\r\n createGeometryFromPositionsExtrudedPositions\r\n );\r\n\r\n windingOrder = PolygonPipeline.computeWindingOrder2D(positions2D);\r\n if (windingOrder === WindingOrder.COUNTER_CLOCKWISE) {\r\n hole = hole.slice().reverse();\r\n }\r\n\r\n wallGeo = PolygonGeometryLibrary.computeWallGeometry(\r\n hole,\r\n ellipsoid,\r\n granularity,\r\n perPositionHeight,\r\n arcType\r\n );\r\n geos.walls.push(\r\n new GeometryInstance({\r\n geometry: wallGeo,\r\n })\r\n );\r\n }\r\n\r\n return geos;\r\n}\r\n\r\n/**\r\n * A description of a polygon on the ellipsoid. The polygon is defined by a polygon hierarchy. Polygon geometry can be rendered with both {@link Primitive} and {@link GroundPrimitive}.\r\n *\r\n * @alias PolygonGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.\r\n * @param {Number} [options.height=0.0] The distance in meters between the polygon and the ellipsoid surface.\r\n * @param {Number} [options.extrudedHeight] The distance in meters between the polygon's extruded face and the ellipsoid surface.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.\r\n * @param {Boolean} [options.closeTop=true] When false, leaves off the top of an extruded polygon open.\r\n * @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open.\r\n * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polygon edges must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.\r\n *\r\n * @see PolygonGeometry#createGeometry\r\n * @see PolygonGeometry#fromPositions\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Polygon.html|Cesium Sandcastle Polygon Demo}\r\n *\r\n * @example\r\n * // 1. create a polygon from points\r\n * var polygon = new Cesium.PolygonGeometry({\r\n * polygonHierarchy : new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ])\r\n * )\r\n * });\r\n * var geometry = Cesium.PolygonGeometry.createGeometry(polygon);\r\n *\r\n * // 2. create a nested polygon with holes\r\n * var polygonWithHole = new Cesium.PolygonGeometry({\r\n * polygonHierarchy : new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -109.0, 30.0,\r\n * -95.0, 30.0,\r\n * -95.0, 40.0,\r\n * -109.0, 40.0\r\n * ]),\r\n * [new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -107.0, 31.0,\r\n * -107.0, 39.0,\r\n * -97.0, 39.0,\r\n * -97.0, 31.0\r\n * ]),\r\n * [new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -105.0, 33.0,\r\n * -99.0, 33.0,\r\n * -99.0, 37.0,\r\n * -105.0, 37.0\r\n * ]),\r\n * [new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -103.0, 34.0,\r\n * -101.0, 34.0,\r\n * -101.0, 36.0,\r\n * -103.0, 36.0\r\n * ])\r\n * )]\r\n * )]\r\n * )]\r\n * )\r\n * });\r\n * var geometry = Cesium.PolygonGeometry.createGeometry(polygonWithHole);\r\n *\r\n * // 3. create extruded polygon\r\n * var extrudedPolygon = new Cesium.PolygonGeometry({\r\n * polygonHierarchy : new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ])\r\n * ),\r\n * extrudedHeight: 300000\r\n * });\r\n * var geometry = Cesium.PolygonGeometry.createGeometry(extrudedPolygon);\r\n */\r\nfunction PolygonGeometry(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.object(\"options.polygonHierarchy\", options.polygonHierarchy);\r\n if (\r\n defined(options.perPositionHeight) &&\r\n options.perPositionHeight &&\r\n defined(options.height)\r\n ) {\r\n throw new DeveloperError(\r\n \"Cannot use both options.perPositionHeight and options.height\"\r\n );\r\n }\r\n if (\r\n defined(options.arcType) &&\r\n options.arcType !== ArcType.GEODESIC &&\r\n options.arcType !== ArcType.RHUMB\r\n ) {\r\n throw new DeveloperError(\r\n \"Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var polygonHierarchy = options.polygonHierarchy;\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var stRotation = defaultValue(options.stRotation, 0.0);\r\n var perPositionHeight = defaultValue(options.perPositionHeight, false);\r\n var perPositionHeightExtrude =\r\n perPositionHeight && defined(options.extrudedHeight);\r\n var height = defaultValue(options.height, 0.0);\r\n var extrudedHeight = defaultValue(options.extrudedHeight, height);\r\n\r\n if (!perPositionHeightExtrude) {\r\n var h = Math.max(height, extrudedHeight);\r\n extrudedHeight = Math.min(height, extrudedHeight);\r\n height = h;\r\n }\r\n\r\n this._vertexFormat = VertexFormat.clone(vertexFormat);\r\n this._ellipsoid = Ellipsoid.clone(ellipsoid);\r\n this._granularity = granularity;\r\n this._stRotation = stRotation;\r\n this._height = height;\r\n this._extrudedHeight = extrudedHeight;\r\n this._closeTop = defaultValue(options.closeTop, true);\r\n this._closeBottom = defaultValue(options.closeBottom, true);\r\n this._polygonHierarchy = polygonHierarchy;\r\n this._perPositionHeight = perPositionHeight;\r\n this._perPositionHeightExtrude = perPositionHeightExtrude;\r\n this._shadowVolume = defaultValue(options.shadowVolume, false);\r\n this._workerName = \"createPolygonGeometry\";\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._arcType = defaultValue(options.arcType, ArcType.GEODESIC);\r\n\r\n this._rectangle = undefined;\r\n this._textureCoordinateRotationPoints = undefined;\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) +\r\n Ellipsoid.packedLength +\r\n VertexFormat.packedLength +\r\n 12;\r\n}\r\n\r\n/**\r\n * A description of a polygon from an array of positions. Polygon geometry can be rendered with both {@link Primitive} and {@link GroundPrimitive}.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of positions that defined the corner points of the polygon.\r\n * @param {Number} [options.height=0.0] The height of the polygon.\r\n * @param {Number} [options.extrudedHeight] The height of the polygon extrusion.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.\r\n * @param {Boolean} [options.closeTop=true] When false, leaves off the top of an extruded polygon open.\r\n * @param {Boolean} [options.closeBottom=true] When false, leaves off the bottom of an extruded polygon open.\r\n * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polygon edges must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.\r\n * @returns {PolygonGeometry}\r\n *\r\n *\r\n * @example\r\n * // create a polygon from points\r\n * var polygon = Cesium.PolygonGeometry.fromPositions({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ])\r\n * });\r\n * var geometry = Cesium.PolygonGeometry.createGeometry(polygon);\r\n *\r\n * @see PolygonGeometry#createGeometry\r\n */\r\nPolygonGeometry.fromPositions = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.positions\", options.positions);\r\n //>>includeEnd('debug');\r\n\r\n var newOptions = {\r\n polygonHierarchy: {\r\n positions: options.positions,\r\n },\r\n height: options.height,\r\n extrudedHeight: options.extrudedHeight,\r\n vertexFormat: options.vertexFormat,\r\n stRotation: options.stRotation,\r\n ellipsoid: options.ellipsoid,\r\n granularity: options.granularity,\r\n perPositionHeight: options.perPositionHeight,\r\n closeTop: options.closeTop,\r\n closeBottom: options.closeBottom,\r\n offsetAttribute: options.offsetAttribute,\r\n arcType: options.arcType,\r\n };\r\n return new PolygonGeometry(newOptions);\r\n};\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PolygonGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nPolygonGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n startingIndex = PolygonGeometryLibrary.packPolygonHierarchy(\r\n value._polygonHierarchy,\r\n array,\r\n startingIndex\r\n );\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._height;\r\n array[startingIndex++] = value._extrudedHeight;\r\n array[startingIndex++] = value._granularity;\r\n array[startingIndex++] = value._stRotation;\r\n array[startingIndex++] = value._perPositionHeightExtrude ? 1.0 : 0.0;\r\n array[startingIndex++] = value._perPositionHeight ? 1.0 : 0.0;\r\n array[startingIndex++] = value._closeTop ? 1.0 : 0.0;\r\n array[startingIndex++] = value._closeBottom ? 1.0 : 0.0;\r\n array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0;\r\n array[startingIndex++] = defaultValue(value._offsetAttribute, -1);\r\n array[startingIndex++] = value._arcType;\r\n array[startingIndex] = value.packedLength;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchVertexFormat = new VertexFormat();\r\n\r\n//Only used to avoid inability to default construct.\r\nvar dummyOptions = {\r\n polygonHierarchy: {},\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PolygonGeometry} [result] The object into which to store the result.\r\n */\r\nPolygonGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var polygonHierarchy = PolygonGeometryLibrary.unpackPolygonHierarchy(\r\n array,\r\n startingIndex\r\n );\r\n startingIndex = polygonHierarchy.startingIndex;\r\n delete polygonHierarchy.startingIndex;\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var height = array[startingIndex++];\r\n var extrudedHeight = array[startingIndex++];\r\n var granularity = array[startingIndex++];\r\n var stRotation = array[startingIndex++];\r\n var perPositionHeightExtrude = array[startingIndex++] === 1.0;\r\n var perPositionHeight = array[startingIndex++] === 1.0;\r\n var closeTop = array[startingIndex++] === 1.0;\r\n var closeBottom = array[startingIndex++] === 1.0;\r\n var shadowVolume = array[startingIndex++] === 1.0;\r\n var offsetAttribute = array[startingIndex++];\r\n var arcType = array[startingIndex++];\r\n var packedLength = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n result = new PolygonGeometry(dummyOptions);\r\n }\r\n\r\n result._polygonHierarchy = polygonHierarchy;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._height = height;\r\n result._extrudedHeight = extrudedHeight;\r\n result._granularity = granularity;\r\n result._stRotation = stRotation;\r\n result._perPositionHeightExtrude = perPositionHeightExtrude;\r\n result._perPositionHeight = perPositionHeight;\r\n result._closeTop = closeTop;\r\n result._closeBottom = closeBottom;\r\n result._shadowVolume = shadowVolume;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n result._arcType = arcType;\r\n result.packedLength = packedLength;\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns the bounding rectangle given the provided options\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions sampled.\r\n * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polygon edges must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Rectangle} [result] An object in which to store the result.\r\n *\r\n * @returns {Rectangle} The result rectangle\r\n */\r\nPolygonGeometry.computeRectangle = function (options, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.object(\"options.polygonHierarchy\", options.polygonHierarchy);\r\n //>>includeEnd('debug');\r\n\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var arcType = defaultValue(options.arcType, ArcType.GEODESIC);\r\n //>>includeStart('debug', pragmas.debug);\r\n if (arcType !== ArcType.GEODESIC && arcType !== ArcType.RHUMB) {\r\n throw new DeveloperError(\r\n \"Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var polygonHierarchy = options.polygonHierarchy;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n\r\n return computeRectangle(\r\n polygonHierarchy.positions,\r\n ellipsoid,\r\n arcType,\r\n granularity,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a polygon, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {PolygonGeometry} polygonGeometry A description of the polygon.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nPolygonGeometry.createGeometry = function (polygonGeometry) {\r\n var vertexFormat = polygonGeometry._vertexFormat;\r\n var ellipsoid = polygonGeometry._ellipsoid;\r\n var granularity = polygonGeometry._granularity;\r\n var stRotation = polygonGeometry._stRotation;\r\n var polygonHierarchy = polygonGeometry._polygonHierarchy;\r\n var perPositionHeight = polygonGeometry._perPositionHeight;\r\n var closeTop = polygonGeometry._closeTop;\r\n var closeBottom = polygonGeometry._closeBottom;\r\n var arcType = polygonGeometry._arcType;\r\n\r\n var outerPositions = polygonHierarchy.positions;\r\n if (outerPositions.length < 3) {\r\n return;\r\n }\r\n\r\n var tangentPlane = EllipsoidTangentPlane.fromPoints(\r\n outerPositions,\r\n ellipsoid\r\n );\r\n\r\n var results = PolygonGeometryLibrary.polygonsFromHierarchy(\r\n polygonHierarchy,\r\n tangentPlane.projectPointsOntoPlane.bind(tangentPlane),\r\n !perPositionHeight,\r\n ellipsoid\r\n );\r\n\r\n var hierarchy = results.hierarchy;\r\n var polygons = results.polygons;\r\n\r\n if (hierarchy.length === 0) {\r\n return;\r\n }\r\n\r\n outerPositions = hierarchy[0].outerRing;\r\n var boundingRectangle = PolygonGeometryLibrary.computeBoundingRectangle(\r\n tangentPlane.plane.normal,\r\n tangentPlane.projectPointOntoPlane.bind(tangentPlane),\r\n outerPositions,\r\n stRotation,\r\n scratchBoundingRectangle\r\n );\r\n\r\n var geometries = [];\r\n\r\n var height = polygonGeometry._height;\r\n var extrudedHeight = polygonGeometry._extrudedHeight;\r\n var extrude =\r\n polygonGeometry._perPositionHeightExtrude ||\r\n !CesiumMath.equalsEpsilon(height, extrudedHeight, 0, CesiumMath.EPSILON2);\r\n\r\n var options = {\r\n perPositionHeight: perPositionHeight,\r\n vertexFormat: vertexFormat,\r\n geometry: undefined,\r\n tangentPlane: tangentPlane,\r\n boundingRectangle: boundingRectangle,\r\n ellipsoid: ellipsoid,\r\n stRotation: stRotation,\r\n bottom: false,\r\n top: true,\r\n wall: false,\r\n extrude: false,\r\n arcType: arcType,\r\n };\r\n\r\n var i;\r\n\r\n if (extrude) {\r\n options.extrude = true;\r\n options.top = closeTop;\r\n options.bottom = closeBottom;\r\n options.shadowVolume = polygonGeometry._shadowVolume;\r\n options.offsetAttribute = polygonGeometry._offsetAttribute;\r\n for (i = 0; i < polygons.length; i++) {\r\n var splitGeometry = createGeometryFromPositionsExtruded(\r\n ellipsoid,\r\n polygons[i],\r\n granularity,\r\n hierarchy[i],\r\n perPositionHeight,\r\n closeTop,\r\n closeBottom,\r\n vertexFormat,\r\n arcType\r\n );\r\n\r\n var topAndBottom;\r\n if (closeTop && closeBottom) {\r\n topAndBottom = splitGeometry.topAndBottom;\r\n options.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(\r\n topAndBottom.geometry,\r\n height,\r\n extrudedHeight,\r\n ellipsoid,\r\n perPositionHeight\r\n );\r\n } else if (closeTop) {\r\n topAndBottom = splitGeometry.topAndBottom;\r\n topAndBottom.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(\r\n topAndBottom.geometry.attributes.position.values,\r\n height,\r\n ellipsoid,\r\n !perPositionHeight\r\n );\r\n options.geometry = topAndBottom.geometry;\r\n } else if (closeBottom) {\r\n topAndBottom = splitGeometry.topAndBottom;\r\n topAndBottom.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(\r\n topAndBottom.geometry.attributes.position.values,\r\n extrudedHeight,\r\n ellipsoid,\r\n true\r\n );\r\n options.geometry = topAndBottom.geometry;\r\n }\r\n if (closeTop || closeBottom) {\r\n options.wall = false;\r\n topAndBottom.geometry = computeAttributes(options);\r\n geometries.push(topAndBottom);\r\n }\r\n\r\n var walls = splitGeometry.walls;\r\n options.wall = true;\r\n for (var k = 0; k < walls.length; k++) {\r\n var wall = walls[k];\r\n options.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(\r\n wall.geometry,\r\n height,\r\n extrudedHeight,\r\n ellipsoid,\r\n perPositionHeight\r\n );\r\n wall.geometry = computeAttributes(options);\r\n geometries.push(wall);\r\n }\r\n }\r\n } else {\r\n for (i = 0; i < polygons.length; i++) {\r\n var geometryInstance = new GeometryInstance({\r\n geometry: PolygonGeometryLibrary.createGeometryFromPositions(\r\n ellipsoid,\r\n polygons[i],\r\n granularity,\r\n perPositionHeight,\r\n vertexFormat,\r\n arcType\r\n ),\r\n });\r\n geometryInstance.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(\r\n geometryInstance.geometry.attributes.position.values,\r\n height,\r\n ellipsoid,\r\n !perPositionHeight\r\n );\r\n options.geometry = geometryInstance.geometry;\r\n geometryInstance.geometry = computeAttributes(options);\r\n\r\n if (defined(polygonGeometry._offsetAttribute)) {\r\n var length =\r\n geometryInstance.geometry.attributes.position.values.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n polygonGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute(\r\n {\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n }\r\n );\r\n }\r\n\r\n geometries.push(geometryInstance);\r\n }\r\n }\r\n\r\n var geometry = GeometryPipeline.combineInstances(geometries)[0];\r\n geometry.attributes.position.values = new Float64Array(\r\n geometry.attributes.position.values\r\n );\r\n geometry.indices = IndexDatatype.createTypedArray(\r\n geometry.attributes.position.values.length / 3,\r\n geometry.indices\r\n );\r\n\r\n var attributes = geometry.attributes;\r\n var boundingSphere = BoundingSphere.fromVertices(attributes.position.values);\r\n\r\n if (!vertexFormat.position) {\r\n delete attributes.position;\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: geometry.indices,\r\n primitiveType: geometry.primitiveType,\r\n boundingSphere: boundingSphere,\r\n offsetAttribute: polygonGeometry._offsetAttribute,\r\n });\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPolygonGeometry.createShadowVolume = function (\r\n polygonGeometry,\r\n minHeightFunc,\r\n maxHeightFunc\r\n) {\r\n var granularity = polygonGeometry._granularity;\r\n var ellipsoid = polygonGeometry._ellipsoid;\r\n\r\n var minHeight = minHeightFunc(granularity, ellipsoid);\r\n var maxHeight = maxHeightFunc(granularity, ellipsoid);\r\n\r\n return new PolygonGeometry({\r\n polygonHierarchy: polygonGeometry._polygonHierarchy,\r\n ellipsoid: ellipsoid,\r\n stRotation: polygonGeometry._stRotation,\r\n granularity: granularity,\r\n perPositionHeight: false,\r\n extrudedHeight: minHeight,\r\n height: maxHeight,\r\n vertexFormat: VertexFormat.POSITION_ONLY,\r\n shadowVolume: true,\r\n arcType: polygonGeometry._arcType,\r\n });\r\n};\r\n\r\nfunction textureCoordinateRotationPoints(polygonGeometry) {\r\n var stRotation = -polygonGeometry._stRotation;\r\n if (stRotation === 0.0) {\r\n return [0, 0, 0, 1, 1, 0];\r\n }\r\n var ellipsoid = polygonGeometry._ellipsoid;\r\n var positions = polygonGeometry._polygonHierarchy.positions;\r\n var boundingRectangle = polygonGeometry.rectangle;\r\n return Geometry._textureCoordinateRotationPoints(\r\n positions,\r\n stRotation,\r\n ellipsoid,\r\n boundingRectangle\r\n );\r\n}\r\n\r\nObject.defineProperties(PolygonGeometry.prototype, {\r\n /**\r\n * @private\r\n */\r\n rectangle: {\r\n get: function () {\r\n if (!defined(this._rectangle)) {\r\n var positions = this._polygonHierarchy.positions;\r\n this._rectangle = computeRectangle(\r\n positions,\r\n this._ellipsoid,\r\n this._arcType,\r\n this._granularity\r\n );\r\n }\r\n\r\n return this._rectangle;\r\n },\r\n },\r\n /**\r\n * For remapping texture coordinates when rendering PolygonGeometries as GroundPrimitives.\r\n * @private\r\n */\r\n textureCoordinateRotationPoints: {\r\n get: function () {\r\n if (!defined(this._textureCoordinateRotationPoints)) {\r\n this._textureCoordinateRotationPoints = textureCoordinateRotationPoints(\r\n this\r\n );\r\n }\r\n return this._textureCoordinateRotationPoints;\r\n },\r\n },\r\n});\r\nexport default PolygonGeometry;\r\n","import defined from \"./defined.js\";\r\n\r\n/**\r\n * An hierarchy of linear rings which define a polygon and its holes.\r\n * The holes themselves may also have holes which nest inner polygons.\r\n * @alias PolygonHierarchy\r\n * @constructor\r\n *\r\n * @param {Cartesian3[]} [positions] A linear ring defining the outer boundary of the polygon or hole.\r\n * @param {PolygonHierarchy[]} [holes] An array of polygon hierarchies defining holes in the polygon.\r\n */\r\nfunction PolygonHierarchy(positions, holes) {\r\n /**\r\n * A linear ring defining the outer boundary of the polygon or hole.\r\n * @type {Cartesian3[]}\r\n */\r\n this.positions = defined(positions) ? positions : [];\r\n\r\n /**\r\n * An array of polygon hierarchies defining holes in the polygon.\r\n * @type {PolygonHierarchy[]}\r\n */\r\n this.holes = defined(holes) ? holes : [];\r\n}\r\nexport default PolygonHierarchy;\r\n","import ArcType from \"./ArcType.js\";\r\nimport arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport EllipsoidTangentPlane from \"./EllipsoidTangentPlane.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryInstance from \"./GeometryInstance.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport GeometryPipeline from \"./GeometryPipeline.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PolygonGeometryLibrary from \"./PolygonGeometryLibrary.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport WindingOrder from \"./WindingOrder.js\";\r\nvar createGeometryFromPositionsPositions = [];\r\nvar createGeometryFromPositionsSubdivided = [];\r\n\r\nfunction createGeometryFromPositions(\r\n ellipsoid,\r\n positions,\r\n minDistance,\r\n perPositionHeight,\r\n arcType\r\n) {\r\n var tangentPlane = EllipsoidTangentPlane.fromPoints(positions, ellipsoid);\r\n var positions2D = tangentPlane.projectPointsOntoPlane(\r\n positions,\r\n createGeometryFromPositionsPositions\r\n );\r\n\r\n var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D);\r\n if (originalWindingOrder === WindingOrder.CLOCKWISE) {\r\n positions2D.reverse();\r\n positions = positions.slice().reverse();\r\n }\r\n\r\n var subdividedPositions;\r\n var i;\r\n\r\n var length = positions.length;\r\n var index = 0;\r\n\r\n if (!perPositionHeight) {\r\n var numVertices = 0;\r\n if (arcType === ArcType.GEODESIC) {\r\n for (i = 0; i < length; i++) {\r\n numVertices += PolygonGeometryLibrary.subdivideLineCount(\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance\r\n );\r\n }\r\n } else if (arcType === ArcType.RHUMB) {\r\n for (i = 0; i < length; i++) {\r\n numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(\r\n ellipsoid,\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance\r\n );\r\n }\r\n }\r\n subdividedPositions = new Float64Array(numVertices * 3);\r\n for (i = 0; i < length; i++) {\r\n var tempPositions;\r\n if (arcType === ArcType.GEODESIC) {\r\n tempPositions = PolygonGeometryLibrary.subdivideLine(\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance,\r\n createGeometryFromPositionsSubdivided\r\n );\r\n } else if (arcType === ArcType.RHUMB) {\r\n tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(\r\n ellipsoid,\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance,\r\n createGeometryFromPositionsSubdivided\r\n );\r\n }\r\n var tempPositionsLength = tempPositions.length;\r\n for (var j = 0; j < tempPositionsLength; ++j) {\r\n subdividedPositions[index++] = tempPositions[j];\r\n }\r\n }\r\n } else {\r\n subdividedPositions = new Float64Array(length * 2 * 3);\r\n for (i = 0; i < length; i++) {\r\n var p0 = positions[i];\r\n var p1 = positions[(i + 1) % length];\r\n subdividedPositions[index++] = p0.x;\r\n subdividedPositions[index++] = p0.y;\r\n subdividedPositions[index++] = p0.z;\r\n subdividedPositions[index++] = p1.x;\r\n subdividedPositions[index++] = p1.y;\r\n subdividedPositions[index++] = p1.z;\r\n }\r\n }\r\n\r\n length = subdividedPositions.length / 3;\r\n var indicesSize = length * 2;\r\n var indices = IndexDatatype.createTypedArray(length, indicesSize);\r\n index = 0;\r\n for (i = 0; i < length - 1; i++) {\r\n indices[index++] = i;\r\n indices[index++] = i + 1;\r\n }\r\n indices[index++] = length - 1;\r\n indices[index++] = 0;\r\n\r\n return new GeometryInstance({\r\n geometry: new Geometry({\r\n attributes: new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: subdividedPositions,\r\n }),\r\n }),\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n }),\r\n });\r\n}\r\n\r\nfunction createGeometryFromPositionsExtruded(\r\n ellipsoid,\r\n positions,\r\n minDistance,\r\n perPositionHeight,\r\n arcType\r\n) {\r\n var tangentPlane = EllipsoidTangentPlane.fromPoints(positions, ellipsoid);\r\n var positions2D = tangentPlane.projectPointsOntoPlane(\r\n positions,\r\n createGeometryFromPositionsPositions\r\n );\r\n\r\n var originalWindingOrder = PolygonPipeline.computeWindingOrder2D(positions2D);\r\n if (originalWindingOrder === WindingOrder.CLOCKWISE) {\r\n positions2D.reverse();\r\n positions = positions.slice().reverse();\r\n }\r\n\r\n var subdividedPositions;\r\n var i;\r\n\r\n var length = positions.length;\r\n var corners = new Array(length);\r\n var index = 0;\r\n\r\n if (!perPositionHeight) {\r\n var numVertices = 0;\r\n if (arcType === ArcType.GEODESIC) {\r\n for (i = 0; i < length; i++) {\r\n numVertices += PolygonGeometryLibrary.subdivideLineCount(\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance\r\n );\r\n }\r\n } else if (arcType === ArcType.RHUMB) {\r\n for (i = 0; i < length; i++) {\r\n numVertices += PolygonGeometryLibrary.subdivideRhumbLineCount(\r\n ellipsoid,\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance\r\n );\r\n }\r\n }\r\n\r\n subdividedPositions = new Float64Array(numVertices * 3 * 2);\r\n for (i = 0; i < length; ++i) {\r\n corners[i] = index / 3;\r\n var tempPositions;\r\n if (arcType === ArcType.GEODESIC) {\r\n tempPositions = PolygonGeometryLibrary.subdivideLine(\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance,\r\n createGeometryFromPositionsSubdivided\r\n );\r\n } else if (arcType === ArcType.RHUMB) {\r\n tempPositions = PolygonGeometryLibrary.subdivideRhumbLine(\r\n ellipsoid,\r\n positions[i],\r\n positions[(i + 1) % length],\r\n minDistance,\r\n createGeometryFromPositionsSubdivided\r\n );\r\n }\r\n var tempPositionsLength = tempPositions.length;\r\n for (var j = 0; j < tempPositionsLength; ++j) {\r\n subdividedPositions[index++] = tempPositions[j];\r\n }\r\n }\r\n } else {\r\n subdividedPositions = new Float64Array(length * 2 * 3 * 2);\r\n for (i = 0; i < length; ++i) {\r\n corners[i] = index / 3;\r\n var p0 = positions[i];\r\n var p1 = positions[(i + 1) % length];\r\n\r\n subdividedPositions[index++] = p0.x;\r\n subdividedPositions[index++] = p0.y;\r\n subdividedPositions[index++] = p0.z;\r\n subdividedPositions[index++] = p1.x;\r\n subdividedPositions[index++] = p1.y;\r\n subdividedPositions[index++] = p1.z;\r\n }\r\n }\r\n\r\n length = subdividedPositions.length / (3 * 2);\r\n var cornersLength = corners.length;\r\n\r\n var indicesSize = (length * 2 + cornersLength) * 2;\r\n var indices = IndexDatatype.createTypedArray(\r\n length + cornersLength,\r\n indicesSize\r\n );\r\n\r\n index = 0;\r\n for (i = 0; i < length; ++i) {\r\n indices[index++] = i;\r\n indices[index++] = (i + 1) % length;\r\n indices[index++] = i + length;\r\n indices[index++] = ((i + 1) % length) + length;\r\n }\r\n\r\n for (i = 0; i < cornersLength; i++) {\r\n var corner = corners[i];\r\n indices[index++] = corner;\r\n indices[index++] = corner + length;\r\n }\r\n\r\n return new GeometryInstance({\r\n geometry: new Geometry({\r\n attributes: new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: subdividedPositions,\r\n }),\r\n }),\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n }),\r\n });\r\n}\r\n\r\n/**\r\n * A description of the outline of a polygon on the ellipsoid. The polygon is defined by a polygon hierarchy.\r\n *\r\n * @alias PolygonOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {PolygonHierarchy} options.polygonHierarchy A polygon hierarchy that can include holes.\r\n * @param {Number} [options.height=0.0] The distance in meters between the polygon and the ellipsoid surface.\r\n * @param {Number} [options.extrudedHeight] The distance in meters between the polygon's extruded face and the ellipsoid surface.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.\r\n * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of path the outline must follow. Valid options are {@link ArcType.GEODESIC} and {@link ArcType.RHUMB}.\r\n *\r\n * @see PolygonOutlineGeometry#createGeometry\r\n * @see PolygonOutlineGeometry#fromPositions\r\n *\r\n * @example\r\n * // 1. create a polygon outline from points\r\n * var polygon = new Cesium.PolygonOutlineGeometry({\r\n * polygonHierarchy : new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ])\r\n * )\r\n * });\r\n * var geometry = Cesium.PolygonOutlineGeometry.createGeometry(polygon);\r\n *\r\n * // 2. create a nested polygon with holes outline\r\n * var polygonWithHole = new Cesium.PolygonOutlineGeometry({\r\n * polygonHierarchy : new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -109.0, 30.0,\r\n * -95.0, 30.0,\r\n * -95.0, 40.0,\r\n * -109.0, 40.0\r\n * ]),\r\n * [new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -107.0, 31.0,\r\n * -107.0, 39.0,\r\n * -97.0, 39.0,\r\n * -97.0, 31.0\r\n * ]),\r\n * [new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -105.0, 33.0,\r\n * -99.0, 33.0,\r\n * -99.0, 37.0,\r\n * -105.0, 37.0\r\n * ]),\r\n * [new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -103.0, 34.0,\r\n * -101.0, 34.0,\r\n * -101.0, 36.0,\r\n * -103.0, 36.0\r\n * ])\r\n * )]\r\n * )]\r\n * )]\r\n * )\r\n * });\r\n * var geometry = Cesium.PolygonOutlineGeometry.createGeometry(polygonWithHole);\r\n *\r\n * // 3. create extruded polygon outline\r\n * var extrudedPolygon = new Cesium.PolygonOutlineGeometry({\r\n * polygonHierarchy : new Cesium.PolygonHierarchy(\r\n * Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ])\r\n * ),\r\n * extrudedHeight: 300000\r\n * });\r\n * var geometry = Cesium.PolygonOutlineGeometry.createGeometry(extrudedPolygon);\r\n */\r\nfunction PolygonOutlineGeometry(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.object(\"options.polygonHierarchy\", options.polygonHierarchy);\r\n\r\n if (options.perPositionHeight && defined(options.height)) {\r\n throw new DeveloperError(\r\n \"Cannot use both options.perPositionHeight and options.height\"\r\n );\r\n }\r\n if (\r\n defined(options.arcType) &&\r\n options.arcType !== ArcType.GEODESIC &&\r\n options.arcType !== ArcType.RHUMB\r\n ) {\r\n throw new DeveloperError(\r\n \"Invalid arcType. Valid options are ArcType.GEODESIC and ArcType.RHUMB.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var polygonHierarchy = options.polygonHierarchy;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var perPositionHeight = defaultValue(options.perPositionHeight, false);\r\n var perPositionHeightExtrude =\r\n perPositionHeight && defined(options.extrudedHeight);\r\n var arcType = defaultValue(options.arcType, ArcType.GEODESIC);\r\n\r\n var height = defaultValue(options.height, 0.0);\r\n var extrudedHeight = defaultValue(options.extrudedHeight, height);\r\n\r\n if (!perPositionHeightExtrude) {\r\n var h = Math.max(height, extrudedHeight);\r\n extrudedHeight = Math.min(height, extrudedHeight);\r\n height = h;\r\n }\r\n\r\n this._ellipsoid = Ellipsoid.clone(ellipsoid);\r\n this._granularity = granularity;\r\n this._height = height;\r\n this._extrudedHeight = extrudedHeight;\r\n this._arcType = arcType;\r\n this._polygonHierarchy = polygonHierarchy;\r\n this._perPositionHeight = perPositionHeight;\r\n this._perPositionHeightExtrude = perPositionHeightExtrude;\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createPolygonOutlineGeometry\";\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n PolygonGeometryLibrary.computeHierarchyPackedLength(polygonHierarchy) +\r\n Ellipsoid.packedLength +\r\n 8;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PolygonOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nPolygonOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n startingIndex = PolygonGeometryLibrary.packPolygonHierarchy(\r\n value._polygonHierarchy,\r\n array,\r\n startingIndex\r\n );\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n array[startingIndex++] = value._height;\r\n array[startingIndex++] = value._extrudedHeight;\r\n array[startingIndex++] = value._granularity;\r\n array[startingIndex++] = value._perPositionHeightExtrude ? 1.0 : 0.0;\r\n array[startingIndex++] = value._perPositionHeight ? 1.0 : 0.0;\r\n array[startingIndex++] = value._arcType;\r\n array[startingIndex++] = defaultValue(value._offsetAttribute, -1);\r\n array[startingIndex] = value.packedLength;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar dummyOptions = {\r\n polygonHierarchy: {},\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PolygonOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {PolygonOutlineGeometry} The modified result parameter or a new PolygonOutlineGeometry instance if one was not provided.\r\n */\r\nPolygonOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var polygonHierarchy = PolygonGeometryLibrary.unpackPolygonHierarchy(\r\n array,\r\n startingIndex\r\n );\r\n startingIndex = polygonHierarchy.startingIndex;\r\n delete polygonHierarchy.startingIndex;\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var height = array[startingIndex++];\r\n var extrudedHeight = array[startingIndex++];\r\n var granularity = array[startingIndex++];\r\n var perPositionHeightExtrude = array[startingIndex++] === 1.0;\r\n var perPositionHeight = array[startingIndex++] === 1.0;\r\n var arcType = array[startingIndex++];\r\n var offsetAttribute = array[startingIndex++];\r\n var packedLength = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n result = new PolygonOutlineGeometry(dummyOptions);\r\n }\r\n\r\n result._polygonHierarchy = polygonHierarchy;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._height = height;\r\n result._extrudedHeight = extrudedHeight;\r\n result._granularity = granularity;\r\n result._perPositionHeight = perPositionHeight;\r\n result._perPositionHeightExtrude = perPositionHeightExtrude;\r\n result._arcType = arcType;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n result.packedLength = packedLength;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * A description of a polygon outline from an array of positions.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of positions that defined the corner points of the polygon.\r\n * @param {Number} [options.height=0.0] The height of the polygon.\r\n * @param {Number} [options.extrudedHeight] The height of the polygon extrusion.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Boolean} [options.perPositionHeight=false] Use the height of options.positions for each position instead of using options.height to determine the height.\r\n * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of path the outline must follow. Valid options are {@link LinkType.GEODESIC} and {@link ArcType.RHUMB}.\r\n * @returns {PolygonOutlineGeometry}\r\n *\r\n *\r\n * @example\r\n * // create a polygon from points\r\n * var polygon = Cesium.PolygonOutlineGeometry.fromPositions({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0,\r\n * -75.0, 30.0,\r\n * -70.0, 30.0,\r\n * -68.0, 40.0\r\n * ])\r\n * });\r\n * var geometry = Cesium.PolygonOutlineGeometry.createGeometry(polygon);\r\n *\r\n * @see PolygonOutlineGeometry#createGeometry\r\n */\r\nPolygonOutlineGeometry.fromPositions = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.positions\", options.positions);\r\n //>>includeEnd('debug');\r\n\r\n var newOptions = {\r\n polygonHierarchy: {\r\n positions: options.positions,\r\n },\r\n height: options.height,\r\n extrudedHeight: options.extrudedHeight,\r\n ellipsoid: options.ellipsoid,\r\n granularity: options.granularity,\r\n perPositionHeight: options.perPositionHeight,\r\n arcType: options.arcType,\r\n offsetAttribute: options.offsetAttribute,\r\n };\r\n return new PolygonOutlineGeometry(newOptions);\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a polygon outline, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {PolygonOutlineGeometry} polygonGeometry A description of the polygon outline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nPolygonOutlineGeometry.createGeometry = function (polygonGeometry) {\r\n var ellipsoid = polygonGeometry._ellipsoid;\r\n var granularity = polygonGeometry._granularity;\r\n var polygonHierarchy = polygonGeometry._polygonHierarchy;\r\n var perPositionHeight = polygonGeometry._perPositionHeight;\r\n var arcType = polygonGeometry._arcType;\r\n\r\n var polygons = PolygonGeometryLibrary.polygonOutlinesFromHierarchy(\r\n polygonHierarchy,\r\n !perPositionHeight,\r\n ellipsoid\r\n );\r\n\r\n if (polygons.length === 0) {\r\n return undefined;\r\n }\r\n\r\n var geometryInstance;\r\n var geometries = [];\r\n var minDistance = CesiumMath.chordLength(\r\n granularity,\r\n ellipsoid.maximumRadius\r\n );\r\n\r\n var height = polygonGeometry._height;\r\n var extrudedHeight = polygonGeometry._extrudedHeight;\r\n var extrude =\r\n polygonGeometry._perPositionHeightExtrude ||\r\n !CesiumMath.equalsEpsilon(height, extrudedHeight, 0, CesiumMath.EPSILON2);\r\n var offsetValue;\r\n var i;\r\n if (extrude) {\r\n for (i = 0; i < polygons.length; i++) {\r\n geometryInstance = createGeometryFromPositionsExtruded(\r\n ellipsoid,\r\n polygons[i],\r\n minDistance,\r\n perPositionHeight,\r\n arcType\r\n );\r\n geometryInstance.geometry = PolygonGeometryLibrary.scaleToGeodeticHeightExtruded(\r\n geometryInstance.geometry,\r\n height,\r\n extrudedHeight,\r\n ellipsoid,\r\n perPositionHeight\r\n );\r\n if (defined(polygonGeometry._offsetAttribute)) {\r\n var size =\r\n geometryInstance.geometry.attributes.position.values.length / 3;\r\n var offsetAttribute = new Uint8Array(size);\r\n if (polygonGeometry._offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);\r\n } else {\r\n offsetValue =\r\n polygonGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n offsetAttribute = arrayFill(offsetAttribute, offsetValue);\r\n }\r\n\r\n geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute(\r\n {\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: offsetAttribute,\r\n }\r\n );\r\n }\r\n geometries.push(geometryInstance);\r\n }\r\n } else {\r\n for (i = 0; i < polygons.length; i++) {\r\n geometryInstance = createGeometryFromPositions(\r\n ellipsoid,\r\n polygons[i],\r\n minDistance,\r\n perPositionHeight,\r\n arcType\r\n );\r\n geometryInstance.geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(\r\n geometryInstance.geometry.attributes.position.values,\r\n height,\r\n ellipsoid,\r\n !perPositionHeight\r\n );\r\n\r\n if (defined(polygonGeometry._offsetAttribute)) {\r\n var length =\r\n geometryInstance.geometry.attributes.position.values.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n offsetValue =\r\n polygonGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n geometryInstance.geometry.attributes.applyOffset = new GeometryAttribute(\r\n {\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n }\r\n );\r\n }\r\n\r\n geometries.push(geometryInstance);\r\n }\r\n }\r\n\r\n var geometry = GeometryPipeline.combineInstances(geometries)[0];\r\n var boundingSphere = BoundingSphere.fromVertices(\r\n geometry.attributes.position.values\r\n );\r\n\r\n return new Geometry({\r\n attributes: geometry.attributes,\r\n indices: geometry.indices,\r\n primitiveType: geometry.primitiveType,\r\n boundingSphere: boundingSphere,\r\n offsetAttribute: polygonGeometry._offsetAttribute,\r\n });\r\n};\r\nexport default PolygonOutlineGeometry;\r\n","import ArcType from \"./ArcType.js\";\r\nimport arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Color from \"./Color.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryType from \"./GeometryType.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PolylinePipeline from \"./PolylinePipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar scratchInterpolateColorsArray = [];\r\n\r\nfunction interpolateColors(p0, p1, color0, color1, numPoints) {\r\n var colors = scratchInterpolateColorsArray;\r\n colors.length = numPoints;\r\n var i;\r\n\r\n var r0 = color0.red;\r\n var g0 = color0.green;\r\n var b0 = color0.blue;\r\n var a0 = color0.alpha;\r\n\r\n var r1 = color1.red;\r\n var g1 = color1.green;\r\n var b1 = color1.blue;\r\n var a1 = color1.alpha;\r\n\r\n if (Color.equals(color0, color1)) {\r\n for (i = 0; i < numPoints; i++) {\r\n colors[i] = Color.clone(color0);\r\n }\r\n return colors;\r\n }\r\n\r\n var redPerVertex = (r1 - r0) / numPoints;\r\n var greenPerVertex = (g1 - g0) / numPoints;\r\n var bluePerVertex = (b1 - b0) / numPoints;\r\n var alphaPerVertex = (a1 - a0) / numPoints;\r\n\r\n for (i = 0; i < numPoints; i++) {\r\n colors[i] = new Color(\r\n r0 + i * redPerVertex,\r\n g0 + i * greenPerVertex,\r\n b0 + i * bluePerVertex,\r\n a0 + i * alphaPerVertex\r\n );\r\n }\r\n\r\n return colors;\r\n}\r\n\r\n/**\r\n * A description of a polyline modeled as a line strip; the first two positions define a line segment,\r\n * and each additional position defines a line segment from the previous position. The polyline is capable of\r\n * displaying with a material.\r\n *\r\n * @alias PolylineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of {@link Cartesian3} defining the positions in the polyline as a line strip.\r\n * @param {Number} [options.width=1.0] The width in pixels.\r\n * @param {Color[]} [options.colors] An Array of {@link Color} defining the per vertex or per segment colors.\r\n * @param {Boolean} [options.colorsPerVertex=false] A boolean that determines whether the colors will be flat across each segment of the line or interpolated across the vertices.\r\n * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polyline segments must follow.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude if options.arcType is not ArcType.NONE. Determines the number of positions in the buffer.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n *\r\n * @exception {DeveloperError} At least two positions are required.\r\n * @exception {DeveloperError} width must be greater than or equal to one.\r\n * @exception {DeveloperError} colors has an invalid length.\r\n *\r\n * @see PolylineGeometry#createGeometry\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Polyline.html|Cesium Sandcastle Polyline Demo}\r\n *\r\n * @example\r\n * // A polyline with two connected line segments\r\n * var polyline = new Cesium.PolylineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * 0.0, 0.0,\r\n * 5.0, 0.0,\r\n * 5.0, 5.0\r\n * ]),\r\n * width : 10.0\r\n * });\r\n * var geometry = Cesium.PolylineGeometry.createGeometry(polyline);\r\n */\r\nfunction PolylineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.positions;\r\n var colors = options.colors;\r\n var width = defaultValue(options.width, 1.0);\r\n var colorsPerVertex = defaultValue(options.colorsPerVertex, false);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions) || positions.length < 2) {\r\n throw new DeveloperError(\"At least two positions are required.\");\r\n }\r\n if (typeof width !== \"number\") {\r\n throw new DeveloperError(\"width must be a number\");\r\n }\r\n if (\r\n defined(colors) &&\r\n ((colorsPerVertex && colors.length < positions.length) ||\r\n (!colorsPerVertex && colors.length < positions.length - 1))\r\n ) {\r\n throw new DeveloperError(\"colors has an invalid length.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._positions = positions;\r\n this._colors = colors;\r\n this._width = width;\r\n this._colorsPerVertex = colorsPerVertex;\r\n this._vertexFormat = VertexFormat.clone(\r\n defaultValue(options.vertexFormat, VertexFormat.DEFAULT)\r\n );\r\n\r\n this._arcType = defaultValue(options.arcType, ArcType.GEODESIC);\r\n this._granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n this._ellipsoid = Ellipsoid.clone(\r\n defaultValue(options.ellipsoid, Ellipsoid.WGS84)\r\n );\r\n this._workerName = \"createPolylineGeometry\";\r\n\r\n var numComponents = 1 + positions.length * Cartesian3.packedLength;\r\n numComponents += defined(colors) ? 1 + colors.length * Color.packedLength : 1;\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n numComponents + Ellipsoid.packedLength + VertexFormat.packedLength + 4;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PolylineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nPolylineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var positions = value._positions;\r\n var length = positions.length;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n\r\n var colors = value._colors;\r\n length = defined(colors) ? colors.length : 0.0;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Color.packedLength) {\r\n Color.pack(colors[i], array, startingIndex);\r\n }\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._width;\r\n array[startingIndex++] = value._colorsPerVertex ? 1.0 : 0.0;\r\n array[startingIndex++] = value._arcType;\r\n array[startingIndex] = value._granularity;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n positions: undefined,\r\n colors: undefined,\r\n ellipsoid: scratchEllipsoid,\r\n vertexFormat: scratchVertexFormat,\r\n width: undefined,\r\n colorsPerVertex: undefined,\r\n arcType: undefined,\r\n granularity: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PolylineGeometry} [result] The object into which to store the result.\r\n * @returns {PolylineGeometry} The modified result parameter or a new PolylineGeometry instance if one was not provided.\r\n */\r\nPolylineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var length = array[startingIndex++];\r\n var positions = new Array(length);\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n length = array[startingIndex++];\r\n var colors = length > 0 ? new Array(length) : undefined;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Color.packedLength) {\r\n colors[i] = Color.unpack(array, startingIndex);\r\n }\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var width = array[startingIndex++];\r\n var colorsPerVertex = array[startingIndex++] === 1.0;\r\n var arcType = array[startingIndex++];\r\n var granularity = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.positions = positions;\r\n scratchOptions.colors = colors;\r\n scratchOptions.width = width;\r\n scratchOptions.colorsPerVertex = colorsPerVertex;\r\n scratchOptions.arcType = arcType;\r\n scratchOptions.granularity = granularity;\r\n return new PolylineGeometry(scratchOptions);\r\n }\r\n\r\n result._positions = positions;\r\n result._colors = colors;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._width = width;\r\n result._colorsPerVertex = colorsPerVertex;\r\n result._arcType = arcType;\r\n result._granularity = granularity;\r\n\r\n return result;\r\n};\r\n\r\nvar scratchCartesian3 = new Cartesian3();\r\nvar scratchPosition = new Cartesian3();\r\nvar scratchPrevPosition = new Cartesian3();\r\nvar scratchNextPosition = new Cartesian3();\r\n\r\n/**\r\n * Computes the geometric representation of a polyline, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {PolylineGeometry} polylineGeometry A description of the polyline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nPolylineGeometry.createGeometry = function (polylineGeometry) {\r\n var width = polylineGeometry._width;\r\n var vertexFormat = polylineGeometry._vertexFormat;\r\n var colors = polylineGeometry._colors;\r\n var colorsPerVertex = polylineGeometry._colorsPerVertex;\r\n var arcType = polylineGeometry._arcType;\r\n var granularity = polylineGeometry._granularity;\r\n var ellipsoid = polylineGeometry._ellipsoid;\r\n\r\n var i;\r\n var j;\r\n var k;\r\n\r\n var positions = arrayRemoveDuplicates(\r\n polylineGeometry._positions,\r\n Cartesian3.equalsEpsilon\r\n );\r\n var positionsLength = positions.length;\r\n\r\n // A width of a pixel or less is not a valid geometry, but in order to support external data\r\n // that may have errors we treat this as an empty geometry.\r\n if (positionsLength < 2 || width <= 0.0) {\r\n return undefined;\r\n }\r\n\r\n if (arcType === ArcType.GEODESIC || arcType === ArcType.RHUMB) {\r\n var subdivisionSize;\r\n var numberOfPointsFunction;\r\n if (arcType === ArcType.GEODESIC) {\r\n subdivisionSize = CesiumMath.chordLength(\r\n granularity,\r\n ellipsoid.maximumRadius\r\n );\r\n numberOfPointsFunction = PolylinePipeline.numberOfPoints;\r\n } else {\r\n subdivisionSize = granularity;\r\n numberOfPointsFunction = PolylinePipeline.numberOfPointsRhumbLine;\r\n }\r\n\r\n var heights = PolylinePipeline.extractHeights(positions, ellipsoid);\r\n\r\n if (defined(colors)) {\r\n var colorLength = 1;\r\n for (i = 0; i < positionsLength - 1; ++i) {\r\n colorLength += numberOfPointsFunction(\r\n positions[i],\r\n positions[i + 1],\r\n subdivisionSize\r\n );\r\n }\r\n\r\n var newColors = new Array(colorLength);\r\n var newColorIndex = 0;\r\n\r\n for (i = 0; i < positionsLength - 1; ++i) {\r\n var p0 = positions[i];\r\n var p1 = positions[i + 1];\r\n var c0 = colors[i];\r\n\r\n var numColors = numberOfPointsFunction(p0, p1, subdivisionSize);\r\n if (colorsPerVertex && i < colorLength) {\r\n var c1 = colors[i + 1];\r\n var interpolatedColors = interpolateColors(p0, p1, c0, c1, numColors);\r\n var interpolatedColorsLength = interpolatedColors.length;\r\n for (j = 0; j < interpolatedColorsLength; ++j) {\r\n newColors[newColorIndex++] = interpolatedColors[j];\r\n }\r\n } else {\r\n for (j = 0; j < numColors; ++j) {\r\n newColors[newColorIndex++] = Color.clone(c0);\r\n }\r\n }\r\n }\r\n\r\n newColors[newColorIndex] = Color.clone(colors[colors.length - 1]);\r\n colors = newColors;\r\n\r\n scratchInterpolateColorsArray.length = 0;\r\n }\r\n\r\n if (arcType === ArcType.GEODESIC) {\r\n positions = PolylinePipeline.generateCartesianArc({\r\n positions: positions,\r\n minDistance: subdivisionSize,\r\n ellipsoid: ellipsoid,\r\n height: heights,\r\n });\r\n } else {\r\n positions = PolylinePipeline.generateCartesianRhumbArc({\r\n positions: positions,\r\n granularity: subdivisionSize,\r\n ellipsoid: ellipsoid,\r\n height: heights,\r\n });\r\n }\r\n }\r\n\r\n positionsLength = positions.length;\r\n var size = positionsLength * 4.0 - 4.0;\r\n\r\n var finalPositions = new Float64Array(size * 3);\r\n var prevPositions = new Float64Array(size * 3);\r\n var nextPositions = new Float64Array(size * 3);\r\n var expandAndWidth = new Float32Array(size * 2);\r\n var st = vertexFormat.st ? new Float32Array(size * 2) : undefined;\r\n var finalColors = defined(colors) ? new Uint8Array(size * 4) : undefined;\r\n\r\n var positionIndex = 0;\r\n var expandAndWidthIndex = 0;\r\n var stIndex = 0;\r\n var colorIndex = 0;\r\n var position;\r\n\r\n for (j = 0; j < positionsLength; ++j) {\r\n if (j === 0) {\r\n position = scratchCartesian3;\r\n Cartesian3.subtract(positions[0], positions[1], position);\r\n Cartesian3.add(positions[0], position, position);\r\n } else {\r\n position = positions[j - 1];\r\n }\r\n\r\n Cartesian3.clone(position, scratchPrevPosition);\r\n Cartesian3.clone(positions[j], scratchPosition);\r\n\r\n if (j === positionsLength - 1) {\r\n position = scratchCartesian3;\r\n Cartesian3.subtract(\r\n positions[positionsLength - 1],\r\n positions[positionsLength - 2],\r\n position\r\n );\r\n Cartesian3.add(positions[positionsLength - 1], position, position);\r\n } else {\r\n position = positions[j + 1];\r\n }\r\n\r\n Cartesian3.clone(position, scratchNextPosition);\r\n\r\n var color0, color1;\r\n if (defined(finalColors)) {\r\n if (j !== 0 && !colorsPerVertex) {\r\n color0 = colors[j - 1];\r\n } else {\r\n color0 = colors[j];\r\n }\r\n\r\n if (j !== positionsLength - 1) {\r\n color1 = colors[j];\r\n }\r\n }\r\n\r\n var startK = j === 0 ? 2 : 0;\r\n var endK = j === positionsLength - 1 ? 2 : 4;\r\n\r\n for (k = startK; k < endK; ++k) {\r\n Cartesian3.pack(scratchPosition, finalPositions, positionIndex);\r\n Cartesian3.pack(scratchPrevPosition, prevPositions, positionIndex);\r\n Cartesian3.pack(scratchNextPosition, nextPositions, positionIndex);\r\n positionIndex += 3;\r\n\r\n var direction = k - 2 < 0 ? -1.0 : 1.0;\r\n expandAndWidth[expandAndWidthIndex++] = 2 * (k % 2) - 1; // expand direction\r\n expandAndWidth[expandAndWidthIndex++] = direction * width;\r\n\r\n if (vertexFormat.st) {\r\n st[stIndex++] = j / (positionsLength - 1);\r\n st[stIndex++] = Math.max(expandAndWidth[expandAndWidthIndex - 2], 0.0);\r\n }\r\n\r\n if (defined(finalColors)) {\r\n var color = k < 2 ? color0 : color1;\r\n\r\n finalColors[colorIndex++] = Color.floatToByte(color.red);\r\n finalColors[colorIndex++] = Color.floatToByte(color.green);\r\n finalColors[colorIndex++] = Color.floatToByte(color.blue);\r\n finalColors[colorIndex++] = Color.floatToByte(color.alpha);\r\n }\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: finalPositions,\r\n });\r\n\r\n attributes.prevPosition = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: prevPositions,\r\n });\r\n\r\n attributes.nextPosition = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: nextPositions,\r\n });\r\n\r\n attributes.expandAndWidth = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: expandAndWidth,\r\n });\r\n\r\n if (vertexFormat.st) {\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: st,\r\n });\r\n }\r\n\r\n if (defined(finalColors)) {\r\n attributes.color = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 4,\r\n values: finalColors,\r\n normalize: true,\r\n });\r\n }\r\n\r\n var indices = IndexDatatype.createTypedArray(size, positionsLength * 6 - 6);\r\n var index = 0;\r\n var indicesIndex = 0;\r\n var length = positionsLength - 1.0;\r\n for (j = 0; j < length; ++j) {\r\n indices[indicesIndex++] = index;\r\n indices[indicesIndex++] = index + 2;\r\n indices[indicesIndex++] = index + 1;\r\n\r\n indices[indicesIndex++] = index + 1;\r\n indices[indicesIndex++] = index + 2;\r\n indices[indicesIndex++] = index + 3;\r\n\r\n index += 4;\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: BoundingSphere.fromPoints(positions),\r\n geometryType: GeometryType.POLYLINES,\r\n });\r\n};\r\nexport default PolylineGeometry;\r\n","import arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport BoundingRectangle from \"./BoundingRectangle.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport CornerType from \"./CornerType.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryPipeline from \"./GeometryPipeline.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport oneTimeWarning from \"./oneTimeWarning.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PolylineVolumeGeometryLibrary from \"./PolylineVolumeGeometryLibrary.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\nimport WindingOrder from \"./WindingOrder.js\";\r\n\r\nfunction computeAttributes(\r\n combinedPositions,\r\n shape,\r\n boundingRectangle,\r\n vertexFormat\r\n) {\r\n var attributes = new GeometryAttributes();\r\n if (vertexFormat.position) {\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: combinedPositions,\r\n });\r\n }\r\n var shapeLength = shape.length;\r\n var vertexCount = combinedPositions.length / 3;\r\n var length = (vertexCount - shapeLength * 2) / (shapeLength * 2);\r\n var firstEndIndices = PolygonPipeline.triangulate(shape);\r\n\r\n var indicesCount =\r\n (length - 1) * shapeLength * 6 + firstEndIndices.length * 2;\r\n var indices = IndexDatatype.createTypedArray(vertexCount, indicesCount);\r\n var i, j;\r\n var ll, ul, ur, lr;\r\n var offset = shapeLength * 2;\r\n var index = 0;\r\n for (i = 0; i < length - 1; i++) {\r\n for (j = 0; j < shapeLength - 1; j++) {\r\n ll = j * 2 + i * shapeLength * 2;\r\n lr = ll + offset;\r\n ul = ll + 1;\r\n ur = ul + offset;\r\n\r\n indices[index++] = ul;\r\n indices[index++] = ll;\r\n indices[index++] = ur;\r\n indices[index++] = ur;\r\n indices[index++] = ll;\r\n indices[index++] = lr;\r\n }\r\n ll = shapeLength * 2 - 2 + i * shapeLength * 2;\r\n ul = ll + 1;\r\n ur = ul + offset;\r\n lr = ll + offset;\r\n\r\n indices[index++] = ul;\r\n indices[index++] = ll;\r\n indices[index++] = ur;\r\n indices[index++] = ur;\r\n indices[index++] = ll;\r\n indices[index++] = lr;\r\n }\r\n\r\n if (vertexFormat.st || vertexFormat.tangent || vertexFormat.bitangent) {\r\n // st required for tangent/bitangent calculation\r\n var st = new Float32Array(vertexCount * 2);\r\n var lengthSt = 1 / (length - 1);\r\n var heightSt = 1 / boundingRectangle.height;\r\n var heightOffset = boundingRectangle.height / 2;\r\n var s, t;\r\n var stindex = 0;\r\n for (i = 0; i < length; i++) {\r\n s = i * lengthSt;\r\n t = heightSt * (shape[0].y + heightOffset);\r\n st[stindex++] = s;\r\n st[stindex++] = t;\r\n for (j = 1; j < shapeLength; j++) {\r\n t = heightSt * (shape[j].y + heightOffset);\r\n st[stindex++] = s;\r\n st[stindex++] = t;\r\n st[stindex++] = s;\r\n st[stindex++] = t;\r\n }\r\n t = heightSt * (shape[0].y + heightOffset);\r\n st[stindex++] = s;\r\n st[stindex++] = t;\r\n }\r\n for (j = 0; j < shapeLength; j++) {\r\n s = 0;\r\n t = heightSt * (shape[j].y + heightOffset);\r\n st[stindex++] = s;\r\n st[stindex++] = t;\r\n }\r\n for (j = 0; j < shapeLength; j++) {\r\n s = (length - 1) * lengthSt;\r\n t = heightSt * (shape[j].y + heightOffset);\r\n st[stindex++] = s;\r\n st[stindex++] = t;\r\n }\r\n\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: new Float32Array(st),\r\n });\r\n }\r\n\r\n var endOffset = vertexCount - shapeLength * 2;\r\n for (i = 0; i < firstEndIndices.length; i += 3) {\r\n var v0 = firstEndIndices[i] + endOffset;\r\n var v1 = firstEndIndices[i + 1] + endOffset;\r\n var v2 = firstEndIndices[i + 2] + endOffset;\r\n\r\n indices[index++] = v0;\r\n indices[index++] = v1;\r\n indices[index++] = v2;\r\n indices[index++] = v2 + shapeLength;\r\n indices[index++] = v1 + shapeLength;\r\n indices[index++] = v0 + shapeLength;\r\n }\r\n\r\n var geometry = new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n boundingSphere: BoundingSphere.fromVertices(combinedPositions),\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n\r\n if (vertexFormat.normal) {\r\n geometry = GeometryPipeline.computeNormal(geometry);\r\n }\r\n\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n try {\r\n geometry = GeometryPipeline.computeTangentAndBitangent(geometry);\r\n } catch (e) {\r\n oneTimeWarning(\r\n \"polyline-volume-tangent-bitangent\",\r\n \"Unable to compute tangents and bitangents for polyline volume geometry\"\r\n );\r\n //TODO https://github.com/CesiumGS/cesium/issues/3609\r\n }\r\n\r\n if (!vertexFormat.tangent) {\r\n geometry.attributes.tangent = undefined;\r\n }\r\n if (!vertexFormat.bitangent) {\r\n geometry.attributes.bitangent = undefined;\r\n }\r\n if (!vertexFormat.st) {\r\n geometry.attributes.st = undefined;\r\n }\r\n }\r\n\r\n return geometry;\r\n}\r\n\r\n/**\r\n * A description of a polyline with a volume (a 2D shape extruded along a polyline).\r\n *\r\n * @alias PolylineVolumeGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.polylinePositions An array of {@link Cartesian3} positions that define the center of the polyline volume.\r\n * @param {Cartesian2[]} options.shapePositions An array of {@link Cartesian2} positions that define the shape to be extruded along the polyline\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {CornerType} [options.cornerType=CornerType.ROUNDED] Determines the style of the corners.\r\n *\r\n * @see PolylineVolumeGeometry#createGeometry\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Polyline%20Volume.html|Cesium Sandcastle Polyline Volume Demo}\r\n *\r\n * @example\r\n * function computeCircle(radius) {\r\n * var positions = [];\r\n * for (var i = 0; i < 360; i++) {\r\n * var radians = Cesium.Math.toRadians(i);\r\n * positions.push(new Cesium.Cartesian2(radius * Math.cos(radians), radius * Math.sin(radians)));\r\n * }\r\n * return positions;\r\n * }\r\n *\r\n * var volume = new Cesium.PolylineVolumeGeometry({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_ONLY,\r\n * polylinePositions : Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0\r\n * ]),\r\n * shapePositions : computeCircle(100000.0)\r\n * });\r\n */\r\nfunction PolylineVolumeGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.polylinePositions;\r\n var shape = options.shapePositions;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions)) {\r\n throw new DeveloperError(\"options.polylinePositions is required.\");\r\n }\r\n if (!defined(shape)) {\r\n throw new DeveloperError(\"options.shapePositions is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._positions = positions;\r\n this._shape = shape;\r\n this._ellipsoid = Ellipsoid.clone(\r\n defaultValue(options.ellipsoid, Ellipsoid.WGS84)\r\n );\r\n this._cornerType = defaultValue(options.cornerType, CornerType.ROUNDED);\r\n this._vertexFormat = VertexFormat.clone(\r\n defaultValue(options.vertexFormat, VertexFormat.DEFAULT)\r\n );\r\n this._granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n this._workerName = \"createPolylineVolumeGeometry\";\r\n\r\n var numComponents = 1 + positions.length * Cartesian3.packedLength;\r\n numComponents += 1 + shape.length * Cartesian2.packedLength;\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n numComponents + Ellipsoid.packedLength + VertexFormat.packedLength + 2;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PolylineVolumeGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nPolylineVolumeGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var positions = value._positions;\r\n var length = positions.length;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n\r\n var shape = value._shape;\r\n length = shape.length;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian2.packedLength) {\r\n Cartesian2.pack(shape[i], array, startingIndex);\r\n }\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._cornerType;\r\n array[startingIndex] = value._granularity;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n polylinePositions: undefined,\r\n shapePositions: undefined,\r\n ellipsoid: scratchEllipsoid,\r\n vertexFormat: scratchVertexFormat,\r\n cornerType: undefined,\r\n granularity: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PolylineVolumeGeometry} [result] The object into which to store the result.\r\n * @returns {PolylineVolumeGeometry} The modified result parameter or a new PolylineVolumeGeometry instance if one was not provided.\r\n */\r\nPolylineVolumeGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var length = array[startingIndex++];\r\n var positions = new Array(length);\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n length = array[startingIndex++];\r\n var shape = new Array(length);\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian2.packedLength) {\r\n shape[i] = Cartesian2.unpack(array, startingIndex);\r\n }\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var cornerType = array[startingIndex++];\r\n var granularity = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.polylinePositions = positions;\r\n scratchOptions.shapePositions = shape;\r\n scratchOptions.cornerType = cornerType;\r\n scratchOptions.granularity = granularity;\r\n return new PolylineVolumeGeometry(scratchOptions);\r\n }\r\n\r\n result._positions = positions;\r\n result._shape = shape;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._cornerType = cornerType;\r\n result._granularity = granularity;\r\n\r\n return result;\r\n};\r\n\r\nvar brScratch = new BoundingRectangle();\r\n\r\n/**\r\n * Computes the geometric representation of a polyline with a volume, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {PolylineVolumeGeometry} polylineVolumeGeometry A description of the polyline volume.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nPolylineVolumeGeometry.createGeometry = function (polylineVolumeGeometry) {\r\n var positions = polylineVolumeGeometry._positions;\r\n var cleanPositions = arrayRemoveDuplicates(\r\n positions,\r\n Cartesian3.equalsEpsilon\r\n );\r\n var shape2D = polylineVolumeGeometry._shape;\r\n shape2D = PolylineVolumeGeometryLibrary.removeDuplicatesFromShape(shape2D);\r\n\r\n if (cleanPositions.length < 2 || shape2D.length < 3) {\r\n return undefined;\r\n }\r\n\r\n if (\r\n PolygonPipeline.computeWindingOrder2D(shape2D) === WindingOrder.CLOCKWISE\r\n ) {\r\n shape2D.reverse();\r\n }\r\n var boundingRectangle = BoundingRectangle.fromPoints(shape2D, brScratch);\r\n\r\n var computedPositions = PolylineVolumeGeometryLibrary.computePositions(\r\n cleanPositions,\r\n shape2D,\r\n boundingRectangle,\r\n polylineVolumeGeometry,\r\n true\r\n );\r\n return computeAttributes(\r\n computedPositions,\r\n shape2D,\r\n boundingRectangle,\r\n polylineVolumeGeometry._vertexFormat\r\n );\r\n};\r\nexport default PolylineVolumeGeometry;\r\n","import arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport BoundingRectangle from \"./BoundingRectangle.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport CornerType from \"./CornerType.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PolylineVolumeGeometryLibrary from \"./PolylineVolumeGeometryLibrary.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport WindingOrder from \"./WindingOrder.js\";\r\n\r\nfunction computeAttributes(positions, shape) {\r\n var attributes = new GeometryAttributes();\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n\r\n var shapeLength = shape.length;\r\n var vertexCount = attributes.position.values.length / 3;\r\n var positionLength = positions.length / 3;\r\n var shapeCount = positionLength / shapeLength;\r\n var indices = IndexDatatype.createTypedArray(\r\n vertexCount,\r\n 2 * shapeLength * (shapeCount + 1)\r\n );\r\n var i, j;\r\n var index = 0;\r\n i = 0;\r\n var offset = i * shapeLength;\r\n for (j = 0; j < shapeLength - 1; j++) {\r\n indices[index++] = j + offset;\r\n indices[index++] = j + offset + 1;\r\n }\r\n indices[index++] = shapeLength - 1 + offset;\r\n indices[index++] = offset;\r\n\r\n i = shapeCount - 1;\r\n offset = i * shapeLength;\r\n for (j = 0; j < shapeLength - 1; j++) {\r\n indices[index++] = j + offset;\r\n indices[index++] = j + offset + 1;\r\n }\r\n indices[index++] = shapeLength - 1 + offset;\r\n indices[index++] = offset;\r\n\r\n for (i = 0; i < shapeCount - 1; i++) {\r\n var firstOffset = shapeLength * i;\r\n var secondOffset = firstOffset + shapeLength;\r\n for (j = 0; j < shapeLength; j++) {\r\n indices[index++] = j + firstOffset;\r\n indices[index++] = j + secondOffset;\r\n }\r\n }\r\n\r\n var geometry = new Geometry({\r\n attributes: attributes,\r\n indices: IndexDatatype.createTypedArray(vertexCount, indices),\r\n boundingSphere: BoundingSphere.fromVertices(positions),\r\n primitiveType: PrimitiveType.LINES,\r\n });\r\n\r\n return geometry;\r\n}\r\n\r\n/**\r\n * A description of a polyline with a volume (a 2D shape extruded along a polyline).\r\n *\r\n * @alias PolylineVolumeOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.polylinePositions An array of positions that define the center of the polyline volume.\r\n * @param {Cartesian2[]} options.shapePositions An array of positions that define the shape to be extruded along the polyline\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {CornerType} [options.cornerType=CornerType.ROUNDED] Determines the style of the corners.\r\n *\r\n * @see PolylineVolumeOutlineGeometry#createGeometry\r\n *\r\n * @example\r\n * function computeCircle(radius) {\r\n * var positions = [];\r\n * for (var i = 0; i < 360; i++) {\r\n * var radians = Cesium.Math.toRadians(i);\r\n * positions.push(new Cesium.Cartesian2(radius * Math.cos(radians), radius * Math.sin(radians)));\r\n * }\r\n * return positions;\r\n * }\r\n *\r\n * var volumeOutline = new Cesium.PolylineVolumeOutlineGeometry({\r\n * polylinePositions : Cesium.Cartesian3.fromDegreesArray([\r\n * -72.0, 40.0,\r\n * -70.0, 35.0\r\n * ]),\r\n * shapePositions : computeCircle(100000.0)\r\n * });\r\n */\r\nfunction PolylineVolumeOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.polylinePositions;\r\n var shape = options.shapePositions;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions)) {\r\n throw new DeveloperError(\"options.polylinePositions is required.\");\r\n }\r\n if (!defined(shape)) {\r\n throw new DeveloperError(\"options.shapePositions is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._positions = positions;\r\n this._shape = shape;\r\n this._ellipsoid = Ellipsoid.clone(\r\n defaultValue(options.ellipsoid, Ellipsoid.WGS84)\r\n );\r\n this._cornerType = defaultValue(options.cornerType, CornerType.ROUNDED);\r\n this._granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n this._workerName = \"createPolylineVolumeOutlineGeometry\";\r\n\r\n var numComponents = 1 + positions.length * Cartesian3.packedLength;\r\n numComponents += 1 + shape.length * Cartesian2.packedLength;\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength = numComponents + Ellipsoid.packedLength + 2;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {PolylineVolumeOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nPolylineVolumeOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var positions = value._positions;\r\n var length = positions.length;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n\r\n var shape = value._shape;\r\n length = shape.length;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian2.packedLength) {\r\n Cartesian2.pack(shape[i], array, startingIndex);\r\n }\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n array[startingIndex++] = value._cornerType;\r\n array[startingIndex] = value._granularity;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchOptions = {\r\n polylinePositions: undefined,\r\n shapePositions: undefined,\r\n ellipsoid: scratchEllipsoid,\r\n height: undefined,\r\n cornerType: undefined,\r\n granularity: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {PolylineVolumeOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {PolylineVolumeOutlineGeometry} The modified result parameter or a new PolylineVolumeOutlineGeometry instance if one was not provided.\r\n */\r\nPolylineVolumeOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var length = array[startingIndex++];\r\n var positions = new Array(length);\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n length = array[startingIndex++];\r\n var shape = new Array(length);\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian2.packedLength) {\r\n shape[i] = Cartesian2.unpack(array, startingIndex);\r\n }\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var cornerType = array[startingIndex++];\r\n var granularity = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.polylinePositions = positions;\r\n scratchOptions.shapePositions = shape;\r\n scratchOptions.cornerType = cornerType;\r\n scratchOptions.granularity = granularity;\r\n return new PolylineVolumeOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._positions = positions;\r\n result._shape = shape;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._cornerType = cornerType;\r\n result._granularity = granularity;\r\n\r\n return result;\r\n};\r\n\r\nvar brScratch = new BoundingRectangle();\r\n\r\n/**\r\n * Computes the geometric representation of the outline of a polyline with a volume, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {PolylineVolumeOutlineGeometry} polylineVolumeOutlineGeometry A description of the polyline volume outline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nPolylineVolumeOutlineGeometry.createGeometry = function (\r\n polylineVolumeOutlineGeometry\r\n) {\r\n var positions = polylineVolumeOutlineGeometry._positions;\r\n var cleanPositions = arrayRemoveDuplicates(\r\n positions,\r\n Cartesian3.equalsEpsilon\r\n );\r\n var shape2D = polylineVolumeOutlineGeometry._shape;\r\n shape2D = PolylineVolumeGeometryLibrary.removeDuplicatesFromShape(shape2D);\r\n\r\n if (cleanPositions.length < 2 || shape2D.length < 3) {\r\n return undefined;\r\n }\r\n\r\n if (\r\n PolygonPipeline.computeWindingOrder2D(shape2D) === WindingOrder.CLOCKWISE\r\n ) {\r\n shape2D.reverse();\r\n }\r\n var boundingRectangle = BoundingRectangle.fromPoints(shape2D, brScratch);\r\n\r\n var computedPositions = PolylineVolumeGeometryLibrary.computePositions(\r\n cleanPositions,\r\n shape2D,\r\n boundingRectangle,\r\n polylineVolumeOutlineGeometry,\r\n false\r\n );\r\n return computeAttributes(computedPositions, shape2D);\r\n};\r\nexport default PolylineVolumeOutlineGeometry;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Base class for proxying requested made by {@link Resource}.\r\n *\r\n * @alias Proxy\r\n * @constructor\r\n *\r\n * @see DefaultProxy\r\n */\r\nfunction Proxy() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\n/**\r\n * Get the final URL to use to request a given resource.\r\n *\r\n * @param {String} resource The resource to request.\r\n * @returns {String} proxied resource\r\n * @function\r\n */\r\nProxy.prototype.getURL = DeveloperError.throwInstantiationError;\r\n\r\nexport default Proxy;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport Spline from \"./Spline.js\";\r\n\r\nfunction createEvaluateFunction(spline) {\r\n var points = spline.points;\r\n var times = spline.times;\r\n\r\n // use slerp interpolation\r\n return function (time, result) {\r\n if (!defined(result)) {\r\n result = new Quaternion();\r\n }\r\n var i = (spline._lastTimeIndex = spline.findTimeInterval(\r\n time,\r\n spline._lastTimeIndex\r\n ));\r\n var u = (time - times[i]) / (times[i + 1] - times[i]);\r\n\r\n var q0 = points[i];\r\n var q1 = points[i + 1];\r\n\r\n return Quaternion.fastSlerp(q0, q1, u, result);\r\n };\r\n}\r\n\r\n/**\r\n * A spline that uses spherical linear (slerp) interpolation to create a quaternion curve.\r\n * The generated curve is in the class C1.\r\n *\r\n * @alias QuaternionSpline\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.times An array of strictly increasing, unit-less, floating-point times at each point.\r\n * The values are in no way connected to the clock time. They are the parameterization for the curve.\r\n * @param {Quaternion[]} options.points The array of {@link Quaternion} control points.\r\n *\r\n * @exception {DeveloperError} points.length must be greater than or equal to 2.\r\n * @exception {DeveloperError} times.length must be equal to points.length.\r\n *\r\n * @see HermiteSpline\r\n * @see CatmullRomSpline\r\n * @see LinearSpline\r\n * @see WeightSpline\r\n */\r\nfunction QuaternionSpline(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var points = options.points;\r\n var times = options.times;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(points) || !defined(times)) {\r\n throw new DeveloperError(\"points and times are required.\");\r\n }\r\n if (points.length < 2) {\r\n throw new DeveloperError(\r\n \"points.length must be greater than or equal to 2.\"\r\n );\r\n }\r\n if (times.length !== points.length) {\r\n throw new DeveloperError(\"times.length must be equal to points.length.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._times = times;\r\n this._points = points;\r\n\r\n this._evaluateFunction = createEvaluateFunction(this);\r\n this._lastTimeIndex = 0;\r\n}\r\n\r\nObject.defineProperties(QuaternionSpline.prototype, {\r\n /**\r\n * An array of times for the control points.\r\n *\r\n * @memberof QuaternionSpline.prototype\r\n *\r\n * @type {Number[]}\r\n * @readonly\r\n */\r\n times: {\r\n get: function () {\r\n return this._times;\r\n },\r\n },\r\n\r\n /**\r\n * An array of {@link Quaternion} control points.\r\n *\r\n * @memberof QuaternionSpline.prototype\r\n *\r\n * @type {Quaternion[]}\r\n * @readonly\r\n */\r\n points: {\r\n get: function () {\r\n return this._points;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Finds an index i in times such that the parameter\r\n * time is in the interval [times[i], times[i + 1]].\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @returns {Number} The index for the element at the start of the interval.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nQuaternionSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;\r\n\r\n/**\r\n * Wraps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, wrapped around to the updated animation.\r\n */\r\nQuaternionSpline.prototype.wrapTime = Spline.prototype.wrapTime;\r\n\r\n/**\r\n * Clamps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, clamped to the animation period.\r\n */\r\nQuaternionSpline.prototype.clampTime = Spline.prototype.clampTime;\r\n\r\n/**\r\n * Evaluates the curve at a given time.\r\n *\r\n * @param {Number} time The time at which to evaluate the curve.\r\n * @param {Quaternion} [result] The object onto which to store the result.\r\n * @returns {Quaternion} The modified result parameter or a new instance of the point on the curve at the given time.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nQuaternionSpline.prototype.evaluate = function (time, result) {\r\n return this._evaluateFunction(time, result);\r\n};\r\nexport default QuaternionSpline;\r\n","function quickselect(arr, k, left, right, compare) {\r\n quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare);\r\n}\r\n\r\nfunction quickselectStep(arr, k, left, right, compare) {\r\n\r\n while (right > left) {\r\n if (right - left > 600) {\r\n var n = right - left + 1;\r\n var m = k - left + 1;\r\n var z = Math.log(n);\r\n var s = 0.5 * Math.exp(2 * z / 3);\r\n var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);\r\n var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));\r\n var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));\r\n quickselectStep(arr, k, newLeft, newRight, compare);\r\n }\r\n\r\n var t = arr[k];\r\n var i = left;\r\n var j = right;\r\n\r\n swap(arr, left, k);\r\n if (compare(arr[right], t) > 0) { swap(arr, left, right); }\r\n\r\n while (i < j) {\r\n swap(arr, i, j);\r\n i++;\r\n j--;\r\n while (compare(arr[i], t) < 0) { i++; }\r\n while (compare(arr[j], t) > 0) { j--; }\r\n }\r\n\r\n if (compare(arr[left], t) === 0) { swap(arr, left, j); }\r\n else {\r\n j++;\r\n swap(arr, j, right);\r\n }\r\n\r\n if (j <= k) { left = j + 1; }\r\n if (k <= j) { right = j - 1; }\r\n }\r\n}\r\n\r\nfunction swap(arr, i, j) {\r\n var tmp = arr[i];\r\n arr[i] = arr[j];\r\n arr[j] = tmp;\r\n}\r\n\r\nfunction defaultCompare(a, b) {\r\n return a < b ? -1 : a > b ? 1 : 0;\r\n}\r\n\r\nfunction RBush(maxEntries) {\r\n if ( maxEntries === void 0 ) maxEntries = 9;\r\n\r\n // max entries in a node is 9 by default; min node fill is 40% for best performance\r\n this._maxEntries = Math.max(4, maxEntries);\r\n this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));\r\n this.clear();\r\n};\r\n\r\nRBush.prototype.all = function all () {\r\n return this._all(this.data, []);\r\n};\r\n\r\nRBush.prototype.search = function search (bbox) {\r\n var node = this.data;\r\n var result = [];\r\n\r\n if (!intersects(bbox, node)) { return result; }\r\n\r\n var toBBox = this.toBBox;\r\n var nodesToSearch = [];\r\n\r\n while (node) {\r\n for (var i = 0; i < node.children.length; i++) {\r\n var child = node.children[i];\r\n var childBBox = node.leaf ? toBBox(child) : child;\r\n\r\n if (intersects(bbox, childBBox)) {\r\n if (node.leaf) { result.push(child); }\r\n else if (contains(bbox, childBBox)) { this._all(child, result); }\r\n else { nodesToSearch.push(child); }\r\n }\r\n }\r\n node = nodesToSearch.pop();\r\n }\r\n\r\n return result;\r\n};\r\n\r\nRBush.prototype.collides = function collides (bbox) {\r\n var node = this.data;\r\n\r\n if (!intersects(bbox, node)) { return false; }\r\n\r\n var nodesToSearch = [];\r\n while (node) {\r\n for (var i = 0; i < node.children.length; i++) {\r\n var child = node.children[i];\r\n var childBBox = node.leaf ? this.toBBox(child) : child;\r\n\r\n if (intersects(bbox, childBBox)) {\r\n if (node.leaf || contains(bbox, childBBox)) { return true; }\r\n nodesToSearch.push(child);\r\n }\r\n }\r\n node = nodesToSearch.pop();\r\n }\r\n\r\n return false;\r\n};\r\n\r\nRBush.prototype.load = function load (data) {\r\n if (!(data && data.length)) { return this; }\r\n\r\n if (data.length < this._minEntries) {\r\n for (var i = 0; i < data.length; i++) {\r\n this.insert(data[i]);\r\n }\r\n return this;\r\n }\r\n\r\n // recursively build the tree with the given data from scratch using OMT algorithm\r\n var node = this._build(data.slice(), 0, data.length - 1, 0);\r\n\r\n if (!this.data.children.length) {\r\n // save as is if tree is empty\r\n this.data = node;\r\n\r\n } else if (this.data.height === node.height) {\r\n // split root if trees have the same height\r\n this._splitRoot(this.data, node);\r\n\r\n } else {\r\n if (this.data.height < node.height) {\r\n // swap trees if inserted one is bigger\r\n var tmpNode = this.data;\r\n this.data = node;\r\n node = tmpNode;\r\n }\r\n\r\n // insert the small tree into the large tree at appropriate level\r\n this._insert(node, this.data.height - node.height - 1, true);\r\n }\r\n\r\n return this;\r\n};\r\n\r\nRBush.prototype.insert = function insert (item) {\r\n if (item) { this._insert(item, this.data.height - 1); }\r\n return this;\r\n};\r\n\r\nRBush.prototype.clear = function clear () {\r\n this.data = createNode([]);\r\n return this;\r\n};\r\n\r\nRBush.prototype.remove = function remove (item, equalsFn) {\r\n if (!item) { return this; }\r\n\r\n var node = this.data;\r\n var bbox = this.toBBox(item);\r\n var path = [];\r\n var indexes = [];\r\n var i, parent, goingUp;\r\n\r\n // depth-first iterative tree traversal\r\n while (node || path.length) {\r\n\r\n if (!node) { // go up\r\n node = path.pop();\r\n parent = path[path.length - 1];\r\n i = indexes.pop();\r\n goingUp = true;\r\n }\r\n\r\n if (node.leaf) { // check current node\r\n var index = findItem(item, node.children, equalsFn);\r\n\r\n if (index !== -1) {\r\n // item found, remove the item and condense tree upwards\r\n node.children.splice(index, 1);\r\n path.push(node);\r\n this._condense(path);\r\n return this;\r\n }\r\n }\r\n\r\n if (!goingUp && !node.leaf && contains(node, bbox)) { // go down\r\n path.push(node);\r\n indexes.push(i);\r\n i = 0;\r\n parent = node;\r\n node = node.children[0];\r\n\r\n } else if (parent) { // go right\r\n i++;\r\n node = parent.children[i];\r\n goingUp = false;\r\n\r\n } else { node = null; } // nothing found\r\n }\r\n\r\n return this;\r\n};\r\n\r\nRBush.prototype.toBBox = function toBBox (item) { return item; };\r\n\r\nRBush.prototype.compareMinX = function compareMinX (a, b) { return a.minX - b.minX; };\r\nRBush.prototype.compareMinY = function compareMinY (a, b) { return a.minY - b.minY; };\r\n\r\nRBush.prototype.toJSON = function toJSON () { return this.data; };\r\n\r\nRBush.prototype.fromJSON = function fromJSON (data) {\r\n this.data = data;\r\n return this;\r\n};\r\n\r\nRBush.prototype._all = function _all (node, result) {\r\n var nodesToSearch = [];\r\n while (node) {\r\n if (node.leaf) { result.push.apply(result, node.children); }\r\n else { nodesToSearch.push.apply(nodesToSearch, node.children); }\r\n\r\n node = nodesToSearch.pop();\r\n }\r\n return result;\r\n};\r\n\r\nRBush.prototype._build = function _build (items, left, right, height) {\r\n\r\n var N = right - left + 1;\r\n var M = this._maxEntries;\r\n var node;\r\n\r\n if (N <= M) {\r\n // reached leaf level; return leaf\r\n node = createNode(items.slice(left, right + 1));\r\n calcBBox(node, this.toBBox);\r\n return node;\r\n }\r\n\r\n if (!height) {\r\n // target height of the bulk-loaded tree\r\n height = Math.ceil(Math.log(N) / Math.log(M));\r\n\r\n // target number of root entries to maximize storage utilization\r\n M = Math.ceil(N / Math.pow(M, height - 1));\r\n }\r\n\r\n node = createNode([]);\r\n node.leaf = false;\r\n node.height = height;\r\n\r\n // split the items into M mostly square tiles\r\n\r\n var N2 = Math.ceil(N / M);\r\n var N1 = N2 * Math.ceil(Math.sqrt(M));\r\n\r\n multiSelect(items, left, right, N1, this.compareMinX);\r\n\r\n for (var i = left; i <= right; i += N1) {\r\n\r\n var right2 = Math.min(i + N1 - 1, right);\r\n\r\n multiSelect(items, i, right2, N2, this.compareMinY);\r\n\r\n for (var j = i; j <= right2; j += N2) {\r\n\r\n var right3 = Math.min(j + N2 - 1, right2);\r\n\r\n // pack each entry recursively\r\n node.children.push(this._build(items, j, right3, height - 1));\r\n }\r\n }\r\n\r\n calcBBox(node, this.toBBox);\r\n\r\n return node;\r\n};\r\n\r\nRBush.prototype._chooseSubtree = function _chooseSubtree (bbox, node, level, path) {\r\n while (true) {\r\n path.push(node);\r\n\r\n if (node.leaf || path.length - 1 === level) { break; }\r\n\r\n var minArea = Infinity;\r\n var minEnlargement = Infinity;\r\n var targetNode = (void 0);\r\n\r\n for (var i = 0; i < node.children.length; i++) {\r\n var child = node.children[i];\r\n var area = bboxArea(child);\r\n var enlargement = enlargedArea(bbox, child) - area;\r\n\r\n // choose entry with the least area enlargement\r\n if (enlargement < minEnlargement) {\r\n minEnlargement = enlargement;\r\n minArea = area < minArea ? area : minArea;\r\n targetNode = child;\r\n\r\n } else if (enlargement === minEnlargement) {\r\n // otherwise choose one with the smallest area\r\n if (area < minArea) {\r\n minArea = area;\r\n targetNode = child;\r\n }\r\n }\r\n }\r\n\r\n node = targetNode || node.children[0];\r\n }\r\n\r\n return node;\r\n};\r\n\r\nRBush.prototype._insert = function _insert (item, level, isNode) {\r\n var bbox = isNode ? item : this.toBBox(item);\r\n var insertPath = [];\r\n\r\n // find the best node for accommodating the item, saving all nodes along the path too\r\n var node = this._chooseSubtree(bbox, this.data, level, insertPath);\r\n\r\n // put the item into the node\r\n node.children.push(item);\r\n extend(node, bbox);\r\n\r\n // split on node overflow; propagate upwards if necessary\r\n while (level >= 0) {\r\n if (insertPath[level].children.length > this._maxEntries) {\r\n this._split(insertPath, level);\r\n level--;\r\n } else { break; }\r\n }\r\n\r\n // adjust bboxes along the insertion path\r\n this._adjustParentBBoxes(bbox, insertPath, level);\r\n};\r\n\r\n// split overflowed node into two\r\nRBush.prototype._split = function _split (insertPath, level) {\r\n var node = insertPath[level];\r\n var M = node.children.length;\r\n var m = this._minEntries;\r\n\r\n this._chooseSplitAxis(node, m, M);\r\n\r\n var splitIndex = this._chooseSplitIndex(node, m, M);\r\n\r\n var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));\r\n newNode.height = node.height;\r\n newNode.leaf = node.leaf;\r\n\r\n calcBBox(node, this.toBBox);\r\n calcBBox(newNode, this.toBBox);\r\n\r\n if (level) { insertPath[level - 1].children.push(newNode); }\r\n else { this._splitRoot(node, newNode); }\r\n};\r\n\r\nRBush.prototype._splitRoot = function _splitRoot (node, newNode) {\r\n // split root node\r\n this.data = createNode([node, newNode]);\r\n this.data.height = node.height + 1;\r\n this.data.leaf = false;\r\n calcBBox(this.data, this.toBBox);\r\n};\r\n\r\nRBush.prototype._chooseSplitIndex = function _chooseSplitIndex (node, m, M) {\r\n var index;\r\n var minOverlap = Infinity;\r\n var minArea = Infinity;\r\n\r\n for (var i = m; i <= M - m; i++) {\r\n var bbox1 = distBBox(node, 0, i, this.toBBox);\r\n var bbox2 = distBBox(node, i, M, this.toBBox);\r\n\r\n var overlap = intersectionArea(bbox1, bbox2);\r\n var area = bboxArea(bbox1) + bboxArea(bbox2);\r\n\r\n // choose distribution with minimum overlap\r\n if (overlap < minOverlap) {\r\n minOverlap = overlap;\r\n index = i;\r\n\r\n minArea = area < minArea ? area : minArea;\r\n\r\n } else if (overlap === minOverlap) {\r\n // otherwise choose distribution with minimum area\r\n if (area < minArea) {\r\n minArea = area;\r\n index = i;\r\n }\r\n }\r\n }\r\n\r\n return index || M - m;\r\n};\r\n\r\n// sorts node children by the best axis for split\r\nRBush.prototype._chooseSplitAxis = function _chooseSplitAxis (node, m, M) {\r\n var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX;\r\n var compareMinY = node.leaf ? this.compareMinY : compareNodeMinY;\r\n var xMargin = this._allDistMargin(node, m, M, compareMinX);\r\n var yMargin = this._allDistMargin(node, m, M, compareMinY);\r\n\r\n // if total distributions margin value is minimal for x, sort by minX,\r\n // otherwise it's already sorted by minY\r\n if (xMargin < yMargin) { node.children.sort(compareMinX); }\r\n};\r\n\r\n// total margin of all possible split distributions where each node is at least m full\r\nRBush.prototype._allDistMargin = function _allDistMargin (node, m, M, compare) {\r\n node.children.sort(compare);\r\n\r\n var toBBox = this.toBBox;\r\n var leftBBox = distBBox(node, 0, m, toBBox);\r\n var rightBBox = distBBox(node, M - m, M, toBBox);\r\n var margin = bboxMargin(leftBBox) + bboxMargin(rightBBox);\r\n\r\n for (var i = m; i < M - m; i++) {\r\n var child = node.children[i];\r\n extend(leftBBox, node.leaf ? toBBox(child) : child);\r\n margin += bboxMargin(leftBBox);\r\n }\r\n\r\n for (var i$1 = M - m - 1; i$1 >= m; i$1--) {\r\n var child$1 = node.children[i$1];\r\n extend(rightBBox, node.leaf ? toBBox(child$1) : child$1);\r\n margin += bboxMargin(rightBBox);\r\n }\r\n\r\n return margin;\r\n};\r\n\r\nRBush.prototype._adjustParentBBoxes = function _adjustParentBBoxes (bbox, path, level) {\r\n // adjust bboxes along the given tree path\r\n for (var i = level; i >= 0; i--) {\r\n extend(path[i], bbox);\r\n }\r\n};\r\n\r\nRBush.prototype._condense = function _condense (path) {\r\n // go through the path, removing empty nodes and updating bboxes\r\n for (var i = path.length - 1, siblings = (void 0); i >= 0; i--) {\r\n if (path[i].children.length === 0) {\r\n if (i > 0) {\r\n siblings = path[i - 1].children;\r\n siblings.splice(siblings.indexOf(path[i]), 1);\r\n\r\n } else { this.clear(); }\r\n\r\n } else { calcBBox(path[i], this.toBBox); }\r\n }\r\n};\r\n\r\nfunction findItem(item, items, equalsFn) {\r\n if (!equalsFn) { return items.indexOf(item); }\r\n\r\n for (var i = 0; i < items.length; i++) {\r\n if (equalsFn(item, items[i])) { return i; }\r\n }\r\n return -1;\r\n}\r\n\r\n// calculate node's bbox from bboxes of its children\r\nfunction calcBBox(node, toBBox) {\r\n distBBox(node, 0, node.children.length, toBBox, node);\r\n}\r\n\r\n// min bounding rectangle of node children from k to p-1\r\nfunction distBBox(node, k, p, toBBox, destNode) {\r\n if (!destNode) { destNode = createNode(null); }\r\n destNode.minX = Infinity;\r\n destNode.minY = Infinity;\r\n destNode.maxX = -Infinity;\r\n destNode.maxY = -Infinity;\r\n\r\n for (var i = k; i < p; i++) {\r\n var child = node.children[i];\r\n extend(destNode, node.leaf ? toBBox(child) : child);\r\n }\r\n\r\n return destNode;\r\n}\r\n\r\nfunction extend(a, b) {\r\n a.minX = Math.min(a.minX, b.minX);\r\n a.minY = Math.min(a.minY, b.minY);\r\n a.maxX = Math.max(a.maxX, b.maxX);\r\n a.maxY = Math.max(a.maxY, b.maxY);\r\n return a;\r\n}\r\n\r\nfunction compareNodeMinX(a, b) { return a.minX - b.minX; }\r\nfunction compareNodeMinY(a, b) { return a.minY - b.minY; }\r\n\r\nfunction bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); }\r\nfunction bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }\r\n\r\nfunction enlargedArea(a, b) {\r\n return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *\r\n (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));\r\n}\r\n\r\nfunction intersectionArea(a, b) {\r\n var minX = Math.max(a.minX, b.minX);\r\n var minY = Math.max(a.minY, b.minY);\r\n var maxX = Math.min(a.maxX, b.maxX);\r\n var maxY = Math.min(a.maxY, b.maxY);\r\n\r\n return Math.max(0, maxX - minX) *\r\n Math.max(0, maxY - minY);\r\n}\r\n\r\nfunction contains(a, b) {\r\n return a.minX <= b.minX &&\r\n a.minY <= b.minY &&\r\n b.maxX <= a.maxX &&\r\n b.maxY <= a.maxY;\r\n}\r\n\r\nfunction intersects(a, b) {\r\n return b.minX <= a.maxX &&\r\n b.minY <= a.maxY &&\r\n b.maxX >= a.minX &&\r\n b.maxY >= a.minY;\r\n}\r\n\r\nfunction createNode(children) {\r\n return {\r\n children: children,\r\n height: 1,\r\n leaf: true,\r\n minX: Infinity,\r\n minY: Infinity,\r\n maxX: -Infinity,\r\n maxY: -Infinity\r\n };\r\n}\r\n\r\n// sort an array so that items come in groups of n unsorted items, with groups sorted between each other;\r\n// combines selection algorithm with binary divide & conquer approach\r\n\r\nfunction multiSelect(arr, left, right, n, compare) {\r\n var stack = [left, right];\r\n\r\n while (stack.length) {\r\n right = stack.pop();\r\n left = stack.pop();\r\n\r\n if (right - left <= n) { continue; }\r\n\r\n var mid = left + Math.ceil((right - left) / n / 2) * n;\r\n quickselect(arr, mid, left, right, compare);\r\n\r\n stack.push(left, mid, mid, right);\r\n }\r\n}\r\n\r\nexport default RBush;\r\n","import RBush from \"../ThirdParty/rbush.js\";\r\nimport Check from \"./Check.js\";\r\n\r\n/**\r\n * Wrapper around rbush for use with Rectangle types.\r\n * @private\r\n */\r\nfunction RectangleCollisionChecker() {\r\n this._tree = new RBush();\r\n}\r\n\r\nfunction RectangleWithId() {\r\n this.minX = 0.0;\r\n this.minY = 0.0;\r\n this.maxX = 0.0;\r\n this.maxY = 0.0;\r\n this.id = \"\";\r\n}\r\n\r\nRectangleWithId.fromRectangleAndId = function (id, rectangle, result) {\r\n result.minX = rectangle.west;\r\n result.minY = rectangle.south;\r\n result.maxX = rectangle.east;\r\n result.maxY = rectangle.north;\r\n result.id = id;\r\n return result;\r\n};\r\n\r\n/**\r\n * Insert a rectangle into the collision checker.\r\n *\r\n * @param {String} id Unique string ID for the rectangle being inserted.\r\n * @param {Rectangle} rectangle A Rectangle\r\n * @private\r\n */\r\nRectangleCollisionChecker.prototype.insert = function (id, rectangle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"id\", id);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n var withId = RectangleWithId.fromRectangleAndId(\r\n id,\r\n rectangle,\r\n new RectangleWithId()\r\n );\r\n this._tree.insert(withId);\r\n};\r\n\r\nfunction idCompare(a, b) {\r\n return a.id === b.id;\r\n}\r\n\r\nvar removalScratch = new RectangleWithId();\r\n/**\r\n * Remove a rectangle from the collision checker.\r\n *\r\n * @param {String} id Unique string ID for the rectangle being removed.\r\n * @param {Rectangle} rectangle A Rectangle\r\n * @private\r\n */\r\nRectangleCollisionChecker.prototype.remove = function (id, rectangle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"id\", id);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n var withId = RectangleWithId.fromRectangleAndId(\r\n id,\r\n rectangle,\r\n removalScratch\r\n );\r\n this._tree.remove(withId, idCompare);\r\n};\r\n\r\nvar collisionScratch = new RectangleWithId();\r\n/**\r\n * Checks if a given rectangle collides with any of the rectangles in the collection.\r\n *\r\n * @param {Rectangle} rectangle A Rectangle that should be checked against the rectangles in the collision checker.\r\n * @returns {Boolean} Whether the rectangle collides with any of the rectangles in the collision checker.\r\n */\r\nRectangleCollisionChecker.prototype.collides = function (rectangle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n var withId = RectangleWithId.fromRectangleAndId(\r\n \"\",\r\n rectangle,\r\n collisionScratch\r\n );\r\n return this._tree.collides(withId);\r\n};\r\nexport default RectangleCollisionChecker;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport GeographicProjection from \"./GeographicProjection.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix2 from \"./Matrix2.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\n\r\nvar cos = Math.cos;\r\nvar sin = Math.sin;\r\nvar sqrt = Math.sqrt;\r\n\r\n/**\r\n * @private\r\n */\r\nvar RectangleGeometryLibrary = {};\r\n\r\n/**\r\n * @private\r\n */\r\nRectangleGeometryLibrary.computePosition = function (\r\n computedOptions,\r\n ellipsoid,\r\n computeST,\r\n row,\r\n col,\r\n position,\r\n st\r\n) {\r\n var radiiSquared = ellipsoid.radiiSquared;\r\n var nwCorner = computedOptions.nwCorner;\r\n var rectangle = computedOptions.boundingRectangle;\r\n\r\n var stLatitude =\r\n nwCorner.latitude -\r\n computedOptions.granYCos * row +\r\n col * computedOptions.granXSin;\r\n var cosLatitude = cos(stLatitude);\r\n var nZ = sin(stLatitude);\r\n var kZ = radiiSquared.z * nZ;\r\n\r\n var stLongitude =\r\n nwCorner.longitude +\r\n row * computedOptions.granYSin +\r\n col * computedOptions.granXCos;\r\n var nX = cosLatitude * cos(stLongitude);\r\n var nY = cosLatitude * sin(stLongitude);\r\n\r\n var kX = radiiSquared.x * nX;\r\n var kY = radiiSquared.y * nY;\r\n\r\n var gamma = sqrt(kX * nX + kY * nY + kZ * nZ);\r\n\r\n position.x = kX / gamma;\r\n position.y = kY / gamma;\r\n position.z = kZ / gamma;\r\n\r\n if (computeST) {\r\n var stNwCorner = computedOptions.stNwCorner;\r\n if (defined(stNwCorner)) {\r\n stLatitude =\r\n stNwCorner.latitude -\r\n computedOptions.stGranYCos * row +\r\n col * computedOptions.stGranXSin;\r\n stLongitude =\r\n stNwCorner.longitude +\r\n row * computedOptions.stGranYSin +\r\n col * computedOptions.stGranXCos;\r\n\r\n st.x = (stLongitude - computedOptions.stWest) * computedOptions.lonScalar;\r\n st.y = (stLatitude - computedOptions.stSouth) * computedOptions.latScalar;\r\n } else {\r\n st.x = (stLongitude - rectangle.west) * computedOptions.lonScalar;\r\n st.y = (stLatitude - rectangle.south) * computedOptions.latScalar;\r\n }\r\n }\r\n};\r\n\r\nvar rotationMatrixScratch = new Matrix2();\r\nvar nwCartesian = new Cartesian3();\r\nvar centerScratch = new Cartographic();\r\nvar centerCartesian = new Cartesian3();\r\nvar proj = new GeographicProjection();\r\n\r\nfunction getRotationOptions(\r\n nwCorner,\r\n rotation,\r\n granularityX,\r\n granularityY,\r\n center,\r\n width,\r\n height\r\n) {\r\n var cosRotation = Math.cos(rotation);\r\n var granYCos = granularityY * cosRotation;\r\n var granXCos = granularityX * cosRotation;\r\n\r\n var sinRotation = Math.sin(rotation);\r\n var granYSin = granularityY * sinRotation;\r\n var granXSin = granularityX * sinRotation;\r\n\r\n nwCartesian = proj.project(nwCorner, nwCartesian);\r\n\r\n nwCartesian = Cartesian3.subtract(nwCartesian, centerCartesian, nwCartesian);\r\n var rotationMatrix = Matrix2.fromRotation(rotation, rotationMatrixScratch);\r\n nwCartesian = Matrix2.multiplyByVector(\r\n rotationMatrix,\r\n nwCartesian,\r\n nwCartesian\r\n );\r\n nwCartesian = Cartesian3.add(nwCartesian, centerCartesian, nwCartesian);\r\n nwCorner = proj.unproject(nwCartesian, nwCorner);\r\n\r\n width -= 1;\r\n height -= 1;\r\n\r\n var latitude = nwCorner.latitude;\r\n var latitude0 = latitude + width * granXSin;\r\n var latitude1 = latitude - granYCos * height;\r\n var latitude2 = latitude - granYCos * height + width * granXSin;\r\n\r\n var north = Math.max(latitude, latitude0, latitude1, latitude2);\r\n var south = Math.min(latitude, latitude0, latitude1, latitude2);\r\n\r\n var longitude = nwCorner.longitude;\r\n var longitude0 = longitude + width * granXCos;\r\n var longitude1 = longitude + height * granYSin;\r\n var longitude2 = longitude + height * granYSin + width * granXCos;\r\n\r\n var east = Math.max(longitude, longitude0, longitude1, longitude2);\r\n var west = Math.min(longitude, longitude0, longitude1, longitude2);\r\n\r\n return {\r\n north: north,\r\n south: south,\r\n east: east,\r\n west: west,\r\n granYCos: granYCos,\r\n granYSin: granYSin,\r\n granXCos: granXCos,\r\n granXSin: granXSin,\r\n nwCorner: nwCorner,\r\n };\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nRectangleGeometryLibrary.computeOptions = function (\r\n rectangle,\r\n granularity,\r\n rotation,\r\n stRotation,\r\n boundingRectangleScratch,\r\n nwCornerResult,\r\n stNwCornerResult\r\n) {\r\n var east = rectangle.east;\r\n var west = rectangle.west;\r\n var north = rectangle.north;\r\n var south = rectangle.south;\r\n\r\n var northCap = false;\r\n var southCap = false;\r\n\r\n if (north === CesiumMath.PI_OVER_TWO) {\r\n northCap = true;\r\n }\r\n if (south === -CesiumMath.PI_OVER_TWO) {\r\n southCap = true;\r\n }\r\n\r\n var width;\r\n var height;\r\n var granularityX;\r\n var granularityY;\r\n var dx;\r\n var dy = north - south;\r\n if (west > east) {\r\n dx = CesiumMath.TWO_PI - west + east;\r\n } else {\r\n dx = east - west;\r\n }\r\n\r\n width = Math.ceil(dx / granularity) + 1;\r\n height = Math.ceil(dy / granularity) + 1;\r\n granularityX = dx / (width - 1);\r\n granularityY = dy / (height - 1);\r\n\r\n var nwCorner = Rectangle.northwest(rectangle, nwCornerResult);\r\n var center = Rectangle.center(rectangle, centerScratch);\r\n if (rotation !== 0 || stRotation !== 0) {\r\n if (center.longitude < nwCorner.longitude) {\r\n center.longitude += CesiumMath.TWO_PI;\r\n }\r\n centerCartesian = proj.project(center, centerCartesian);\r\n }\r\n\r\n var granYCos = granularityY;\r\n var granXCos = granularityX;\r\n var granYSin = 0.0;\r\n var granXSin = 0.0;\r\n\r\n var boundingRectangle = Rectangle.clone(rectangle, boundingRectangleScratch);\r\n\r\n var computedOptions = {\r\n granYCos: granYCos,\r\n granYSin: granYSin,\r\n granXCos: granXCos,\r\n granXSin: granXSin,\r\n nwCorner: nwCorner,\r\n boundingRectangle: boundingRectangle,\r\n width: width,\r\n height: height,\r\n northCap: northCap,\r\n southCap: southCap,\r\n };\r\n\r\n if (rotation !== 0) {\r\n var rotationOptions = getRotationOptions(\r\n nwCorner,\r\n rotation,\r\n granularityX,\r\n granularityY,\r\n center,\r\n width,\r\n height\r\n );\r\n north = rotationOptions.north;\r\n south = rotationOptions.south;\r\n east = rotationOptions.east;\r\n west = rotationOptions.west;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n north < -CesiumMath.PI_OVER_TWO ||\r\n north > CesiumMath.PI_OVER_TWO ||\r\n south < -CesiumMath.PI_OVER_TWO ||\r\n south > CesiumMath.PI_OVER_TWO\r\n ) {\r\n throw new DeveloperError(\r\n \"Rotated rectangle is invalid. It crosses over either the north or south pole.\"\r\n );\r\n }\r\n //>>includeEnd('debug')\r\n\r\n computedOptions.granYCos = rotationOptions.granYCos;\r\n computedOptions.granYSin = rotationOptions.granYSin;\r\n computedOptions.granXCos = rotationOptions.granXCos;\r\n computedOptions.granXSin = rotationOptions.granXSin;\r\n\r\n boundingRectangle.north = north;\r\n boundingRectangle.south = south;\r\n boundingRectangle.east = east;\r\n boundingRectangle.west = west;\r\n }\r\n\r\n if (stRotation !== 0) {\r\n rotation = rotation - stRotation;\r\n var stNwCorner = Rectangle.northwest(boundingRectangle, stNwCornerResult);\r\n\r\n var stRotationOptions = getRotationOptions(\r\n stNwCorner,\r\n rotation,\r\n granularityX,\r\n granularityY,\r\n center,\r\n width,\r\n height\r\n );\r\n\r\n computedOptions.stGranYCos = stRotationOptions.granYCos;\r\n computedOptions.stGranXCos = stRotationOptions.granXCos;\r\n computedOptions.stGranYSin = stRotationOptions.granYSin;\r\n computedOptions.stGranXSin = stRotationOptions.granXSin;\r\n computedOptions.stNwCorner = stNwCorner;\r\n computedOptions.stWest = stRotationOptions.west;\r\n computedOptions.stSouth = stRotationOptions.south;\r\n }\r\n\r\n return computedOptions;\r\n};\r\nexport default RectangleGeometryLibrary;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport Check from \"./Check.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryInstance from \"./GeometryInstance.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport GeometryPipeline from \"./GeometryPipeline.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix2 from \"./Matrix2.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport RectangleGeometryLibrary from \"./RectangleGeometryLibrary.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\nvar positionScratch = new Cartesian3();\r\nvar normalScratch = new Cartesian3();\r\nvar tangentScratch = new Cartesian3();\r\nvar bitangentScratch = new Cartesian3();\r\nvar rectangleScratch = new Rectangle();\r\nvar stScratch = new Cartesian2();\r\nvar bottomBoundingSphere = new BoundingSphere();\r\nvar topBoundingSphere = new BoundingSphere();\r\n\r\nfunction createAttributes(vertexFormat, attributes) {\r\n var geo = new Geometry({\r\n attributes: new GeometryAttributes(),\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n });\r\n\r\n geo.attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: attributes.positions,\r\n });\r\n if (vertexFormat.normal) {\r\n geo.attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: attributes.normals,\r\n });\r\n }\r\n if (vertexFormat.tangent) {\r\n geo.attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: attributes.tangents,\r\n });\r\n }\r\n if (vertexFormat.bitangent) {\r\n geo.attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: attributes.bitangents,\r\n });\r\n }\r\n return geo;\r\n}\r\n\r\nfunction calculateAttributes(\r\n positions,\r\n vertexFormat,\r\n ellipsoid,\r\n tangentRotationMatrix\r\n) {\r\n var length = positions.length;\r\n\r\n var normals = vertexFormat.normal ? new Float32Array(length) : undefined;\r\n var tangents = vertexFormat.tangent ? new Float32Array(length) : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(length)\r\n : undefined;\r\n\r\n var attrIndex = 0;\r\n var bitangent = bitangentScratch;\r\n var tangent = tangentScratch;\r\n var normal = normalScratch;\r\n if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {\r\n for (var i = 0; i < length; i += 3) {\r\n var p = Cartesian3.fromArray(positions, i, positionScratch);\r\n var attrIndex1 = attrIndex + 1;\r\n var attrIndex2 = attrIndex + 2;\r\n\r\n normal = ellipsoid.geodeticSurfaceNormal(p, normal);\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n Cartesian3.cross(Cartesian3.UNIT_Z, normal, tangent);\r\n Matrix3.multiplyByVector(tangentRotationMatrix, tangent, tangent);\r\n Cartesian3.normalize(tangent, tangent);\r\n\r\n if (vertexFormat.bitangent) {\r\n Cartesian3.normalize(\r\n Cartesian3.cross(normal, tangent, bitangent),\r\n bitangent\r\n );\r\n }\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n normals[attrIndex] = normal.x;\r\n normals[attrIndex1] = normal.y;\r\n normals[attrIndex2] = normal.z;\r\n }\r\n if (vertexFormat.tangent) {\r\n tangents[attrIndex] = tangent.x;\r\n tangents[attrIndex1] = tangent.y;\r\n tangents[attrIndex2] = tangent.z;\r\n }\r\n if (vertexFormat.bitangent) {\r\n bitangents[attrIndex] = bitangent.x;\r\n bitangents[attrIndex1] = bitangent.y;\r\n bitangents[attrIndex2] = bitangent.z;\r\n }\r\n attrIndex += 3;\r\n }\r\n }\r\n return createAttributes(vertexFormat, {\r\n positions: positions,\r\n normals: normals,\r\n tangents: tangents,\r\n bitangents: bitangents,\r\n });\r\n}\r\n\r\nvar v1Scratch = new Cartesian3();\r\nvar v2Scratch = new Cartesian3();\r\n\r\nfunction calculateAttributesWall(positions, vertexFormat, ellipsoid) {\r\n var length = positions.length;\r\n\r\n var normals = vertexFormat.normal ? new Float32Array(length) : undefined;\r\n var tangents = vertexFormat.tangent ? new Float32Array(length) : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(length)\r\n : undefined;\r\n\r\n var normalIndex = 0;\r\n var tangentIndex = 0;\r\n var bitangentIndex = 0;\r\n var recomputeNormal = true;\r\n\r\n var bitangent = bitangentScratch;\r\n var tangent = tangentScratch;\r\n var normal = normalScratch;\r\n if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {\r\n for (var i = 0; i < length; i += 6) {\r\n var p = Cartesian3.fromArray(positions, i, positionScratch);\r\n var p1 = Cartesian3.fromArray(positions, (i + 6) % length, v1Scratch);\r\n if (recomputeNormal) {\r\n var p2 = Cartesian3.fromArray(positions, (i + 3) % length, v2Scratch);\r\n Cartesian3.subtract(p1, p, p1);\r\n Cartesian3.subtract(p2, p, p2);\r\n normal = Cartesian3.normalize(Cartesian3.cross(p2, p1, normal), normal);\r\n recomputeNormal = false;\r\n }\r\n\r\n if (Cartesian3.equalsEpsilon(p1, p, CesiumMath.EPSILON10)) {\r\n // if we've reached a corner\r\n recomputeNormal = true;\r\n }\r\n\r\n if (vertexFormat.tangent || vertexFormat.bitangent) {\r\n bitangent = ellipsoid.geodeticSurfaceNormal(p, bitangent);\r\n if (vertexFormat.tangent) {\r\n tangent = Cartesian3.normalize(\r\n Cartesian3.cross(bitangent, normal, tangent),\r\n tangent\r\n );\r\n }\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n normals[normalIndex++] = normal.x;\r\n normals[normalIndex++] = normal.y;\r\n normals[normalIndex++] = normal.z;\r\n normals[normalIndex++] = normal.x;\r\n normals[normalIndex++] = normal.y;\r\n normals[normalIndex++] = normal.z;\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n tangents[tangentIndex++] = tangent.x;\r\n tangents[tangentIndex++] = tangent.y;\r\n tangents[tangentIndex++] = tangent.z;\r\n tangents[tangentIndex++] = tangent.x;\r\n tangents[tangentIndex++] = tangent.y;\r\n tangents[tangentIndex++] = tangent.z;\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n bitangents[bitangentIndex++] = bitangent.x;\r\n bitangents[bitangentIndex++] = bitangent.y;\r\n bitangents[bitangentIndex++] = bitangent.z;\r\n bitangents[bitangentIndex++] = bitangent.x;\r\n bitangents[bitangentIndex++] = bitangent.y;\r\n bitangents[bitangentIndex++] = bitangent.z;\r\n }\r\n }\r\n }\r\n\r\n return createAttributes(vertexFormat, {\r\n positions: positions,\r\n normals: normals,\r\n tangents: tangents,\r\n bitangents: bitangents,\r\n });\r\n}\r\n\r\nfunction constructRectangle(rectangleGeometry, computedOptions) {\r\n var vertexFormat = rectangleGeometry._vertexFormat;\r\n var ellipsoid = rectangleGeometry._ellipsoid;\r\n var height = computedOptions.height;\r\n var width = computedOptions.width;\r\n var northCap = computedOptions.northCap;\r\n var southCap = computedOptions.southCap;\r\n\r\n var rowStart = 0;\r\n var rowEnd = height;\r\n var rowHeight = height;\r\n var size = 0;\r\n if (northCap) {\r\n rowStart = 1;\r\n rowHeight -= 1;\r\n size += 1;\r\n }\r\n if (southCap) {\r\n rowEnd -= 1;\r\n rowHeight -= 1;\r\n size += 1;\r\n }\r\n size += width * rowHeight;\r\n\r\n var positions = vertexFormat.position\r\n ? new Float64Array(size * 3)\r\n : undefined;\r\n var textureCoordinates = vertexFormat.st\r\n ? new Float32Array(size * 2)\r\n : undefined;\r\n\r\n var posIndex = 0;\r\n var stIndex = 0;\r\n\r\n var position = positionScratch;\r\n var st = stScratch;\r\n\r\n var minX = Number.MAX_VALUE;\r\n var minY = Number.MAX_VALUE;\r\n var maxX = -Number.MAX_VALUE;\r\n var maxY = -Number.MAX_VALUE;\r\n\r\n for (var row = rowStart; row < rowEnd; ++row) {\r\n for (var col = 0; col < width; ++col) {\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n vertexFormat.st,\r\n row,\r\n col,\r\n position,\r\n st\r\n );\r\n\r\n positions[posIndex++] = position.x;\r\n positions[posIndex++] = position.y;\r\n positions[posIndex++] = position.z;\r\n\r\n if (vertexFormat.st) {\r\n textureCoordinates[stIndex++] = st.x;\r\n textureCoordinates[stIndex++] = st.y;\r\n\r\n minX = Math.min(minX, st.x);\r\n minY = Math.min(minY, st.y);\r\n maxX = Math.max(maxX, st.x);\r\n maxY = Math.max(maxY, st.y);\r\n }\r\n }\r\n }\r\n if (northCap) {\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n vertexFormat.st,\r\n 0,\r\n 0,\r\n position,\r\n st\r\n );\r\n\r\n positions[posIndex++] = position.x;\r\n positions[posIndex++] = position.y;\r\n positions[posIndex++] = position.z;\r\n\r\n if (vertexFormat.st) {\r\n textureCoordinates[stIndex++] = st.x;\r\n textureCoordinates[stIndex++] = st.y;\r\n\r\n minX = st.x;\r\n minY = st.y;\r\n maxX = st.x;\r\n maxY = st.y;\r\n }\r\n }\r\n if (southCap) {\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n vertexFormat.st,\r\n height - 1,\r\n 0,\r\n position,\r\n st\r\n );\r\n\r\n positions[posIndex++] = position.x;\r\n positions[posIndex++] = position.y;\r\n positions[posIndex] = position.z;\r\n\r\n if (vertexFormat.st) {\r\n textureCoordinates[stIndex++] = st.x;\r\n textureCoordinates[stIndex] = st.y;\r\n\r\n minX = Math.min(minX, st.x);\r\n minY = Math.min(minY, st.y);\r\n maxX = Math.max(maxX, st.x);\r\n maxY = Math.max(maxY, st.y);\r\n }\r\n }\r\n\r\n if (\r\n vertexFormat.st &&\r\n (minX < 0.0 || minY < 0.0 || maxX > 1.0 || maxY > 1.0)\r\n ) {\r\n for (var k = 0; k < textureCoordinates.length; k += 2) {\r\n textureCoordinates[k] = (textureCoordinates[k] - minX) / (maxX - minX);\r\n textureCoordinates[k + 1] =\r\n (textureCoordinates[k + 1] - minY) / (maxY - minY);\r\n }\r\n }\r\n\r\n var geo = calculateAttributes(\r\n positions,\r\n vertexFormat,\r\n ellipsoid,\r\n computedOptions.tangentRotationMatrix\r\n );\r\n\r\n var indicesSize = 6 * (width - 1) * (rowHeight - 1);\r\n if (northCap) {\r\n indicesSize += 3 * (width - 1);\r\n }\r\n if (southCap) {\r\n indicesSize += 3 * (width - 1);\r\n }\r\n var indices = IndexDatatype.createTypedArray(size, indicesSize);\r\n var index = 0;\r\n var indicesIndex = 0;\r\n var i;\r\n for (i = 0; i < rowHeight - 1; ++i) {\r\n for (var j = 0; j < width - 1; ++j) {\r\n var upperLeft = index;\r\n var lowerLeft = upperLeft + width;\r\n var lowerRight = lowerLeft + 1;\r\n var upperRight = upperLeft + 1;\r\n indices[indicesIndex++] = upperLeft;\r\n indices[indicesIndex++] = lowerLeft;\r\n indices[indicesIndex++] = upperRight;\r\n indices[indicesIndex++] = upperRight;\r\n indices[indicesIndex++] = lowerLeft;\r\n indices[indicesIndex++] = lowerRight;\r\n ++index;\r\n }\r\n ++index;\r\n }\r\n if (northCap || southCap) {\r\n var northIndex = size - 1;\r\n var southIndex = size - 1;\r\n if (northCap && southCap) {\r\n northIndex = size - 2;\r\n }\r\n\r\n var p1;\r\n var p2;\r\n index = 0;\r\n\r\n if (northCap) {\r\n for (i = 0; i < width - 1; i++) {\r\n p1 = index;\r\n p2 = p1 + 1;\r\n indices[indicesIndex++] = northIndex;\r\n indices[indicesIndex++] = p1;\r\n indices[indicesIndex++] = p2;\r\n ++index;\r\n }\r\n }\r\n if (southCap) {\r\n index = (rowHeight - 1) * width;\r\n for (i = 0; i < width - 1; i++) {\r\n p1 = index;\r\n p2 = p1 + 1;\r\n indices[indicesIndex++] = p1;\r\n indices[indicesIndex++] = southIndex;\r\n indices[indicesIndex++] = p2;\r\n ++index;\r\n }\r\n }\r\n }\r\n\r\n geo.indices = indices;\r\n if (vertexFormat.st) {\r\n geo.attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: textureCoordinates,\r\n });\r\n }\r\n\r\n return geo;\r\n}\r\n\r\nfunction addWallPositions(\r\n wallPositions,\r\n posIndex,\r\n i,\r\n topPositions,\r\n bottomPositions\r\n) {\r\n wallPositions[posIndex++] = topPositions[i];\r\n wallPositions[posIndex++] = topPositions[i + 1];\r\n wallPositions[posIndex++] = topPositions[i + 2];\r\n wallPositions[posIndex++] = bottomPositions[i];\r\n wallPositions[posIndex++] = bottomPositions[i + 1];\r\n wallPositions[posIndex] = bottomPositions[i + 2];\r\n return wallPositions;\r\n}\r\n\r\nfunction addWallTextureCoordinates(wallTextures, stIndex, i, st) {\r\n wallTextures[stIndex++] = st[i];\r\n wallTextures[stIndex++] = st[i + 1];\r\n wallTextures[stIndex++] = st[i];\r\n wallTextures[stIndex] = st[i + 1];\r\n return wallTextures;\r\n}\r\n\r\nvar scratchVertexFormat = new VertexFormat();\r\n\r\nfunction constructExtrudedRectangle(rectangleGeometry, computedOptions) {\r\n var shadowVolume = rectangleGeometry._shadowVolume;\r\n var offsetAttributeValue = rectangleGeometry._offsetAttribute;\r\n var vertexFormat = rectangleGeometry._vertexFormat;\r\n var minHeight = rectangleGeometry._extrudedHeight;\r\n var maxHeight = rectangleGeometry._surfaceHeight;\r\n var ellipsoid = rectangleGeometry._ellipsoid;\r\n\r\n var height = computedOptions.height;\r\n var width = computedOptions.width;\r\n\r\n var i;\r\n\r\n if (shadowVolume) {\r\n var newVertexFormat = VertexFormat.clone(vertexFormat, scratchVertexFormat);\r\n newVertexFormat.normal = true;\r\n rectangleGeometry._vertexFormat = newVertexFormat;\r\n }\r\n\r\n var topBottomGeo = constructRectangle(rectangleGeometry, computedOptions);\r\n\r\n if (shadowVolume) {\r\n rectangleGeometry._vertexFormat = vertexFormat;\r\n }\r\n\r\n var topPositions = PolygonPipeline.scaleToGeodeticHeight(\r\n topBottomGeo.attributes.position.values,\r\n maxHeight,\r\n ellipsoid,\r\n false\r\n );\r\n topPositions = new Float64Array(topPositions);\r\n var length = topPositions.length;\r\n var newLength = length * 2;\r\n var positions = new Float64Array(newLength);\r\n positions.set(topPositions);\r\n var bottomPositions = PolygonPipeline.scaleToGeodeticHeight(\r\n topBottomGeo.attributes.position.values,\r\n minHeight,\r\n ellipsoid\r\n );\r\n positions.set(bottomPositions, length);\r\n topBottomGeo.attributes.position.values = positions;\r\n\r\n var normals = vertexFormat.normal ? new Float32Array(newLength) : undefined;\r\n var tangents = vertexFormat.tangent ? new Float32Array(newLength) : undefined;\r\n var bitangents = vertexFormat.bitangent\r\n ? new Float32Array(newLength)\r\n : undefined;\r\n var textures = vertexFormat.st\r\n ? new Float32Array((newLength / 3) * 2)\r\n : undefined;\r\n var topSt;\r\n var topNormals;\r\n if (vertexFormat.normal) {\r\n topNormals = topBottomGeo.attributes.normal.values;\r\n normals.set(topNormals);\r\n for (i = 0; i < length; i++) {\r\n topNormals[i] = -topNormals[i];\r\n }\r\n normals.set(topNormals, length);\r\n topBottomGeo.attributes.normal.values = normals;\r\n }\r\n if (shadowVolume) {\r\n topNormals = topBottomGeo.attributes.normal.values;\r\n if (!vertexFormat.normal) {\r\n topBottomGeo.attributes.normal = undefined;\r\n }\r\n var extrudeNormals = new Float32Array(newLength);\r\n for (i = 0; i < length; i++) {\r\n topNormals[i] = -topNormals[i];\r\n }\r\n extrudeNormals.set(topNormals, length); //only get normals for bottom layer that's going to be pushed down\r\n topBottomGeo.attributes.extrudeDirection = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: extrudeNormals,\r\n });\r\n }\r\n\r\n var offsetValue;\r\n var hasOffsets = defined(offsetAttributeValue);\r\n if (hasOffsets) {\r\n var size = (length / 3) * 2;\r\n var offsetAttribute = new Uint8Array(size);\r\n if (offsetAttributeValue === GeometryOffsetAttribute.TOP) {\r\n offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);\r\n } else {\r\n offsetValue =\r\n offsetAttributeValue === GeometryOffsetAttribute.NONE ? 0 : 1;\r\n offsetAttribute = arrayFill(offsetAttribute, offsetValue);\r\n }\r\n\r\n topBottomGeo.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: offsetAttribute,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n var topTangents = topBottomGeo.attributes.tangent.values;\r\n tangents.set(topTangents);\r\n for (i = 0; i < length; i++) {\r\n topTangents[i] = -topTangents[i];\r\n }\r\n tangents.set(topTangents, length);\r\n topBottomGeo.attributes.tangent.values = tangents;\r\n }\r\n if (vertexFormat.bitangent) {\r\n var topBitangents = topBottomGeo.attributes.bitangent.values;\r\n bitangents.set(topBitangents);\r\n bitangents.set(topBitangents, length);\r\n topBottomGeo.attributes.bitangent.values = bitangents;\r\n }\r\n if (vertexFormat.st) {\r\n topSt = topBottomGeo.attributes.st.values;\r\n textures.set(topSt);\r\n textures.set(topSt, (length / 3) * 2);\r\n topBottomGeo.attributes.st.values = textures;\r\n }\r\n\r\n var indices = topBottomGeo.indices;\r\n var indicesLength = indices.length;\r\n var posLength = length / 3;\r\n var newIndices = IndexDatatype.createTypedArray(\r\n newLength / 3,\r\n indicesLength * 2\r\n );\r\n newIndices.set(indices);\r\n for (i = 0; i < indicesLength; i += 3) {\r\n newIndices[i + indicesLength] = indices[i + 2] + posLength;\r\n newIndices[i + 1 + indicesLength] = indices[i + 1] + posLength;\r\n newIndices[i + 2 + indicesLength] = indices[i] + posLength;\r\n }\r\n topBottomGeo.indices = newIndices;\r\n\r\n var northCap = computedOptions.northCap;\r\n var southCap = computedOptions.southCap;\r\n\r\n var rowHeight = height;\r\n var widthMultiplier = 2;\r\n var perimeterPositions = 0;\r\n var corners = 4;\r\n var dupliateCorners = 4;\r\n if (northCap) {\r\n widthMultiplier -= 1;\r\n rowHeight -= 1;\r\n perimeterPositions += 1;\r\n corners -= 2;\r\n dupliateCorners -= 1;\r\n }\r\n if (southCap) {\r\n widthMultiplier -= 1;\r\n rowHeight -= 1;\r\n perimeterPositions += 1;\r\n corners -= 2;\r\n dupliateCorners -= 1;\r\n }\r\n perimeterPositions += widthMultiplier * width + 2 * rowHeight - corners;\r\n\r\n var wallCount = (perimeterPositions + dupliateCorners) * 2;\r\n\r\n var wallPositions = new Float64Array(wallCount * 3);\r\n var wallExtrudeNormals = shadowVolume\r\n ? new Float32Array(wallCount * 3)\r\n : undefined;\r\n var wallOffsetAttribute = hasOffsets ? new Uint8Array(wallCount) : undefined;\r\n var wallTextures = vertexFormat.st\r\n ? new Float32Array(wallCount * 2)\r\n : undefined;\r\n\r\n var computeTopOffsets = offsetAttributeValue === GeometryOffsetAttribute.TOP;\r\n if (hasOffsets && !computeTopOffsets) {\r\n offsetValue = offsetAttributeValue === GeometryOffsetAttribute.ALL ? 1 : 0;\r\n wallOffsetAttribute = arrayFill(wallOffsetAttribute, offsetValue);\r\n }\r\n\r\n var posIndex = 0;\r\n var stIndex = 0;\r\n var extrudeNormalIndex = 0;\r\n var wallOffsetIndex = 0;\r\n var area = width * rowHeight;\r\n var threeI;\r\n for (i = 0; i < area; i += width) {\r\n threeI = i * 3;\r\n wallPositions = addWallPositions(\r\n wallPositions,\r\n posIndex,\r\n threeI,\r\n topPositions,\r\n bottomPositions\r\n );\r\n posIndex += 6;\r\n if (vertexFormat.st) {\r\n wallTextures = addWallTextureCoordinates(\r\n wallTextures,\r\n stIndex,\r\n i * 2,\r\n topSt\r\n );\r\n stIndex += 4;\r\n }\r\n if (shadowVolume) {\r\n extrudeNormalIndex += 3;\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];\r\n }\r\n if (computeTopOffsets) {\r\n wallOffsetAttribute[wallOffsetIndex++] = 1;\r\n wallOffsetIndex += 1;\r\n }\r\n }\r\n\r\n if (!southCap) {\r\n for (i = area - width; i < area; i++) {\r\n threeI = i * 3;\r\n wallPositions = addWallPositions(\r\n wallPositions,\r\n posIndex,\r\n threeI,\r\n topPositions,\r\n bottomPositions\r\n );\r\n posIndex += 6;\r\n if (vertexFormat.st) {\r\n wallTextures = addWallTextureCoordinates(\r\n wallTextures,\r\n stIndex,\r\n i * 2,\r\n topSt\r\n );\r\n stIndex += 4;\r\n }\r\n if (shadowVolume) {\r\n extrudeNormalIndex += 3;\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];\r\n }\r\n if (computeTopOffsets) {\r\n wallOffsetAttribute[wallOffsetIndex++] = 1;\r\n wallOffsetIndex += 1;\r\n }\r\n }\r\n } else {\r\n var southIndex = northCap ? area + 1 : area;\r\n threeI = southIndex * 3;\r\n\r\n for (i = 0; i < 2; i++) {\r\n // duplicate corner points\r\n wallPositions = addWallPositions(\r\n wallPositions,\r\n posIndex,\r\n threeI,\r\n topPositions,\r\n bottomPositions\r\n );\r\n posIndex += 6;\r\n if (vertexFormat.st) {\r\n wallTextures = addWallTextureCoordinates(\r\n wallTextures,\r\n stIndex,\r\n southIndex * 2,\r\n topSt\r\n );\r\n stIndex += 4;\r\n }\r\n if (shadowVolume) {\r\n extrudeNormalIndex += 3;\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];\r\n }\r\n if (computeTopOffsets) {\r\n wallOffsetAttribute[wallOffsetIndex++] = 1;\r\n wallOffsetIndex += 1;\r\n }\r\n }\r\n }\r\n\r\n for (i = area - 1; i > 0; i -= width) {\r\n threeI = i * 3;\r\n wallPositions = addWallPositions(\r\n wallPositions,\r\n posIndex,\r\n threeI,\r\n topPositions,\r\n bottomPositions\r\n );\r\n posIndex += 6;\r\n if (vertexFormat.st) {\r\n wallTextures = addWallTextureCoordinates(\r\n wallTextures,\r\n stIndex,\r\n i * 2,\r\n topSt\r\n );\r\n stIndex += 4;\r\n }\r\n if (shadowVolume) {\r\n extrudeNormalIndex += 3;\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];\r\n }\r\n if (computeTopOffsets) {\r\n wallOffsetAttribute[wallOffsetIndex++] = 1;\r\n wallOffsetIndex += 1;\r\n }\r\n }\r\n\r\n if (!northCap) {\r\n for (i = width - 1; i >= 0; i--) {\r\n threeI = i * 3;\r\n wallPositions = addWallPositions(\r\n wallPositions,\r\n posIndex,\r\n threeI,\r\n topPositions,\r\n bottomPositions\r\n );\r\n posIndex += 6;\r\n if (vertexFormat.st) {\r\n wallTextures = addWallTextureCoordinates(\r\n wallTextures,\r\n stIndex,\r\n i * 2,\r\n topSt\r\n );\r\n stIndex += 4;\r\n }\r\n if (shadowVolume) {\r\n extrudeNormalIndex += 3;\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];\r\n }\r\n if (computeTopOffsets) {\r\n wallOffsetAttribute[wallOffsetIndex++] = 1;\r\n wallOffsetIndex += 1;\r\n }\r\n }\r\n } else {\r\n var northIndex = area;\r\n threeI = northIndex * 3;\r\n\r\n for (i = 0; i < 2; i++) {\r\n // duplicate corner points\r\n wallPositions = addWallPositions(\r\n wallPositions,\r\n posIndex,\r\n threeI,\r\n topPositions,\r\n bottomPositions\r\n );\r\n posIndex += 6;\r\n if (vertexFormat.st) {\r\n wallTextures = addWallTextureCoordinates(\r\n wallTextures,\r\n stIndex,\r\n northIndex * 2,\r\n topSt\r\n );\r\n stIndex += 4;\r\n }\r\n if (shadowVolume) {\r\n extrudeNormalIndex += 3;\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 1];\r\n wallExtrudeNormals[extrudeNormalIndex++] = topNormals[threeI + 2];\r\n }\r\n if (computeTopOffsets) {\r\n wallOffsetAttribute[wallOffsetIndex++] = 1;\r\n wallOffsetIndex += 1;\r\n }\r\n }\r\n }\r\n\r\n var geo = calculateAttributesWall(wallPositions, vertexFormat, ellipsoid);\r\n\r\n if (vertexFormat.st) {\r\n geo.attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: wallTextures,\r\n });\r\n }\r\n if (shadowVolume) {\r\n geo.attributes.extrudeDirection = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: wallExtrudeNormals,\r\n });\r\n }\r\n if (hasOffsets) {\r\n geo.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: wallOffsetAttribute,\r\n });\r\n }\r\n\r\n var wallIndices = IndexDatatype.createTypedArray(\r\n wallCount,\r\n perimeterPositions * 6\r\n );\r\n\r\n var upperLeft;\r\n var lowerLeft;\r\n var lowerRight;\r\n var upperRight;\r\n length = wallPositions.length / 3;\r\n var index = 0;\r\n for (i = 0; i < length - 1; i += 2) {\r\n upperLeft = i;\r\n upperRight = (upperLeft + 2) % length;\r\n var p1 = Cartesian3.fromArray(wallPositions, upperLeft * 3, v1Scratch);\r\n var p2 = Cartesian3.fromArray(wallPositions, upperRight * 3, v2Scratch);\r\n if (Cartesian3.equalsEpsilon(p1, p2, CesiumMath.EPSILON10)) {\r\n continue;\r\n }\r\n lowerLeft = (upperLeft + 1) % length;\r\n lowerRight = (lowerLeft + 2) % length;\r\n wallIndices[index++] = upperLeft;\r\n wallIndices[index++] = lowerLeft;\r\n wallIndices[index++] = upperRight;\r\n wallIndices[index++] = upperRight;\r\n wallIndices[index++] = lowerLeft;\r\n wallIndices[index++] = lowerRight;\r\n }\r\n\r\n geo.indices = wallIndices;\r\n\r\n geo = GeometryPipeline.combineInstances([\r\n new GeometryInstance({\r\n geometry: topBottomGeo,\r\n }),\r\n new GeometryInstance({\r\n geometry: geo,\r\n }),\r\n ]);\r\n\r\n return geo[0];\r\n}\r\n\r\nvar scratchRectanglePoints = [\r\n new Cartesian3(),\r\n new Cartesian3(),\r\n new Cartesian3(),\r\n new Cartesian3(),\r\n];\r\nvar nwScratch = new Cartographic();\r\nvar stNwScratch = new Cartographic();\r\nfunction computeRectangle(rectangle, granularity, rotation, ellipsoid, result) {\r\n if (rotation === 0.0) {\r\n return Rectangle.clone(rectangle, result);\r\n }\r\n\r\n var computedOptions = RectangleGeometryLibrary.computeOptions(\r\n rectangle,\r\n granularity,\r\n rotation,\r\n 0,\r\n rectangleScratch,\r\n nwScratch\r\n );\r\n\r\n var height = computedOptions.height;\r\n var width = computedOptions.width;\r\n\r\n var positions = scratchRectanglePoints;\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n 0,\r\n 0,\r\n positions[0]\r\n );\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n 0,\r\n width - 1,\r\n positions[1]\r\n );\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n height - 1,\r\n 0,\r\n positions[2]\r\n );\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n height - 1,\r\n width - 1,\r\n positions[3]\r\n );\r\n\r\n return Rectangle.fromCartesianArray(positions, ellipsoid, result);\r\n}\r\n\r\n/**\r\n * A description of a cartographic rectangle on an ellipsoid centered at the origin. Rectangle geometry can be rendered with both {@link Primitive} and {@link GroundPrimitive}.\r\n *\r\n * @alias RectangleGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Rectangle} options.rectangle A cartographic rectangle with north, south, east and west properties in radians.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the rectangle lies.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Number} [options.height=0.0] The distance in meters between the rectangle and the ellipsoid surface.\r\n * @param {Number} [options.rotation=0.0] The rotation of the rectangle, in radians. A positive rotation is counter-clockwise.\r\n * @param {Number} [options.stRotation=0.0] The rotation of the texture coordinates, in radians. A positive rotation is counter-clockwise.\r\n * @param {Number} [options.extrudedHeight] The distance in meters between the rectangle's extruded face and the ellipsoid surface.\r\n *\r\n * @exception {DeveloperError} options.rectangle.north must be in the interval [-Pi/2, Pi/2].\r\n * @exception {DeveloperError} options.rectangle.south must be in the interval [-Pi/2, Pi/2].\r\n * @exception {DeveloperError} options.rectangle.east must be in the interval [-Pi, Pi].\r\n * @exception {DeveloperError} options.rectangle.west must be in the interval [-Pi, Pi].\r\n * @exception {DeveloperError} options.rectangle.north must be greater than options.rectangle.south.\r\n *\r\n * @see RectangleGeometry#createGeometry\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Rectangle.html|Cesium Sandcastle Rectangle Demo}\r\n *\r\n * @example\r\n * // 1. create a rectangle\r\n * var rectangle = new Cesium.RectangleGeometry({\r\n * ellipsoid : Cesium.Ellipsoid.WGS84,\r\n * rectangle : Cesium.Rectangle.fromDegrees(-80.0, 39.0, -74.0, 42.0),\r\n * height : 10000.0\r\n * });\r\n * var geometry = Cesium.RectangleGeometry.createGeometry(rectangle);\r\n *\r\n * // 2. create an extruded rectangle without a top\r\n * var rectangle = new Cesium.RectangleGeometry({\r\n * ellipsoid : Cesium.Ellipsoid.WGS84,\r\n * rectangle : Cesium.Rectangle.fromDegrees(-80.0, 39.0, -74.0, 42.0),\r\n * height : 10000.0,\r\n * extrudedHeight: 300000\r\n * });\r\n * var geometry = Cesium.RectangleGeometry.createGeometry(rectangle);\r\n */\r\nfunction RectangleGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var rectangle = options.rectangle;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n Rectangle.validate(rectangle);\r\n if (rectangle.north < rectangle.south) {\r\n throw new DeveloperError(\r\n \"options.rectangle.north must be greater than or equal to options.rectangle.south\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var height = defaultValue(options.height, 0.0);\r\n var extrudedHeight = defaultValue(options.extrudedHeight, height);\r\n\r\n this._rectangle = Rectangle.clone(rectangle);\r\n this._granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n this._ellipsoid = Ellipsoid.clone(\r\n defaultValue(options.ellipsoid, Ellipsoid.WGS84)\r\n );\r\n this._surfaceHeight = Math.max(height, extrudedHeight);\r\n this._rotation = defaultValue(options.rotation, 0.0);\r\n this._stRotation = defaultValue(options.stRotation, 0.0);\r\n this._vertexFormat = VertexFormat.clone(\r\n defaultValue(options.vertexFormat, VertexFormat.DEFAULT)\r\n );\r\n this._extrudedHeight = Math.min(height, extrudedHeight);\r\n this._shadowVolume = defaultValue(options.shadowVolume, false);\r\n this._workerName = \"createRectangleGeometry\";\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._rotatedRectangle = undefined;\r\n\r\n this._textureCoordinateRotationPoints = undefined;\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nRectangleGeometry.packedLength =\r\n Rectangle.packedLength +\r\n Ellipsoid.packedLength +\r\n VertexFormat.packedLength +\r\n 7;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {RectangleGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nRectangleGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Rectangle.pack(value._rectangle, array, startingIndex);\r\n startingIndex += Rectangle.packedLength;\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex++] = value._granularity;\r\n array[startingIndex++] = value._surfaceHeight;\r\n array[startingIndex++] = value._rotation;\r\n array[startingIndex++] = value._stRotation;\r\n array[startingIndex++] = value._extrudedHeight;\r\n array[startingIndex++] = value._shadowVolume ? 1.0 : 0.0;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchRectangle = new Rectangle();\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchOptions = {\r\n rectangle: scratchRectangle,\r\n ellipsoid: scratchEllipsoid,\r\n vertexFormat: scratchVertexFormat,\r\n granularity: undefined,\r\n height: undefined,\r\n rotation: undefined,\r\n stRotation: undefined,\r\n extrudedHeight: undefined,\r\n shadowVolume: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {RectangleGeometry} [result] The object into which to store the result.\r\n * @returns {RectangleGeometry} The modified result parameter or a new RectangleGeometry instance if one was not provided.\r\n */\r\nRectangleGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"array\", array);\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var rectangle = Rectangle.unpack(array, startingIndex, scratchRectangle);\r\n startingIndex += Rectangle.packedLength;\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var granularity = array[startingIndex++];\r\n var surfaceHeight = array[startingIndex++];\r\n var rotation = array[startingIndex++];\r\n var stRotation = array[startingIndex++];\r\n var extrudedHeight = array[startingIndex++];\r\n var shadowVolume = array[startingIndex++] === 1.0;\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.granularity = granularity;\r\n scratchOptions.height = surfaceHeight;\r\n scratchOptions.rotation = rotation;\r\n scratchOptions.stRotation = stRotation;\r\n scratchOptions.extrudedHeight = extrudedHeight;\r\n scratchOptions.shadowVolume = shadowVolume;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return new RectangleGeometry(scratchOptions);\r\n }\r\n\r\n result._rectangle = Rectangle.clone(rectangle, result._rectangle);\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._granularity = granularity;\r\n result._surfaceHeight = surfaceHeight;\r\n result._rotation = rotation;\r\n result._stRotation = stRotation;\r\n result._extrudedHeight = extrudedHeight;\r\n result._shadowVolume = shadowVolume;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the bounding rectangle based on the provided options\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Rectangle} options.rectangle A cartographic rectangle with north, south, east and west properties in radians.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the rectangle lies.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Number} [options.rotation=0.0] The rotation of the rectangle, in radians. A positive rotation is counter-clockwise.\r\n * @param {Rectangle} [result] An object in which to store the result.\r\n *\r\n * @returns {Rectangle} The result rectangle\r\n */\r\nRectangleGeometry.computeRectangle = function (options, result) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var rectangle = options.rectangle;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n Rectangle.validate(rectangle);\r\n if (rectangle.north < rectangle.south) {\r\n throw new DeveloperError(\r\n \"options.rectangle.north must be greater than or equal to options.rectangle.south\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var rotation = defaultValue(options.rotation, 0.0);\r\n\r\n return computeRectangle(rectangle, granularity, rotation, ellipsoid, result);\r\n};\r\n\r\nvar tangentRotationMatrixScratch = new Matrix3();\r\nvar quaternionScratch = new Quaternion();\r\nvar centerScratch = new Cartographic();\r\n/**\r\n * Computes the geometric representation of a rectangle, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {RectangleGeometry} rectangleGeometry A description of the rectangle.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n *\r\n * @exception {DeveloperError} Rotated rectangle is invalid.\r\n */\r\nRectangleGeometry.createGeometry = function (rectangleGeometry) {\r\n if (\r\n CesiumMath.equalsEpsilon(\r\n rectangleGeometry._rectangle.north,\r\n rectangleGeometry._rectangle.south,\r\n CesiumMath.EPSILON10\r\n ) ||\r\n CesiumMath.equalsEpsilon(\r\n rectangleGeometry._rectangle.east,\r\n rectangleGeometry._rectangle.west,\r\n CesiumMath.EPSILON10\r\n )\r\n ) {\r\n return undefined;\r\n }\r\n\r\n var rectangle = rectangleGeometry._rectangle;\r\n var ellipsoid = rectangleGeometry._ellipsoid;\r\n var rotation = rectangleGeometry._rotation;\r\n var stRotation = rectangleGeometry._stRotation;\r\n var vertexFormat = rectangleGeometry._vertexFormat;\r\n\r\n var computedOptions = RectangleGeometryLibrary.computeOptions(\r\n rectangle,\r\n rectangleGeometry._granularity,\r\n rotation,\r\n stRotation,\r\n rectangleScratch,\r\n nwScratch,\r\n stNwScratch\r\n );\r\n\r\n var tangentRotationMatrix = tangentRotationMatrixScratch;\r\n if (stRotation !== 0 || rotation !== 0) {\r\n var center = Rectangle.center(rectangle, centerScratch);\r\n var axis = ellipsoid.geodeticSurfaceNormalCartographic(center, v1Scratch);\r\n Quaternion.fromAxisAngle(axis, -stRotation, quaternionScratch);\r\n Matrix3.fromQuaternion(quaternionScratch, tangentRotationMatrix);\r\n } else {\r\n Matrix3.clone(Matrix3.IDENTITY, tangentRotationMatrix);\r\n }\r\n\r\n var surfaceHeight = rectangleGeometry._surfaceHeight;\r\n var extrudedHeight = rectangleGeometry._extrudedHeight;\r\n var extrude = !CesiumMath.equalsEpsilon(\r\n surfaceHeight,\r\n extrudedHeight,\r\n 0,\r\n CesiumMath.EPSILON2\r\n );\r\n\r\n computedOptions.lonScalar = 1.0 / rectangleGeometry._rectangle.width;\r\n computedOptions.latScalar = 1.0 / rectangleGeometry._rectangle.height;\r\n computedOptions.tangentRotationMatrix = tangentRotationMatrix;\r\n\r\n var geometry;\r\n var boundingSphere;\r\n rectangle = rectangleGeometry._rectangle;\r\n if (extrude) {\r\n geometry = constructExtrudedRectangle(rectangleGeometry, computedOptions);\r\n var topBS = BoundingSphere.fromRectangle3D(\r\n rectangle,\r\n ellipsoid,\r\n surfaceHeight,\r\n topBoundingSphere\r\n );\r\n var bottomBS = BoundingSphere.fromRectangle3D(\r\n rectangle,\r\n ellipsoid,\r\n extrudedHeight,\r\n bottomBoundingSphere\r\n );\r\n boundingSphere = BoundingSphere.union(topBS, bottomBS);\r\n } else {\r\n geometry = constructRectangle(rectangleGeometry, computedOptions);\r\n geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(\r\n geometry.attributes.position.values,\r\n surfaceHeight,\r\n ellipsoid,\r\n false\r\n );\r\n\r\n if (defined(rectangleGeometry._offsetAttribute)) {\r\n var length = geometry.attributes.position.values.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n var offsetValue =\r\n rectangleGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n geometry.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n boundingSphere = BoundingSphere.fromRectangle3D(\r\n rectangle,\r\n ellipsoid,\r\n surfaceHeight\r\n );\r\n }\r\n\r\n if (!vertexFormat.position) {\r\n delete geometry.attributes.position;\r\n }\r\n\r\n return new Geometry({\r\n attributes: geometry.attributes,\r\n indices: geometry.indices,\r\n primitiveType: geometry.primitiveType,\r\n boundingSphere: boundingSphere,\r\n offsetAttribute: rectangleGeometry._offsetAttribute,\r\n });\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nRectangleGeometry.createShadowVolume = function (\r\n rectangleGeometry,\r\n minHeightFunc,\r\n maxHeightFunc\r\n) {\r\n var granularity = rectangleGeometry._granularity;\r\n var ellipsoid = rectangleGeometry._ellipsoid;\r\n\r\n var minHeight = minHeightFunc(granularity, ellipsoid);\r\n var maxHeight = maxHeightFunc(granularity, ellipsoid);\r\n\r\n return new RectangleGeometry({\r\n rectangle: rectangleGeometry._rectangle,\r\n rotation: rectangleGeometry._rotation,\r\n ellipsoid: ellipsoid,\r\n stRotation: rectangleGeometry._stRotation,\r\n granularity: granularity,\r\n extrudedHeight: maxHeight,\r\n height: minHeight,\r\n vertexFormat: VertexFormat.POSITION_ONLY,\r\n shadowVolume: true,\r\n });\r\n};\r\n\r\nvar unrotatedTextureRectangleScratch = new Rectangle();\r\nvar points2DScratch = [new Cartesian2(), new Cartesian2(), new Cartesian2()];\r\nvar rotation2DScratch = new Matrix2();\r\nvar rectangleCenterScratch = new Cartographic();\r\n\r\nfunction textureCoordinateRotationPoints(rectangleGeometry) {\r\n if (rectangleGeometry._stRotation === 0.0) {\r\n return [0, 0, 0, 1, 1, 0];\r\n }\r\n\r\n var rectangle = Rectangle.clone(\r\n rectangleGeometry._rectangle,\r\n unrotatedTextureRectangleScratch\r\n );\r\n var granularity = rectangleGeometry._granularity;\r\n var ellipsoid = rectangleGeometry._ellipsoid;\r\n\r\n // Rotate to align the texture coordinates with ENU\r\n var rotation = rectangleGeometry._rotation - rectangleGeometry._stRotation;\r\n\r\n var unrotatedTextureRectangle = computeRectangle(\r\n rectangle,\r\n granularity,\r\n rotation,\r\n ellipsoid,\r\n unrotatedTextureRectangleScratch\r\n );\r\n\r\n // Assume a computed \"east-north\" texture coordinate system based on spherical or planar tricks, bounded by `boundingRectangle`.\r\n // The \"desired\" texture coordinate system forms an oriented rectangle (un-oriented computed) around the geometry that completely and tightly bounds it.\r\n // We want to map from the \"east-north\" texture coordinate system into the \"desired\" system using a pair of lines (analagous planes in 2D)\r\n // Compute 3 corners of the \"desired\" texture coordinate system in \"east-north\" texture space by the following in cartographic space:\r\n // - rotate 3 of the corners in unrotatedTextureRectangle by stRotation around the center of the bounding rectangle\r\n // - apply the \"east-north\" system's normalization formula to the rotated cartographics, even though this is likely to produce values outside [0-1].\r\n // This gives us a set of points in the \"east-north\" texture coordinate system that can be used to map \"east-north\" texture coordinates to \"desired.\"\r\n\r\n var points2D = points2DScratch;\r\n points2D[0].x = unrotatedTextureRectangle.west;\r\n points2D[0].y = unrotatedTextureRectangle.south;\r\n\r\n points2D[1].x = unrotatedTextureRectangle.west;\r\n points2D[1].y = unrotatedTextureRectangle.north;\r\n\r\n points2D[2].x = unrotatedTextureRectangle.east;\r\n points2D[2].y = unrotatedTextureRectangle.south;\r\n\r\n var boundingRectangle = rectangleGeometry.rectangle;\r\n var toDesiredInComputed = Matrix2.fromRotation(\r\n rectangleGeometry._stRotation,\r\n rotation2DScratch\r\n );\r\n var boundingRectangleCenter = Rectangle.center(\r\n boundingRectangle,\r\n rectangleCenterScratch\r\n );\r\n\r\n for (var i = 0; i < 3; ++i) {\r\n var point2D = points2D[i];\r\n point2D.x -= boundingRectangleCenter.longitude;\r\n point2D.y -= boundingRectangleCenter.latitude;\r\n Matrix2.multiplyByVector(toDesiredInComputed, point2D, point2D);\r\n point2D.x += boundingRectangleCenter.longitude;\r\n point2D.y += boundingRectangleCenter.latitude;\r\n\r\n // Convert point into east-north texture coordinate space\r\n point2D.x = (point2D.x - boundingRectangle.west) / boundingRectangle.width;\r\n point2D.y =\r\n (point2D.y - boundingRectangle.south) / boundingRectangle.height;\r\n }\r\n\r\n var minXYCorner = points2D[0];\r\n var maxYCorner = points2D[1];\r\n var maxXCorner = points2D[2];\r\n var result = new Array(6);\r\n Cartesian2.pack(minXYCorner, result);\r\n Cartesian2.pack(maxYCorner, result, 2);\r\n Cartesian2.pack(maxXCorner, result, 4);\r\n return result;\r\n}\r\n\r\nObject.defineProperties(RectangleGeometry.prototype, {\r\n /**\r\n * @private\r\n */\r\n rectangle: {\r\n get: function () {\r\n if (!defined(this._rotatedRectangle)) {\r\n this._rotatedRectangle = computeRectangle(\r\n this._rectangle,\r\n this._granularity,\r\n this._rotation,\r\n this._ellipsoid\r\n );\r\n }\r\n return this._rotatedRectangle;\r\n },\r\n },\r\n /**\r\n * For remapping texture coordinates when rendering RectangleGeometries as GroundPrimitives.\r\n * This version permits skew in textures by computing offsets directly in cartographic space and\r\n * more accurately approximates rendering RectangleGeometries with height as standard Primitives.\r\n * @see Geometry#_textureCoordinateRotationPoints\r\n * @private\r\n */\r\n textureCoordinateRotationPoints: {\r\n get: function () {\r\n if (!defined(this._textureCoordinateRotationPoints)) {\r\n this._textureCoordinateRotationPoints = textureCoordinateRotationPoints(\r\n this\r\n );\r\n }\r\n return this._textureCoordinateRotationPoints;\r\n },\r\n },\r\n});\r\nexport default RectangleGeometry;\r\n","import arrayFill from \"./arrayFill.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"./GeometryOffsetAttribute.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PolygonPipeline from \"./PolygonPipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport RectangleGeometryLibrary from \"./RectangleGeometryLibrary.js\";\r\n\r\nvar bottomBoundingSphere = new BoundingSphere();\r\nvar topBoundingSphere = new BoundingSphere();\r\nvar positionScratch = new Cartesian3();\r\nvar rectangleScratch = new Rectangle();\r\n\r\nfunction constructRectangle(geometry, computedOptions) {\r\n var ellipsoid = geometry._ellipsoid;\r\n var height = computedOptions.height;\r\n var width = computedOptions.width;\r\n var northCap = computedOptions.northCap;\r\n var southCap = computedOptions.southCap;\r\n\r\n var rowHeight = height;\r\n var widthMultiplier = 2;\r\n var size = 0;\r\n var corners = 4;\r\n if (northCap) {\r\n widthMultiplier -= 1;\r\n rowHeight -= 1;\r\n size += 1;\r\n corners -= 2;\r\n }\r\n if (southCap) {\r\n widthMultiplier -= 1;\r\n rowHeight -= 1;\r\n size += 1;\r\n corners -= 2;\r\n }\r\n size += widthMultiplier * width + 2 * rowHeight - corners;\r\n\r\n var positions = new Float64Array(size * 3);\r\n\r\n var posIndex = 0;\r\n var row = 0;\r\n var col;\r\n var position = positionScratch;\r\n if (northCap) {\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n row,\r\n 0,\r\n position\r\n );\r\n positions[posIndex++] = position.x;\r\n positions[posIndex++] = position.y;\r\n positions[posIndex++] = position.z;\r\n } else {\r\n for (col = 0; col < width; col++) {\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n row,\r\n col,\r\n position\r\n );\r\n positions[posIndex++] = position.x;\r\n positions[posIndex++] = position.y;\r\n positions[posIndex++] = position.z;\r\n }\r\n }\r\n\r\n col = width - 1;\r\n for (row = 1; row < height; row++) {\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n row,\r\n col,\r\n position\r\n );\r\n positions[posIndex++] = position.x;\r\n positions[posIndex++] = position.y;\r\n positions[posIndex++] = position.z;\r\n }\r\n\r\n row = height - 1;\r\n if (!southCap) {\r\n // if southCap is true, we dont need to add any more points because the south pole point was added by the iteration above\r\n for (col = width - 2; col >= 0; col--) {\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n row,\r\n col,\r\n position\r\n );\r\n positions[posIndex++] = position.x;\r\n positions[posIndex++] = position.y;\r\n positions[posIndex++] = position.z;\r\n }\r\n }\r\n\r\n col = 0;\r\n for (row = height - 2; row > 0; row--) {\r\n RectangleGeometryLibrary.computePosition(\r\n computedOptions,\r\n ellipsoid,\r\n false,\r\n row,\r\n col,\r\n position\r\n );\r\n positions[posIndex++] = position.x;\r\n positions[posIndex++] = position.y;\r\n positions[posIndex++] = position.z;\r\n }\r\n\r\n var indicesSize = (positions.length / 3) * 2;\r\n var indices = IndexDatatype.createTypedArray(\r\n positions.length / 3,\r\n indicesSize\r\n );\r\n\r\n var index = 0;\r\n for (var i = 0; i < positions.length / 3 - 1; i++) {\r\n indices[index++] = i;\r\n indices[index++] = i + 1;\r\n }\r\n indices[index++] = positions.length / 3 - 1;\r\n indices[index++] = 0;\r\n\r\n var geo = new Geometry({\r\n attributes: new GeometryAttributes(),\r\n primitiveType: PrimitiveType.LINES,\r\n });\r\n\r\n geo.attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n geo.indices = indices;\r\n\r\n return geo;\r\n}\r\n\r\nfunction constructExtrudedRectangle(rectangleGeometry, computedOptions) {\r\n var surfaceHeight = rectangleGeometry._surfaceHeight;\r\n var extrudedHeight = rectangleGeometry._extrudedHeight;\r\n var ellipsoid = rectangleGeometry._ellipsoid;\r\n var minHeight = extrudedHeight;\r\n var maxHeight = surfaceHeight;\r\n var geo = constructRectangle(rectangleGeometry, computedOptions);\r\n\r\n var height = computedOptions.height;\r\n var width = computedOptions.width;\r\n\r\n var topPositions = PolygonPipeline.scaleToGeodeticHeight(\r\n geo.attributes.position.values,\r\n maxHeight,\r\n ellipsoid,\r\n false\r\n );\r\n var length = topPositions.length;\r\n var positions = new Float64Array(length * 2);\r\n positions.set(topPositions);\r\n var bottomPositions = PolygonPipeline.scaleToGeodeticHeight(\r\n geo.attributes.position.values,\r\n minHeight,\r\n ellipsoid\r\n );\r\n positions.set(bottomPositions, length);\r\n geo.attributes.position.values = positions;\r\n\r\n var northCap = computedOptions.northCap;\r\n var southCap = computedOptions.southCap;\r\n var corners = 4;\r\n if (northCap) {\r\n corners -= 1;\r\n }\r\n if (southCap) {\r\n corners -= 1;\r\n }\r\n\r\n var indicesSize = (positions.length / 3 + corners) * 2;\r\n var indices = IndexDatatype.createTypedArray(\r\n positions.length / 3,\r\n indicesSize\r\n );\r\n length = positions.length / 6;\r\n var index = 0;\r\n for (var i = 0; i < length - 1; i++) {\r\n indices[index++] = i;\r\n indices[index++] = i + 1;\r\n indices[index++] = i + length;\r\n indices[index++] = i + length + 1;\r\n }\r\n indices[index++] = length - 1;\r\n indices[index++] = 0;\r\n indices[index++] = length + length - 1;\r\n indices[index++] = length;\r\n\r\n indices[index++] = 0;\r\n indices[index++] = length;\r\n\r\n var bottomCorner;\r\n if (northCap) {\r\n bottomCorner = height - 1;\r\n } else {\r\n var topRightCorner = width - 1;\r\n indices[index++] = topRightCorner;\r\n indices[index++] = topRightCorner + length;\r\n bottomCorner = width + height - 2;\r\n }\r\n\r\n indices[index++] = bottomCorner;\r\n indices[index++] = bottomCorner + length;\r\n\r\n if (!southCap) {\r\n var bottomLeftCorner = width + bottomCorner - 1;\r\n indices[index++] = bottomLeftCorner;\r\n indices[index] = bottomLeftCorner + length;\r\n }\r\n\r\n geo.indices = indices;\r\n\r\n return geo;\r\n}\r\n\r\n/**\r\n * A description of the outline of a a cartographic rectangle on an ellipsoid centered at the origin.\r\n *\r\n * @alias RectangleOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Rectangle} options.rectangle A cartographic rectangle with north, south, east and west properties in radians.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid on which the rectangle lies.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Number} [options.height=0.0] The distance in meters between the rectangle and the ellipsoid surface.\r\n * @param {Number} [options.rotation=0.0] The rotation of the rectangle, in radians. A positive rotation is counter-clockwise.\r\n * @param {Number} [options.extrudedHeight] The distance in meters between the rectangle's extruded face and the ellipsoid surface.\r\n *\r\n * @exception {DeveloperError} options.rectangle.north must be in the interval [-Pi/2, Pi/2].\r\n * @exception {DeveloperError} options.rectangle.south must be in the interval [-Pi/2, Pi/2].\r\n * @exception {DeveloperError} options.rectangle.east must be in the interval [-Pi, Pi].\r\n * @exception {DeveloperError} options.rectangle.west must be in the interval [-Pi, Pi].\r\n * @exception {DeveloperError} options.rectangle.north must be greater than rectangle.south.\r\n *\r\n * @see RectangleOutlineGeometry#createGeometry\r\n *\r\n * @example\r\n * var rectangle = new Cesium.RectangleOutlineGeometry({\r\n * ellipsoid : Cesium.Ellipsoid.WGS84,\r\n * rectangle : Cesium.Rectangle.fromDegrees(-80.0, 39.0, -74.0, 42.0),\r\n * height : 10000.0\r\n * });\r\n * var geometry = Cesium.RectangleOutlineGeometry.createGeometry(rectangle);\r\n */\r\nfunction RectangleOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var rectangle = options.rectangle;\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n var rotation = defaultValue(options.rotation, 0.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(rectangle)) {\r\n throw new DeveloperError(\"rectangle is required.\");\r\n }\r\n Rectangle.validate(rectangle);\r\n if (rectangle.north < rectangle.south) {\r\n throw new DeveloperError(\r\n \"options.rectangle.north must be greater than options.rectangle.south\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var height = defaultValue(options.height, 0.0);\r\n var extrudedHeight = defaultValue(options.extrudedHeight, height);\r\n\r\n this._rectangle = Rectangle.clone(rectangle);\r\n this._granularity = granularity;\r\n this._ellipsoid = ellipsoid;\r\n this._surfaceHeight = Math.max(height, extrudedHeight);\r\n this._rotation = rotation;\r\n this._extrudedHeight = Math.min(height, extrudedHeight);\r\n this._offsetAttribute = options.offsetAttribute;\r\n this._workerName = \"createRectangleOutlineGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nRectangleOutlineGeometry.packedLength =\r\n Rectangle.packedLength + Ellipsoid.packedLength + 5;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {RectangleOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nRectangleOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n Rectangle.pack(value._rectangle, array, startingIndex);\r\n startingIndex += Rectangle.packedLength;\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n array[startingIndex++] = value._granularity;\r\n array[startingIndex++] = value._surfaceHeight;\r\n array[startingIndex++] = value._rotation;\r\n array[startingIndex++] = value._extrudedHeight;\r\n array[startingIndex] = defaultValue(value._offsetAttribute, -1);\r\n\r\n return array;\r\n};\r\n\r\nvar scratchRectangle = new Rectangle();\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchOptions = {\r\n rectangle: scratchRectangle,\r\n ellipsoid: scratchEllipsoid,\r\n granularity: undefined,\r\n height: undefined,\r\n rotation: undefined,\r\n extrudedHeight: undefined,\r\n offsetAttribute: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {RectangleOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {RectangleOutlineGeometry} The modified result parameter or a new Quaternion instance if one was not provided.\r\n */\r\nRectangleOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var rectangle = Rectangle.unpack(array, startingIndex, scratchRectangle);\r\n startingIndex += Rectangle.packedLength;\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var granularity = array[startingIndex++];\r\n var height = array[startingIndex++];\r\n var rotation = array[startingIndex++];\r\n var extrudedHeight = array[startingIndex++];\r\n var offsetAttribute = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.granularity = granularity;\r\n scratchOptions.height = height;\r\n scratchOptions.rotation = rotation;\r\n scratchOptions.extrudedHeight = extrudedHeight;\r\n scratchOptions.offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return new RectangleOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._rectangle = Rectangle.clone(rectangle, result._rectangle);\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._surfaceHeight = height;\r\n result._rotation = rotation;\r\n result._extrudedHeight = extrudedHeight;\r\n result._offsetAttribute =\r\n offsetAttribute === -1 ? undefined : offsetAttribute;\r\n\r\n return result;\r\n};\r\n\r\nvar nwScratch = new Cartographic();\r\n/**\r\n * Computes the geometric representation of an outline of a rectangle, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {RectangleOutlineGeometry} rectangleGeometry A description of the rectangle outline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n *\r\n * @exception {DeveloperError} Rotated rectangle is invalid.\r\n */\r\nRectangleOutlineGeometry.createGeometry = function (rectangleGeometry) {\r\n var rectangle = rectangleGeometry._rectangle;\r\n var ellipsoid = rectangleGeometry._ellipsoid;\r\n var computedOptions = RectangleGeometryLibrary.computeOptions(\r\n rectangle,\r\n rectangleGeometry._granularity,\r\n rectangleGeometry._rotation,\r\n 0,\r\n rectangleScratch,\r\n nwScratch\r\n );\r\n\r\n var geometry;\r\n var boundingSphere;\r\n\r\n if (\r\n CesiumMath.equalsEpsilon(\r\n rectangle.north,\r\n rectangle.south,\r\n CesiumMath.EPSILON10\r\n ) ||\r\n CesiumMath.equalsEpsilon(\r\n rectangle.east,\r\n rectangle.west,\r\n CesiumMath.EPSILON10\r\n )\r\n ) {\r\n return undefined;\r\n }\r\n\r\n var surfaceHeight = rectangleGeometry._surfaceHeight;\r\n var extrudedHeight = rectangleGeometry._extrudedHeight;\r\n var extrude = !CesiumMath.equalsEpsilon(\r\n surfaceHeight,\r\n extrudedHeight,\r\n 0,\r\n CesiumMath.EPSILON2\r\n );\r\n var offsetValue;\r\n if (extrude) {\r\n geometry = constructExtrudedRectangle(rectangleGeometry, computedOptions);\r\n if (defined(rectangleGeometry._offsetAttribute)) {\r\n var size = geometry.attributes.position.values.length / 3;\r\n var offsetAttribute = new Uint8Array(size);\r\n if (rectangleGeometry._offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n offsetAttribute = arrayFill(offsetAttribute, 1, 0, size / 2);\r\n } else {\r\n offsetValue =\r\n rectangleGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n offsetAttribute = arrayFill(offsetAttribute, offsetValue);\r\n }\r\n\r\n geometry.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: offsetAttribute,\r\n });\r\n }\r\n var topBS = BoundingSphere.fromRectangle3D(\r\n rectangle,\r\n ellipsoid,\r\n surfaceHeight,\r\n topBoundingSphere\r\n );\r\n var bottomBS = BoundingSphere.fromRectangle3D(\r\n rectangle,\r\n ellipsoid,\r\n extrudedHeight,\r\n bottomBoundingSphere\r\n );\r\n boundingSphere = BoundingSphere.union(topBS, bottomBS);\r\n } else {\r\n geometry = constructRectangle(rectangleGeometry, computedOptions);\r\n geometry.attributes.position.values = PolygonPipeline.scaleToGeodeticHeight(\r\n geometry.attributes.position.values,\r\n surfaceHeight,\r\n ellipsoid,\r\n false\r\n );\r\n\r\n if (defined(rectangleGeometry._offsetAttribute)) {\r\n var length = geometry.attributes.position.values.length;\r\n var applyOffset = new Uint8Array(length / 3);\r\n offsetValue =\r\n rectangleGeometry._offsetAttribute === GeometryOffsetAttribute.NONE\r\n ? 0\r\n : 1;\r\n arrayFill(applyOffset, offsetValue);\r\n geometry.attributes.applyOffset = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1,\r\n values: applyOffset,\r\n });\r\n }\r\n\r\n boundingSphere = BoundingSphere.fromRectangle3D(\r\n rectangle,\r\n ellipsoid,\r\n surfaceHeight\r\n );\r\n }\r\n\r\n return new Geometry({\r\n attributes: geometry.attributes,\r\n indices: geometry.indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: boundingSphere,\r\n offsetAttribute: rectangleGeometry._offsetAttribute,\r\n });\r\n};\r\nexport default RectangleOutlineGeometry;\r\n","/**\r\n * Constants for identifying well-known reference frames.\r\n *\r\n * @enum {Number}\r\n */\r\nvar ReferenceFrame = {\r\n /**\r\n * The fixed frame.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n FIXED: 0,\r\n\r\n /**\r\n * The inertial frame.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n INERTIAL: 1,\r\n};\r\nexport default Object.freeze(ReferenceFrame);\r\n","import defined from \"./defined.js\";\r\nimport getTimestamp from \"./getTimestamp.js\";\r\n\r\nvar implementation;\r\nif (typeof requestAnimationFrame !== \"undefined\") {\r\n implementation = requestAnimationFrame;\r\n}\r\n\r\n(function () {\r\n // look for vendor prefixed function\r\n if (!defined(implementation) && typeof window !== \"undefined\") {\r\n var vendors = [\"webkit\", \"moz\", \"ms\", \"o\"];\r\n var i = 0;\r\n var len = vendors.length;\r\n while (i < len && !defined(implementation)) {\r\n implementation = window[vendors[i] + \"RequestAnimationFrame\"];\r\n ++i;\r\n }\r\n }\r\n\r\n // build an implementation based on setTimeout\r\n if (!defined(implementation)) {\r\n var msPerFrame = 1000.0 / 60.0;\r\n var lastFrameTime = 0;\r\n implementation = function (callback) {\r\n var currentTime = getTimestamp();\r\n\r\n // schedule the callback to target 60fps, 16.7ms per frame,\r\n // accounting for the time taken by the callback\r\n var delay = Math.max(msPerFrame - (currentTime - lastFrameTime), 0);\r\n lastFrameTime = currentTime + delay;\r\n\r\n return setTimeout(function () {\r\n callback(lastFrameTime);\r\n }, delay);\r\n };\r\n }\r\n})();\r\n\r\n/**\r\n * A browser-independent function to request a new animation frame. This is used to create\r\n * an application's draw loop as shown in the example below.\r\n *\r\n * @function requestAnimationFrame\r\n *\r\n * @param {requestAnimationFrameCallback} callback The function to call when the next frame should be drawn.\r\n * @returns {Number} An ID that can be passed to {@link cancelAnimationFrame} to cancel the request.\r\n *\r\n *\r\n * @example\r\n * // Create a draw loop using requestAnimationFrame. The\r\n * // tick callback function is called for every animation frame.\r\n * function tick() {\r\n * scene.render();\r\n * Cesium.requestAnimationFrame(tick);\r\n * }\r\n * tick();\r\n *\r\n * @see {@link https://www.w3.org/TR/html51/webappapis.html#animation-frames|The Web API Animation Frames interface}\r\n */\r\nfunction requestAnimationFramePolyFill(callback) {\r\n // we need this extra wrapper function because the native requestAnimationFrame\r\n // functions must be invoked on the global scope (window), which is not the case\r\n // if invoked as Cesium.requestAnimationFrame(callback)\r\n return implementation(callback);\r\n}\r\n\r\n/**\r\n * A function that will be called when the next frame should be drawn.\r\n * @callback requestAnimationFrameCallback\r\n *\r\n * @param {Number} timestamp A timestamp for the frame, in milliseconds.\r\n */\r\nexport default requestAnimationFramePolyFill;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Check from \"./Check.js\";\r\n\r\n/**\r\n * Initiates a terrain height query for an array of {@link Cartographic} positions by\r\n * requesting tiles from a terrain provider, sampling, and interpolating. The interpolation\r\n * matches the triangles used to render the terrain at the specified level. The query\r\n * happens asynchronously, so this function returns a promise that is resolved when\r\n * the query completes. Each point height is modified in place. If a height can not be\r\n * determined because no terrain data is available for the specified level at that location,\r\n * or another error occurs, the height is set to undefined. As is typical of the\r\n * {@link Cartographic} type, the supplied height is a height above the reference ellipsoid\r\n * (such as {@link Ellipsoid.WGS84}) rather than an altitude above mean sea level. In other\r\n * words, it will not necessarily be 0.0 if sampled in the ocean. This function needs the\r\n * terrain level of detail as input, if you need to get the altitude of the terrain as precisely\r\n * as possible (i.e. with maximum level of detail) use {@link sampleTerrainMostDetailed}.\r\n *\r\n * @function sampleTerrain\r\n *\r\n * @param {TerrainProvider} terrainProvider The terrain provider from which to query heights.\r\n * @param {Number} level The terrain level-of-detail from which to query terrain heights.\r\n * @param {Cartographic[]} positions The positions to update with terrain heights.\r\n * @returns {Promise.} A promise that resolves to the provided list of positions when terrain the query has completed.\r\n *\r\n * @see sampleTerrainMostDetailed\r\n *\r\n * @example\r\n * // Query the terrain height of two Cartographic positions\r\n * var terrainProvider = Cesium.createWorldTerrain();\r\n * var positions = [\r\n * Cesium.Cartographic.fromDegrees(86.925145, 27.988257),\r\n * Cesium.Cartographic.fromDegrees(87.0, 28.0)\r\n * ];\r\n * var promise = Cesium.sampleTerrain(terrainProvider, 11, positions);\r\n * Cesium.when(promise, function(updatedPositions) {\r\n * // positions[0].height and positions[1].height have been updated.\r\n * // updatedPositions is just a reference to positions.\r\n * });\r\n */\r\nfunction sampleTerrain(terrainProvider, level, positions) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"terrainProvider\", terrainProvider);\r\n Check.typeOf.number(\"level\", level);\r\n Check.defined(\"positions\", positions);\r\n //>>includeEnd('debug');\r\n\r\n return terrainProvider.readyPromise.then(function () {\r\n return doSampling(terrainProvider, level, positions);\r\n });\r\n}\r\n\r\nfunction doSampling(terrainProvider, level, positions) {\r\n var tilingScheme = terrainProvider.tilingScheme;\r\n\r\n var i;\r\n\r\n // Sort points into a set of tiles\r\n var tileRequests = []; // Result will be an Array as it's easier to work with\r\n var tileRequestSet = {}; // A unique set\r\n for (i = 0; i < positions.length; ++i) {\r\n var xy = tilingScheme.positionToTileXY(positions[i], level);\r\n var key = xy.toString();\r\n\r\n if (!tileRequestSet.hasOwnProperty(key)) {\r\n // When tile is requested for the first time\r\n var value = {\r\n x: xy.x,\r\n y: xy.y,\r\n level: level,\r\n tilingScheme: tilingScheme,\r\n terrainProvider: terrainProvider,\r\n positions: [],\r\n };\r\n tileRequestSet[key] = value;\r\n tileRequests.push(value);\r\n }\r\n\r\n // Now append to array of points for the tile\r\n tileRequestSet[key].positions.push(positions[i]);\r\n }\r\n\r\n // Send request for each required tile\r\n var tilePromises = [];\r\n for (i = 0; i < tileRequests.length; ++i) {\r\n var tileRequest = tileRequests[i];\r\n var requestPromise = tileRequest.terrainProvider.requestTileGeometry(\r\n tileRequest.x,\r\n tileRequest.y,\r\n tileRequest.level\r\n );\r\n var tilePromise = requestPromise\r\n .then(createInterpolateFunction(tileRequest))\r\n .otherwise(createMarkFailedFunction(tileRequest));\r\n tilePromises.push(tilePromise);\r\n }\r\n\r\n return when.all(tilePromises, function () {\r\n return positions;\r\n });\r\n}\r\n\r\n/**\r\n * Calls {@link TerrainData#interpolateHeight} on a given {@link TerrainData} for a given {@link Cartographic} and\r\n * will assign the height property if the return value is not undefined.\r\n *\r\n * If the return value is false; it's suggesting that you should call {@link TerrainData#createMesh} first.\r\n * @param {Cartographic} position The position to interpolate for and assign the height value to\r\n * @param {TerrainData} terrainData\r\n * @param {Rectangle} rectangle\r\n * @returns {Boolean} If the height was actually interpolated and assigned\r\n * @private\r\n */\r\nfunction interpolateAndAssignHeight(position, terrainData, rectangle) {\r\n var height = terrainData.interpolateHeight(\r\n rectangle,\r\n position.longitude,\r\n position.latitude\r\n );\r\n if (height === undefined) {\r\n // if height comes back as undefined, it may implicitly mean the terrain data\r\n // requires us to call TerrainData.createMesh() first (ArcGIS requires this in particular)\r\n // so we'll return false and do that next!\r\n return false;\r\n }\r\n position.height = height;\r\n return true;\r\n}\r\n\r\nfunction createInterpolateFunction(tileRequest) {\r\n var tilePositions = tileRequest.positions;\r\n var rectangle = tileRequest.tilingScheme.tileXYToRectangle(\r\n tileRequest.x,\r\n tileRequest.y,\r\n tileRequest.level\r\n );\r\n return function (terrainData) {\r\n var isMeshRequired = false;\r\n for (var i = 0; i < tilePositions.length; ++i) {\r\n var position = tilePositions[i];\r\n var isHeightAssigned = interpolateAndAssignHeight(\r\n position,\r\n terrainData,\r\n rectangle\r\n );\r\n // we've found a position which returned undefined - hinting to us\r\n // that we probably need to create a mesh for this terrain data.\r\n // so break out of this loop and create the mesh - then we'll interpolate all the heights again\r\n if (!isHeightAssigned) {\r\n isMeshRequired = true;\r\n break;\r\n }\r\n }\r\n\r\n if (!isMeshRequired) {\r\n // all position heights were interpolated - we don't need the mesh\r\n return when.resolve();\r\n }\r\n\r\n // create the mesh - and interpolate all the positions again\r\n return terrainData\r\n .createMesh({\r\n tilingScheme: tileRequest.tilingScheme,\r\n x: tileRequest.x,\r\n y: tileRequest.y,\r\n level: tileRequest.level,\r\n // interpolateHeight will divide away the exaggeration - so passing in 1 is fine; it doesn't really matter\r\n exaggeration: 1,\r\n // don't throttle this mesh creation because we've asked to sample these points;\r\n // so sample them! We don't care how many tiles that is!\r\n throttle: false,\r\n })\r\n .then(function () {\r\n // mesh has been created - so go through every position (maybe again)\r\n // and re-interpolate the heights - presumably using the mesh this time\r\n for (var i = 0; i < tilePositions.length; ++i) {\r\n var position = tilePositions[i];\r\n // if it doesn't work this time - that's fine, we tried.\r\n interpolateAndAssignHeight(position, terrainData, rectangle);\r\n }\r\n });\r\n };\r\n}\r\n\r\nfunction createMarkFailedFunction(tileRequest) {\r\n var tilePositions = tileRequest.positions;\r\n return function () {\r\n for (var i = 0; i < tilePositions.length; ++i) {\r\n var position = tilePositions[i];\r\n position.height = undefined;\r\n }\r\n };\r\n}\r\nexport default sampleTerrain;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport sampleTerrain from \"./sampleTerrain.js\";\r\n\r\nvar scratchCartesian2 = new Cartesian2();\r\n\r\n/**\r\n * Initiates a sampleTerrain() request at the maximum available tile level for a terrain dataset.\r\n *\r\n * @function sampleTerrainMostDetailed\r\n *\r\n * @param {TerrainProvider} terrainProvider The terrain provider from which to query heights.\r\n * @param {Cartographic[]} positions The positions to update with terrain heights.\r\n * @returns {Promise.} A promise that resolves to the provided list of positions when terrain the query has completed. This\r\n * promise will reject if the terrain provider's `availability` property is undefined.\r\n *\r\n * @example\r\n * // Query the terrain height of two Cartographic positions\r\n * var terrainProvider = Cesium.createWorldTerrain();\r\n * var positions = [\r\n * Cesium.Cartographic.fromDegrees(86.925145, 27.988257),\r\n * Cesium.Cartographic.fromDegrees(87.0, 28.0)\r\n * ];\r\n * var promise = Cesium.sampleTerrainMostDetailed(terrainProvider, positions);\r\n * Cesium.when(promise, function(updatedPositions) {\r\n * // positions[0].height and positions[1].height have been updated.\r\n * // updatedPositions is just a reference to positions.\r\n * });\r\n */\r\nfunction sampleTerrainMostDetailed(terrainProvider, positions) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(terrainProvider)) {\r\n throw new DeveloperError(\"terrainProvider is required.\");\r\n }\r\n if (!defined(positions)) {\r\n throw new DeveloperError(\"positions is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return terrainProvider.readyPromise.then(function () {\r\n var byLevel = [];\r\n var maxLevels = [];\r\n\r\n var availability = terrainProvider.availability;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(availability)) {\r\n throw new DeveloperError(\r\n \"sampleTerrainMostDetailed requires a terrain provider that has tile availability.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var promises = [];\r\n for (var i = 0; i < positions.length; ++i) {\r\n var position = positions[i];\r\n var maxLevel = availability.computeMaximumLevelAtPosition(position);\r\n maxLevels[i] = maxLevel;\r\n if (maxLevel === 0) {\r\n // This is a special case where we have a parent terrain and we are requesting\r\n // heights from an area that isn't covered by the top level terrain at all.\r\n // This will essentially trigger the loading of the parent terrains root tile\r\n terrainProvider.tilingScheme.positionToTileXY(\r\n position,\r\n 1,\r\n scratchCartesian2\r\n );\r\n var promise = terrainProvider.loadTileDataAvailability(\r\n scratchCartesian2.x,\r\n scratchCartesian2.y,\r\n 1\r\n );\r\n if (defined(promise)) {\r\n promises.push(promise);\r\n }\r\n }\r\n\r\n var atLevel = byLevel[maxLevel];\r\n if (!defined(atLevel)) {\r\n byLevel[maxLevel] = atLevel = [];\r\n }\r\n atLevel.push(position);\r\n }\r\n\r\n return when\r\n .all(promises)\r\n .then(function () {\r\n return when.all(\r\n byLevel.map(function (positionsAtLevel, index) {\r\n if (defined(positionsAtLevel)) {\r\n return sampleTerrain(terrainProvider, index, positionsAtLevel);\r\n }\r\n })\r\n );\r\n })\r\n .then(function () {\r\n var changedPositions = [];\r\n for (var i = 0; i < positions.length; ++i) {\r\n var position = positions[i];\r\n var maxLevel = availability.computeMaximumLevelAtPosition(position);\r\n\r\n if (maxLevel !== maxLevels[i]) {\r\n // Now that we loaded the max availability, a higher level has become available\r\n changedPositions.push(position);\r\n }\r\n }\r\n\r\n if (changedPositions.length > 0) {\r\n return sampleTerrainMostDetailed(terrainProvider, changedPositions);\r\n }\r\n })\r\n .then(function () {\r\n return positions;\r\n });\r\n });\r\n}\r\nexport default sampleTerrainMostDetailed;\r\n","/**\r\n * This enumerated type is for classifying mouse events: down, up, click, double click, move and move while a button is held down.\r\n *\r\n * @enum {Number}\r\n */\r\nvar ScreenSpaceEventType = {\r\n /**\r\n * Represents a mouse left button down event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LEFT_DOWN: 0,\r\n\r\n /**\r\n * Represents a mouse left button up event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LEFT_UP: 1,\r\n\r\n /**\r\n * Represents a mouse left click event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LEFT_CLICK: 2,\r\n\r\n /**\r\n * Represents a mouse left double click event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LEFT_DOUBLE_CLICK: 3,\r\n\r\n /**\r\n * Represents a mouse left button down event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RIGHT_DOWN: 5,\r\n\r\n /**\r\n * Represents a mouse right button up event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RIGHT_UP: 6,\r\n\r\n /**\r\n * Represents a mouse right click event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RIGHT_CLICK: 7,\r\n\r\n /**\r\n * Represents a mouse middle button down event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MIDDLE_DOWN: 10,\r\n\r\n /**\r\n * Represents a mouse middle button up event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MIDDLE_UP: 11,\r\n\r\n /**\r\n * Represents a mouse middle click event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MIDDLE_CLICK: 12,\r\n\r\n /**\r\n * Represents a mouse move event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MOUSE_MOVE: 15,\r\n\r\n /**\r\n * Represents a mouse wheel event.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n WHEEL: 16,\r\n\r\n /**\r\n * Represents the start of a two-finger event on a touch surface.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n PINCH_START: 17,\r\n\r\n /**\r\n * Represents the end of a two-finger event on a touch surface.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n PINCH_END: 18,\r\n\r\n /**\r\n * Represents a change of a two-finger event on a touch surface.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n PINCH_MOVE: 19,\r\n};\r\nexport default Object.freeze(ScreenSpaceEventType);\r\n","import AssociativeArray from \"./AssociativeArray.js\";\r\nimport Cartesian2 from \"./Cartesian2.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport destroyObject from \"./destroyObject.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport FeatureDetection from \"./FeatureDetection.js\";\r\nimport getTimestamp from \"./getTimestamp.js\";\r\nimport KeyboardEventModifier from \"./KeyboardEventModifier.js\";\r\nimport ScreenSpaceEventType from \"./ScreenSpaceEventType.js\";\r\n\r\nfunction getPosition(screenSpaceEventHandler, event, result) {\r\n var element = screenSpaceEventHandler._element;\r\n if (element === document) {\r\n result.x = event.clientX;\r\n result.y = event.clientY;\r\n return result;\r\n }\r\n\r\n var rect = element.getBoundingClientRect();\r\n result.x = event.clientX - rect.left;\r\n result.y = event.clientY - rect.top;\r\n return result;\r\n}\r\n\r\nfunction getInputEventKey(type, modifier) {\r\n var key = type;\r\n if (defined(modifier)) {\r\n key += \"+\" + modifier;\r\n }\r\n return key;\r\n}\r\n\r\nfunction getModifier(event) {\r\n if (event.shiftKey) {\r\n return KeyboardEventModifier.SHIFT;\r\n } else if (event.ctrlKey) {\r\n return KeyboardEventModifier.CTRL;\r\n } else if (event.altKey) {\r\n return KeyboardEventModifier.ALT;\r\n }\r\n\r\n return undefined;\r\n}\r\n\r\nvar MouseButton = {\r\n LEFT: 0,\r\n MIDDLE: 1,\r\n RIGHT: 2,\r\n};\r\n\r\nfunction registerListener(screenSpaceEventHandler, domType, element, callback) {\r\n function listener(e) {\r\n callback(screenSpaceEventHandler, e);\r\n }\r\n\r\n if (FeatureDetection.isInternetExplorer()) {\r\n element.addEventListener(domType, listener, false);\r\n } else {\r\n element.addEventListener(domType, listener, {\r\n capture: false,\r\n passive: false,\r\n });\r\n }\r\n\r\n screenSpaceEventHandler._removalFunctions.push(function () {\r\n element.removeEventListener(domType, listener, false);\r\n });\r\n}\r\n\r\nfunction registerListeners(screenSpaceEventHandler) {\r\n var element = screenSpaceEventHandler._element;\r\n\r\n // some listeners may be registered on the document, so we still get events even after\r\n // leaving the bounds of element.\r\n // this is affected by the existence of an undocumented disableRootEvents property on element.\r\n var alternateElement = !defined(element.disableRootEvents)\r\n ? document\r\n : element;\r\n\r\n if (FeatureDetection.supportsPointerEvents()) {\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"pointerdown\",\r\n element,\r\n handlePointerDown\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"pointerup\",\r\n element,\r\n handlePointerUp\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"pointermove\",\r\n element,\r\n handlePointerMove\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"pointercancel\",\r\n element,\r\n handlePointerUp\r\n );\r\n } else {\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"mousedown\",\r\n element,\r\n handleMouseDown\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"mouseup\",\r\n alternateElement,\r\n handleMouseUp\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"mousemove\",\r\n alternateElement,\r\n handleMouseMove\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"touchstart\",\r\n element,\r\n handleTouchStart\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"touchend\",\r\n alternateElement,\r\n handleTouchEnd\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"touchmove\",\r\n alternateElement,\r\n handleTouchMove\r\n );\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"touchcancel\",\r\n alternateElement,\r\n handleTouchEnd\r\n );\r\n }\r\n\r\n registerListener(\r\n screenSpaceEventHandler,\r\n \"dblclick\",\r\n element,\r\n handleDblClick\r\n );\r\n\r\n // detect available wheel event\r\n var wheelEvent;\r\n if (\"onwheel\" in element) {\r\n // spec event type\r\n wheelEvent = \"wheel\";\r\n } else if (document.onmousewheel !== undefined) {\r\n // legacy event type\r\n wheelEvent = \"mousewheel\";\r\n } else {\r\n // older Firefox\r\n wheelEvent = \"DOMMouseScroll\";\r\n }\r\n\r\n registerListener(screenSpaceEventHandler, wheelEvent, element, handleWheel);\r\n}\r\n\r\nfunction unregisterListeners(screenSpaceEventHandler) {\r\n var removalFunctions = screenSpaceEventHandler._removalFunctions;\r\n for (var i = 0; i < removalFunctions.length; ++i) {\r\n removalFunctions[i]();\r\n }\r\n}\r\n\r\nvar mouseDownEvent = {\r\n position: new Cartesian2(),\r\n};\r\n\r\nfunction gotTouchEvent(screenSpaceEventHandler) {\r\n screenSpaceEventHandler._lastSeenTouchEvent = getTimestamp();\r\n}\r\n\r\nfunction canProcessMouseEvent(screenSpaceEventHandler) {\r\n return (\r\n getTimestamp() - screenSpaceEventHandler._lastSeenTouchEvent >\r\n ScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds\r\n );\r\n}\r\n\r\nfunction checkPixelTolerance(startPosition, endPosition, pixelTolerance) {\r\n var xDiff = startPosition.x - endPosition.x;\r\n var yDiff = startPosition.y - endPosition.y;\r\n var totalPixels = Math.sqrt(xDiff * xDiff + yDiff * yDiff);\r\n\r\n return totalPixels < pixelTolerance;\r\n}\r\n\r\nfunction handleMouseDown(screenSpaceEventHandler, event) {\r\n if (!canProcessMouseEvent(screenSpaceEventHandler)) {\r\n return;\r\n }\r\n\r\n var button = event.button;\r\n screenSpaceEventHandler._buttonDown[button] = true;\r\n\r\n var screenSpaceEventType;\r\n if (button === MouseButton.LEFT) {\r\n screenSpaceEventType = ScreenSpaceEventType.LEFT_DOWN;\r\n } else if (button === MouseButton.MIDDLE) {\r\n screenSpaceEventType = ScreenSpaceEventType.MIDDLE_DOWN;\r\n } else if (button === MouseButton.RIGHT) {\r\n screenSpaceEventType = ScreenSpaceEventType.RIGHT_DOWN;\r\n } else {\r\n return;\r\n }\r\n\r\n var position = getPosition(\r\n screenSpaceEventHandler,\r\n event,\r\n screenSpaceEventHandler._primaryPosition\r\n );\r\n Cartesian2.clone(position, screenSpaceEventHandler._primaryStartPosition);\r\n Cartesian2.clone(position, screenSpaceEventHandler._primaryPreviousPosition);\r\n\r\n var modifier = getModifier(event);\r\n\r\n var action = screenSpaceEventHandler.getInputAction(\r\n screenSpaceEventType,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n Cartesian2.clone(position, mouseDownEvent.position);\r\n\r\n action(mouseDownEvent);\r\n\r\n event.preventDefault();\r\n }\r\n}\r\n\r\nvar mouseUpEvent = {\r\n position: new Cartesian2(),\r\n};\r\nvar mouseClickEvent = {\r\n position: new Cartesian2(),\r\n};\r\n\r\nfunction cancelMouseEvent(\r\n screenSpaceEventHandler,\r\n screenSpaceEventType,\r\n clickScreenSpaceEventType,\r\n event\r\n) {\r\n var modifier = getModifier(event);\r\n\r\n var action = screenSpaceEventHandler.getInputAction(\r\n screenSpaceEventType,\r\n modifier\r\n );\r\n var clickAction = screenSpaceEventHandler.getInputAction(\r\n clickScreenSpaceEventType,\r\n modifier\r\n );\r\n\r\n if (defined(action) || defined(clickAction)) {\r\n var position = getPosition(\r\n screenSpaceEventHandler,\r\n event,\r\n screenSpaceEventHandler._primaryPosition\r\n );\r\n\r\n if (defined(action)) {\r\n Cartesian2.clone(position, mouseUpEvent.position);\r\n\r\n action(mouseUpEvent);\r\n }\r\n\r\n if (defined(clickAction)) {\r\n var startPosition = screenSpaceEventHandler._primaryStartPosition;\r\n if (\r\n checkPixelTolerance(\r\n startPosition,\r\n position,\r\n screenSpaceEventHandler._clickPixelTolerance\r\n )\r\n ) {\r\n Cartesian2.clone(position, mouseClickEvent.position);\r\n\r\n clickAction(mouseClickEvent);\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction handleMouseUp(screenSpaceEventHandler, event) {\r\n if (!canProcessMouseEvent(screenSpaceEventHandler)) {\r\n return;\r\n }\r\n\r\n var button = event.button;\r\n\r\n if (\r\n button !== MouseButton.LEFT &&\r\n button !== MouseButton.MIDDLE &&\r\n button !== MouseButton.RIGHT\r\n ) {\r\n return;\r\n }\r\n\r\n if (screenSpaceEventHandler._buttonDown[MouseButton.LEFT]) {\r\n cancelMouseEvent(\r\n screenSpaceEventHandler,\r\n ScreenSpaceEventType.LEFT_UP,\r\n ScreenSpaceEventType.LEFT_CLICK,\r\n event\r\n );\r\n screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = false;\r\n }\r\n if (screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE]) {\r\n cancelMouseEvent(\r\n screenSpaceEventHandler,\r\n ScreenSpaceEventType.MIDDLE_UP,\r\n ScreenSpaceEventType.MIDDLE_CLICK,\r\n event\r\n );\r\n screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE] = false;\r\n }\r\n if (screenSpaceEventHandler._buttonDown[MouseButton.RIGHT]) {\r\n cancelMouseEvent(\r\n screenSpaceEventHandler,\r\n ScreenSpaceEventType.RIGHT_UP,\r\n ScreenSpaceEventType.RIGHT_CLICK,\r\n event\r\n );\r\n screenSpaceEventHandler._buttonDown[MouseButton.RIGHT] = false;\r\n }\r\n}\r\n\r\nvar mouseMoveEvent = {\r\n startPosition: new Cartesian2(),\r\n endPosition: new Cartesian2(),\r\n};\r\n\r\nfunction handleMouseMove(screenSpaceEventHandler, event) {\r\n if (!canProcessMouseEvent(screenSpaceEventHandler)) {\r\n return;\r\n }\r\n\r\n var modifier = getModifier(event);\r\n\r\n var position = getPosition(\r\n screenSpaceEventHandler,\r\n event,\r\n screenSpaceEventHandler._primaryPosition\r\n );\r\n var previousPosition = screenSpaceEventHandler._primaryPreviousPosition;\r\n\r\n var action = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.MOUSE_MOVE,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n Cartesian2.clone(previousPosition, mouseMoveEvent.startPosition);\r\n Cartesian2.clone(position, mouseMoveEvent.endPosition);\r\n\r\n action(mouseMoveEvent);\r\n }\r\n\r\n Cartesian2.clone(position, previousPosition);\r\n\r\n if (\r\n screenSpaceEventHandler._buttonDown[MouseButton.LEFT] ||\r\n screenSpaceEventHandler._buttonDown[MouseButton.MIDDLE] ||\r\n screenSpaceEventHandler._buttonDown[MouseButton.RIGHT]\r\n ) {\r\n event.preventDefault();\r\n }\r\n}\r\n\r\nvar mouseDblClickEvent = {\r\n position: new Cartesian2(),\r\n};\r\n\r\nfunction handleDblClick(screenSpaceEventHandler, event) {\r\n var button = event.button;\r\n\r\n var screenSpaceEventType;\r\n if (button === MouseButton.LEFT) {\r\n screenSpaceEventType = ScreenSpaceEventType.LEFT_DOUBLE_CLICK;\r\n } else {\r\n return;\r\n }\r\n\r\n var modifier = getModifier(event);\r\n\r\n var action = screenSpaceEventHandler.getInputAction(\r\n screenSpaceEventType,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n getPosition(screenSpaceEventHandler, event, mouseDblClickEvent.position);\r\n\r\n action(mouseDblClickEvent);\r\n }\r\n}\r\n\r\nfunction handleWheel(screenSpaceEventHandler, event) {\r\n // currently this event exposes the delta value in terms of\r\n // the obsolete mousewheel event type. so, for now, we adapt the other\r\n // values to that scheme.\r\n var delta;\r\n\r\n // standard wheel event uses deltaY. sign is opposite wheelDelta.\r\n // deltaMode indicates what unit it is in.\r\n if (defined(event.deltaY)) {\r\n var deltaMode = event.deltaMode;\r\n if (deltaMode === event.DOM_DELTA_PIXEL) {\r\n delta = -event.deltaY;\r\n } else if (deltaMode === event.DOM_DELTA_LINE) {\r\n delta = -event.deltaY * 40;\r\n } else {\r\n // DOM_DELTA_PAGE\r\n delta = -event.deltaY * 120;\r\n }\r\n } else if (event.detail > 0) {\r\n // old Firefox versions use event.detail to count the number of clicks. The sign\r\n // of the integer is the direction the wheel is scrolled.\r\n delta = event.detail * -120;\r\n } else {\r\n delta = event.wheelDelta;\r\n }\r\n\r\n if (!defined(delta)) {\r\n return;\r\n }\r\n\r\n var modifier = getModifier(event);\r\n var action = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.WHEEL,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n action(delta);\r\n\r\n event.preventDefault();\r\n }\r\n}\r\n\r\nfunction handleTouchStart(screenSpaceEventHandler, event) {\r\n gotTouchEvent(screenSpaceEventHandler);\r\n\r\n var changedTouches = event.changedTouches;\r\n\r\n var i;\r\n var length = changedTouches.length;\r\n var touch;\r\n var identifier;\r\n var positions = screenSpaceEventHandler._positions;\r\n\r\n for (i = 0; i < length; ++i) {\r\n touch = changedTouches[i];\r\n identifier = touch.identifier;\r\n positions.set(\r\n identifier,\r\n getPosition(screenSpaceEventHandler, touch, new Cartesian2())\r\n );\r\n }\r\n\r\n fireTouchEvents(screenSpaceEventHandler, event);\r\n\r\n var previousPositions = screenSpaceEventHandler._previousPositions;\r\n\r\n for (i = 0; i < length; ++i) {\r\n touch = changedTouches[i];\r\n identifier = touch.identifier;\r\n previousPositions.set(\r\n identifier,\r\n Cartesian2.clone(positions.get(identifier))\r\n );\r\n }\r\n}\r\n\r\nfunction handleTouchEnd(screenSpaceEventHandler, event) {\r\n gotTouchEvent(screenSpaceEventHandler);\r\n\r\n var changedTouches = event.changedTouches;\r\n\r\n var i;\r\n var length = changedTouches.length;\r\n var touch;\r\n var identifier;\r\n var positions = screenSpaceEventHandler._positions;\r\n\r\n for (i = 0; i < length; ++i) {\r\n touch = changedTouches[i];\r\n identifier = touch.identifier;\r\n positions.remove(identifier);\r\n }\r\n\r\n fireTouchEvents(screenSpaceEventHandler, event);\r\n\r\n var previousPositions = screenSpaceEventHandler._previousPositions;\r\n\r\n for (i = 0; i < length; ++i) {\r\n touch = changedTouches[i];\r\n identifier = touch.identifier;\r\n previousPositions.remove(identifier);\r\n }\r\n}\r\n\r\nvar touchStartEvent = {\r\n position: new Cartesian2(),\r\n};\r\nvar touch2StartEvent = {\r\n position1: new Cartesian2(),\r\n position2: new Cartesian2(),\r\n};\r\nvar touchEndEvent = {\r\n position: new Cartesian2(),\r\n};\r\nvar touchClickEvent = {\r\n position: new Cartesian2(),\r\n};\r\nvar touchHoldEvent = {\r\n position: new Cartesian2(),\r\n};\r\n\r\nfunction fireTouchEvents(screenSpaceEventHandler, event) {\r\n var modifier = getModifier(event);\r\n var positions = screenSpaceEventHandler._positions;\r\n var numberOfTouches = positions.length;\r\n var action;\r\n var clickAction;\r\n var pinching = screenSpaceEventHandler._isPinching;\r\n\r\n if (\r\n numberOfTouches !== 1 &&\r\n screenSpaceEventHandler._buttonDown[MouseButton.LEFT]\r\n ) {\r\n // transitioning from single touch, trigger UP and might trigger CLICK\r\n screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = false;\r\n\r\n if (defined(screenSpaceEventHandler._touchHoldTimer)) {\r\n clearTimeout(screenSpaceEventHandler._touchHoldTimer);\r\n screenSpaceEventHandler._touchHoldTimer = undefined;\r\n }\r\n\r\n action = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.LEFT_UP,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n Cartesian2.clone(\r\n screenSpaceEventHandler._primaryPosition,\r\n touchEndEvent.position\r\n );\r\n\r\n action(touchEndEvent);\r\n }\r\n\r\n if (numberOfTouches === 0 && !screenSpaceEventHandler._isTouchHolding) {\r\n // releasing single touch, check for CLICK\r\n clickAction = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.LEFT_CLICK,\r\n modifier\r\n );\r\n\r\n if (defined(clickAction)) {\r\n var startPosition = screenSpaceEventHandler._primaryStartPosition;\r\n var endPosition = screenSpaceEventHandler._previousPositions.values[0];\r\n if (\r\n checkPixelTolerance(\r\n startPosition,\r\n endPosition,\r\n screenSpaceEventHandler._clickPixelTolerance\r\n )\r\n ) {\r\n Cartesian2.clone(\r\n screenSpaceEventHandler._primaryPosition,\r\n touchClickEvent.position\r\n );\r\n\r\n clickAction(touchClickEvent);\r\n }\r\n }\r\n }\r\n\r\n screenSpaceEventHandler._isTouchHolding = false;\r\n\r\n // Otherwise don't trigger CLICK, because we are adding more touches.\r\n }\r\n\r\n if (numberOfTouches === 0 && pinching) {\r\n // transitioning from pinch, trigger PINCH_END\r\n screenSpaceEventHandler._isPinching = false;\r\n\r\n action = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.PINCH_END,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n action();\r\n }\r\n }\r\n\r\n if (numberOfTouches === 1 && !pinching) {\r\n // transitioning to single touch, trigger DOWN\r\n var position = positions.values[0];\r\n Cartesian2.clone(position, screenSpaceEventHandler._primaryPosition);\r\n Cartesian2.clone(position, screenSpaceEventHandler._primaryStartPosition);\r\n Cartesian2.clone(\r\n position,\r\n screenSpaceEventHandler._primaryPreviousPosition\r\n );\r\n\r\n screenSpaceEventHandler._buttonDown[MouseButton.LEFT] = true;\r\n\r\n action = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.LEFT_DOWN,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n Cartesian2.clone(position, touchStartEvent.position);\r\n\r\n action(touchStartEvent);\r\n }\r\n\r\n screenSpaceEventHandler._touchHoldTimer = setTimeout(function () {\r\n if (!screenSpaceEventHandler.isDestroyed()) {\r\n screenSpaceEventHandler._touchHoldTimer = undefined;\r\n screenSpaceEventHandler._isTouchHolding = true;\r\n\r\n clickAction = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.RIGHT_CLICK,\r\n modifier\r\n );\r\n\r\n if (defined(clickAction)) {\r\n var startPosition = screenSpaceEventHandler._primaryStartPosition;\r\n var endPosition =\r\n screenSpaceEventHandler._previousPositions.values[0];\r\n if (\r\n checkPixelTolerance(\r\n startPosition,\r\n endPosition,\r\n screenSpaceEventHandler._holdPixelTolerance\r\n )\r\n ) {\r\n Cartesian2.clone(\r\n screenSpaceEventHandler._primaryPosition,\r\n touchHoldEvent.position\r\n );\r\n\r\n clickAction(touchHoldEvent);\r\n }\r\n }\r\n }\r\n }, ScreenSpaceEventHandler.touchHoldDelayMilliseconds);\r\n\r\n event.preventDefault();\r\n }\r\n\r\n if (numberOfTouches === 2 && !pinching) {\r\n // transitioning to pinch, trigger PINCH_START\r\n screenSpaceEventHandler._isPinching = true;\r\n\r\n action = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.PINCH_START,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n Cartesian2.clone(positions.values[0], touch2StartEvent.position1);\r\n Cartesian2.clone(positions.values[1], touch2StartEvent.position2);\r\n\r\n action(touch2StartEvent);\r\n\r\n // Touch-enabled devices, in particular iOS can have many default behaviours for\r\n // \"pinch\" events, which can still be executed unless we prevent them here.\r\n event.preventDefault();\r\n }\r\n }\r\n}\r\n\r\nfunction handleTouchMove(screenSpaceEventHandler, event) {\r\n gotTouchEvent(screenSpaceEventHandler);\r\n\r\n var changedTouches = event.changedTouches;\r\n\r\n var i;\r\n var length = changedTouches.length;\r\n var touch;\r\n var identifier;\r\n var positions = screenSpaceEventHandler._positions;\r\n\r\n for (i = 0; i < length; ++i) {\r\n touch = changedTouches[i];\r\n identifier = touch.identifier;\r\n var position = positions.get(identifier);\r\n if (defined(position)) {\r\n getPosition(screenSpaceEventHandler, touch, position);\r\n }\r\n }\r\n\r\n fireTouchMoveEvents(screenSpaceEventHandler, event);\r\n\r\n var previousPositions = screenSpaceEventHandler._previousPositions;\r\n\r\n for (i = 0; i < length; ++i) {\r\n touch = changedTouches[i];\r\n identifier = touch.identifier;\r\n Cartesian2.clone(\r\n positions.get(identifier),\r\n previousPositions.get(identifier)\r\n );\r\n }\r\n}\r\n\r\nvar touchMoveEvent = {\r\n startPosition: new Cartesian2(),\r\n endPosition: new Cartesian2(),\r\n};\r\nvar touchPinchMovementEvent = {\r\n distance: {\r\n startPosition: new Cartesian2(),\r\n endPosition: new Cartesian2(),\r\n },\r\n angleAndHeight: {\r\n startPosition: new Cartesian2(),\r\n endPosition: new Cartesian2(),\r\n },\r\n};\r\n\r\nfunction fireTouchMoveEvents(screenSpaceEventHandler, event) {\r\n var modifier = getModifier(event);\r\n var positions = screenSpaceEventHandler._positions;\r\n var previousPositions = screenSpaceEventHandler._previousPositions;\r\n var numberOfTouches = positions.length;\r\n var action;\r\n\r\n if (\r\n numberOfTouches === 1 &&\r\n screenSpaceEventHandler._buttonDown[MouseButton.LEFT]\r\n ) {\r\n // moving single touch\r\n var position = positions.values[0];\r\n Cartesian2.clone(position, screenSpaceEventHandler._primaryPosition);\r\n\r\n var previousPosition = screenSpaceEventHandler._primaryPreviousPosition;\r\n\r\n action = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.MOUSE_MOVE,\r\n modifier\r\n );\r\n\r\n if (defined(action)) {\r\n Cartesian2.clone(previousPosition, touchMoveEvent.startPosition);\r\n Cartesian2.clone(position, touchMoveEvent.endPosition);\r\n\r\n action(touchMoveEvent);\r\n }\r\n\r\n Cartesian2.clone(position, previousPosition);\r\n\r\n event.preventDefault();\r\n } else if (numberOfTouches === 2 && screenSpaceEventHandler._isPinching) {\r\n // moving pinch\r\n\r\n action = screenSpaceEventHandler.getInputAction(\r\n ScreenSpaceEventType.PINCH_MOVE,\r\n modifier\r\n );\r\n if (defined(action)) {\r\n var position1 = positions.values[0];\r\n var position2 = positions.values[1];\r\n var previousPosition1 = previousPositions.values[0];\r\n var previousPosition2 = previousPositions.values[1];\r\n\r\n var dX = position2.x - position1.x;\r\n var dY = position2.y - position1.y;\r\n var dist = Math.sqrt(dX * dX + dY * dY) * 0.25;\r\n\r\n var prevDX = previousPosition2.x - previousPosition1.x;\r\n var prevDY = previousPosition2.y - previousPosition1.y;\r\n var prevDist = Math.sqrt(prevDX * prevDX + prevDY * prevDY) * 0.25;\r\n\r\n var cY = (position2.y + position1.y) * 0.125;\r\n var prevCY = (previousPosition2.y + previousPosition1.y) * 0.125;\r\n var angle = Math.atan2(dY, dX);\r\n var prevAngle = Math.atan2(prevDY, prevDX);\r\n\r\n Cartesian2.fromElements(\r\n 0.0,\r\n prevDist,\r\n touchPinchMovementEvent.distance.startPosition\r\n );\r\n Cartesian2.fromElements(\r\n 0.0,\r\n dist,\r\n touchPinchMovementEvent.distance.endPosition\r\n );\r\n\r\n Cartesian2.fromElements(\r\n prevAngle,\r\n prevCY,\r\n touchPinchMovementEvent.angleAndHeight.startPosition\r\n );\r\n Cartesian2.fromElements(\r\n angle,\r\n cY,\r\n touchPinchMovementEvent.angleAndHeight.endPosition\r\n );\r\n\r\n action(touchPinchMovementEvent);\r\n }\r\n }\r\n}\r\n\r\nfunction handlePointerDown(screenSpaceEventHandler, event) {\r\n event.target.setPointerCapture(event.pointerId);\r\n\r\n if (event.pointerType === \"touch\") {\r\n var positions = screenSpaceEventHandler._positions;\r\n\r\n var identifier = event.pointerId;\r\n positions.set(\r\n identifier,\r\n getPosition(screenSpaceEventHandler, event, new Cartesian2())\r\n );\r\n\r\n fireTouchEvents(screenSpaceEventHandler, event);\r\n\r\n var previousPositions = screenSpaceEventHandler._previousPositions;\r\n previousPositions.set(\r\n identifier,\r\n Cartesian2.clone(positions.get(identifier))\r\n );\r\n } else {\r\n handleMouseDown(screenSpaceEventHandler, event);\r\n }\r\n}\r\n\r\nfunction handlePointerUp(screenSpaceEventHandler, event) {\r\n if (event.pointerType === \"touch\") {\r\n var positions = screenSpaceEventHandler._positions;\r\n\r\n var identifier = event.pointerId;\r\n positions.remove(identifier);\r\n\r\n fireTouchEvents(screenSpaceEventHandler, event);\r\n\r\n var previousPositions = screenSpaceEventHandler._previousPositions;\r\n previousPositions.remove(identifier);\r\n } else {\r\n handleMouseUp(screenSpaceEventHandler, event);\r\n }\r\n}\r\n\r\nfunction handlePointerMove(screenSpaceEventHandler, event) {\r\n if (event.pointerType === \"touch\") {\r\n var positions = screenSpaceEventHandler._positions;\r\n\r\n var identifier = event.pointerId;\r\n var position = positions.get(identifier);\r\n if (!defined(position)) {\r\n return;\r\n }\r\n\r\n getPosition(screenSpaceEventHandler, event, position);\r\n fireTouchMoveEvents(screenSpaceEventHandler, event);\r\n\r\n var previousPositions = screenSpaceEventHandler._previousPositions;\r\n Cartesian2.clone(\r\n positions.get(identifier),\r\n previousPositions.get(identifier)\r\n );\r\n } else {\r\n handleMouseMove(screenSpaceEventHandler, event);\r\n }\r\n}\r\n\r\n/**\r\n * Handles user input events. Custom functions can be added to be executed on\r\n * when the user enters input.\r\n *\r\n * @alias ScreenSpaceEventHandler\r\n *\r\n * @param {HTMLCanvasElement} [element=document] The element to add events to.\r\n *\r\n * @constructor\r\n */\r\nfunction ScreenSpaceEventHandler(element) {\r\n this._inputEvents = {};\r\n this._buttonDown = {\r\n LEFT: false,\r\n MIDDLE: false,\r\n RIGHT: false,\r\n };\r\n this._isPinching = false;\r\n this._isTouchHolding = false;\r\n this._lastSeenTouchEvent = -ScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds;\r\n\r\n this._primaryStartPosition = new Cartesian2();\r\n this._primaryPosition = new Cartesian2();\r\n this._primaryPreviousPosition = new Cartesian2();\r\n\r\n this._positions = new AssociativeArray();\r\n this._previousPositions = new AssociativeArray();\r\n\r\n this._removalFunctions = [];\r\n\r\n this._touchHoldTimer = undefined;\r\n\r\n // TODO: Revisit when doing mobile development. May need to be configurable\r\n // or determined based on the platform?\r\n this._clickPixelTolerance = 5;\r\n this._holdPixelTolerance = 25;\r\n\r\n this._element = defaultValue(element, document);\r\n\r\n registerListeners(this);\r\n}\r\n\r\n/**\r\n * Set a function to be executed on an input event.\r\n *\r\n * @param {Function} action Function to be executed when the input event occurs.\r\n * @param {Number} type The ScreenSpaceEventType of input event.\r\n * @param {Number} [modifier] A KeyboardEventModifier key that is held when a type\r\n * event occurs.\r\n *\r\n * @see ScreenSpaceEventHandler#getInputAction\r\n * @see ScreenSpaceEventHandler#removeInputAction\r\n */\r\nScreenSpaceEventHandler.prototype.setInputAction = function (\r\n action,\r\n type,\r\n modifier\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(action)) {\r\n throw new DeveloperError(\"action is required.\");\r\n }\r\n if (!defined(type)) {\r\n throw new DeveloperError(\"type is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var key = getInputEventKey(type, modifier);\r\n this._inputEvents[key] = action;\r\n};\r\n\r\n/**\r\n * Returns the function to be executed on an input event.\r\n *\r\n * @param {Number} type The ScreenSpaceEventType of input event.\r\n * @param {Number} [modifier] A KeyboardEventModifier key that is held when a type\r\n * event occurs.\r\n *\r\n * @returns {Function} The function to be executed on an input event.\r\n *\r\n * @see ScreenSpaceEventHandler#setInputAction\r\n * @see ScreenSpaceEventHandler#removeInputAction\r\n */\r\nScreenSpaceEventHandler.prototype.getInputAction = function (type, modifier) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(type)) {\r\n throw new DeveloperError(\"type is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var key = getInputEventKey(type, modifier);\r\n return this._inputEvents[key];\r\n};\r\n\r\n/**\r\n * Removes the function to be executed on an input event.\r\n *\r\n * @param {Number} type The ScreenSpaceEventType of input event.\r\n * @param {Number} [modifier] A KeyboardEventModifier key that is held when a type\r\n * event occurs.\r\n *\r\n * @see ScreenSpaceEventHandler#getInputAction\r\n * @see ScreenSpaceEventHandler#setInputAction\r\n */\r\nScreenSpaceEventHandler.prototype.removeInputAction = function (\r\n type,\r\n modifier\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(type)) {\r\n throw new DeveloperError(\"type is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var key = getInputEventKey(type, modifier);\r\n delete this._inputEvents[key];\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see ScreenSpaceEventHandler#destroy\r\n */\r\nScreenSpaceEventHandler.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes listeners held by this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * handler = handler && handler.destroy();\r\n *\r\n * @see ScreenSpaceEventHandler#isDestroyed\r\n */\r\nScreenSpaceEventHandler.prototype.destroy = function () {\r\n unregisterListeners(this);\r\n\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * The amount of time, in milliseconds, that mouse events will be disabled after\r\n * receiving any touch events, such that any emulated mouse events will be ignored.\r\n * @type {Number}\r\n * @default 800\r\n */\r\nScreenSpaceEventHandler.mouseEmulationIgnoreMilliseconds = 800;\r\n\r\n/**\r\n * The amount of time, in milliseconds, before a touch on the screen becomes a\r\n * touch and hold.\r\n * @type {Number}\r\n * @default 1500\r\n */\r\nScreenSpaceEventHandler.touchHoldDelayMilliseconds = 1500;\r\nexport default ScreenSpaceEventHandler;\r\n","import ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Value and type information for per-instance geometry attribute that determines if the geometry instance will be shown.\r\n *\r\n * @alias ShowGeometryInstanceAttribute\r\n * @constructor\r\n *\r\n * @param {Boolean} [show=true] Determines if the geometry instance will be shown.\r\n *\r\n *\r\n * @example\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.BoxGeometry({\r\n * vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL,\r\n * minimum : new Cesium.Cartesian3(-250000.0, -250000.0, -250000.0),\r\n * maximum : new Cesium.Cartesian3(250000.0, 250000.0, 250000.0)\r\n * }),\r\n * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(\r\n * Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 1000000.0), new Cesium.Matrix4()),\r\n * id : 'box',\r\n * attributes : {\r\n * show : new Cesium.ShowGeometryInstanceAttribute(false)\r\n * }\r\n * });\r\n *\r\n * @see GeometryInstance\r\n * @see GeometryInstanceAttribute\r\n */\r\nfunction ShowGeometryInstanceAttribute(show) {\r\n show = defaultValue(show, true);\r\n\r\n /**\r\n * The values for the attributes stored in a typed array.\r\n *\r\n * @type Uint8Array\r\n *\r\n * @default [1.0]\r\n */\r\n this.value = ShowGeometryInstanceAttribute.toValue(show);\r\n}\r\n\r\nObject.defineProperties(ShowGeometryInstanceAttribute.prototype, {\r\n /**\r\n * The datatype of each component in the attribute, e.g., individual elements in\r\n * {@link ColorGeometryInstanceAttribute#value}.\r\n *\r\n * @memberof ShowGeometryInstanceAttribute.prototype\r\n *\r\n * @type {ComponentDatatype}\r\n * @readonly\r\n *\r\n * @default {@link ComponentDatatype.UNSIGNED_BYTE}\r\n */\r\n componentDatatype: {\r\n get: function () {\r\n return ComponentDatatype.UNSIGNED_BYTE;\r\n },\r\n },\r\n\r\n /**\r\n * The number of components in the attributes, i.e., {@link ColorGeometryInstanceAttribute#value}.\r\n *\r\n * @memberof ShowGeometryInstanceAttribute.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n *\r\n * @default 1\r\n */\r\n componentsPerAttribute: {\r\n get: function () {\r\n return 1;\r\n },\r\n },\r\n\r\n /**\r\n * When true and componentDatatype is an integer format,\r\n * indicate that the components should be mapped to the range [0, 1] (unsigned)\r\n * or [-1, 1] (signed) when they are accessed as floating-point for rendering.\r\n *\r\n * @memberof ShowGeometryInstanceAttribute.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n normalize: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Converts a boolean show to a typed array that can be used to assign a show attribute.\r\n *\r\n * @param {Boolean} show The show value.\r\n * @param {Uint8Array} [result] The array to store the result in, if undefined a new instance will be created.\r\n * @returns {Uint8Array} The modified result parameter or a new instance if result was undefined.\r\n *\r\n * @example\r\n * var attributes = primitive.getGeometryInstanceAttributes('an id');\r\n * attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true, attributes.show);\r\n */\r\nShowGeometryInstanceAttribute.toValue = function (show, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(show)) {\r\n throw new DeveloperError(\"show is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Uint8Array([show]);\r\n }\r\n result[0] = show;\r\n return result;\r\n};\r\nexport default ShowGeometryInstanceAttribute;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Matrix3 from \"./Matrix3.js\";\r\nimport TimeConstants from \"./TimeConstants.js\";\r\nimport TimeStandard from \"./TimeStandard.js\";\r\n\r\n/**\r\n * Contains functions for finding the Cartesian coordinates of the sun and the moon in the\r\n * Earth-centered inertial frame.\r\n *\r\n * @namespace Simon1994PlanetaryPositions\r\n */\r\nvar Simon1994PlanetaryPositions = {};\r\n\r\nfunction computeTdbMinusTtSpice(daysSinceJ2000InTerrestrialTime) {\r\n /* STK Comments ------------------------------------------------------\r\n * This function uses constants designed to be consistent with\r\n * the SPICE Toolkit from JPL version N0051 (unitim.c)\r\n * M0 = 6.239996\r\n * M0Dot = 1.99096871e-7 rad/s = 0.01720197 rad/d\r\n * EARTH_ECC = 1.671e-2\r\n * TDB_AMPL = 1.657e-3 secs\r\n *--------------------------------------------------------------------*/\r\n\r\n //* Values taken as specified in STK Comments except: 0.01720197 rad/day = 1.99096871e-7 rad/sec\r\n //* Here we use the more precise value taken from the SPICE value 1.99096871e-7 rad/sec converted to rad/day\r\n //* All other constants are consistent with the SPICE implementation of the TDB conversion\r\n //* except where we treat the independent time parameter to be in TT instead of TDB.\r\n //* This is an approximation made to facilitate performance due to the higher prevalance of\r\n //* the TT2TDB conversion over TDB2TT in order to avoid having to iterate when converting to TDB for the JPL ephemeris.\r\n //* Days are used instead of seconds to provide a slight improvement in numerical precision.\r\n\r\n //* For more information see:\r\n //* http://www.cv.nrao.edu/~rfisher/Ephemerides/times.html#TDB\r\n //* ftp://ssd.jpl.nasa.gov/pub/eph/planets/ioms/ExplSupplChap8.pdf\r\n\r\n var g = 6.239996 + 0.0172019696544 * daysSinceJ2000InTerrestrialTime;\r\n return 1.657e-3 * Math.sin(g + 1.671e-2 * Math.sin(g));\r\n}\r\n\r\nvar TdtMinusTai = 32.184;\r\nvar J2000d = 2451545;\r\nfunction taiToTdb(date, result) {\r\n //Converts TAI to TT\r\n result = JulianDate.addSeconds(date, TdtMinusTai, result);\r\n\r\n //Converts TT to TDB\r\n var days = JulianDate.totalDays(result) - J2000d;\r\n result = JulianDate.addSeconds(result, computeTdbMinusTtSpice(days), result);\r\n\r\n return result;\r\n}\r\n\r\nvar epoch = new JulianDate(2451545, 0, TimeStandard.TAI); //Actually TDB (not TAI)\r\nvar MetersPerKilometer = 1000.0;\r\nvar RadiansPerDegree = CesiumMath.RADIANS_PER_DEGREE;\r\nvar RadiansPerArcSecond = CesiumMath.RADIANS_PER_ARCSECOND;\r\nvar MetersPerAstronomicalUnit = 1.4959787e11; // IAU 1976 value\r\n\r\nvar perifocalToEquatorial = new Matrix3();\r\nfunction elementsToCartesian(\r\n semimajorAxis,\r\n eccentricity,\r\n inclination,\r\n longitudeOfPerigee,\r\n longitudeOfNode,\r\n meanLongitude,\r\n result\r\n) {\r\n if (inclination < 0.0) {\r\n inclination = -inclination;\r\n longitudeOfNode += CesiumMath.PI;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (inclination < 0 || inclination > CesiumMath.PI) {\r\n throw new DeveloperError(\r\n \"The inclination is out of range. Inclination must be greater than or equal to zero and less than or equal to Pi radians.\"\r\n );\r\n }\r\n //>>includeEnd('debug')\r\n\r\n var radiusOfPeriapsis = semimajorAxis * (1.0 - eccentricity);\r\n var argumentOfPeriapsis = longitudeOfPerigee - longitudeOfNode;\r\n var rightAscensionOfAscendingNode = longitudeOfNode;\r\n var trueAnomaly = meanAnomalyToTrueAnomaly(\r\n meanLongitude - longitudeOfPerigee,\r\n eccentricity\r\n );\r\n var type = chooseOrbit(eccentricity, 0.0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n type === \"Hyperbolic\" &&\r\n Math.abs(CesiumMath.negativePiToPi(trueAnomaly)) >=\r\n Math.acos(-1.0 / eccentricity)\r\n ) {\r\n throw new DeveloperError(\r\n \"The true anomaly of the hyperbolic orbit lies outside of the bounds of the hyperbola.\"\r\n );\r\n }\r\n //>>includeEnd('debug')\r\n\r\n perifocalToCartesianMatrix(\r\n argumentOfPeriapsis,\r\n inclination,\r\n rightAscensionOfAscendingNode,\r\n perifocalToEquatorial\r\n );\r\n var semilatus = radiusOfPeriapsis * (1.0 + eccentricity);\r\n var costheta = Math.cos(trueAnomaly);\r\n var sintheta = Math.sin(trueAnomaly);\r\n\r\n var denom = 1.0 + eccentricity * costheta;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (denom <= CesiumMath.Epsilon10) {\r\n throw new DeveloperError(\"elements cannot be converted to cartesian\");\r\n }\r\n //>>includeEnd('debug')\r\n\r\n var radius = semilatus / denom;\r\n if (!defined(result)) {\r\n result = new Cartesian3(radius * costheta, radius * sintheta, 0.0);\r\n } else {\r\n result.x = radius * costheta;\r\n result.y = radius * sintheta;\r\n result.z = 0.0;\r\n }\r\n\r\n return Matrix3.multiplyByVector(perifocalToEquatorial, result, result);\r\n}\r\n\r\nfunction chooseOrbit(eccentricity, tolerance) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (eccentricity < 0) {\r\n throw new DeveloperError(\"eccentricity cannot be negative.\");\r\n }\r\n //>>includeEnd('debug')\r\n\r\n if (eccentricity <= tolerance) {\r\n return \"Circular\";\r\n } else if (eccentricity < 1.0 - tolerance) {\r\n return \"Elliptical\";\r\n } else if (eccentricity <= 1.0 + tolerance) {\r\n return \"Parabolic\";\r\n }\r\n return \"Hyperbolic\";\r\n}\r\n\r\n// Calculates the true anomaly given the mean anomaly and the eccentricity.\r\nfunction meanAnomalyToTrueAnomaly(meanAnomaly, eccentricity) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (eccentricity < 0.0 || eccentricity >= 1.0) {\r\n throw new DeveloperError(\"eccentricity out of range.\");\r\n }\r\n //>>includeEnd('debug')\r\n\r\n var eccentricAnomaly = meanAnomalyToEccentricAnomaly(\r\n meanAnomaly,\r\n eccentricity\r\n );\r\n return eccentricAnomalyToTrueAnomaly(eccentricAnomaly, eccentricity);\r\n}\r\n\r\nvar maxIterationCount = 50;\r\nvar keplerEqConvergence = CesiumMath.EPSILON8;\r\n// Calculates the eccentric anomaly given the mean anomaly and the eccentricity.\r\nfunction meanAnomalyToEccentricAnomaly(meanAnomaly, eccentricity) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (eccentricity < 0.0 || eccentricity >= 1.0) {\r\n throw new DeveloperError(\"eccentricity out of range.\");\r\n }\r\n //>>includeEnd('debug')\r\n\r\n var revs = Math.floor(meanAnomaly / CesiumMath.TWO_PI);\r\n\r\n // Find angle in current revolution\r\n meanAnomaly -= revs * CesiumMath.TWO_PI;\r\n\r\n // calculate starting value for iteration sequence\r\n var iterationValue =\r\n meanAnomaly +\r\n (eccentricity * Math.sin(meanAnomaly)) /\r\n (1.0 - Math.sin(meanAnomaly + eccentricity) + Math.sin(meanAnomaly));\r\n\r\n // Perform Newton-Raphson iteration on Kepler's equation\r\n var eccentricAnomaly = Number.MAX_VALUE;\r\n\r\n var count;\r\n for (\r\n count = 0;\r\n count < maxIterationCount &&\r\n Math.abs(eccentricAnomaly - iterationValue) > keplerEqConvergence;\r\n ++count\r\n ) {\r\n eccentricAnomaly = iterationValue;\r\n var NRfunction =\r\n eccentricAnomaly -\r\n eccentricity * Math.sin(eccentricAnomaly) -\r\n meanAnomaly;\r\n var dNRfunction = 1 - eccentricity * Math.cos(eccentricAnomaly);\r\n iterationValue = eccentricAnomaly - NRfunction / dNRfunction;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (count >= maxIterationCount) {\r\n throw new DeveloperError(\"Kepler equation did not converge\");\r\n // STK Components uses a numerical method to find the eccentric anomaly in the case that Kepler's\r\n // equation does not converge. We don't expect that to ever be necessary for the reasonable orbits used here.\r\n }\r\n //>>includeEnd('debug')\r\n\r\n eccentricAnomaly = iterationValue + revs * CesiumMath.TWO_PI;\r\n return eccentricAnomaly;\r\n}\r\n\r\n// Calculates the true anomaly given the eccentric anomaly and the eccentricity.\r\nfunction eccentricAnomalyToTrueAnomaly(eccentricAnomaly, eccentricity) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (eccentricity < 0.0 || eccentricity >= 1.0) {\r\n throw new DeveloperError(\"eccentricity out of range.\");\r\n }\r\n //>>includeEnd('debug')\r\n\r\n // Calculate the number of previous revolutions\r\n var revs = Math.floor(eccentricAnomaly / CesiumMath.TWO_PI);\r\n\r\n // Find angle in current revolution\r\n eccentricAnomaly -= revs * CesiumMath.TWO_PI;\r\n\r\n // Calculate true anomaly from eccentric anomaly\r\n var trueAnomalyX = Math.cos(eccentricAnomaly) - eccentricity;\r\n var trueAnomalyY =\r\n Math.sin(eccentricAnomaly) * Math.sqrt(1 - eccentricity * eccentricity);\r\n\r\n var trueAnomaly = Math.atan2(trueAnomalyY, trueAnomalyX);\r\n\r\n // Ensure the correct quadrant\r\n trueAnomaly = CesiumMath.zeroToTwoPi(trueAnomaly);\r\n if (eccentricAnomaly < 0) {\r\n trueAnomaly -= CesiumMath.TWO_PI;\r\n }\r\n\r\n // Add on previous revolutions\r\n trueAnomaly += revs * CesiumMath.TWO_PI;\r\n\r\n return trueAnomaly;\r\n}\r\n\r\n// Calculates the transformation matrix to convert from the perifocal (PQW) coordinate\r\n// system to inertial cartesian coordinates.\r\nfunction perifocalToCartesianMatrix(\r\n argumentOfPeriapsis,\r\n inclination,\r\n rightAscension,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (inclination < 0 || inclination > CesiumMath.PI) {\r\n throw new DeveloperError(\"inclination out of range\");\r\n }\r\n //>>includeEnd('debug')\r\n\r\n var cosap = Math.cos(argumentOfPeriapsis);\r\n var sinap = Math.sin(argumentOfPeriapsis);\r\n\r\n var cosi = Math.cos(inclination);\r\n var sini = Math.sin(inclination);\r\n\r\n var cosraan = Math.cos(rightAscension);\r\n var sinraan = Math.sin(rightAscension);\r\n if (!defined(result)) {\r\n result = new Matrix3(\r\n cosraan * cosap - sinraan * sinap * cosi,\r\n -cosraan * sinap - sinraan * cosap * cosi,\r\n sinraan * sini,\r\n\r\n sinraan * cosap + cosraan * sinap * cosi,\r\n -sinraan * sinap + cosraan * cosap * cosi,\r\n -cosraan * sini,\r\n\r\n sinap * sini,\r\n cosap * sini,\r\n cosi\r\n );\r\n } else {\r\n result[0] = cosraan * cosap - sinraan * sinap * cosi;\r\n result[1] = sinraan * cosap + cosraan * sinap * cosi;\r\n result[2] = sinap * sini;\r\n result[3] = -cosraan * sinap - sinraan * cosap * cosi;\r\n result[4] = -sinraan * sinap + cosraan * cosap * cosi;\r\n result[5] = cosap * sini;\r\n result[6] = sinraan * sini;\r\n result[7] = -cosraan * sini;\r\n result[8] = cosi;\r\n }\r\n return result;\r\n}\r\n\r\n// From section 5.8\r\nvar semiMajorAxis0 = 1.0000010178 * MetersPerAstronomicalUnit;\r\nvar meanLongitude0 = 100.46645683 * RadiansPerDegree;\r\nvar meanLongitude1 = 1295977422.83429 * RadiansPerArcSecond;\r\n\r\n// From table 6\r\nvar p1u = 16002;\r\nvar p2u = 21863;\r\nvar p3u = 32004;\r\nvar p4u = 10931;\r\nvar p5u = 14529;\r\nvar p6u = 16368;\r\nvar p7u = 15318;\r\nvar p8u = 32794;\r\n\r\nvar Ca1 = 64 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Ca2 = -152 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Ca3 = 62 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Ca4 = -8 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Ca5 = 32 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Ca6 = -41 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Ca7 = 19 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Ca8 = -11 * 1e-7 * MetersPerAstronomicalUnit;\r\n\r\nvar Sa1 = -150 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Sa2 = -46 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Sa3 = 68 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Sa4 = 54 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Sa5 = 14 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Sa6 = 24 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Sa7 = -28 * 1e-7 * MetersPerAstronomicalUnit;\r\nvar Sa8 = 22 * 1e-7 * MetersPerAstronomicalUnit;\r\n\r\nvar q1u = 10;\r\nvar q2u = 16002;\r\nvar q3u = 21863;\r\nvar q4u = 10931;\r\nvar q5u = 1473;\r\nvar q6u = 32004;\r\nvar q7u = 4387;\r\nvar q8u = 73;\r\n\r\nvar Cl1 = -325 * 1e-7;\r\nvar Cl2 = -322 * 1e-7;\r\nvar Cl3 = -79 * 1e-7;\r\nvar Cl4 = 232 * 1e-7;\r\nvar Cl5 = -52 * 1e-7;\r\nvar Cl6 = 97 * 1e-7;\r\nvar Cl7 = 55 * 1e-7;\r\nvar Cl8 = -41 * 1e-7;\r\n\r\nvar Sl1 = -105 * 1e-7;\r\nvar Sl2 = -137 * 1e-7;\r\nvar Sl3 = 258 * 1e-7;\r\nvar Sl4 = 35 * 1e-7;\r\nvar Sl5 = -116 * 1e-7;\r\nvar Sl6 = -88 * 1e-7;\r\nvar Sl7 = -112 * 1e-7;\r\nvar Sl8 = -80 * 1e-7;\r\n\r\nvar scratchDate = new JulianDate(0, 0.0, TimeStandard.TAI);\r\n// Gets a point describing the motion of the Earth-Moon barycenter according to the equations described in section 6.\r\nfunction computeSimonEarthMoonBarycenter(date, result) {\r\n // t is thousands of years from J2000 TDB\r\n taiToTdb(date, scratchDate);\r\n var x =\r\n scratchDate.dayNumber -\r\n epoch.dayNumber +\r\n (scratchDate.secondsOfDay - epoch.secondsOfDay) /\r\n TimeConstants.SECONDS_PER_DAY;\r\n var t = x / (TimeConstants.DAYS_PER_JULIAN_CENTURY * 10.0);\r\n\r\n var u = 0.3595362 * t;\r\n var semimajorAxis =\r\n semiMajorAxis0 +\r\n Ca1 * Math.cos(p1u * u) +\r\n Sa1 * Math.sin(p1u * u) +\r\n Ca2 * Math.cos(p2u * u) +\r\n Sa2 * Math.sin(p2u * u) +\r\n Ca3 * Math.cos(p3u * u) +\r\n Sa3 * Math.sin(p3u * u) +\r\n Ca4 * Math.cos(p4u * u) +\r\n Sa4 * Math.sin(p4u * u) +\r\n Ca5 * Math.cos(p5u * u) +\r\n Sa5 * Math.sin(p5u * u) +\r\n Ca6 * Math.cos(p6u * u) +\r\n Sa6 * Math.sin(p6u * u) +\r\n Ca7 * Math.cos(p7u * u) +\r\n Sa7 * Math.sin(p7u * u) +\r\n Ca8 * Math.cos(p8u * u) +\r\n Sa8 * Math.sin(p8u * u);\r\n var meanLongitude =\r\n meanLongitude0 +\r\n meanLongitude1 * t +\r\n Cl1 * Math.cos(q1u * u) +\r\n Sl1 * Math.sin(q1u * u) +\r\n Cl2 * Math.cos(q2u * u) +\r\n Sl2 * Math.sin(q2u * u) +\r\n Cl3 * Math.cos(q3u * u) +\r\n Sl3 * Math.sin(q3u * u) +\r\n Cl4 * Math.cos(q4u * u) +\r\n Sl4 * Math.sin(q4u * u) +\r\n Cl5 * Math.cos(q5u * u) +\r\n Sl5 * Math.sin(q5u * u) +\r\n Cl6 * Math.cos(q6u * u) +\r\n Sl6 * Math.sin(q6u * u) +\r\n Cl7 * Math.cos(q7u * u) +\r\n Sl7 * Math.sin(q7u * u) +\r\n Cl8 * Math.cos(q8u * u) +\r\n Sl8 * Math.sin(q8u * u);\r\n\r\n // All constants in this part are from section 5.8\r\n var eccentricity = 0.0167086342 - 0.0004203654 * t;\r\n var longitudeOfPerigee =\r\n 102.93734808 * RadiansPerDegree + 11612.3529 * RadiansPerArcSecond * t;\r\n var inclination = 469.97289 * RadiansPerArcSecond * t;\r\n var longitudeOfNode =\r\n 174.87317577 * RadiansPerDegree - 8679.27034 * RadiansPerArcSecond * t;\r\n\r\n return elementsToCartesian(\r\n semimajorAxis,\r\n eccentricity,\r\n inclination,\r\n longitudeOfPerigee,\r\n longitudeOfNode,\r\n meanLongitude,\r\n result\r\n );\r\n}\r\n\r\n// Gets a point describing the position of the moon according to the equations described in section 4.\r\nfunction computeSimonMoon(date, result) {\r\n taiToTdb(date, scratchDate);\r\n var x =\r\n scratchDate.dayNumber -\r\n epoch.dayNumber +\r\n (scratchDate.secondsOfDay - epoch.secondsOfDay) /\r\n TimeConstants.SECONDS_PER_DAY;\r\n var t = x / TimeConstants.DAYS_PER_JULIAN_CENTURY;\r\n var t2 = t * t;\r\n var t3 = t2 * t;\r\n var t4 = t3 * t;\r\n\r\n // Terms from section 3.4 (b.1)\r\n var semimajorAxis = 383397.7725 + 0.004 * t;\r\n var eccentricity = 0.055545526 - 0.000000016 * t;\r\n var inclinationConstant = 5.15668983 * RadiansPerDegree;\r\n var inclinationSecPart =\r\n -0.00008 * t + 0.02966 * t2 - 0.000042 * t3 - 0.00000013 * t4;\r\n var longitudeOfPerigeeConstant = 83.35324312 * RadiansPerDegree;\r\n var longitudeOfPerigeeSecPart =\r\n 14643420.2669 * t - 38.2702 * t2 - 0.045047 * t3 + 0.00021301 * t4;\r\n var longitudeOfNodeConstant = 125.04455501 * RadiansPerDegree;\r\n var longitudeOfNodeSecPart =\r\n -6967919.3631 * t + 6.3602 * t2 + 0.007625 * t3 - 0.00003586 * t4;\r\n var meanLongitudeConstant = 218.31664563 * RadiansPerDegree;\r\n var meanLongitudeSecPart =\r\n 1732559343.4847 * t - 6.391 * t2 + 0.006588 * t3 - 0.00003169 * t4;\r\n\r\n // Delaunay arguments from section 3.5 b\r\n var D =\r\n 297.85019547 * RadiansPerDegree +\r\n RadiansPerArcSecond *\r\n (1602961601.209 * t - 6.3706 * t2 + 0.006593 * t3 - 0.00003169 * t4);\r\n var F =\r\n 93.27209062 * RadiansPerDegree +\r\n RadiansPerArcSecond *\r\n (1739527262.8478 * t - 12.7512 * t2 - 0.001037 * t3 + 0.00000417 * t4);\r\n var l =\r\n 134.96340251 * RadiansPerDegree +\r\n RadiansPerArcSecond *\r\n (1717915923.2178 * t + 31.8792 * t2 + 0.051635 * t3 - 0.0002447 * t4);\r\n var lprime =\r\n 357.52910918 * RadiansPerDegree +\r\n RadiansPerArcSecond *\r\n (129596581.0481 * t - 0.5532 * t2 + 0.000136 * t3 - 0.00001149 * t4);\r\n var psi =\r\n 310.17137918 * RadiansPerDegree -\r\n RadiansPerArcSecond *\r\n (6967051.436 * t + 6.2068 * t2 + 0.007618 * t3 - 0.00003219 * t4);\r\n\r\n // Add terms from Table 4\r\n var twoD = 2.0 * D;\r\n var fourD = 4.0 * D;\r\n var sixD = 6.0 * D;\r\n var twol = 2.0 * l;\r\n var threel = 3.0 * l;\r\n var fourl = 4.0 * l;\r\n var twoF = 2.0 * F;\r\n semimajorAxis +=\r\n 3400.4 * Math.cos(twoD) -\r\n 635.6 * Math.cos(twoD - l) -\r\n 235.6 * Math.cos(l) +\r\n 218.1 * Math.cos(twoD - lprime) +\r\n 181.0 * Math.cos(twoD + l);\r\n eccentricity +=\r\n 0.014216 * Math.cos(twoD - l) +\r\n 0.008551 * Math.cos(twoD - twol) -\r\n 0.001383 * Math.cos(l) +\r\n 0.001356 * Math.cos(twoD + l) -\r\n 0.001147 * Math.cos(fourD - threel) -\r\n 0.000914 * Math.cos(fourD - twol) +\r\n 0.000869 * Math.cos(twoD - lprime - l) -\r\n 0.000627 * Math.cos(twoD) -\r\n 0.000394 * Math.cos(fourD - fourl) +\r\n 0.000282 * Math.cos(twoD - lprime - twol) -\r\n 0.000279 * Math.cos(D - l) -\r\n 0.000236 * Math.cos(twol) +\r\n 0.000231 * Math.cos(fourD) +\r\n 0.000229 * Math.cos(sixD - fourl) -\r\n 0.000201 * Math.cos(twol - twoF);\r\n inclinationSecPart +=\r\n 486.26 * Math.cos(twoD - twoF) -\r\n 40.13 * Math.cos(twoD) +\r\n 37.51 * Math.cos(twoF) +\r\n 25.73 * Math.cos(twol - twoF) +\r\n 19.97 * Math.cos(twoD - lprime - twoF);\r\n longitudeOfPerigeeSecPart +=\r\n -55609 * Math.sin(twoD - l) -\r\n 34711 * Math.sin(twoD - twol) -\r\n 9792 * Math.sin(l) +\r\n 9385 * Math.sin(fourD - threel) +\r\n 7505 * Math.sin(fourD - twol) +\r\n 5318 * Math.sin(twoD + l) +\r\n 3484 * Math.sin(fourD - fourl) -\r\n 3417 * Math.sin(twoD - lprime - l) -\r\n 2530 * Math.sin(sixD - fourl) -\r\n 2376 * Math.sin(twoD) -\r\n 2075 * Math.sin(twoD - threel) -\r\n 1883 * Math.sin(twol) -\r\n 1736 * Math.sin(sixD - 5.0 * l) +\r\n 1626 * Math.sin(lprime) -\r\n 1370 * Math.sin(sixD - threel);\r\n longitudeOfNodeSecPart +=\r\n -5392 * Math.sin(twoD - twoF) -\r\n 540 * Math.sin(lprime) -\r\n 441 * Math.sin(twoD) +\r\n 423 * Math.sin(twoF) -\r\n 288 * Math.sin(twol - twoF);\r\n meanLongitudeSecPart +=\r\n -3332.9 * Math.sin(twoD) +\r\n 1197.4 * Math.sin(twoD - l) -\r\n 662.5 * Math.sin(lprime) +\r\n 396.3 * Math.sin(l) -\r\n 218.0 * Math.sin(twoD - lprime);\r\n\r\n // Add terms from Table 5\r\n var twoPsi = 2.0 * psi;\r\n var threePsi = 3.0 * psi;\r\n inclinationSecPart +=\r\n 46.997 * Math.cos(psi) * t -\r\n 0.614 * Math.cos(twoD - twoF + psi) * t +\r\n 0.614 * Math.cos(twoD - twoF - psi) * t -\r\n 0.0297 * Math.cos(twoPsi) * t2 -\r\n 0.0335 * Math.cos(psi) * t2 +\r\n 0.0012 * Math.cos(twoD - twoF + twoPsi) * t2 -\r\n 0.00016 * Math.cos(psi) * t3 +\r\n 0.00004 * Math.cos(threePsi) * t3 +\r\n 0.00004 * Math.cos(twoPsi) * t3;\r\n var perigeeAndMean =\r\n 2.116 * Math.sin(psi) * t -\r\n 0.111 * Math.sin(twoD - twoF - psi) * t -\r\n 0.0015 * Math.sin(psi) * t2;\r\n longitudeOfPerigeeSecPart += perigeeAndMean;\r\n meanLongitudeSecPart += perigeeAndMean;\r\n longitudeOfNodeSecPart +=\r\n -520.77 * Math.sin(psi) * t +\r\n 13.66 * Math.sin(twoD - twoF + psi) * t +\r\n 1.12 * Math.sin(twoD - psi) * t -\r\n 1.06 * Math.sin(twoF - psi) * t +\r\n 0.66 * Math.sin(twoPsi) * t2 +\r\n 0.371 * Math.sin(psi) * t2 -\r\n 0.035 * Math.sin(twoD - twoF + twoPsi) * t2 -\r\n 0.015 * Math.sin(twoD - twoF + psi) * t2 +\r\n 0.0014 * Math.sin(psi) * t3 -\r\n 0.0011 * Math.sin(threePsi) * t3 -\r\n 0.0009 * Math.sin(twoPsi) * t3;\r\n\r\n // Add constants and convert units\r\n semimajorAxis *= MetersPerKilometer;\r\n var inclination =\r\n inclinationConstant + inclinationSecPart * RadiansPerArcSecond;\r\n var longitudeOfPerigee =\r\n longitudeOfPerigeeConstant +\r\n longitudeOfPerigeeSecPart * RadiansPerArcSecond;\r\n var meanLongitude =\r\n meanLongitudeConstant + meanLongitudeSecPart * RadiansPerArcSecond;\r\n var longitudeOfNode =\r\n longitudeOfNodeConstant + longitudeOfNodeSecPart * RadiansPerArcSecond;\r\n\r\n return elementsToCartesian(\r\n semimajorAxis,\r\n eccentricity,\r\n inclination,\r\n longitudeOfPerigee,\r\n longitudeOfNode,\r\n meanLongitude,\r\n result\r\n );\r\n}\r\n\r\n// Gets a point describing the motion of the Earth. This point uses the Moon point and\r\n// the 1992 mu value (ratio between Moon and Earth masses) in Table 2 of the paper in order\r\n// to determine the position of the Earth relative to the Earth-Moon barycenter.\r\nvar moonEarthMassRatio = 0.012300034; // From 1992 mu value in Table 2\r\nvar factor = (moonEarthMassRatio / (moonEarthMassRatio + 1.0)) * -1;\r\nfunction computeSimonEarth(date, result) {\r\n result = computeSimonMoon(date, result);\r\n return Cartesian3.multiplyByScalar(result, factor, result);\r\n}\r\n\r\n// Values for the axesTransformation needed for the rotation were found using the STK Components\r\n// GreographicTransformer on the position of the sun center of mass point and the earth J2000 frame.\r\n\r\nvar axesTransformation = new Matrix3(\r\n 1.0000000000000002,\r\n 5.619723173785822e-16,\r\n 4.690511510146299e-19,\r\n -5.154129427414611e-16,\r\n 0.9174820620691819,\r\n -0.39777715593191376,\r\n -2.23970096136568e-16,\r\n 0.39777715593191376,\r\n 0.9174820620691819\r\n);\r\nvar translation = new Cartesian3();\r\n/**\r\n * Computes the position of the Sun in the Earth-centered inertial frame\r\n *\r\n * @param {JulianDate} [julianDate] The time at which to compute the Sun's position, if not provided the current system time is used.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} Calculated sun position\r\n */\r\nSimon1994PlanetaryPositions.computeSunPositionInEarthInertialFrame = function (\r\n julianDate,\r\n result\r\n) {\r\n if (!defined(julianDate)) {\r\n julianDate = JulianDate.now();\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n //first forward transformation\r\n translation = computeSimonEarthMoonBarycenter(julianDate, translation);\r\n result = Cartesian3.negate(translation, result);\r\n\r\n //second forward transformation\r\n computeSimonEarth(julianDate, translation);\r\n\r\n Cartesian3.subtract(result, translation, result);\r\n Matrix3.multiplyByVector(axesTransformation, result, result);\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the position of the Moon in the Earth-centered inertial frame\r\n *\r\n * @param {JulianDate} [julianDate] The time at which to compute the Sun's position, if not provided the current system time is used.\r\n * @param {Cartesian3} [result] The object onto which to store the result.\r\n * @returns {Cartesian3} Calculated moon position\r\n */\r\nSimon1994PlanetaryPositions.computeMoonPositionInEarthInertialFrame = function (\r\n julianDate,\r\n result\r\n) {\r\n if (!defined(julianDate)) {\r\n julianDate = JulianDate.now();\r\n }\r\n\r\n result = computeSimonMoon(julianDate, result);\r\n Matrix3.multiplyByVector(axesTransformation, result, result);\r\n\r\n return result;\r\n};\r\nexport default Simon1994PlanetaryPositions;\r\n","import ArcType from \"./ArcType.js\";\r\nimport BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Color from \"./Color.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PolylinePipeline from \"./PolylinePipeline.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\n\r\nfunction interpolateColors(p0, p1, color0, color1, minDistance, array, offset) {\r\n var numPoints = PolylinePipeline.numberOfPoints(p0, p1, minDistance);\r\n var i;\r\n\r\n var r0 = color0.red;\r\n var g0 = color0.green;\r\n var b0 = color0.blue;\r\n var a0 = color0.alpha;\r\n\r\n var r1 = color1.red;\r\n var g1 = color1.green;\r\n var b1 = color1.blue;\r\n var a1 = color1.alpha;\r\n\r\n if (Color.equals(color0, color1)) {\r\n for (i = 0; i < numPoints; i++) {\r\n array[offset++] = Color.floatToByte(r0);\r\n array[offset++] = Color.floatToByte(g0);\r\n array[offset++] = Color.floatToByte(b0);\r\n array[offset++] = Color.floatToByte(a0);\r\n }\r\n return offset;\r\n }\r\n\r\n var redPerVertex = (r1 - r0) / numPoints;\r\n var greenPerVertex = (g1 - g0) / numPoints;\r\n var bluePerVertex = (b1 - b0) / numPoints;\r\n var alphaPerVertex = (a1 - a0) / numPoints;\r\n\r\n var index = offset;\r\n for (i = 0; i < numPoints; i++) {\r\n array[index++] = Color.floatToByte(r0 + i * redPerVertex);\r\n array[index++] = Color.floatToByte(g0 + i * greenPerVertex);\r\n array[index++] = Color.floatToByte(b0 + i * bluePerVertex);\r\n array[index++] = Color.floatToByte(a0 + i * alphaPerVertex);\r\n }\r\n\r\n return index;\r\n}\r\n\r\n/**\r\n * A description of a polyline modeled as a line strip; the first two positions define a line segment,\r\n * and each additional position defines a line segment from the previous position.\r\n *\r\n * @alias SimplePolylineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of {@link Cartesian3} defining the positions in the polyline as a line strip.\r\n * @param {Color[]} [options.colors] An Array of {@link Color} defining the per vertex or per segment colors.\r\n * @param {Boolean} [options.colorsPerVertex=false] A boolean that determines whether the colors will be flat across each segment of the line or interpolated across the vertices.\r\n * @param {ArcType} [options.arcType=ArcType.GEODESIC] The type of line the polyline segments must follow.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude if options.arcType is not ArcType.NONE. Determines the number of positions in the buffer.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid to be used as a reference.\r\n *\r\n * @exception {DeveloperError} At least two positions are required.\r\n * @exception {DeveloperError} colors has an invalid length.\r\n *\r\n * @see SimplePolylineGeometry#createGeometry\r\n *\r\n * @example\r\n * // A polyline with two connected line segments\r\n * var polyline = new Cesium.SimplePolylineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * 0.0, 0.0,\r\n * 5.0, 0.0,\r\n * 5.0, 5.0\r\n * ])\r\n * });\r\n * var geometry = Cesium.SimplePolylineGeometry.createGeometry(polyline);\r\n */\r\nfunction SimplePolylineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.positions;\r\n var colors = options.colors;\r\n var colorsPerVertex = defaultValue(options.colorsPerVertex, false);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions) || positions.length < 2) {\r\n throw new DeveloperError(\"At least two positions are required.\");\r\n }\r\n if (\r\n defined(colors) &&\r\n ((colorsPerVertex && colors.length < positions.length) ||\r\n (!colorsPerVertex && colors.length < positions.length - 1))\r\n ) {\r\n throw new DeveloperError(\"colors has an invalid length.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._positions = positions;\r\n this._colors = colors;\r\n this._colorsPerVertex = colorsPerVertex;\r\n\r\n this._arcType = defaultValue(options.arcType, ArcType.GEODESIC);\r\n this._granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n this._workerName = \"createSimplePolylineGeometry\";\r\n\r\n var numComponents = 1 + positions.length * Cartesian3.packedLength;\r\n numComponents += defined(colors) ? 1 + colors.length * Color.packedLength : 1;\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength = numComponents + Ellipsoid.packedLength + 3;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {SimplePolylineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nSimplePolylineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var positions = value._positions;\r\n var length = positions.length;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n\r\n var colors = value._colors;\r\n length = defined(colors) ? colors.length : 0.0;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Color.packedLength) {\r\n Color.pack(colors[i], array, startingIndex);\r\n }\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n array[startingIndex++] = value._colorsPerVertex ? 1.0 : 0.0;\r\n array[startingIndex++] = value._arcType;\r\n array[startingIndex] = value._granularity;\r\n\r\n return array;\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {SimplePolylineGeometry} [result] The object into which to store the result.\r\n * @returns {SimplePolylineGeometry} The modified result parameter or a new SimplePolylineGeometry instance if one was not provided.\r\n */\r\nSimplePolylineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var length = array[startingIndex++];\r\n var positions = new Array(length);\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n length = array[startingIndex++];\r\n var colors = length > 0 ? new Array(length) : undefined;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Color.packedLength) {\r\n colors[i] = Color.unpack(array, startingIndex);\r\n }\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var colorsPerVertex = array[startingIndex++] === 1.0;\r\n var arcType = array[startingIndex++];\r\n var granularity = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n return new SimplePolylineGeometry({\r\n positions: positions,\r\n colors: colors,\r\n ellipsoid: ellipsoid,\r\n colorsPerVertex: colorsPerVertex,\r\n arcType: arcType,\r\n granularity: granularity,\r\n });\r\n }\r\n\r\n result._positions = positions;\r\n result._colors = colors;\r\n result._ellipsoid = ellipsoid;\r\n result._colorsPerVertex = colorsPerVertex;\r\n result._arcType = arcType;\r\n result._granularity = granularity;\r\n\r\n return result;\r\n};\r\n\r\nvar scratchArray1 = new Array(2);\r\nvar scratchArray2 = new Array(2);\r\nvar generateArcOptionsScratch = {\r\n positions: scratchArray1,\r\n height: scratchArray2,\r\n ellipsoid: undefined,\r\n minDistance: undefined,\r\n granularity: undefined,\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a simple polyline, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {SimplePolylineGeometry} simplePolylineGeometry A description of the polyline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nSimplePolylineGeometry.createGeometry = function (simplePolylineGeometry) {\r\n var positions = simplePolylineGeometry._positions;\r\n var colors = simplePolylineGeometry._colors;\r\n var colorsPerVertex = simplePolylineGeometry._colorsPerVertex;\r\n var arcType = simplePolylineGeometry._arcType;\r\n var granularity = simplePolylineGeometry._granularity;\r\n var ellipsoid = simplePolylineGeometry._ellipsoid;\r\n\r\n var minDistance = CesiumMath.chordLength(\r\n granularity,\r\n ellipsoid.maximumRadius\r\n );\r\n var perSegmentColors = defined(colors) && !colorsPerVertex;\r\n\r\n var i;\r\n var length = positions.length;\r\n\r\n var positionValues;\r\n var numberOfPositions;\r\n var colorValues;\r\n var color;\r\n var offset = 0;\r\n\r\n if (arcType === ArcType.GEODESIC || arcType === ArcType.RHUMB) {\r\n var subdivisionSize;\r\n var numberOfPointsFunction;\r\n var generateArcFunction;\r\n if (arcType === ArcType.GEODESIC) {\r\n subdivisionSize = CesiumMath.chordLength(\r\n granularity,\r\n ellipsoid.maximumRadius\r\n );\r\n numberOfPointsFunction = PolylinePipeline.numberOfPoints;\r\n generateArcFunction = PolylinePipeline.generateArc;\r\n } else {\r\n subdivisionSize = granularity;\r\n numberOfPointsFunction = PolylinePipeline.numberOfPointsRhumbLine;\r\n generateArcFunction = PolylinePipeline.generateRhumbArc;\r\n }\r\n\r\n var heights = PolylinePipeline.extractHeights(positions, ellipsoid);\r\n\r\n var generateArcOptions = generateArcOptionsScratch;\r\n if (arcType === ArcType.GEODESIC) {\r\n generateArcOptions.minDistance = minDistance;\r\n } else {\r\n generateArcOptions.granularity = granularity;\r\n }\r\n generateArcOptions.ellipsoid = ellipsoid;\r\n\r\n if (perSegmentColors) {\r\n var positionCount = 0;\r\n for (i = 0; i < length - 1; i++) {\r\n positionCount +=\r\n numberOfPointsFunction(\r\n positions[i],\r\n positions[i + 1],\r\n subdivisionSize\r\n ) + 1;\r\n }\r\n\r\n positionValues = new Float64Array(positionCount * 3);\r\n colorValues = new Uint8Array(positionCount * 4);\r\n\r\n generateArcOptions.positions = scratchArray1;\r\n generateArcOptions.height = scratchArray2;\r\n\r\n var ci = 0;\r\n for (i = 0; i < length - 1; ++i) {\r\n scratchArray1[0] = positions[i];\r\n scratchArray1[1] = positions[i + 1];\r\n\r\n scratchArray2[0] = heights[i];\r\n scratchArray2[1] = heights[i + 1];\r\n\r\n var pos = generateArcFunction(generateArcOptions);\r\n\r\n if (defined(colors)) {\r\n var segLen = pos.length / 3;\r\n color = colors[i];\r\n for (var k = 0; k < segLen; ++k) {\r\n colorValues[ci++] = Color.floatToByte(color.red);\r\n colorValues[ci++] = Color.floatToByte(color.green);\r\n colorValues[ci++] = Color.floatToByte(color.blue);\r\n colorValues[ci++] = Color.floatToByte(color.alpha);\r\n }\r\n }\r\n\r\n positionValues.set(pos, offset);\r\n offset += pos.length;\r\n }\r\n } else {\r\n generateArcOptions.positions = positions;\r\n generateArcOptions.height = heights;\r\n positionValues = new Float64Array(\r\n generateArcFunction(generateArcOptions)\r\n );\r\n\r\n if (defined(colors)) {\r\n colorValues = new Uint8Array((positionValues.length / 3) * 4);\r\n\r\n for (i = 0; i < length - 1; ++i) {\r\n var p0 = positions[i];\r\n var p1 = positions[i + 1];\r\n var c0 = colors[i];\r\n var c1 = colors[i + 1];\r\n offset = interpolateColors(\r\n p0,\r\n p1,\r\n c0,\r\n c1,\r\n minDistance,\r\n colorValues,\r\n offset\r\n );\r\n }\r\n\r\n var lastColor = colors[length - 1];\r\n colorValues[offset++] = Color.floatToByte(lastColor.red);\r\n colorValues[offset++] = Color.floatToByte(lastColor.green);\r\n colorValues[offset++] = Color.floatToByte(lastColor.blue);\r\n colorValues[offset++] = Color.floatToByte(lastColor.alpha);\r\n }\r\n }\r\n } else {\r\n numberOfPositions = perSegmentColors ? length * 2 - 2 : length;\r\n positionValues = new Float64Array(numberOfPositions * 3);\r\n colorValues = defined(colors)\r\n ? new Uint8Array(numberOfPositions * 4)\r\n : undefined;\r\n\r\n var positionIndex = 0;\r\n var colorIndex = 0;\r\n\r\n for (i = 0; i < length; ++i) {\r\n var p = positions[i];\r\n\r\n if (perSegmentColors && i > 0) {\r\n Cartesian3.pack(p, positionValues, positionIndex);\r\n positionIndex += 3;\r\n\r\n color = colors[i - 1];\r\n colorValues[colorIndex++] = Color.floatToByte(color.red);\r\n colorValues[colorIndex++] = Color.floatToByte(color.green);\r\n colorValues[colorIndex++] = Color.floatToByte(color.blue);\r\n colorValues[colorIndex++] = Color.floatToByte(color.alpha);\r\n }\r\n\r\n if (perSegmentColors && i === length - 1) {\r\n break;\r\n }\r\n\r\n Cartesian3.pack(p, positionValues, positionIndex);\r\n positionIndex += 3;\r\n\r\n if (defined(colors)) {\r\n color = colors[i];\r\n colorValues[colorIndex++] = Color.floatToByte(color.red);\r\n colorValues[colorIndex++] = Color.floatToByte(color.green);\r\n colorValues[colorIndex++] = Color.floatToByte(color.blue);\r\n colorValues[colorIndex++] = Color.floatToByte(color.alpha);\r\n }\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positionValues,\r\n });\r\n\r\n if (defined(colors)) {\r\n attributes.color = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 4,\r\n values: colorValues,\r\n normalize: true,\r\n });\r\n }\r\n\r\n numberOfPositions = positionValues.length / 3;\r\n var numberOfIndices = (numberOfPositions - 1) * 2;\r\n var indices = IndexDatatype.createTypedArray(\r\n numberOfPositions,\r\n numberOfIndices\r\n );\r\n\r\n var index = 0;\r\n for (i = 0; i < numberOfPositions - 1; ++i) {\r\n indices[index++] = i;\r\n indices[index++] = i + 1;\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: BoundingSphere.fromPoints(positions),\r\n });\r\n};\r\nexport default SimplePolylineGeometry;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport EllipsoidGeometry from \"./EllipsoidGeometry.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\n\r\n/**\r\n * A description of a sphere centered at the origin.\r\n *\r\n * @alias SphereGeometry\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Number} [options.radius=1.0] The radius of the sphere.\r\n * @param {Number} [options.stackPartitions=64] The number of times to partition the ellipsoid into stacks.\r\n * @param {Number} [options.slicePartitions=64] The number of times to partition the ellipsoid into radial slices.\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n *\r\n * @exception {DeveloperError} options.slicePartitions cannot be less than three.\r\n * @exception {DeveloperError} options.stackPartitions cannot be less than three.\r\n *\r\n * @see SphereGeometry#createGeometry\r\n *\r\n * @example\r\n * var sphere = new Cesium.SphereGeometry({\r\n * radius : 100.0,\r\n * vertexFormat : Cesium.VertexFormat.POSITION_ONLY\r\n * });\r\n * var geometry = Cesium.SphereGeometry.createGeometry(sphere);\r\n */\r\nfunction SphereGeometry(options) {\r\n var radius = defaultValue(options.radius, 1.0);\r\n var radii = new Cartesian3(radius, radius, radius);\r\n var ellipsoidOptions = {\r\n radii: radii,\r\n stackPartitions: options.stackPartitions,\r\n slicePartitions: options.slicePartitions,\r\n vertexFormat: options.vertexFormat,\r\n };\r\n\r\n this._ellipsoidGeometry = new EllipsoidGeometry(ellipsoidOptions);\r\n this._workerName = \"createSphereGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nSphereGeometry.packedLength = EllipsoidGeometry.packedLength;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {SphereGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nSphereGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n //>>includeEnd('debug');\r\n\r\n return EllipsoidGeometry.pack(value._ellipsoidGeometry, array, startingIndex);\r\n};\r\n\r\nvar scratchEllipsoidGeometry = new EllipsoidGeometry();\r\nvar scratchOptions = {\r\n radius: undefined,\r\n radii: new Cartesian3(),\r\n vertexFormat: new VertexFormat(),\r\n stackPartitions: undefined,\r\n slicePartitions: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {SphereGeometry} [result] The object into which to store the result.\r\n * @returns {SphereGeometry} The modified result parameter or a new SphereGeometry instance if one was not provided.\r\n */\r\nSphereGeometry.unpack = function (array, startingIndex, result) {\r\n var ellipsoidGeometry = EllipsoidGeometry.unpack(\r\n array,\r\n startingIndex,\r\n scratchEllipsoidGeometry\r\n );\r\n scratchOptions.vertexFormat = VertexFormat.clone(\r\n ellipsoidGeometry._vertexFormat,\r\n scratchOptions.vertexFormat\r\n );\r\n scratchOptions.stackPartitions = ellipsoidGeometry._stackPartitions;\r\n scratchOptions.slicePartitions = ellipsoidGeometry._slicePartitions;\r\n\r\n if (!defined(result)) {\r\n scratchOptions.radius = ellipsoidGeometry._radii.x;\r\n return new SphereGeometry(scratchOptions);\r\n }\r\n\r\n Cartesian3.clone(ellipsoidGeometry._radii, scratchOptions.radii);\r\n result._ellipsoidGeometry = new EllipsoidGeometry(scratchOptions);\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a sphere, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {SphereGeometry} sphereGeometry A description of the sphere.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nSphereGeometry.createGeometry = function (sphereGeometry) {\r\n return EllipsoidGeometry.createGeometry(sphereGeometry._ellipsoidGeometry);\r\n};\r\nexport default SphereGeometry;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport EllipsoidOutlineGeometry from \"./EllipsoidOutlineGeometry.js\";\r\n\r\n/**\r\n * A description of the outline of a sphere.\r\n *\r\n * @alias SphereOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Number} [options.radius=1.0] The radius of the sphere.\r\n * @param {Number} [options.stackPartitions=10] The count of stacks for the sphere (1 greater than the number of parallel lines).\r\n * @param {Number} [options.slicePartitions=8] The count of slices for the sphere (Equal to the number of radial lines).\r\n * @param {Number} [options.subdivisions=200] The number of points per line, determining the granularity of the curvature .\r\n *\r\n * @exception {DeveloperError} options.stackPartitions must be greater than or equal to one.\r\n * @exception {DeveloperError} options.slicePartitions must be greater than or equal to zero.\r\n * @exception {DeveloperError} options.subdivisions must be greater than or equal to zero.\r\n *\r\n * @example\r\n * var sphere = new Cesium.SphereOutlineGeometry({\r\n * radius : 100.0,\r\n * stackPartitions : 6,\r\n * slicePartitions: 5\r\n * });\r\n * var geometry = Cesium.SphereOutlineGeometry.createGeometry(sphere);\r\n */\r\nfunction SphereOutlineGeometry(options) {\r\n var radius = defaultValue(options.radius, 1.0);\r\n var radii = new Cartesian3(radius, radius, radius);\r\n var ellipsoidOptions = {\r\n radii: radii,\r\n stackPartitions: options.stackPartitions,\r\n slicePartitions: options.slicePartitions,\r\n subdivisions: options.subdivisions,\r\n };\r\n\r\n this._ellipsoidGeometry = new EllipsoidOutlineGeometry(ellipsoidOptions);\r\n this._workerName = \"createSphereOutlineGeometry\";\r\n}\r\n\r\n/**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\nSphereOutlineGeometry.packedLength = EllipsoidOutlineGeometry.packedLength;\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {SphereOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nSphereOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n //>>includeEnd('debug');\r\n\r\n return EllipsoidOutlineGeometry.pack(\r\n value._ellipsoidGeometry,\r\n array,\r\n startingIndex\r\n );\r\n};\r\n\r\nvar scratchEllipsoidGeometry = new EllipsoidOutlineGeometry();\r\nvar scratchOptions = {\r\n radius: undefined,\r\n radii: new Cartesian3(),\r\n stackPartitions: undefined,\r\n slicePartitions: undefined,\r\n subdivisions: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {SphereOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {SphereOutlineGeometry} The modified result parameter or a new SphereOutlineGeometry instance if one was not provided.\r\n */\r\nSphereOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n var ellipsoidGeometry = EllipsoidOutlineGeometry.unpack(\r\n array,\r\n startingIndex,\r\n scratchEllipsoidGeometry\r\n );\r\n scratchOptions.stackPartitions = ellipsoidGeometry._stackPartitions;\r\n scratchOptions.slicePartitions = ellipsoidGeometry._slicePartitions;\r\n scratchOptions.subdivisions = ellipsoidGeometry._subdivisions;\r\n\r\n if (!defined(result)) {\r\n scratchOptions.radius = ellipsoidGeometry._radii.x;\r\n return new SphereOutlineGeometry(scratchOptions);\r\n }\r\n\r\n Cartesian3.clone(ellipsoidGeometry._radii, scratchOptions.radii);\r\n result._ellipsoidGeometry = new EllipsoidOutlineGeometry(scratchOptions);\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of an outline of a sphere, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {SphereOutlineGeometry} sphereGeometry A description of the sphere outline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nSphereOutlineGeometry.createGeometry = function (sphereGeometry) {\r\n return EllipsoidOutlineGeometry.createGeometry(\r\n sphereGeometry._ellipsoidGeometry\r\n );\r\n};\r\nexport default SphereOutlineGeometry;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\n\r\n/**\r\n * A set of curvilinear 3-dimensional coordinates.\r\n *\r\n * @alias Spherical\r\n * @constructor\r\n *\r\n * @param {Number} [clock=0.0] The angular coordinate lying in the xy-plane measured from the positive x-axis and toward the positive y-axis.\r\n * @param {Number} [cone=0.0] The angular coordinate measured from the positive z-axis and toward the negative z-axis.\r\n * @param {Number} [magnitude=1.0] The linear coordinate measured from the origin.\r\n */\r\nfunction Spherical(clock, cone, magnitude) {\r\n /**\r\n * The clock component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.clock = defaultValue(clock, 0.0);\r\n /**\r\n * The cone component.\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.cone = defaultValue(cone, 0.0);\r\n /**\r\n * The magnitude component.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.magnitude = defaultValue(magnitude, 1.0);\r\n}\r\n\r\n/**\r\n * Converts the provided Cartesian3 into Spherical coordinates.\r\n *\r\n * @param {Cartesian3} cartesian3 The Cartesian3 to be converted to Spherical.\r\n * @param {Spherical} [result] The object in which the result will be stored, if undefined a new instance will be created.\r\n * @returns {Spherical} The modified result parameter, or a new instance if one was not provided.\r\n */\r\nSpherical.fromCartesian3 = function (cartesian3, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"cartesian3\", cartesian3);\r\n //>>includeEnd('debug');\r\n\r\n var x = cartesian3.x;\r\n var y = cartesian3.y;\r\n var z = cartesian3.z;\r\n var radialSquared = x * x + y * y;\r\n\r\n if (!defined(result)) {\r\n result = new Spherical();\r\n }\r\n\r\n result.clock = Math.atan2(y, x);\r\n result.cone = Math.atan2(Math.sqrt(radialSquared), z);\r\n result.magnitude = Math.sqrt(radialSquared + z * z);\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a duplicate of a Spherical.\r\n *\r\n * @param {Spherical} spherical The spherical to clone.\r\n * @param {Spherical} [result] The object to store the result into, if undefined a new instance will be created.\r\n * @returns {Spherical} The modified result parameter or a new instance if result was undefined. (Returns undefined if spherical is undefined)\r\n */\r\nSpherical.clone = function (spherical, result) {\r\n if (!defined(spherical)) {\r\n return undefined;\r\n }\r\n\r\n if (!defined(result)) {\r\n return new Spherical(spherical.clock, spherical.cone, spherical.magnitude);\r\n }\r\n\r\n result.clock = spherical.clock;\r\n result.cone = spherical.cone;\r\n result.magnitude = spherical.magnitude;\r\n return result;\r\n};\r\n\r\n/**\r\n * Computes the normalized version of the provided spherical.\r\n *\r\n * @param {Spherical} spherical The spherical to be normalized.\r\n * @param {Spherical} [result] The object to store the result into, if undefined a new instance will be created.\r\n * @returns {Spherical} The modified result parameter or a new instance if result was undefined.\r\n */\r\nSpherical.normalize = function (spherical, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"spherical\", spherical);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n return new Spherical(spherical.clock, spherical.cone, 1.0);\r\n }\r\n\r\n result.clock = spherical.clock;\r\n result.cone = spherical.cone;\r\n result.magnitude = 1.0;\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns true if the first spherical is equal to the second spherical, false otherwise.\r\n *\r\n * @param {Spherical} left The first Spherical to be compared.\r\n * @param {Spherical} right The second Spherical to be compared.\r\n * @returns {Boolean} true if the first spherical is equal to the second spherical, false otherwise.\r\n */\r\nSpherical.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left.clock === right.clock &&\r\n left.cone === right.cone &&\r\n left.magnitude === right.magnitude)\r\n );\r\n};\r\n\r\n/**\r\n * Returns true if the first spherical is within the provided epsilon of the second spherical, false otherwise.\r\n *\r\n * @param {Spherical} left The first Spherical to be compared.\r\n * @param {Spherical} right The second Spherical to be compared.\r\n * @param {Number} [epsilon=0.0] The epsilon to compare against.\r\n * @returns {Boolean} true if the first spherical is within the provided epsilon of the second spherical, false otherwise.\r\n */\r\nSpherical.equalsEpsilon = function (left, right, epsilon) {\r\n epsilon = defaultValue(epsilon, 0.0);\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n Math.abs(left.clock - right.clock) <= epsilon &&\r\n Math.abs(left.cone - right.cone) <= epsilon &&\r\n Math.abs(left.magnitude - right.magnitude) <= epsilon)\r\n );\r\n};\r\n\r\n/**\r\n * Returns true if this spherical is equal to the provided spherical, false otherwise.\r\n *\r\n * @param {Spherical} other The Spherical to be compared.\r\n * @returns {Boolean} true if this spherical is equal to the provided spherical, false otherwise.\r\n */\r\nSpherical.prototype.equals = function (other) {\r\n return Spherical.equals(this, other);\r\n};\r\n\r\n/**\r\n * Creates a duplicate of this Spherical.\r\n *\r\n * @param {Spherical} [result] The object to store the result into, if undefined a new instance will be created.\r\n * @returns {Spherical} The modified result parameter or a new instance if result was undefined.\r\n */\r\nSpherical.prototype.clone = function (result) {\r\n return Spherical.clone(this, result);\r\n};\r\n\r\n/**\r\n * Returns true if this spherical is within the provided epsilon of the provided spherical, false otherwise.\r\n *\r\n * @param {Spherical} other The Spherical to be compared.\r\n * @param {Number} epsilon The epsilon to compare against.\r\n * @returns {Boolean} true if this spherical is within the provided epsilon of the provided spherical, false otherwise.\r\n */\r\nSpherical.prototype.equalsEpsilon = function (other, epsilon) {\r\n return Spherical.equalsEpsilon(this, other, epsilon);\r\n};\r\n\r\n/**\r\n * Returns a string representing this instance in the format (clock, cone, magnitude).\r\n *\r\n * @returns {String} A string representing this instance.\r\n */\r\nSpherical.prototype.toString = function () {\r\n return \"(\" + this.clock + \", \" + this.cone + \", \" + this.magnitude + \")\";\r\n};\r\nexport default Spherical;\r\n","import defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Subdivides an array into a number of smaller, equal sized arrays.\r\n *\r\n * @function subdivideArray\r\n *\r\n * @param {Array} array The array to divide.\r\n * @param {Number} numberOfArrays The number of arrays to divide the provided array into.\r\n *\r\n * @exception {DeveloperError} numberOfArrays must be greater than 0.\r\n */\r\nfunction subdivideArray(array, numberOfArrays) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required.\");\r\n }\r\n\r\n if (!defined(numberOfArrays) || numberOfArrays < 1) {\r\n throw new DeveloperError(\"numberOfArrays must be greater than 0.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var result = [];\r\n var len = array.length;\r\n var i = 0;\r\n while (i < len) {\r\n var size = Math.ceil((len - i) / numberOfArrays--);\r\n result.push(array.slice(i, i + size));\r\n i += size;\r\n }\r\n return result;\r\n}\r\nexport default subdivideArray;\r\n","/**\r\n * @private\r\n */\r\nvar TileEdge = {\r\n WEST: 0,\r\n NORTH: 1,\r\n EAST: 2,\r\n SOUTH: 3,\r\n NORTHWEST: 4,\r\n NORTHEAST: 5,\r\n SOUTHWEST: 6,\r\n SOUTHEAST: 7,\r\n};\r\nexport default TileEdge;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * A tiling scheme for geometry or imagery on the surface of an ellipsoid. At level-of-detail zero,\r\n * the coarsest, least-detailed level, the number of tiles is configurable.\r\n * At level of detail one, each of the level zero tiles has four children, two in each direction.\r\n * At level of detail two, each of the level one tiles has four children, two in each direction.\r\n * This continues for as many levels as are present in the geometry or imagery source.\r\n *\r\n * @alias TilingScheme\r\n * @constructor\r\n *\r\n * @see WebMercatorTilingScheme\r\n * @see GeographicTilingScheme\r\n */\r\nfunction TilingScheme(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\r\n \"This type should not be instantiated directly. Instead, use WebMercatorTilingScheme or GeographicTilingScheme.\"\r\n );\r\n //>>includeEnd('debug');\r\n}\r\n\r\nObject.defineProperties(TilingScheme.prototype, {\r\n /**\r\n * Gets the ellipsoid that is tiled by the tiling scheme.\r\n * @memberof TilingScheme.prototype\r\n * @type {Ellipsoid}\r\n */\r\n ellipsoid: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets the rectangle, in radians, covered by this tiling scheme.\r\n * @memberof TilingScheme.prototype\r\n * @type {Rectangle}\r\n */\r\n rectangle: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets the map projection used by the tiling scheme.\r\n * @memberof TilingScheme.prototype\r\n * @type {MapProjection}\r\n */\r\n projection: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n});\r\n\r\n/**\r\n * Gets the total number of tiles in the X direction at a specified level-of-detail.\r\n * @function\r\n *\r\n * @param {Number} level The level-of-detail.\r\n * @returns {Number} The number of tiles in the X direction at the given level.\r\n */\r\nTilingScheme.prototype.getNumberOfXTilesAtLevel =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Gets the total number of tiles in the Y direction at a specified level-of-detail.\r\n * @function\r\n *\r\n * @param {Number} level The level-of-detail.\r\n * @returns {Number} The number of tiles in the Y direction at the given level.\r\n */\r\nTilingScheme.prototype.getNumberOfYTilesAtLevel =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Transforms a rectangle specified in geodetic radians to the native coordinate system\r\n * of this tiling scheme.\r\n * @function\r\n *\r\n * @param {Rectangle} rectangle The rectangle to transform.\r\n * @param {Rectangle} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the native rectangle if 'result'\r\n * is undefined.\r\n */\r\nTilingScheme.prototype.rectangleToNativeRectangle =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Converts tile x, y coordinates and level to a rectangle expressed in the native coordinates\r\n * of the tiling scheme.\r\n * @function\r\n *\r\n * @param {Number} x The integer x coordinate of the tile.\r\n * @param {Number} y The integer y coordinate of the tile.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Object} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the rectangle\r\n * if 'result' is undefined.\r\n */\r\nTilingScheme.prototype.tileXYToNativeRectangle =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Converts tile x, y coordinates and level to a cartographic rectangle in radians.\r\n * @function\r\n *\r\n * @param {Number} x The integer x coordinate of the tile.\r\n * @param {Number} y The integer y coordinate of the tile.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Object} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Rectangle} The specified 'result', or a new object containing the rectangle\r\n * if 'result' is undefined.\r\n */\r\nTilingScheme.prototype.tileXYToRectangle =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Calculates the tile x, y coordinates of the tile containing\r\n * a given cartographic position.\r\n * @function\r\n *\r\n * @param {Cartographic} position The position.\r\n * @param {Number} level The tile level-of-detail. Zero is the least detailed.\r\n * @param {Cartesian2} [result] The instance to which to copy the result, or undefined if a new instance\r\n * should be created.\r\n * @returns {Cartesian2} The specified 'result', or a new object containing the tile x, y coordinates\r\n * if 'result' is undefined.\r\n */\r\nTilingScheme.prototype.positionToTileXY =\r\n DeveloperError.throwInstantiationError;\r\nexport default TilingScheme;\r\n","import binarySearch from \"./binarySearch.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Event from \"./Event.js\";\r\nimport GregorianDate from \"./GregorianDate.js\";\r\nimport isLeapYear from \"./isLeapYear.js\";\r\nimport Iso8601 from \"./Iso8601.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\nimport TimeInterval from \"./TimeInterval.js\";\r\n\r\nfunction compareIntervalStartTimes(left, right) {\r\n return JulianDate.compare(left.start, right.start);\r\n}\r\n\r\n/**\r\n * A non-overlapping collection of {@link TimeInterval} instances sorted by start time.\r\n * @alias TimeIntervalCollection\r\n * @constructor\r\n *\r\n * @param {TimeInterval[]} [intervals] An array of intervals to add to the collection.\r\n */\r\nfunction TimeIntervalCollection(intervals) {\r\n this._intervals = [];\r\n this._changedEvent = new Event();\r\n\r\n if (defined(intervals)) {\r\n var length = intervals.length;\r\n for (var i = 0; i < length; i++) {\r\n this.addInterval(intervals[i]);\r\n }\r\n }\r\n}\r\n\r\nObject.defineProperties(TimeIntervalCollection.prototype, {\r\n /**\r\n * Gets an event that is raised whenever the collection of intervals change.\r\n * @memberof TimeIntervalCollection.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n changedEvent: {\r\n get: function () {\r\n return this._changedEvent;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the start time of the collection.\r\n * @memberof TimeIntervalCollection.prototype\r\n * @type {JulianDate}\r\n * @readonly\r\n */\r\n start: {\r\n get: function () {\r\n var intervals = this._intervals;\r\n return intervals.length === 0 ? undefined : intervals[0].start;\r\n },\r\n },\r\n\r\n /**\r\n * Gets whether or not the start time is included in the collection.\r\n * @memberof TimeIntervalCollection.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isStartIncluded: {\r\n get: function () {\r\n var intervals = this._intervals;\r\n return intervals.length === 0 ? false : intervals[0].isStartIncluded;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the stop time of the collection.\r\n * @memberof TimeIntervalCollection.prototype\r\n * @type {JulianDate}\r\n * @readonly\r\n */\r\n stop: {\r\n get: function () {\r\n var intervals = this._intervals;\r\n var length = intervals.length;\r\n return length === 0 ? undefined : intervals[length - 1].stop;\r\n },\r\n },\r\n\r\n /**\r\n * Gets whether or not the stop time is included in the collection.\r\n * @memberof TimeIntervalCollection.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isStopIncluded: {\r\n get: function () {\r\n var intervals = this._intervals;\r\n var length = intervals.length;\r\n return length === 0 ? false : intervals[length - 1].isStopIncluded;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the number of intervals in the collection.\r\n * @memberof TimeIntervalCollection.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._intervals.length;\r\n },\r\n },\r\n\r\n /**\r\n * Gets whether or not the collection is empty.\r\n * @memberof TimeIntervalCollection.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isEmpty: {\r\n get: function () {\r\n return this._intervals.length === 0;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Compares this instance against the provided instance componentwise and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {TimeIntervalCollection} [right] The right hand side collection.\r\n * @param {TimeInterval.DataComparer} [dataComparer] A function which compares the data of the two intervals. If omitted, reference equality is used.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nTimeIntervalCollection.prototype.equals = function (right, dataComparer) {\r\n if (this === right) {\r\n return true;\r\n }\r\n if (!(right instanceof TimeIntervalCollection)) {\r\n return false;\r\n }\r\n var intervals = this._intervals;\r\n var rightIntervals = right._intervals;\r\n var length = intervals.length;\r\n if (length !== rightIntervals.length) {\r\n return false;\r\n }\r\n for (var i = 0; i < length; i++) {\r\n if (!TimeInterval.equals(intervals[i], rightIntervals[i], dataComparer)) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n/**\r\n * Gets the interval at the specified index.\r\n *\r\n * @param {Number} index The index of the interval to retrieve.\r\n * @returns {TimeInterval|undefined} The interval at the specified index, or undefined if no interval exists as that index.\r\n */\r\nTimeIntervalCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._intervals[index];\r\n};\r\n\r\n/**\r\n * Removes all intervals from the collection.\r\n */\r\nTimeIntervalCollection.prototype.removeAll = function () {\r\n if (this._intervals.length > 0) {\r\n this._intervals.length = 0;\r\n this._changedEvent.raiseEvent(this);\r\n }\r\n};\r\n\r\n/**\r\n * Finds and returns the interval that contains the specified date.\r\n *\r\n * @param {JulianDate} date The date to search for.\r\n * @returns {TimeInterval|undefined} The interval containing the specified date, undefined if no such interval exists.\r\n */\r\nTimeIntervalCollection.prototype.findIntervalContainingDate = function (date) {\r\n var index = this.indexOf(date);\r\n return index >= 0 ? this._intervals[index] : undefined;\r\n};\r\n\r\n/**\r\n * Finds and returns the data for the interval that contains the specified date.\r\n *\r\n * @param {JulianDate} date The date to search for.\r\n * @returns {Object} The data for the interval containing the specified date, or undefined if no such interval exists.\r\n */\r\nTimeIntervalCollection.prototype.findDataForIntervalContainingDate = function (\r\n date\r\n) {\r\n var index = this.indexOf(date);\r\n return index >= 0 ? this._intervals[index].data : undefined;\r\n};\r\n\r\n/**\r\n * Checks if the specified date is inside this collection.\r\n *\r\n * @param {JulianDate} julianDate The date to check.\r\n * @returns {Boolean} true if the collection contains the specified date, false otherwise.\r\n */\r\nTimeIntervalCollection.prototype.contains = function (julianDate) {\r\n return this.indexOf(julianDate) >= 0;\r\n};\r\n\r\nvar indexOfScratch = new TimeInterval();\r\n\r\n/**\r\n * Finds and returns the index of the interval in the collection that contains the specified date.\r\n *\r\n * @param {JulianDate} date The date to search for.\r\n * @returns {Number} The index of the interval that contains the specified date, if no such interval exists,\r\n * it returns a negative number which is the bitwise complement of the index of the next interval that\r\n * starts after the date, or if no interval starts after the specified date, the bitwise complement of\r\n * the length of the collection.\r\n */\r\nTimeIntervalCollection.prototype.indexOf = function (date) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(date)) {\r\n throw new DeveloperError(\"date is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var intervals = this._intervals;\r\n indexOfScratch.start = date;\r\n indexOfScratch.stop = date;\r\n var index = binarySearch(\r\n intervals,\r\n indexOfScratch,\r\n compareIntervalStartTimes\r\n );\r\n if (index >= 0) {\r\n if (intervals[index].isStartIncluded) {\r\n return index;\r\n }\r\n\r\n if (\r\n index > 0 &&\r\n intervals[index - 1].stop.equals(date) &&\r\n intervals[index - 1].isStopIncluded\r\n ) {\r\n return index - 1;\r\n }\r\n return ~index;\r\n }\r\n\r\n index = ~index;\r\n if (\r\n index > 0 &&\r\n index - 1 < intervals.length &&\r\n TimeInterval.contains(intervals[index - 1], date)\r\n ) {\r\n return index - 1;\r\n }\r\n return ~index;\r\n};\r\n\r\n/**\r\n * Returns the first interval in the collection that matches the specified parameters.\r\n * All parameters are optional and undefined parameters are treated as a don't care condition.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {JulianDate} [options.start] The start time of the interval.\r\n * @param {JulianDate} [options.stop] The stop time of the interval.\r\n * @param {Boolean} [options.isStartIncluded] true if options.start is included in the interval, false otherwise.\r\n * @param {Boolean} [options.isStopIncluded] true if options.stop is included in the interval, false otherwise.\r\n * @returns {TimeInterval|undefined} The first interval in the collection that matches the specified parameters.\r\n */\r\nTimeIntervalCollection.prototype.findInterval = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var start = options.start;\r\n var stop = options.stop;\r\n var isStartIncluded = options.isStartIncluded;\r\n var isStopIncluded = options.isStopIncluded;\r\n\r\n var intervals = this._intervals;\r\n for (var i = 0, len = intervals.length; i < len; i++) {\r\n var interval = intervals[i];\r\n if (\r\n (!defined(start) || interval.start.equals(start)) &&\r\n (!defined(stop) || interval.stop.equals(stop)) &&\r\n (!defined(isStartIncluded) ||\r\n interval.isStartIncluded === isStartIncluded) &&\r\n (!defined(isStopIncluded) || interval.isStopIncluded === isStopIncluded)\r\n ) {\r\n return intervals[i];\r\n }\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Adds an interval to the collection, merging intervals that contain the same data and\r\n * splitting intervals of different data as needed in order to maintain a non-overlapping collection.\r\n * The data in the new interval takes precedence over any existing intervals in the collection.\r\n *\r\n * @param {TimeInterval} interval The interval to add.\r\n * @param {TimeInterval.DataComparer} [dataComparer] A function which compares the data of the two intervals. If omitted, reference equality is used.\r\n */\r\nTimeIntervalCollection.prototype.addInterval = function (\r\n interval,\r\n dataComparer\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(interval)) {\r\n throw new DeveloperError(\"interval is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (interval.isEmpty) {\r\n return;\r\n }\r\n\r\n var intervals = this._intervals;\r\n\r\n // Handle the common case quickly: we're adding a new interval which is after all existing intervals.\r\n if (\r\n intervals.length === 0 ||\r\n JulianDate.greaterThan(interval.start, intervals[intervals.length - 1].stop)\r\n ) {\r\n intervals.push(interval);\r\n this._changedEvent.raiseEvent(this);\r\n return;\r\n }\r\n\r\n // Keep the list sorted by the start date\r\n var index = binarySearch(intervals, interval, compareIntervalStartTimes);\r\n if (index < 0) {\r\n index = ~index;\r\n } else {\r\n // interval's start date exactly equals the start date of at least one interval in the collection.\r\n // It could actually equal the start date of two intervals if one of them does not actually\r\n // include the date. In that case, the binary search could have found either. We need to\r\n // look at the surrounding intervals and their IsStartIncluded properties in order to make sure\r\n // we're working with the correct interval.\r\n\r\n // eslint-disable-next-line no-lonely-if\r\n if (\r\n index > 0 &&\r\n interval.isStartIncluded &&\r\n intervals[index - 1].isStartIncluded &&\r\n intervals[index - 1].start.equals(interval.start)\r\n ) {\r\n --index;\r\n } else if (\r\n index < intervals.length &&\r\n !interval.isStartIncluded &&\r\n intervals[index].isStartIncluded &&\r\n intervals[index].start.equals(interval.start)\r\n ) {\r\n ++index;\r\n }\r\n }\r\n\r\n var comparison;\r\n if (index > 0) {\r\n // Not the first thing in the list, so see if the interval before this one\r\n // overlaps this one.\r\n\r\n comparison = JulianDate.compare(intervals[index - 1].stop, interval.start);\r\n if (\r\n comparison > 0 ||\r\n (comparison === 0 &&\r\n (intervals[index - 1].isStopIncluded || interval.isStartIncluded))\r\n ) {\r\n // There is an overlap\r\n if (\r\n defined(dataComparer)\r\n ? dataComparer(intervals[index - 1].data, interval.data)\r\n : intervals[index - 1].data === interval.data\r\n ) {\r\n // Overlapping intervals have the same data, so combine them\r\n if (JulianDate.greaterThan(interval.stop, intervals[index - 1].stop)) {\r\n interval = new TimeInterval({\r\n start: intervals[index - 1].start,\r\n stop: interval.stop,\r\n isStartIncluded: intervals[index - 1].isStartIncluded,\r\n isStopIncluded: interval.isStopIncluded,\r\n data: interval.data,\r\n });\r\n } else {\r\n interval = new TimeInterval({\r\n start: intervals[index - 1].start,\r\n stop: intervals[index - 1].stop,\r\n isStartIncluded: intervals[index - 1].isStartIncluded,\r\n isStopIncluded:\r\n intervals[index - 1].isStopIncluded ||\r\n (interval.stop.equals(intervals[index - 1].stop) &&\r\n interval.isStopIncluded),\r\n data: interval.data,\r\n });\r\n }\r\n intervals.splice(index - 1, 1);\r\n --index;\r\n } else {\r\n // Overlapping intervals have different data. The new interval\r\n // being added 'wins' so truncate the previous interval.\r\n // If the existing interval extends past the end of the new one,\r\n // split the existing interval into two intervals.\r\n comparison = JulianDate.compare(\r\n intervals[index - 1].stop,\r\n interval.stop\r\n );\r\n if (\r\n comparison > 0 ||\r\n (comparison === 0 &&\r\n intervals[index - 1].isStopIncluded &&\r\n !interval.isStopIncluded)\r\n ) {\r\n intervals.splice(\r\n index,\r\n 0,\r\n new TimeInterval({\r\n start: interval.stop,\r\n stop: intervals[index - 1].stop,\r\n isStartIncluded: !interval.isStopIncluded,\r\n isStopIncluded: intervals[index - 1].isStopIncluded,\r\n data: intervals[index - 1].data,\r\n })\r\n );\r\n }\r\n intervals[index - 1] = new TimeInterval({\r\n start: intervals[index - 1].start,\r\n stop: interval.start,\r\n isStartIncluded: intervals[index - 1].isStartIncluded,\r\n isStopIncluded: !interval.isStartIncluded,\r\n data: intervals[index - 1].data,\r\n });\r\n }\r\n }\r\n }\r\n\r\n while (index < intervals.length) {\r\n // Not the last thing in the list, so see if the intervals after this one overlap this one.\r\n comparison = JulianDate.compare(interval.stop, intervals[index].start);\r\n if (\r\n comparison > 0 ||\r\n (comparison === 0 &&\r\n (interval.isStopIncluded || intervals[index].isStartIncluded))\r\n ) {\r\n // There is an overlap\r\n if (\r\n defined(dataComparer)\r\n ? dataComparer(intervals[index].data, interval.data)\r\n : intervals[index].data === interval.data\r\n ) {\r\n // Overlapping intervals have the same data, so combine them\r\n interval = new TimeInterval({\r\n start: interval.start,\r\n stop: JulianDate.greaterThan(intervals[index].stop, interval.stop)\r\n ? intervals[index].stop\r\n : interval.stop,\r\n isStartIncluded: interval.isStartIncluded,\r\n isStopIncluded: JulianDate.greaterThan(\r\n intervals[index].stop,\r\n interval.stop\r\n )\r\n ? intervals[index].isStopIncluded\r\n : interval.isStopIncluded,\r\n data: interval.data,\r\n });\r\n intervals.splice(index, 1);\r\n } else {\r\n // Overlapping intervals have different data. The new interval\r\n // being added 'wins' so truncate the next interval.\r\n intervals[index] = new TimeInterval({\r\n start: interval.stop,\r\n stop: intervals[index].stop,\r\n isStartIncluded: !interval.isStopIncluded,\r\n isStopIncluded: intervals[index].isStopIncluded,\r\n data: intervals[index].data,\r\n });\r\n\r\n if (intervals[index].isEmpty) {\r\n intervals.splice(index, 1);\r\n } else {\r\n // Found a partial span, so it is not possible for the next\r\n // interval to be spanned at all. Stop looking.\r\n break;\r\n }\r\n }\r\n } else {\r\n // Found the last one we're spanning, so stop looking.\r\n break;\r\n }\r\n }\r\n\r\n // Add the new interval\r\n intervals.splice(index, 0, interval);\r\n this._changedEvent.raiseEvent(this);\r\n};\r\n\r\n/**\r\n * Removes the specified interval from this interval collection, creating a hole over the specified interval.\r\n * The data property of the input interval is ignored.\r\n *\r\n * @param {TimeInterval} interval The interval to remove.\r\n * @returns {Boolean} true if the interval was removed, false if no part of the interval was in the collection.\r\n */\r\nTimeIntervalCollection.prototype.removeInterval = function (interval) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(interval)) {\r\n throw new DeveloperError(\"interval is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (interval.isEmpty) {\r\n return false;\r\n }\r\n\r\n var intervals = this._intervals;\r\n\r\n var index = binarySearch(intervals, interval, compareIntervalStartTimes);\r\n if (index < 0) {\r\n index = ~index;\r\n }\r\n\r\n var result = false;\r\n\r\n // Check for truncation of the end of the previous interval.\r\n if (\r\n index > 0 &&\r\n (JulianDate.greaterThan(intervals[index - 1].stop, interval.start) ||\r\n (intervals[index - 1].stop.equals(interval.start) &&\r\n intervals[index - 1].isStopIncluded &&\r\n interval.isStartIncluded))\r\n ) {\r\n result = true;\r\n\r\n if (\r\n JulianDate.greaterThan(intervals[index - 1].stop, interval.stop) ||\r\n (intervals[index - 1].isStopIncluded &&\r\n !interval.isStopIncluded &&\r\n intervals[index - 1].stop.equals(interval.stop))\r\n ) {\r\n // Break the existing interval into two pieces\r\n intervals.splice(\r\n index,\r\n 0,\r\n new TimeInterval({\r\n start: interval.stop,\r\n stop: intervals[index - 1].stop,\r\n isStartIncluded: !interval.isStopIncluded,\r\n isStopIncluded: intervals[index - 1].isStopIncluded,\r\n data: intervals[index - 1].data,\r\n })\r\n );\r\n }\r\n intervals[index - 1] = new TimeInterval({\r\n start: intervals[index - 1].start,\r\n stop: interval.start,\r\n isStartIncluded: intervals[index - 1].isStartIncluded,\r\n isStopIncluded: !interval.isStartIncluded,\r\n data: intervals[index - 1].data,\r\n });\r\n }\r\n\r\n // Check if the Start of the current interval should remain because interval.start is the same but\r\n // it is not included.\r\n if (\r\n index < intervals.length &&\r\n !interval.isStartIncluded &&\r\n intervals[index].isStartIncluded &&\r\n interval.start.equals(intervals[index].start)\r\n ) {\r\n result = true;\r\n\r\n intervals.splice(\r\n index,\r\n 0,\r\n new TimeInterval({\r\n start: intervals[index].start,\r\n stop: intervals[index].start,\r\n isStartIncluded: true,\r\n isStopIncluded: true,\r\n data: intervals[index].data,\r\n })\r\n );\r\n ++index;\r\n }\r\n\r\n // Remove any intervals that are completely overlapped by the input interval.\r\n while (\r\n index < intervals.length &&\r\n JulianDate.greaterThan(interval.stop, intervals[index].stop)\r\n ) {\r\n result = true;\r\n intervals.splice(index, 1);\r\n }\r\n\r\n // Check for the case where the input interval ends on the same date\r\n // as an existing interval.\r\n if (index < intervals.length && interval.stop.equals(intervals[index].stop)) {\r\n result = true;\r\n\r\n if (!interval.isStopIncluded && intervals[index].isStopIncluded) {\r\n // Last point of interval should remain because the stop date is included in\r\n // the existing interval but is not included in the input interval.\r\n if (\r\n index + 1 < intervals.length &&\r\n intervals[index + 1].start.equals(interval.stop) &&\r\n intervals[index].data === intervals[index + 1].data\r\n ) {\r\n // Combine single point with the next interval\r\n intervals.splice(index, 1);\r\n intervals[index] = new TimeInterval({\r\n start: intervals[index].start,\r\n stop: intervals[index].stop,\r\n isStartIncluded: true,\r\n isStopIncluded: intervals[index].isStopIncluded,\r\n data: intervals[index].data,\r\n });\r\n } else {\r\n intervals[index] = new TimeInterval({\r\n start: interval.stop,\r\n stop: interval.stop,\r\n isStartIncluded: true,\r\n isStopIncluded: true,\r\n data: intervals[index].data,\r\n });\r\n }\r\n } else {\r\n // Interval is completely overlapped\r\n intervals.splice(index, 1);\r\n }\r\n }\r\n\r\n // Truncate any partially-overlapped intervals.\r\n if (\r\n index < intervals.length &&\r\n (JulianDate.greaterThan(interval.stop, intervals[index].start) ||\r\n (interval.stop.equals(intervals[index].start) &&\r\n interval.isStopIncluded &&\r\n intervals[index].isStartIncluded))\r\n ) {\r\n result = true;\r\n intervals[index] = new TimeInterval({\r\n start: interval.stop,\r\n stop: intervals[index].stop,\r\n isStartIncluded: !interval.isStopIncluded,\r\n isStopIncluded: intervals[index].isStopIncluded,\r\n data: intervals[index].data,\r\n });\r\n }\r\n\r\n if (result) {\r\n this._changedEvent.raiseEvent(this);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new instance that is the intersection of this collection and the provided collection.\r\n *\r\n * @param {TimeIntervalCollection} other The collection to intersect with.\r\n * @param {TimeInterval.DataComparer} [dataComparer] A function which compares the data of the two intervals. If omitted, reference equality is used.\r\n * @param {TimeInterval.MergeCallback} [mergeCallback] A function which merges the data of the two intervals. If omitted, the data from the left interval will be used.\r\n * @returns {TimeIntervalCollection} A new TimeIntervalCollection which is the intersection of this collection and the provided collection.\r\n */\r\nTimeIntervalCollection.prototype.intersect = function (\r\n other,\r\n dataComparer,\r\n mergeCallback\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(other)) {\r\n throw new DeveloperError(\"other is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var result = new TimeIntervalCollection();\r\n var left = 0;\r\n var right = 0;\r\n var intervals = this._intervals;\r\n var otherIntervals = other._intervals;\r\n\r\n while (left < intervals.length && right < otherIntervals.length) {\r\n var leftInterval = intervals[left];\r\n var rightInterval = otherIntervals[right];\r\n if (JulianDate.lessThan(leftInterval.stop, rightInterval.start)) {\r\n ++left;\r\n } else if (JulianDate.lessThan(rightInterval.stop, leftInterval.start)) {\r\n ++right;\r\n } else {\r\n // The following will return an intersection whose data is 'merged' if the callback is defined\r\n if (\r\n defined(mergeCallback) ||\r\n (defined(dataComparer) &&\r\n dataComparer(leftInterval.data, rightInterval.data)) ||\r\n (!defined(dataComparer) && rightInterval.data === leftInterval.data)\r\n ) {\r\n var intersection = TimeInterval.intersect(\r\n leftInterval,\r\n rightInterval,\r\n new TimeInterval(),\r\n mergeCallback\r\n );\r\n if (!intersection.isEmpty) {\r\n // Since we start with an empty collection for 'result', and there are no overlapping intervals in 'this' (as a rule),\r\n // the 'intersection' will never overlap with a previous interval in 'result'. So, no need to do any additional 'merging'.\r\n result.addInterval(intersection, dataComparer);\r\n }\r\n }\r\n\r\n if (\r\n JulianDate.lessThan(leftInterval.stop, rightInterval.stop) ||\r\n (leftInterval.stop.equals(rightInterval.stop) &&\r\n !leftInterval.isStopIncluded &&\r\n rightInterval.isStopIncluded)\r\n ) {\r\n ++left;\r\n } else {\r\n ++right;\r\n }\r\n }\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Creates a new instance from a JulianDate array.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {JulianDate[]} options.julianDates An array of ISO 8601 dates.\r\n * @param {Boolean} [options.isStartIncluded=true] true if start time is included in the interval, false otherwise.\r\n * @param {Boolean} [options.isStopIncluded=true] true if stop time is included in the interval, false otherwise.\r\n * @param {Boolean} [options.leadingInterval=false] true if you want to add a interval from Iso8601.MINIMUM_VALUE to start time, false otherwise.\r\n * @param {Boolean} [options.trailingInterval=false] true if you want to add a interval from stop time to Iso8601.MAXIMUM_VALUE, false otherwise.\r\n * @param {Function} [options.dataCallback] A function that will be return the data that is called with each interval before it is added to the collection. If unspecified, the data will be the index in the collection.\r\n * @param {TimeIntervalCollection} [result] An existing instance to use for the result.\r\n * @returns {TimeIntervalCollection} The modified result parameter or a new instance if none was provided.\r\n */\r\nTimeIntervalCollection.fromJulianDateArray = function (options, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options)) {\r\n throw new DeveloperError(\"options is required.\");\r\n }\r\n if (!defined(options.julianDates)) {\r\n throw new DeveloperError(\"options.iso8601Array is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new TimeIntervalCollection();\r\n }\r\n\r\n var julianDates = options.julianDates;\r\n var length = julianDates.length;\r\n var dataCallback = options.dataCallback;\r\n\r\n var isStartIncluded = defaultValue(options.isStartIncluded, true);\r\n var isStopIncluded = defaultValue(options.isStopIncluded, true);\r\n var leadingInterval = defaultValue(options.leadingInterval, false);\r\n var trailingInterval = defaultValue(options.trailingInterval, false);\r\n var interval;\r\n\r\n // Add a default interval, which will only end up being used up to first interval\r\n var startIndex = 0;\r\n if (leadingInterval) {\r\n ++startIndex;\r\n interval = new TimeInterval({\r\n start: Iso8601.MINIMUM_VALUE,\r\n stop: julianDates[0],\r\n isStartIncluded: true,\r\n isStopIncluded: !isStartIncluded,\r\n });\r\n interval.data = defined(dataCallback)\r\n ? dataCallback(interval, result.length)\r\n : result.length;\r\n result.addInterval(interval);\r\n }\r\n\r\n for (var i = 0; i < length - 1; ++i) {\r\n var startDate = julianDates[i];\r\n var endDate = julianDates[i + 1];\r\n\r\n interval = new TimeInterval({\r\n start: startDate,\r\n stop: endDate,\r\n isStartIncluded: result.length === startIndex ? isStartIncluded : true,\r\n isStopIncluded: i === length - 2 ? isStopIncluded : false,\r\n });\r\n interval.data = defined(dataCallback)\r\n ? dataCallback(interval, result.length)\r\n : result.length;\r\n result.addInterval(interval);\r\n\r\n startDate = endDate;\r\n }\r\n\r\n if (trailingInterval) {\r\n interval = new TimeInterval({\r\n start: julianDates[length - 1],\r\n stop: Iso8601.MAXIMUM_VALUE,\r\n isStartIncluded: !isStopIncluded,\r\n isStopIncluded: true,\r\n });\r\n interval.data = defined(dataCallback)\r\n ? dataCallback(interval, result.length)\r\n : result.length;\r\n result.addInterval(interval);\r\n }\r\n\r\n return result;\r\n};\r\n\r\nvar scratchGregorianDate = new GregorianDate();\r\nvar monthLengths = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];\r\n\r\n/**\r\n * Adds duration represented as a GregorianDate to a JulianDate\r\n *\r\n * @param {JulianDate} julianDate The date.\r\n * @param {GregorianDate} duration An duration represented as a GregorianDate.\r\n * @param {JulianDate} result An existing instance to use for the result.\r\n * @returns {JulianDate} The modified result parameter.\r\n *\r\n * @private\r\n */\r\nfunction addToDate(julianDate, duration, result) {\r\n if (!defined(result)) {\r\n result = new JulianDate();\r\n }\r\n JulianDate.toGregorianDate(julianDate, scratchGregorianDate);\r\n\r\n var millisecond = scratchGregorianDate.millisecond + duration.millisecond;\r\n var second = scratchGregorianDate.second + duration.second;\r\n var minute = scratchGregorianDate.minute + duration.minute;\r\n var hour = scratchGregorianDate.hour + duration.hour;\r\n var day = scratchGregorianDate.day + duration.day;\r\n var month = scratchGregorianDate.month + duration.month;\r\n var year = scratchGregorianDate.year + duration.year;\r\n\r\n if (millisecond >= 1000) {\r\n second += Math.floor(millisecond / 1000);\r\n millisecond = millisecond % 1000;\r\n }\r\n\r\n if (second >= 60) {\r\n minute += Math.floor(second / 60);\r\n second = second % 60;\r\n }\r\n\r\n if (minute >= 60) {\r\n hour += Math.floor(minute / 60);\r\n minute = minute % 60;\r\n }\r\n\r\n if (hour >= 24) {\r\n day += Math.floor(hour / 24);\r\n hour = hour % 24;\r\n }\r\n\r\n // If days is greater than the month's length we need to remove those number of days,\r\n // readjust month and year and repeat until days is less than the month's length.\r\n monthLengths[2] = isLeapYear(year) ? 29 : 28;\r\n while (day > monthLengths[month] || month >= 13) {\r\n if (day > monthLengths[month]) {\r\n day -= monthLengths[month];\r\n ++month;\r\n }\r\n\r\n if (month >= 13) {\r\n --month;\r\n year += Math.floor(month / 12);\r\n month = month % 12;\r\n ++month;\r\n }\r\n\r\n monthLengths[2] = isLeapYear(year) ? 29 : 28;\r\n }\r\n\r\n scratchGregorianDate.millisecond = millisecond;\r\n scratchGregorianDate.second = second;\r\n scratchGregorianDate.minute = minute;\r\n scratchGregorianDate.hour = hour;\r\n scratchGregorianDate.day = day;\r\n scratchGregorianDate.month = month;\r\n scratchGregorianDate.year = year;\r\n\r\n return JulianDate.fromGregorianDate(scratchGregorianDate, result);\r\n}\r\n\r\nvar scratchJulianDate = new JulianDate();\r\nvar durationRegex = /P(?:([\\d.,]+)Y)?(?:([\\d.,]+)M)?(?:([\\d.,]+)W)?(?:([\\d.,]+)D)?(?:T(?:([\\d.,]+)H)?(?:([\\d.,]+)M)?(?:([\\d.,]+)S)?)?/;\r\n\r\n/**\r\n * Parses ISO8601 duration string\r\n *\r\n * @param {String} iso8601 An ISO 8601 duration.\r\n * @param {GregorianDate} result An existing instance to use for the result.\r\n * @returns {Boolean} True is parsing succeeded, false otherwise\r\n *\r\n * @private\r\n */\r\nfunction parseDuration(iso8601, result) {\r\n if (!defined(iso8601) || iso8601.length === 0) {\r\n return false;\r\n }\r\n\r\n // Reset object\r\n result.year = 0;\r\n result.month = 0;\r\n result.day = 0;\r\n result.hour = 0;\r\n result.minute = 0;\r\n result.second = 0;\r\n result.millisecond = 0;\r\n\r\n if (iso8601[0] === \"P\") {\r\n var matches = iso8601.match(durationRegex);\r\n if (!defined(matches)) {\r\n return false;\r\n }\r\n if (defined(matches[1])) {\r\n // Years\r\n result.year = Number(matches[1].replace(\",\", \".\"));\r\n }\r\n if (defined(matches[2])) {\r\n // Months\r\n result.month = Number(matches[2].replace(\",\", \".\"));\r\n }\r\n if (defined(matches[3])) {\r\n // Weeks\r\n result.day = Number(matches[3].replace(\",\", \".\")) * 7;\r\n }\r\n if (defined(matches[4])) {\r\n // Days\r\n result.day += Number(matches[4].replace(\",\", \".\"));\r\n }\r\n if (defined(matches[5])) {\r\n // Hours\r\n result.hour = Number(matches[5].replace(\",\", \".\"));\r\n }\r\n if (defined(matches[6])) {\r\n // Weeks\r\n result.minute = Number(matches[6].replace(\",\", \".\"));\r\n }\r\n if (defined(matches[7])) {\r\n // Seconds\r\n var seconds = Number(matches[7].replace(\",\", \".\"));\r\n result.second = Math.floor(seconds);\r\n result.millisecond = (seconds % 1) * 1000;\r\n }\r\n } else {\r\n // They can technically specify the duration as a normal date with some caveats. Try our best to load it.\r\n if (iso8601[iso8601.length - 1] !== \"Z\") {\r\n // It's not a date, its a duration, so it always has to be UTC\r\n iso8601 += \"Z\";\r\n }\r\n JulianDate.toGregorianDate(\r\n JulianDate.fromIso8601(iso8601, scratchJulianDate),\r\n result\r\n );\r\n }\r\n\r\n // A duration of 0 will cause an infinite loop, so just make sure something is non-zero\r\n return (\r\n result.year ||\r\n result.month ||\r\n result.day ||\r\n result.hour ||\r\n result.minute ||\r\n result.second ||\r\n result.millisecond\r\n );\r\n}\r\n\r\nvar scratchDuration = new GregorianDate();\r\n/**\r\n * Creates a new instance from an {@link http://en.wikipedia.org/wiki/ISO_8601|ISO 8601} time interval (start/end/duration).\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {String} options.iso8601 An ISO 8601 interval.\r\n * @param {Boolean} [options.isStartIncluded=true] true if start time is included in the interval, false otherwise.\r\n * @param {Boolean} [options.isStopIncluded=true] true if stop time is included in the interval, false otherwise.\r\n * @param {Boolean} [options.leadingInterval=false] true if you want to add a interval from Iso8601.MINIMUM_VALUE to start time, false otherwise.\r\n * @param {Boolean} [options.trailingInterval=false] true if you want to add a interval from stop time to Iso8601.MAXIMUM_VALUE, false otherwise.\r\n * @param {Function} [options.dataCallback] A function that will be return the data that is called with each interval before it is added to the collection. If unspecified, the data will be the index in the collection.\r\n * @param {TimeIntervalCollection} [result] An existing instance to use for the result.\r\n * @returns {TimeIntervalCollection} The modified result parameter or a new instance if none was provided.\r\n */\r\nTimeIntervalCollection.fromIso8601 = function (options, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options)) {\r\n throw new DeveloperError(\"options is required.\");\r\n }\r\n if (!defined(options.iso8601)) {\r\n throw new DeveloperError(\"options.iso8601 is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var dates = options.iso8601.split(\"/\");\r\n var start = JulianDate.fromIso8601(dates[0]);\r\n var stop = JulianDate.fromIso8601(dates[1]);\r\n var julianDates = [];\r\n\r\n if (!parseDuration(dates[2], scratchDuration)) {\r\n julianDates.push(start, stop);\r\n } else {\r\n var date = JulianDate.clone(start);\r\n julianDates.push(date);\r\n while (JulianDate.compare(date, stop) < 0) {\r\n date = addToDate(date, scratchDuration);\r\n var afterStop = JulianDate.compare(stop, date) <= 0;\r\n if (afterStop) {\r\n JulianDate.clone(stop, date);\r\n }\r\n\r\n julianDates.push(date);\r\n }\r\n }\r\n\r\n return TimeIntervalCollection.fromJulianDateArray(\r\n {\r\n julianDates: julianDates,\r\n isStartIncluded: options.isStartIncluded,\r\n isStopIncluded: options.isStopIncluded,\r\n leadingInterval: options.leadingInterval,\r\n trailingInterval: options.trailingInterval,\r\n dataCallback: options.dataCallback,\r\n },\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Creates a new instance from a {@link http://en.wikipedia.org/wiki/ISO_8601|ISO 8601} date array.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {String[]} options.iso8601Dates An array of ISO 8601 dates.\r\n * @param {Boolean} [options.isStartIncluded=true] true if start time is included in the interval, false otherwise.\r\n * @param {Boolean} [options.isStopIncluded=true] true if stop time is included in the interval, false otherwise.\r\n * @param {Boolean} [options.leadingInterval=false] true if you want to add a interval from Iso8601.MINIMUM_VALUE to start time, false otherwise.\r\n * @param {Boolean} [options.trailingInterval=false] true if you want to add a interval from stop time to Iso8601.MAXIMUM_VALUE, false otherwise.\r\n * @param {Function} [options.dataCallback] A function that will be return the data that is called with each interval before it is added to the collection. If unspecified, the data will be the index in the collection.\r\n * @param {TimeIntervalCollection} [result] An existing instance to use for the result.\r\n * @returns {TimeIntervalCollection} The modified result parameter or a new instance if none was provided.\r\n */\r\nTimeIntervalCollection.fromIso8601DateArray = function (options, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options)) {\r\n throw new DeveloperError(\"options is required.\");\r\n }\r\n if (!defined(options.iso8601Dates)) {\r\n throw new DeveloperError(\"options.iso8601Dates is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return TimeIntervalCollection.fromJulianDateArray(\r\n {\r\n julianDates: options.iso8601Dates.map(function (date) {\r\n return JulianDate.fromIso8601(date);\r\n }),\r\n isStartIncluded: options.isStartIncluded,\r\n isStopIncluded: options.isStopIncluded,\r\n leadingInterval: options.leadingInterval,\r\n trailingInterval: options.trailingInterval,\r\n dataCallback: options.dataCallback,\r\n },\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Creates a new instance from a {@link http://en.wikipedia.org/wiki/ISO_8601|ISO 8601} duration array.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {JulianDate} options.epoch An date that the durations are relative to.\r\n * @param {String} options.iso8601Durations An array of ISO 8601 durations.\r\n * @param {Boolean} [options.relativeToPrevious=false] true if durations are relative to previous date, false if always relative to the epoch.\r\n * @param {Boolean} [options.isStartIncluded=true] true if start time is included in the interval, false otherwise.\r\n * @param {Boolean} [options.isStopIncluded=true] true if stop time is included in the interval, false otherwise.\r\n * @param {Boolean} [options.leadingInterval=false] true if you want to add a interval from Iso8601.MINIMUM_VALUE to start time, false otherwise.\r\n * @param {Boolean} [options.trailingInterval=false] true if you want to add a interval from stop time to Iso8601.MAXIMUM_VALUE, false otherwise.\r\n * @param {Function} [options.dataCallback] A function that will be return the data that is called with each interval before it is added to the collection. If unspecified, the data will be the index in the collection.\r\n * @param {TimeIntervalCollection} [result] An existing instance to use for the result.\r\n * @returns {TimeIntervalCollection} The modified result parameter or a new instance if none was provided.\r\n */\r\nTimeIntervalCollection.fromIso8601DurationArray = function (options, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options)) {\r\n throw new DeveloperError(\"options is required.\");\r\n }\r\n if (!defined(options.epoch)) {\r\n throw new DeveloperError(\"options.epoch is required.\");\r\n }\r\n if (!defined(options.iso8601Durations)) {\r\n throw new DeveloperError(\"options.iso8601Durations is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var epoch = options.epoch;\r\n var iso8601Durations = options.iso8601Durations;\r\n var relativeToPrevious = defaultValue(options.relativeToPrevious, false);\r\n var julianDates = [];\r\n var date, previousDate;\r\n\r\n var length = iso8601Durations.length;\r\n for (var i = 0; i < length; ++i) {\r\n // Allow a duration of 0 on the first iteration, because then it is just the epoch\r\n if (parseDuration(iso8601Durations[i], scratchDuration) || i === 0) {\r\n if (relativeToPrevious && defined(previousDate)) {\r\n date = addToDate(previousDate, scratchDuration);\r\n } else {\r\n date = addToDate(epoch, scratchDuration);\r\n }\r\n julianDates.push(date);\r\n previousDate = date;\r\n }\r\n }\r\n\r\n return TimeIntervalCollection.fromJulianDateArray(\r\n {\r\n julianDates: julianDates,\r\n isStartIncluded: options.isStartIncluded,\r\n isStopIncluded: options.isStopIncluded,\r\n leadingInterval: options.leadingInterval,\r\n trailingInterval: options.trailingInterval,\r\n dataCallback: options.dataCallback,\r\n },\r\n result\r\n );\r\n};\r\nexport default TimeIntervalCollection;\r\n","import Cartesian3 from \"./Cartesian3.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport Quaternion from \"./Quaternion.js\";\r\n\r\nvar defaultScale = new Cartesian3(1.0, 1.0, 1.0);\r\nvar defaultTranslation = Cartesian3.ZERO;\r\nvar defaultRotation = Quaternion.IDENTITY;\r\n\r\n/**\r\n * An affine transformation defined by a translation, rotation, and scale.\r\n * @alias TranslationRotationScale\r\n * @constructor\r\n *\r\n * @param {Cartesian3} [translation=Cartesian3.ZERO] A {@link Cartesian3} specifying the (x, y, z) translation to apply to the node.\r\n * @param {Quaternion} [rotation=Quaternion.IDENTITY] A {@link Quaternion} specifying the (x, y, z, w) rotation to apply to the node.\r\n * @param {Cartesian3} [scale=new Cartesian3(1.0, 1.0, 1.0)] A {@link Cartesian3} specifying the (x, y, z) scaling to apply to the node.\r\n */\r\nfunction TranslationRotationScale(translation, rotation, scale) {\r\n /**\r\n * Gets or sets the (x, y, z) translation to apply to the node.\r\n * @type {Cartesian3}\r\n * @default Cartesian3.ZERO\r\n */\r\n this.translation = Cartesian3.clone(\r\n defaultValue(translation, defaultTranslation)\r\n );\r\n\r\n /**\r\n * Gets or sets the (x, y, z, w) rotation to apply to the node.\r\n * @type {Quaternion}\r\n * @default Quaternion.IDENTITY\r\n */\r\n this.rotation = Quaternion.clone(defaultValue(rotation, defaultRotation));\r\n\r\n /**\r\n * Gets or sets the (x, y, z) scaling to apply to the node.\r\n * @type {Cartesian3}\r\n * @default new Cartesian3(1.0, 1.0, 1.0)\r\n */\r\n this.scale = Cartesian3.clone(defaultValue(scale, defaultScale));\r\n}\r\n\r\n/**\r\n * Compares this instance against the provided instance and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {TranslationRotationScale} [right] The right hand side TranslationRotationScale.\r\n * @returns {Boolean} true if they are equal, false otherwise.\r\n */\r\nTranslationRotationScale.prototype.equals = function (right) {\r\n return (\r\n this === right ||\r\n (defined(right) &&\r\n Cartesian3.equals(this.translation, right.translation) &&\r\n Quaternion.equals(this.rotation, right.rotation) &&\r\n Cartesian3.equals(this.scale, right.scale))\r\n );\r\n};\r\nexport default TranslationRotationScale;\r\n","import defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport destroyObject from \"./destroyObject.js\";\r\nimport Iso8601 from \"./Iso8601.js\";\r\nimport JulianDate from \"./JulianDate.js\";\r\n\r\n/**\r\n * Synchronizes a video element with a simulation clock.\r\n *\r\n * @alias VideoSynchronizer\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Clock} [options.clock] The clock instance used to drive the video.\r\n * @param {HTMLVideoElement} [options.element] The video element to be synchronized.\r\n * @param {JulianDate} [options.epoch=Iso8601.MINIMUM_VALUE] The simulation time that marks the start of the video.\r\n * @param {Number} [options.tolerance=1.0] The maximum amount of time, in seconds, that the clock and video can diverge.\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Video.html|Video Material Demo}\r\n */\r\nfunction VideoSynchronizer(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._clock = undefined;\r\n this._element = undefined;\r\n this._clockSubscription = undefined;\r\n this._seekFunction = undefined;\r\n this._lastPlaybackRate = undefined;\r\n\r\n this.clock = options.clock;\r\n this.element = options.element;\r\n\r\n /**\r\n * Gets or sets the simulation time that marks the start of the video.\r\n * @type {JulianDate}\r\n * @default Iso8601.MINIMUM_VALUE\r\n */\r\n this.epoch = defaultValue(options.epoch, Iso8601.MINIMUM_VALUE);\r\n\r\n /**\r\n * Gets or sets the amount of time in seconds the video's currentTime\r\n * and the clock's currentTime can diverge before a video seek is performed.\r\n * Lower values make the synchronization more accurate but video\r\n * performance might suffer. Higher values provide better performance\r\n * but at the cost of accuracy.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.tolerance = defaultValue(options.tolerance, 1.0);\r\n\r\n this._seeking = false;\r\n this._seekFunction = undefined;\r\n this._firstTickAfterSeek = false;\r\n}\r\n\r\nObject.defineProperties(VideoSynchronizer.prototype, {\r\n /**\r\n * Gets or sets the clock used to drive the video element.\r\n *\r\n * @memberof VideoSynchronizer.prototype\r\n * @type {Clock}\r\n */\r\n clock: {\r\n get: function () {\r\n return this._clock;\r\n },\r\n set: function (value) {\r\n var oldValue = this._clock;\r\n\r\n if (oldValue === value) {\r\n return;\r\n }\r\n\r\n if (defined(oldValue)) {\r\n this._clockSubscription();\r\n this._clockSubscription = undefined;\r\n }\r\n\r\n if (defined(value)) {\r\n this._clockSubscription = value.onTick.addEventListener(\r\n VideoSynchronizer.prototype._onTick,\r\n this\r\n );\r\n }\r\n\r\n this._clock = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets the video element to synchronize.\r\n *\r\n * @memberof VideoSynchronizer.prototype\r\n * @type {HTMLVideoElement}\r\n */\r\n element: {\r\n get: function () {\r\n return this._element;\r\n },\r\n set: function (value) {\r\n var oldValue = this._element;\r\n\r\n if (oldValue === value) {\r\n return;\r\n }\r\n\r\n if (defined(oldValue)) {\r\n oldValue.removeEventListener(\"seeked\", this._seekFunction, false);\r\n }\r\n\r\n if (defined(value)) {\r\n this._seeking = false;\r\n this._seekFunction = createSeekFunction(this);\r\n value.addEventListener(\"seeked\", this._seekFunction, false);\r\n }\r\n\r\n this._element = value;\r\n this._seeking = false;\r\n this._firstTickAfterSeek = false;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Destroys and resources used by the object. Once an object is destroyed, it should not be used.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nVideoSynchronizer.prototype.destroy = function () {\r\n this.element = undefined;\r\n this.clock = undefined;\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nVideoSynchronizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nVideoSynchronizer.prototype._trySetPlaybackRate = function (clock) {\r\n if (this._lastPlaybackRate === clock.multiplier) {\r\n return;\r\n }\r\n\r\n var element = this._element;\r\n try {\r\n element.playbackRate = clock.multiplier;\r\n } catch (error) {\r\n // Seek manually for unsupported playbackRates.\r\n element.playbackRate = 0.0;\r\n }\r\n this._lastPlaybackRate = clock.multiplier;\r\n};\r\n\r\nVideoSynchronizer.prototype._onTick = function (clock) {\r\n var element = this._element;\r\n if (!defined(element) || element.readyState < 2) {\r\n return;\r\n }\r\n\r\n var paused = element.paused;\r\n var shouldAnimate = clock.shouldAnimate;\r\n if (shouldAnimate === paused) {\r\n if (shouldAnimate) {\r\n element.play();\r\n } else {\r\n element.pause();\r\n }\r\n }\r\n\r\n //We need to avoid constant seeking or the video will\r\n //never contain a complete frame for us to render.\r\n //So don't do anything if we're seeing or on the first\r\n //tick after a seek (the latter of which allows the frame\r\n //to actually be rendered.\r\n if (this._seeking || this._firstTickAfterSeek) {\r\n this._firstTickAfterSeek = false;\r\n return;\r\n }\r\n\r\n this._trySetPlaybackRate(clock);\r\n\r\n var clockTime = clock.currentTime;\r\n var epoch = defaultValue(this.epoch, Iso8601.MINIMUM_VALUE);\r\n var videoTime = JulianDate.secondsDifference(clockTime, epoch);\r\n\r\n var duration = element.duration;\r\n var desiredTime;\r\n var currentTime = element.currentTime;\r\n if (element.loop) {\r\n videoTime = videoTime % duration;\r\n if (videoTime < 0.0) {\r\n videoTime = duration - videoTime;\r\n }\r\n desiredTime = videoTime;\r\n } else if (videoTime > duration) {\r\n desiredTime = duration;\r\n } else if (videoTime < 0.0) {\r\n desiredTime = 0.0;\r\n } else {\r\n desiredTime = videoTime;\r\n }\r\n\r\n //If the playing video's time and the scene's clock time\r\n //ever drift too far apart, we want to set the video to match\r\n var tolerance = shouldAnimate ? defaultValue(this.tolerance, 1.0) : 0.001;\r\n if (Math.abs(desiredTime - currentTime) > tolerance) {\r\n this._seeking = true;\r\n element.currentTime = desiredTime;\r\n }\r\n};\r\n\r\nfunction createSeekFunction(that) {\r\n return function () {\r\n that._seeking = false;\r\n that._firstTickAfterSeek = true;\r\n };\r\n}\r\nexport default VideoSynchronizer;\r\n","import when from \"../ThirdParty/when.js\";\r\nimport Credit from \"./Credit.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Event from \"./Event.js\";\r\nimport GeographicTilingScheme from \"./GeographicTilingScheme.js\";\r\nimport getImagePixels from \"./getImagePixels.js\";\r\nimport HeightmapTerrainData from \"./HeightmapTerrainData.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport Rectangle from \"./Rectangle.js\";\r\nimport Resource from \"./Resource.js\";\r\nimport TerrainProvider from \"./TerrainProvider.js\";\r\nimport TileProviderError from \"./TileProviderError.js\";\r\n\r\nfunction DataRectangle(rectangle, maxLevel) {\r\n this.rectangle = rectangle;\r\n this.maxLevel = maxLevel;\r\n}\r\n\r\n/**\r\n * A {@link TerrainProvider} that produces terrain geometry by tessellating height maps\r\n * retrieved from a {@link http://vr-theworld.com/|VT MÄK VR-TheWorld server}.\r\n *\r\n * @alias VRTheWorldTerrainProvider\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Resource|String} options.url The URL of the VR-TheWorld TileMap.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid. If this parameter is not\r\n * specified, the WGS84 ellipsoid is used.\r\n * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas.\r\n *\r\n *\r\n * @example\r\n * var terrainProvider = new Cesium.VRTheWorldTerrainProvider({\r\n * url : 'https://www.vr-theworld.com/vr-theworld/tiles1.0.0/73/'\r\n * });\r\n * viewer.terrainProvider = terrainProvider;\r\n *\r\n * @see TerrainProvider\r\n */\r\nfunction VRTheWorldTerrainProvider(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options.url)) {\r\n throw new DeveloperError(\"options.url is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var resource = Resource.createIfNeeded(options.url);\r\n\r\n this._resource = resource;\r\n\r\n this._errorEvent = new Event();\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._terrainDataStructure = {\r\n heightScale: 1.0 / 1000.0,\r\n heightOffset: -1000.0,\r\n elementsPerHeight: 3,\r\n stride: 4,\r\n elementMultiplier: 256.0,\r\n isBigEndian: true,\r\n lowestEncodedHeight: 0,\r\n highestEncodedHeight: 256 * 256 * 256 - 1,\r\n };\r\n\r\n var credit = options.credit;\r\n if (typeof credit === \"string\") {\r\n credit = new Credit(credit);\r\n }\r\n this._credit = credit;\r\n\r\n this._tilingScheme = undefined;\r\n this._rectangles = [];\r\n\r\n var that = this;\r\n var metadataError;\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n\r\n function metadataSuccess(xml) {\r\n var srs = xml.getElementsByTagName(\"SRS\")[0].textContent;\r\n if (srs === \"EPSG:4326\") {\r\n that._tilingScheme = new GeographicTilingScheme({ ellipsoid: ellipsoid });\r\n } else {\r\n metadataFailure(\"SRS \" + srs + \" is not supported.\");\r\n return;\r\n }\r\n\r\n var tileFormat = xml.getElementsByTagName(\"TileFormat\")[0];\r\n that._heightmapWidth = parseInt(tileFormat.getAttribute(\"width\"), 10);\r\n that._heightmapHeight = parseInt(tileFormat.getAttribute(\"height\"), 10);\r\n that._levelZeroMaximumGeometricError = TerrainProvider.getEstimatedLevelZeroGeometricErrorForAHeightmap(\r\n ellipsoid,\r\n Math.min(that._heightmapWidth, that._heightmapHeight),\r\n that._tilingScheme.getNumberOfXTilesAtLevel(0)\r\n );\r\n\r\n var dataRectangles = xml.getElementsByTagName(\"DataExtent\");\r\n\r\n for (var i = 0; i < dataRectangles.length; ++i) {\r\n var dataRectangle = dataRectangles[i];\r\n\r\n var west = CesiumMath.toRadians(\r\n parseFloat(dataRectangle.getAttribute(\"minx\"))\r\n );\r\n var south = CesiumMath.toRadians(\r\n parseFloat(dataRectangle.getAttribute(\"miny\"))\r\n );\r\n var east = CesiumMath.toRadians(\r\n parseFloat(dataRectangle.getAttribute(\"maxx\"))\r\n );\r\n var north = CesiumMath.toRadians(\r\n parseFloat(dataRectangle.getAttribute(\"maxy\"))\r\n );\r\n var maxLevel = parseInt(dataRectangle.getAttribute(\"maxlevel\"), 10);\r\n\r\n that._rectangles.push(\r\n new DataRectangle(new Rectangle(west, south, east, north), maxLevel)\r\n );\r\n }\r\n\r\n that._ready = true;\r\n that._readyPromise.resolve(true);\r\n }\r\n\r\n function metadataFailure(e) {\r\n var message = defaultValue(\r\n e,\r\n \"An error occurred while accessing \" + that._resource.url + \".\"\r\n );\r\n metadataError = TileProviderError.handleError(\r\n metadataError,\r\n that,\r\n that._errorEvent,\r\n message,\r\n undefined,\r\n undefined,\r\n undefined,\r\n requestMetadata\r\n );\r\n }\r\n\r\n function requestMetadata() {\r\n when(that._resource.fetchXML(), metadataSuccess, metadataFailure);\r\n }\r\n\r\n requestMetadata();\r\n}\r\n\r\nObject.defineProperties(VRTheWorldTerrainProvider.prototype, {\r\n /**\r\n * Gets an event that is raised when the terrain provider encounters an asynchronous error. By subscribing\r\n * to the event, you will be notified of the error and can potentially recover from it. Event listeners\r\n * are passed an instance of {@link TileProviderError}.\r\n * @memberof VRTheWorldTerrainProvider.prototype\r\n * @type {Event}\r\n */\r\n errorEvent: {\r\n get: function () {\r\n return this._errorEvent;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the credit to display when this terrain provider is active. Typically this is used to credit\r\n * the source of the terrain. This function should not be called before {@link VRTheWorldTerrainProvider#ready} returns true.\r\n * @memberof VRTheWorldTerrainProvider.prototype\r\n * @type {Credit}\r\n */\r\n credit: {\r\n get: function () {\r\n return this._credit;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tiling scheme used by this provider. This function should\r\n * not be called before {@link VRTheWorldTerrainProvider#ready} returns true.\r\n * @memberof VRTheWorldTerrainProvider.prototype\r\n * @type {GeographicTilingScheme}\r\n */\r\n tilingScheme: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"requestTileGeometry must not be called before ready returns true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._tilingScheme;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider is ready for use.\r\n * @memberof VRTheWorldTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves to true when the provider is ready for use.\r\n * @memberof VRTheWorldTerrainProvider.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the provider includes a water mask. The water mask\r\n * indicates which areas of the globe are water rather than land, so they can be rendered\r\n * as a reflective surface with animated waves. This function should not be\r\n * called before {@link VRTheWorldTerrainProvider#ready} returns true.\r\n * @memberof VRTheWorldTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasWaterMask: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not the requested tiles include vertex normals.\r\n * This function should not be called before {@link VRTheWorldTerrainProvider#ready} returns true.\r\n * @memberof VRTheWorldTerrainProvider.prototype\r\n * @type {Boolean}\r\n */\r\n hasVertexNormals: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n /**\r\n * Gets an object that can be used to determine availability of terrain from this provider, such as\r\n * at points and in rectangles. This function should not be called before\r\n * {@link TerrainProvider#ready} returns true. This property may be undefined if availability\r\n * information is not available.\r\n * @memberof VRTheWorldTerrainProvider.prototype\r\n * @type {TileAvailability}\r\n */\r\n availability: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Requests the geometry for a given tile. This function should not be called before\r\n * {@link VRTheWorldTerrainProvider#ready} returns true. The result includes terrain\r\n * data and indicates that all child tiles are available.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @param {Request} [request] The request object. Intended for internal use only.\r\n * @returns {Promise.|undefined} A promise for the requested geometry. If this method\r\n * returns undefined instead of a promise, it is an indication that too many requests are already\r\n * pending and the request will be retried later.\r\n */\r\nVRTheWorldTerrainProvider.prototype.requestTileGeometry = function (\r\n x,\r\n y,\r\n level,\r\n request\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"requestTileGeometry must not be called before ready returns true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var yTiles = this._tilingScheme.getNumberOfYTilesAtLevel(level);\r\n var resource = this._resource.getDerivedResource({\r\n url: level + \"/\" + x + \"/\" + (yTiles - y - 1) + \".tif\",\r\n queryParameters: {\r\n cesium: true,\r\n },\r\n request: request,\r\n });\r\n var promise = resource.fetchImage({\r\n preferImageBitmap: true,\r\n });\r\n if (!defined(promise)) {\r\n return undefined;\r\n }\r\n\r\n var that = this;\r\n return when(promise).then(function (image) {\r\n return new HeightmapTerrainData({\r\n buffer: getImagePixels(image),\r\n width: that._heightmapWidth,\r\n height: that._heightmapHeight,\r\n childTileMask: getChildMask(that, x, y, level),\r\n structure: that._terrainDataStructure,\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Gets the maximum geometric error allowed in a tile at a given level.\r\n *\r\n * @param {Number} level The tile level for which to get the maximum geometric error.\r\n * @returns {Number} The maximum geometric error.\r\n */\r\nVRTheWorldTerrainProvider.prototype.getLevelMaximumGeometricError = function (\r\n level\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"requestTileGeometry must not be called before ready returns true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return this._levelZeroMaximumGeometricError / (1 << level);\r\n};\r\n\r\nvar rectangleScratch = new Rectangle();\r\n\r\nfunction getChildMask(provider, x, y, level) {\r\n var tilingScheme = provider._tilingScheme;\r\n var rectangles = provider._rectangles;\r\n var parentRectangle = tilingScheme.tileXYToRectangle(x, y, level);\r\n\r\n var childMask = 0;\r\n\r\n for (var i = 0; i < rectangles.length && childMask !== 15; ++i) {\r\n var rectangle = rectangles[i];\r\n if (rectangle.maxLevel <= level) {\r\n continue;\r\n }\r\n\r\n var testRectangle = rectangle.rectangle;\r\n\r\n var intersection = Rectangle.intersection(\r\n testRectangle,\r\n parentRectangle,\r\n rectangleScratch\r\n );\r\n if (defined(intersection)) {\r\n // Parent tile is inside this rectangle, so at least one child is, too.\r\n if (\r\n isTileInRectangle(tilingScheme, testRectangle, x * 2, y * 2, level + 1)\r\n ) {\r\n childMask |= 4; // northwest\r\n }\r\n if (\r\n isTileInRectangle(\r\n tilingScheme,\r\n testRectangle,\r\n x * 2 + 1,\r\n y * 2,\r\n level + 1\r\n )\r\n ) {\r\n childMask |= 8; // northeast\r\n }\r\n if (\r\n isTileInRectangle(\r\n tilingScheme,\r\n testRectangle,\r\n x * 2,\r\n y * 2 + 1,\r\n level + 1\r\n )\r\n ) {\r\n childMask |= 1; // southwest\r\n }\r\n if (\r\n isTileInRectangle(\r\n tilingScheme,\r\n testRectangle,\r\n x * 2 + 1,\r\n y * 2 + 1,\r\n level + 1\r\n )\r\n ) {\r\n childMask |= 2; // southeast\r\n }\r\n }\r\n }\r\n\r\n return childMask;\r\n}\r\n\r\nfunction isTileInRectangle(tilingScheme, rectangle, x, y, level) {\r\n var tileRectangle = tilingScheme.tileXYToRectangle(x, y, level);\r\n return defined(\r\n Rectangle.intersection(tileRectangle, rectangle, rectangleScratch)\r\n );\r\n}\r\n\r\n/**\r\n * Determines whether data for a tile is available to be loaded.\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {Boolean} Undefined if not supported, otherwise true or false.\r\n */\r\nVRTheWorldTerrainProvider.prototype.getTileDataAvailable = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Makes sure we load availability data for a tile\r\n *\r\n * @param {Number} x The X coordinate of the tile for which to request geometry.\r\n * @param {Number} y The Y coordinate of the tile for which to request geometry.\r\n * @param {Number} level The level of the tile for which to request geometry.\r\n * @returns {undefined|Promise} Undefined if nothing need to be loaded or a Promise that resolves when all required tiles are loaded\r\n */\r\nVRTheWorldTerrainProvider.prototype.loadTileDataAvailability = function (\r\n x,\r\n y,\r\n level\r\n) {\r\n return undefined;\r\n};\r\nexport default VRTheWorldTerrainProvider;\r\n","import arrayRemoveDuplicates from \"./arrayRemoveDuplicates.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport Cartographic from \"./Cartographic.js\";\r\nimport defined from \"./defined.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PolylinePipeline from \"./PolylinePipeline.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar WallGeometryLibrary = {};\r\n\r\nfunction latLonEquals(c0, c1) {\r\n return (\r\n CesiumMath.equalsEpsilon(c0.latitude, c1.latitude, CesiumMath.EPSILON10) &&\r\n CesiumMath.equalsEpsilon(c0.longitude, c1.longitude, CesiumMath.EPSILON10)\r\n );\r\n}\r\n\r\nvar scratchCartographic1 = new Cartographic();\r\nvar scratchCartographic2 = new Cartographic();\r\nfunction removeDuplicates(ellipsoid, positions, topHeights, bottomHeights) {\r\n positions = arrayRemoveDuplicates(positions, Cartesian3.equalsEpsilon);\r\n\r\n var length = positions.length;\r\n if (length < 2) {\r\n return;\r\n }\r\n\r\n var hasBottomHeights = defined(bottomHeights);\r\n var hasTopHeights = defined(topHeights);\r\n\r\n var cleanedPositions = new Array(length);\r\n var cleanedTopHeights = new Array(length);\r\n var cleanedBottomHeights = new Array(length);\r\n\r\n var v0 = positions[0];\r\n cleanedPositions[0] = v0;\r\n\r\n var c0 = ellipsoid.cartesianToCartographic(v0, scratchCartographic1);\r\n if (hasTopHeights) {\r\n c0.height = topHeights[0];\r\n }\r\n\r\n cleanedTopHeights[0] = c0.height;\r\n\r\n if (hasBottomHeights) {\r\n cleanedBottomHeights[0] = bottomHeights[0];\r\n } else {\r\n cleanedBottomHeights[0] = 0.0;\r\n }\r\n\r\n var startTopHeight = cleanedTopHeights[0];\r\n var startBottomHeight = cleanedBottomHeights[0];\r\n var hasAllSameHeights = startTopHeight === startBottomHeight;\r\n\r\n var index = 1;\r\n for (var i = 1; i < length; ++i) {\r\n var v1 = positions[i];\r\n var c1 = ellipsoid.cartesianToCartographic(v1, scratchCartographic2);\r\n if (hasTopHeights) {\r\n c1.height = topHeights[i];\r\n }\r\n hasAllSameHeights = hasAllSameHeights && c1.height === 0;\r\n\r\n if (!latLonEquals(c0, c1)) {\r\n cleanedPositions[index] = v1; // Shallow copy!\r\n cleanedTopHeights[index] = c1.height;\r\n\r\n if (hasBottomHeights) {\r\n cleanedBottomHeights[index] = bottomHeights[i];\r\n } else {\r\n cleanedBottomHeights[index] = 0.0;\r\n }\r\n hasAllSameHeights =\r\n hasAllSameHeights &&\r\n cleanedTopHeights[index] === cleanedBottomHeights[index];\r\n\r\n Cartographic.clone(c1, c0);\r\n ++index;\r\n } else if (c0.height < c1.height) {\r\n // two adjacent positions are the same, so use whichever has the greater height\r\n cleanedTopHeights[index - 1] = c1.height;\r\n }\r\n }\r\n\r\n if (hasAllSameHeights || index < 2) {\r\n return;\r\n }\r\n\r\n cleanedPositions.length = index;\r\n cleanedTopHeights.length = index;\r\n cleanedBottomHeights.length = index;\r\n\r\n return {\r\n positions: cleanedPositions,\r\n topHeights: cleanedTopHeights,\r\n bottomHeights: cleanedBottomHeights,\r\n };\r\n}\r\n\r\nvar positionsArrayScratch = new Array(2);\r\nvar heightsArrayScratch = new Array(2);\r\nvar generateArcOptionsScratch = {\r\n positions: undefined,\r\n height: undefined,\r\n granularity: undefined,\r\n ellipsoid: undefined,\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nWallGeometryLibrary.computePositions = function (\r\n ellipsoid,\r\n wallPositions,\r\n maximumHeights,\r\n minimumHeights,\r\n granularity,\r\n duplicateCorners\r\n) {\r\n var o = removeDuplicates(\r\n ellipsoid,\r\n wallPositions,\r\n maximumHeights,\r\n minimumHeights\r\n );\r\n\r\n if (!defined(o)) {\r\n return;\r\n }\r\n\r\n wallPositions = o.positions;\r\n maximumHeights = o.topHeights;\r\n minimumHeights = o.bottomHeights;\r\n\r\n var length = wallPositions.length;\r\n var numCorners = length - 2;\r\n var topPositions;\r\n var bottomPositions;\r\n\r\n var minDistance = CesiumMath.chordLength(\r\n granularity,\r\n ellipsoid.maximumRadius\r\n );\r\n\r\n var generateArcOptions = generateArcOptionsScratch;\r\n generateArcOptions.minDistance = minDistance;\r\n generateArcOptions.ellipsoid = ellipsoid;\r\n\r\n if (duplicateCorners) {\r\n var count = 0;\r\n var i;\r\n\r\n for (i = 0; i < length - 1; i++) {\r\n count +=\r\n PolylinePipeline.numberOfPoints(\r\n wallPositions[i],\r\n wallPositions[i + 1],\r\n minDistance\r\n ) + 1;\r\n }\r\n\r\n topPositions = new Float64Array(count * 3);\r\n bottomPositions = new Float64Array(count * 3);\r\n\r\n var generateArcPositions = positionsArrayScratch;\r\n var generateArcHeights = heightsArrayScratch;\r\n generateArcOptions.positions = generateArcPositions;\r\n generateArcOptions.height = generateArcHeights;\r\n\r\n var offset = 0;\r\n for (i = 0; i < length - 1; i++) {\r\n generateArcPositions[0] = wallPositions[i];\r\n generateArcPositions[1] = wallPositions[i + 1];\r\n\r\n generateArcHeights[0] = maximumHeights[i];\r\n generateArcHeights[1] = maximumHeights[i + 1];\r\n\r\n var pos = PolylinePipeline.generateArc(generateArcOptions);\r\n topPositions.set(pos, offset);\r\n\r\n generateArcHeights[0] = minimumHeights[i];\r\n generateArcHeights[1] = minimumHeights[i + 1];\r\n\r\n bottomPositions.set(\r\n PolylinePipeline.generateArc(generateArcOptions),\r\n offset\r\n );\r\n\r\n offset += pos.length;\r\n }\r\n } else {\r\n generateArcOptions.positions = wallPositions;\r\n generateArcOptions.height = maximumHeights;\r\n topPositions = new Float64Array(\r\n PolylinePipeline.generateArc(generateArcOptions)\r\n );\r\n\r\n generateArcOptions.height = minimumHeights;\r\n bottomPositions = new Float64Array(\r\n PolylinePipeline.generateArc(generateArcOptions)\r\n );\r\n }\r\n\r\n return {\r\n bottomPositions: bottomPositions,\r\n topPositions: topPositions,\r\n numCorners: numCorners,\r\n };\r\n};\r\nexport default WallGeometryLibrary;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport VertexFormat from \"./VertexFormat.js\";\r\nimport WallGeometryLibrary from \"./WallGeometryLibrary.js\";\r\n\r\nvar scratchCartesian3Position1 = new Cartesian3();\r\nvar scratchCartesian3Position2 = new Cartesian3();\r\nvar scratchCartesian3Position4 = new Cartesian3();\r\nvar scratchCartesian3Position5 = new Cartesian3();\r\nvar scratchBitangent = new Cartesian3();\r\nvar scratchTangent = new Cartesian3();\r\nvar scratchNormal = new Cartesian3();\r\n\r\n/**\r\n * A description of a wall, which is similar to a KML line string. A wall is defined by a series of points,\r\n * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.\r\n *\r\n * @alias WallGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Number[]} [options.maximumHeights] An array parallel to positions that give the maximum height of the\r\n * wall at positions. If undefined, the height of each position in used.\r\n * @param {Number[]} [options.minimumHeights] An array parallel to positions that give the minimum height of the\r\n * wall at positions. If undefined, the height at each position is 0.0.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n *\r\n * @exception {DeveloperError} positions length must be greater than or equal to 2.\r\n * @exception {DeveloperError} positions and maximumHeights must have the same length.\r\n * @exception {DeveloperError} positions and minimumHeights must have the same length.\r\n *\r\n * @see WallGeometry#createGeometry\r\n * @see WallGeometry#fromConstantHeight\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Wall.html|Cesium Sandcastle Wall Demo}\r\n *\r\n * @example\r\n * // create a wall that spans from ground level to 10000 meters\r\n * var wall = new Cesium.WallGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArrayHeights([\r\n * 19.0, 47.0, 10000.0,\r\n * 19.0, 48.0, 10000.0,\r\n * 20.0, 48.0, 10000.0,\r\n * 20.0, 47.0, 10000.0,\r\n * 19.0, 47.0, 10000.0\r\n * ])\r\n * });\r\n * var geometry = Cesium.WallGeometry.createGeometry(wall);\r\n */\r\nfunction WallGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var wallPositions = options.positions;\r\n var maximumHeights = options.maximumHeights;\r\n var minimumHeights = options.minimumHeights;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(wallPositions)) {\r\n throw new DeveloperError(\"options.positions is required.\");\r\n }\r\n if (\r\n defined(maximumHeights) &&\r\n maximumHeights.length !== wallPositions.length\r\n ) {\r\n throw new DeveloperError(\r\n \"options.positions and options.maximumHeights must have the same length.\"\r\n );\r\n }\r\n if (\r\n defined(minimumHeights) &&\r\n minimumHeights.length !== wallPositions.length\r\n ) {\r\n throw new DeveloperError(\r\n \"options.positions and options.minimumHeights must have the same length.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var vertexFormat = defaultValue(options.vertexFormat, VertexFormat.DEFAULT);\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n\r\n this._positions = wallPositions;\r\n this._minimumHeights = minimumHeights;\r\n this._maximumHeights = maximumHeights;\r\n this._vertexFormat = VertexFormat.clone(vertexFormat);\r\n this._granularity = granularity;\r\n this._ellipsoid = Ellipsoid.clone(ellipsoid);\r\n this._workerName = \"createWallGeometry\";\r\n\r\n var numComponents = 1 + wallPositions.length * Cartesian3.packedLength + 2;\r\n if (defined(minimumHeights)) {\r\n numComponents += minimumHeights.length;\r\n }\r\n if (defined(maximumHeights)) {\r\n numComponents += maximumHeights.length;\r\n }\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength =\r\n numComponents + Ellipsoid.packedLength + VertexFormat.packedLength + 1;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {WallGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nWallGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var positions = value._positions;\r\n var length = positions.length;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n\r\n var minimumHeights = value._minimumHeights;\r\n length = defined(minimumHeights) ? minimumHeights.length : 0;\r\n array[startingIndex++] = length;\r\n\r\n if (defined(minimumHeights)) {\r\n for (i = 0; i < length; ++i) {\r\n array[startingIndex++] = minimumHeights[i];\r\n }\r\n }\r\n\r\n var maximumHeights = value._maximumHeights;\r\n length = defined(maximumHeights) ? maximumHeights.length : 0;\r\n array[startingIndex++] = length;\r\n\r\n if (defined(maximumHeights)) {\r\n for (i = 0; i < length; ++i) {\r\n array[startingIndex++] = maximumHeights[i];\r\n }\r\n }\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n VertexFormat.pack(value._vertexFormat, array, startingIndex);\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n array[startingIndex] = value._granularity;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchVertexFormat = new VertexFormat();\r\nvar scratchOptions = {\r\n positions: undefined,\r\n minimumHeights: undefined,\r\n maximumHeights: undefined,\r\n ellipsoid: scratchEllipsoid,\r\n vertexFormat: scratchVertexFormat,\r\n granularity: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {WallGeometry} [result] The object into which to store the result.\r\n * @returns {WallGeometry} The modified result parameter or a new WallGeometry instance if one was not provided.\r\n */\r\nWallGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var length = array[startingIndex++];\r\n var positions = new Array(length);\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n length = array[startingIndex++];\r\n var minimumHeights;\r\n\r\n if (length > 0) {\r\n minimumHeights = new Array(length);\r\n for (i = 0; i < length; ++i) {\r\n minimumHeights[i] = array[startingIndex++];\r\n }\r\n }\r\n\r\n length = array[startingIndex++];\r\n var maximumHeights;\r\n\r\n if (length > 0) {\r\n maximumHeights = new Array(length);\r\n for (i = 0; i < length; ++i) {\r\n maximumHeights[i] = array[startingIndex++];\r\n }\r\n }\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var vertexFormat = VertexFormat.unpack(\r\n array,\r\n startingIndex,\r\n scratchVertexFormat\r\n );\r\n startingIndex += VertexFormat.packedLength;\r\n\r\n var granularity = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.positions = positions;\r\n scratchOptions.minimumHeights = minimumHeights;\r\n scratchOptions.maximumHeights = maximumHeights;\r\n scratchOptions.granularity = granularity;\r\n return new WallGeometry(scratchOptions);\r\n }\r\n\r\n result._positions = positions;\r\n result._minimumHeights = minimumHeights;\r\n result._maximumHeights = maximumHeights;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._vertexFormat = VertexFormat.clone(vertexFormat, result._vertexFormat);\r\n result._granularity = granularity;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * A description of a wall, which is similar to a KML line string. A wall is defined by a series of points,\r\n * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.\r\n * @param {Number} [options.maximumHeight] A constant that defines the maximum height of the\r\n * wall at positions. If undefined, the height of each position in used.\r\n * @param {Number} [options.minimumHeight] A constant that defines the minimum height of the\r\n * wall at positions. If undefined, the height at each position is 0.0.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation\r\n * @param {VertexFormat} [options.vertexFormat=VertexFormat.DEFAULT] The vertex attributes to be computed.\r\n * @returns {WallGeometry}\r\n *\r\n *\r\n * @example\r\n * // create a wall that spans from 10000 meters to 20000 meters\r\n * var wall = Cesium.WallGeometry.fromConstantHeights({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * 19.0, 47.0,\r\n * 19.0, 48.0,\r\n * 20.0, 48.0,\r\n * 20.0, 47.0,\r\n * 19.0, 47.0,\r\n * ]),\r\n * minimumHeight : 20000.0,\r\n * maximumHeight : 10000.0\r\n * });\r\n * var geometry = Cesium.WallGeometry.createGeometry(wall);\r\n *\r\n * @see WallGeometry#createGeometry\r\n */\r\nWallGeometry.fromConstantHeights = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.positions;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions)) {\r\n throw new DeveloperError(\"options.positions is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var minHeights;\r\n var maxHeights;\r\n\r\n var min = options.minimumHeight;\r\n var max = options.maximumHeight;\r\n\r\n var doMin = defined(min);\r\n var doMax = defined(max);\r\n if (doMin || doMax) {\r\n var length = positions.length;\r\n minHeights = doMin ? new Array(length) : undefined;\r\n maxHeights = doMax ? new Array(length) : undefined;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n if (doMin) {\r\n minHeights[i] = min;\r\n }\r\n\r\n if (doMax) {\r\n maxHeights[i] = max;\r\n }\r\n }\r\n }\r\n\r\n var newOptions = {\r\n positions: positions,\r\n maximumHeights: maxHeights,\r\n minimumHeights: minHeights,\r\n ellipsoid: options.ellipsoid,\r\n vertexFormat: options.vertexFormat,\r\n };\r\n return new WallGeometry(newOptions);\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a wall, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {WallGeometry} wallGeometry A description of the wall.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nWallGeometry.createGeometry = function (wallGeometry) {\r\n var wallPositions = wallGeometry._positions;\r\n var minimumHeights = wallGeometry._minimumHeights;\r\n var maximumHeights = wallGeometry._maximumHeights;\r\n var vertexFormat = wallGeometry._vertexFormat;\r\n var granularity = wallGeometry._granularity;\r\n var ellipsoid = wallGeometry._ellipsoid;\r\n\r\n var pos = WallGeometryLibrary.computePositions(\r\n ellipsoid,\r\n wallPositions,\r\n maximumHeights,\r\n minimumHeights,\r\n granularity,\r\n true\r\n );\r\n if (!defined(pos)) {\r\n return;\r\n }\r\n\r\n var bottomPositions = pos.bottomPositions;\r\n var topPositions = pos.topPositions;\r\n var numCorners = pos.numCorners;\r\n\r\n var length = topPositions.length;\r\n var size = length * 2;\r\n\r\n var positions = vertexFormat.position ? new Float64Array(size) : undefined;\r\n var normals = vertexFormat.normal ? new Float32Array(size) : undefined;\r\n var tangents = vertexFormat.tangent ? new Float32Array(size) : undefined;\r\n var bitangents = vertexFormat.bitangent ? new Float32Array(size) : undefined;\r\n var textureCoordinates = vertexFormat.st\r\n ? new Float32Array((size / 3) * 2)\r\n : undefined;\r\n\r\n var positionIndex = 0;\r\n var normalIndex = 0;\r\n var bitangentIndex = 0;\r\n var tangentIndex = 0;\r\n var stIndex = 0;\r\n\r\n // add lower and upper points one after the other, lower\r\n // points being even and upper points being odd\r\n var normal = scratchNormal;\r\n var tangent = scratchTangent;\r\n var bitangent = scratchBitangent;\r\n var recomputeNormal = true;\r\n length /= 3;\r\n var i;\r\n var s = 0;\r\n var ds = 1 / (length - numCorners - 1);\r\n for (i = 0; i < length; ++i) {\r\n var i3 = i * 3;\r\n var topPosition = Cartesian3.fromArray(\r\n topPositions,\r\n i3,\r\n scratchCartesian3Position1\r\n );\r\n var bottomPosition = Cartesian3.fromArray(\r\n bottomPositions,\r\n i3,\r\n scratchCartesian3Position2\r\n );\r\n if (vertexFormat.position) {\r\n // insert the lower point\r\n positions[positionIndex++] = bottomPosition.x;\r\n positions[positionIndex++] = bottomPosition.y;\r\n positions[positionIndex++] = bottomPosition.z;\r\n\r\n // insert the upper point\r\n positions[positionIndex++] = topPosition.x;\r\n positions[positionIndex++] = topPosition.y;\r\n positions[positionIndex++] = topPosition.z;\r\n }\r\n\r\n if (vertexFormat.st) {\r\n textureCoordinates[stIndex++] = s;\r\n textureCoordinates[stIndex++] = 0.0;\r\n\r\n textureCoordinates[stIndex++] = s;\r\n textureCoordinates[stIndex++] = 1.0;\r\n }\r\n\r\n if (vertexFormat.normal || vertexFormat.tangent || vertexFormat.bitangent) {\r\n var nextTop = Cartesian3.clone(\r\n Cartesian3.ZERO,\r\n scratchCartesian3Position5\r\n );\r\n var groundPosition = Cartesian3.subtract(\r\n topPosition,\r\n ellipsoid.geodeticSurfaceNormal(\r\n topPosition,\r\n scratchCartesian3Position2\r\n ),\r\n scratchCartesian3Position2\r\n );\r\n if (i + 1 < length) {\r\n nextTop = Cartesian3.fromArray(\r\n topPositions,\r\n i3 + 3,\r\n scratchCartesian3Position5\r\n );\r\n }\r\n\r\n if (recomputeNormal) {\r\n var scalednextPosition = Cartesian3.subtract(\r\n nextTop,\r\n topPosition,\r\n scratchCartesian3Position4\r\n );\r\n var scaledGroundPosition = Cartesian3.subtract(\r\n groundPosition,\r\n topPosition,\r\n scratchCartesian3Position1\r\n );\r\n normal = Cartesian3.normalize(\r\n Cartesian3.cross(scaledGroundPosition, scalednextPosition, normal),\r\n normal\r\n );\r\n recomputeNormal = false;\r\n }\r\n\r\n if (\r\n Cartesian3.equalsEpsilon(topPosition, nextTop, CesiumMath.EPSILON10)\r\n ) {\r\n recomputeNormal = true;\r\n } else {\r\n s += ds;\r\n if (vertexFormat.tangent) {\r\n tangent = Cartesian3.normalize(\r\n Cartesian3.subtract(nextTop, topPosition, tangent),\r\n tangent\r\n );\r\n }\r\n if (vertexFormat.bitangent) {\r\n bitangent = Cartesian3.normalize(\r\n Cartesian3.cross(normal, tangent, bitangent),\r\n bitangent\r\n );\r\n }\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n normals[normalIndex++] = normal.x;\r\n normals[normalIndex++] = normal.y;\r\n normals[normalIndex++] = normal.z;\r\n\r\n normals[normalIndex++] = normal.x;\r\n normals[normalIndex++] = normal.y;\r\n normals[normalIndex++] = normal.z;\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n tangents[tangentIndex++] = tangent.x;\r\n tangents[tangentIndex++] = tangent.y;\r\n tangents[tangentIndex++] = tangent.z;\r\n\r\n tangents[tangentIndex++] = tangent.x;\r\n tangents[tangentIndex++] = tangent.y;\r\n tangents[tangentIndex++] = tangent.z;\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n bitangents[bitangentIndex++] = bitangent.x;\r\n bitangents[bitangentIndex++] = bitangent.y;\r\n bitangents[bitangentIndex++] = bitangent.z;\r\n\r\n bitangents[bitangentIndex++] = bitangent.x;\r\n bitangents[bitangentIndex++] = bitangent.y;\r\n bitangents[bitangentIndex++] = bitangent.z;\r\n }\r\n }\r\n }\r\n\r\n var attributes = new GeometryAttributes();\r\n\r\n if (vertexFormat.position) {\r\n attributes.position = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n });\r\n }\r\n\r\n if (vertexFormat.normal) {\r\n attributes.normal = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: normals,\r\n });\r\n }\r\n\r\n if (vertexFormat.tangent) {\r\n attributes.tangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: tangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.bitangent) {\r\n attributes.bitangent = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n values: bitangents,\r\n });\r\n }\r\n\r\n if (vertexFormat.st) {\r\n attributes.st = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n values: textureCoordinates,\r\n });\r\n }\r\n\r\n // prepare the side walls, two triangles for each wall\r\n //\r\n // A (i+1) B (i+3) E\r\n // +--------+-------+\r\n // | / | /| triangles: A C B\r\n // | / | / | B C D\r\n // | / | / |\r\n // | / | / |\r\n // | / | / |\r\n // | / | / |\r\n // +--------+-------+\r\n // C (i) D (i+2) F\r\n //\r\n\r\n var numVertices = size / 3;\r\n size -= 6 * (numCorners + 1);\r\n var indices = IndexDatatype.createTypedArray(numVertices, size);\r\n\r\n var edgeIndex = 0;\r\n for (i = 0; i < numVertices - 2; i += 2) {\r\n var LL = i;\r\n var LR = i + 2;\r\n var pl = Cartesian3.fromArray(\r\n positions,\r\n LL * 3,\r\n scratchCartesian3Position1\r\n );\r\n var pr = Cartesian3.fromArray(\r\n positions,\r\n LR * 3,\r\n scratchCartesian3Position2\r\n );\r\n if (Cartesian3.equalsEpsilon(pl, pr, CesiumMath.EPSILON10)) {\r\n continue;\r\n }\r\n var UL = i + 1;\r\n var UR = i + 3;\r\n\r\n indices[edgeIndex++] = UL;\r\n indices[edgeIndex++] = LL;\r\n indices[edgeIndex++] = UR;\r\n indices[edgeIndex++] = UR;\r\n indices[edgeIndex++] = LL;\r\n indices[edgeIndex++] = LR;\r\n }\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.TRIANGLES,\r\n boundingSphere: new BoundingSphere.fromVertices(positions),\r\n });\r\n};\r\nexport default WallGeometry;\r\n","import BoundingSphere from \"./BoundingSphere.js\";\r\nimport Cartesian3 from \"./Cartesian3.js\";\r\nimport ComponentDatatype from \"./ComponentDatatype.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Ellipsoid from \"./Ellipsoid.js\";\r\nimport Geometry from \"./Geometry.js\";\r\nimport GeometryAttribute from \"./GeometryAttribute.js\";\r\nimport GeometryAttributes from \"./GeometryAttributes.js\";\r\nimport IndexDatatype from \"./IndexDatatype.js\";\r\nimport CesiumMath from \"./Math.js\";\r\nimport PrimitiveType from \"./PrimitiveType.js\";\r\nimport WallGeometryLibrary from \"./WallGeometryLibrary.js\";\r\n\r\nvar scratchCartesian3Position1 = new Cartesian3();\r\nvar scratchCartesian3Position2 = new Cartesian3();\r\n\r\n/**\r\n * A description of a wall outline. A wall is defined by a series of points,\r\n * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.\r\n *\r\n * @alias WallOutlineGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.\r\n * @param {Number} [options.granularity=CesiumMath.RADIANS_PER_DEGREE] The distance, in radians, between each latitude and longitude. Determines the number of positions in the buffer.\r\n * @param {Number[]} [options.maximumHeights] An array parallel to positions that give the maximum height of the\r\n * wall at positions. If undefined, the height of each position in used.\r\n * @param {Number[]} [options.minimumHeights] An array parallel to positions that give the minimum height of the\r\n * wall at positions. If undefined, the height at each position is 0.0.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation\r\n *\r\n * @exception {DeveloperError} positions length must be greater than or equal to 2.\r\n * @exception {DeveloperError} positions and maximumHeights must have the same length.\r\n * @exception {DeveloperError} positions and minimumHeights must have the same length.\r\n *\r\n * @see WallGeometry#createGeometry\r\n * @see WallGeometry#fromConstantHeight\r\n *\r\n * @example\r\n * // create a wall outline that spans from ground level to 10000 meters\r\n * var wall = new Cesium.WallOutlineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArrayHeights([\r\n * 19.0, 47.0, 10000.0,\r\n * 19.0, 48.0, 10000.0,\r\n * 20.0, 48.0, 10000.0,\r\n * 20.0, 47.0, 10000.0,\r\n * 19.0, 47.0, 10000.0\r\n * ])\r\n * });\r\n * var geometry = Cesium.WallOutlineGeometry.createGeometry(wall);\r\n */\r\nfunction WallOutlineGeometry(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var wallPositions = options.positions;\r\n var maximumHeights = options.maximumHeights;\r\n var minimumHeights = options.minimumHeights;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(wallPositions)) {\r\n throw new DeveloperError(\"options.positions is required.\");\r\n }\r\n if (\r\n defined(maximumHeights) &&\r\n maximumHeights.length !== wallPositions.length\r\n ) {\r\n throw new DeveloperError(\r\n \"options.positions and options.maximumHeights must have the same length.\"\r\n );\r\n }\r\n if (\r\n defined(minimumHeights) &&\r\n minimumHeights.length !== wallPositions.length\r\n ) {\r\n throw new DeveloperError(\r\n \"options.positions and options.minimumHeights must have the same length.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var granularity = defaultValue(\r\n options.granularity,\r\n CesiumMath.RADIANS_PER_DEGREE\r\n );\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n\r\n this._positions = wallPositions;\r\n this._minimumHeights = minimumHeights;\r\n this._maximumHeights = maximumHeights;\r\n this._granularity = granularity;\r\n this._ellipsoid = Ellipsoid.clone(ellipsoid);\r\n this._workerName = \"createWallOutlineGeometry\";\r\n\r\n var numComponents = 1 + wallPositions.length * Cartesian3.packedLength + 2;\r\n if (defined(minimumHeights)) {\r\n numComponents += minimumHeights.length;\r\n }\r\n if (defined(maximumHeights)) {\r\n numComponents += maximumHeights.length;\r\n }\r\n\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n this.packedLength = numComponents + Ellipsoid.packedLength + 1;\r\n}\r\n\r\n/**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {WallOutlineGeometry} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\nWallOutlineGeometry.pack = function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var positions = value._positions;\r\n var length = positions.length;\r\n array[startingIndex++] = length;\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n Cartesian3.pack(positions[i], array, startingIndex);\r\n }\r\n\r\n var minimumHeights = value._minimumHeights;\r\n length = defined(minimumHeights) ? minimumHeights.length : 0;\r\n array[startingIndex++] = length;\r\n\r\n if (defined(minimumHeights)) {\r\n for (i = 0; i < length; ++i) {\r\n array[startingIndex++] = minimumHeights[i];\r\n }\r\n }\r\n\r\n var maximumHeights = value._maximumHeights;\r\n length = defined(maximumHeights) ? maximumHeights.length : 0;\r\n array[startingIndex++] = length;\r\n\r\n if (defined(maximumHeights)) {\r\n for (i = 0; i < length; ++i) {\r\n array[startingIndex++] = maximumHeights[i];\r\n }\r\n }\r\n\r\n Ellipsoid.pack(value._ellipsoid, array, startingIndex);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n array[startingIndex] = value._granularity;\r\n\r\n return array;\r\n};\r\n\r\nvar scratchEllipsoid = Ellipsoid.clone(Ellipsoid.UNIT_SPHERE);\r\nvar scratchOptions = {\r\n positions: undefined,\r\n minimumHeights: undefined,\r\n maximumHeights: undefined,\r\n ellipsoid: scratchEllipsoid,\r\n granularity: undefined,\r\n};\r\n\r\n/**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {WallOutlineGeometry} [result] The object into which to store the result.\r\n * @returns {WallOutlineGeometry} The modified result parameter or a new WallOutlineGeometry instance if one was not provided.\r\n */\r\nWallOutlineGeometry.unpack = function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n\r\n var i;\r\n\r\n var length = array[startingIndex++];\r\n var positions = new Array(length);\r\n\r\n for (i = 0; i < length; ++i, startingIndex += Cartesian3.packedLength) {\r\n positions[i] = Cartesian3.unpack(array, startingIndex);\r\n }\r\n\r\n length = array[startingIndex++];\r\n var minimumHeights;\r\n\r\n if (length > 0) {\r\n minimumHeights = new Array(length);\r\n for (i = 0; i < length; ++i) {\r\n minimumHeights[i] = array[startingIndex++];\r\n }\r\n }\r\n\r\n length = array[startingIndex++];\r\n var maximumHeights;\r\n\r\n if (length > 0) {\r\n maximumHeights = new Array(length);\r\n for (i = 0; i < length; ++i) {\r\n maximumHeights[i] = array[startingIndex++];\r\n }\r\n }\r\n\r\n var ellipsoid = Ellipsoid.unpack(array, startingIndex, scratchEllipsoid);\r\n startingIndex += Ellipsoid.packedLength;\r\n\r\n var granularity = array[startingIndex];\r\n\r\n if (!defined(result)) {\r\n scratchOptions.positions = positions;\r\n scratchOptions.minimumHeights = minimumHeights;\r\n scratchOptions.maximumHeights = maximumHeights;\r\n scratchOptions.granularity = granularity;\r\n return new WallOutlineGeometry(scratchOptions);\r\n }\r\n\r\n result._positions = positions;\r\n result._minimumHeights = minimumHeights;\r\n result._maximumHeights = maximumHeights;\r\n result._ellipsoid = Ellipsoid.clone(ellipsoid, result._ellipsoid);\r\n result._granularity = granularity;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * A description of a walloutline. A wall is defined by a series of points,\r\n * which extrude down to the ground. Optionally, they can extrude downwards to a specified height.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Cartesian3[]} options.positions An array of Cartesian objects, which are the points of the wall.\r\n * @param {Number} [options.maximumHeight] A constant that defines the maximum height of the\r\n * wall at positions. If undefined, the height of each position in used.\r\n * @param {Number} [options.minimumHeight] A constant that defines the minimum height of the\r\n * wall at positions. If undefined, the height at each position is 0.0.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for coordinate manipulation\r\n * @returns {WallOutlineGeometry}\r\n *\r\n *\r\n * @example\r\n * // create a wall that spans from 10000 meters to 20000 meters\r\n * var wall = Cesium.WallOutlineGeometry.fromConstantHeights({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * 19.0, 47.0,\r\n * 19.0, 48.0,\r\n * 20.0, 48.0,\r\n * 20.0, 47.0,\r\n * 19.0, 47.0,\r\n * ]),\r\n * minimumHeight : 20000.0,\r\n * maximumHeight : 10000.0\r\n * });\r\n * var geometry = Cesium.WallOutlineGeometry.createGeometry(wall);\r\n *\r\n * @see WallOutlineGeometry#createGeometry\r\n */\r\nWallOutlineGeometry.fromConstantHeights = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var positions = options.positions;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(positions)) {\r\n throw new DeveloperError(\"options.positions is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var minHeights;\r\n var maxHeights;\r\n\r\n var min = options.minimumHeight;\r\n var max = options.maximumHeight;\r\n\r\n var doMin = defined(min);\r\n var doMax = defined(max);\r\n if (doMin || doMax) {\r\n var length = positions.length;\r\n minHeights = doMin ? new Array(length) : undefined;\r\n maxHeights = doMax ? new Array(length) : undefined;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n if (doMin) {\r\n minHeights[i] = min;\r\n }\r\n\r\n if (doMax) {\r\n maxHeights[i] = max;\r\n }\r\n }\r\n }\r\n\r\n var newOptions = {\r\n positions: positions,\r\n maximumHeights: maxHeights,\r\n minimumHeights: minHeights,\r\n ellipsoid: options.ellipsoid,\r\n };\r\n return new WallOutlineGeometry(newOptions);\r\n};\r\n\r\n/**\r\n * Computes the geometric representation of a wall outline, including its vertices, indices, and a bounding sphere.\r\n *\r\n * @param {WallOutlineGeometry} wallGeometry A description of the wall outline.\r\n * @returns {Geometry|undefined} The computed vertices and indices.\r\n */\r\nWallOutlineGeometry.createGeometry = function (wallGeometry) {\r\n var wallPositions = wallGeometry._positions;\r\n var minimumHeights = wallGeometry._minimumHeights;\r\n var maximumHeights = wallGeometry._maximumHeights;\r\n var granularity = wallGeometry._granularity;\r\n var ellipsoid = wallGeometry._ellipsoid;\r\n\r\n var pos = WallGeometryLibrary.computePositions(\r\n ellipsoid,\r\n wallPositions,\r\n maximumHeights,\r\n minimumHeights,\r\n granularity,\r\n false\r\n );\r\n if (!defined(pos)) {\r\n return;\r\n }\r\n\r\n var bottomPositions = pos.bottomPositions;\r\n var topPositions = pos.topPositions;\r\n\r\n var length = topPositions.length;\r\n var size = length * 2;\r\n\r\n var positions = new Float64Array(size);\r\n var positionIndex = 0;\r\n\r\n // add lower and upper points one after the other, lower\r\n // points being even and upper points being odd\r\n length /= 3;\r\n var i;\r\n for (i = 0; i < length; ++i) {\r\n var i3 = i * 3;\r\n var topPosition = Cartesian3.fromArray(\r\n topPositions,\r\n i3,\r\n scratchCartesian3Position1\r\n );\r\n var bottomPosition = Cartesian3.fromArray(\r\n bottomPositions,\r\n i3,\r\n scratchCartesian3Position2\r\n );\r\n\r\n // insert the lower point\r\n positions[positionIndex++] = bottomPosition.x;\r\n positions[positionIndex++] = bottomPosition.y;\r\n positions[positionIndex++] = bottomPosition.z;\r\n\r\n // insert the upper point\r\n positions[positionIndex++] = topPosition.x;\r\n positions[positionIndex++] = topPosition.y;\r\n positions[positionIndex++] = topPosition.z;\r\n }\r\n\r\n var attributes = new GeometryAttributes({\r\n position: new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.DOUBLE,\r\n componentsPerAttribute: 3,\r\n values: positions,\r\n }),\r\n });\r\n\r\n var numVertices = size / 3;\r\n size = 2 * numVertices - 4 + numVertices;\r\n var indices = IndexDatatype.createTypedArray(numVertices, size);\r\n\r\n var edgeIndex = 0;\r\n for (i = 0; i < numVertices - 2; i += 2) {\r\n var LL = i;\r\n var LR = i + 2;\r\n var pl = Cartesian3.fromArray(\r\n positions,\r\n LL * 3,\r\n scratchCartesian3Position1\r\n );\r\n var pr = Cartesian3.fromArray(\r\n positions,\r\n LR * 3,\r\n scratchCartesian3Position2\r\n );\r\n if (Cartesian3.equalsEpsilon(pl, pr, CesiumMath.EPSILON10)) {\r\n continue;\r\n }\r\n var UL = i + 1;\r\n var UR = i + 3;\r\n\r\n indices[edgeIndex++] = UL;\r\n indices[edgeIndex++] = LL;\r\n indices[edgeIndex++] = UL;\r\n indices[edgeIndex++] = UR;\r\n indices[edgeIndex++] = LL;\r\n indices[edgeIndex++] = LR;\r\n }\r\n\r\n indices[edgeIndex++] = numVertices - 2;\r\n indices[edgeIndex++] = numVertices - 1;\r\n\r\n return new Geometry({\r\n attributes: attributes,\r\n indices: indices,\r\n primitiveType: PrimitiveType.LINES,\r\n boundingSphere: new BoundingSphere.fromVertices(positions),\r\n });\r\n};\r\nexport default WallOutlineGeometry;\r\n","import WebGLConstants from \"./WebGLConstants.js\";\r\n\r\nfunction webGLConstantToGlslType(webGLValue) {\r\n switch (webGLValue) {\r\n case WebGLConstants.FLOAT:\r\n return \"float\";\r\n case WebGLConstants.FLOAT_VEC2:\r\n return \"vec2\";\r\n case WebGLConstants.FLOAT_VEC3:\r\n return \"vec3\";\r\n case WebGLConstants.FLOAT_VEC4:\r\n return \"vec4\";\r\n case WebGLConstants.FLOAT_MAT2:\r\n return \"mat2\";\r\n case WebGLConstants.FLOAT_MAT3:\r\n return \"mat3\";\r\n case WebGLConstants.FLOAT_MAT4:\r\n return \"mat4\";\r\n case WebGLConstants.SAMPLER_2D:\r\n return \"sampler2D\";\r\n case WebGLConstants.BOOL:\r\n return \"bool\";\r\n }\r\n}\r\nexport default webGLConstantToGlslType;\r\n","import Check from \"./Check.js\";\r\nimport defaultValue from \"./defaultValue.js\";\r\nimport defined from \"./defined.js\";\r\nimport DeveloperError from \"./DeveloperError.js\";\r\nimport Spline from \"./Spline.js\";\r\n\r\n/**\r\n * A spline that linearly interpolates over an array of weight values used by morph targets.\r\n *\r\n * @alias WeightSpline\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Number[]} options.times An array of strictly increasing, unit-less, floating-point times at each point.\r\n * The values are in no way connected to the clock time. They are the parameterization for the curve.\r\n * @param {Number[]} options.weights The array of floating-point control weights given. The weights are ordered such\r\n * that all weights for the targets are given in chronological order and order in which they appear in\r\n * the glTF from which the morph targets come. This means for 2 targets, weights = [w(0,0), w(0,1), w(1,0), w(1,1) ...]\r\n * where i and j in w(i,j) are the time indices and target indices, respectively.\r\n *\r\n * @exception {DeveloperError} weights.length must be greater than or equal to 2.\r\n * @exception {DeveloperError} times.length must be a factor of weights.length.\r\n *\r\n *\r\n * @example\r\n * var times = [ 0.0, 1.5, 3.0, 4.5, 6.0 ];\r\n * var weights = [0.0, 1.0, 0.25, 0.75, 0.5, 0.5, 0.75, 0.25, 1.0, 0.0]; //Two targets\r\n * var spline = new Cesium.WeightSpline({\r\n * times : times,\r\n * weights : weights\r\n * });\r\n *\r\n * var p0 = spline.evaluate(times[0]);\r\n *\r\n * @see LinearSpline\r\n * @see HermiteSpline\r\n * @see CatmullRomSpline\r\n * @see QuaternionSpline\r\n */\r\nfunction WeightSpline(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var weights = options.weights;\r\n var times = options.times;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"weights\", weights);\r\n Check.defined(\"times\", times);\r\n Check.typeOf.number.greaterThanOrEquals(\"weights.length\", weights.length, 3);\r\n if (weights.length % times.length !== 0) {\r\n throw new DeveloperError(\r\n \"times.length must be a factor of weights.length.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._times = times;\r\n this._weights = weights;\r\n this._count = weights.length / times.length;\r\n\r\n this._lastTimeIndex = 0;\r\n}\r\n\r\nObject.defineProperties(WeightSpline.prototype, {\r\n /**\r\n * An array of times for the control weights.\r\n *\r\n * @memberof WeightSpline.prototype\r\n *\r\n * @type {Number[]}\r\n * @readonly\r\n */\r\n times: {\r\n get: function () {\r\n return this._times;\r\n },\r\n },\r\n\r\n /**\r\n * An array of floating-point array control weights.\r\n *\r\n * @memberof WeightSpline.prototype\r\n *\r\n * @type {Number[]}\r\n * @readonly\r\n */\r\n weights: {\r\n get: function () {\r\n return this._weights;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Finds an index i in times such that the parameter\r\n * time is in the interval [times[i], times[i + 1]].\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @returns {Number} The index for the element at the start of the interval.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nWeightSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;\r\n\r\n/**\r\n * Wraps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, wrapped around to the updated animation.\r\n */\r\nWeightSpline.prototype.wrapTime = Spline.prototype.wrapTime;\r\n\r\n/**\r\n * Clamps the given time to the period covered by the spline.\r\n * @function\r\n *\r\n * @param {Number} time The time.\r\n * @return {Number} The time, clamped to the animation period.\r\n */\r\nWeightSpline.prototype.clampTime = Spline.prototype.clampTime;\r\n\r\n/**\r\n * Evaluates the curve at a given time.\r\n *\r\n * @param {Number} time The time at which to evaluate the curve.\r\n * @param {Number[]} [result] The object onto which to store the result.\r\n * @returns {Number[]} The modified result parameter or a new instance of the point on the curve at the given time.\r\n *\r\n * @exception {DeveloperError} time must be in the range [t0, tn], where t0\r\n * is the first element in the array times and tn is the last element\r\n * in the array times.\r\n */\r\nWeightSpline.prototype.evaluate = function (time, result) {\r\n var weights = this.weights;\r\n var times = this.times;\r\n\r\n var i = (this._lastTimeIndex = this.findTimeInterval(\r\n time,\r\n this._lastTimeIndex\r\n ));\r\n var u = (time - times[i]) / (times[i + 1] - times[i]);\r\n\r\n if (!defined(result)) {\r\n result = new Array(this._count);\r\n }\r\n\r\n for (var j = 0; j < this._count; j++) {\r\n var index = i * this._count + j;\r\n result[j] = weights[index] * (1.0 - u) + weights[index + this._count] * u;\r\n }\r\n\r\n return result;\r\n};\r\nexport default WeightSpline;\r\n","import DeveloperError from \"./DeveloperError.js\";\r\n\r\n/**\r\n * Wraps a function on the provided objects with another function called in the\r\n * object's context so that the new function is always called immediately\r\n * before the old one.\r\n *\r\n * @private\r\n */\r\nfunction wrapFunction(obj, oldFunction, newFunction) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (typeof oldFunction !== \"function\") {\r\n throw new DeveloperError(\"oldFunction is required to be a function.\");\r\n }\r\n\r\n if (typeof newFunction !== \"function\") {\r\n throw new DeveloperError(\"oldFunction is required to be a function.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return function () {\r\n newFunction.apply(obj, arguments);\r\n oldFunction.apply(obj, arguments);\r\n };\r\n}\r\nexport default wrapFunction;\r\n","import defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\n\r\n/**\r\n * A {@link Property} whose value does not change with respect to simulation time.\r\n *\r\n * @alias ConstantProperty\r\n * @constructor\r\n *\r\n * @param {*} [value] The property value.\r\n *\r\n * @see ConstantPositionProperty\r\n */\r\nfunction ConstantProperty(value) {\r\n this._value = undefined;\r\n this._hasClone = false;\r\n this._hasEquals = false;\r\n this._definitionChanged = new Event();\r\n this.setValue(value);\r\n}\r\n\r\nObject.defineProperties(ConstantProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant.\r\n * This property always returns true.\r\n * @memberof ConstantProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n value: true,\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever setValue is called with data different\r\n * than the current value.\r\n * @memberof ConstantProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property.\r\n *\r\n * @param {JulianDate} [time] The time for which to retrieve the value. This parameter is unused since the value does not change with respect to time.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nConstantProperty.prototype.getValue = function (time, result) {\r\n return this._hasClone ? this._value.clone(result) : this._value;\r\n};\r\n\r\n/**\r\n * Sets the value of the property.\r\n *\r\n * @param {*} value The property value.\r\n */\r\nConstantProperty.prototype.setValue = function (value) {\r\n var oldValue = this._value;\r\n if (oldValue !== value) {\r\n var isDefined = defined(value);\r\n var hasClone = isDefined && typeof value.clone === \"function\";\r\n var hasEquals = isDefined && typeof value.equals === \"function\";\r\n\r\n var changed = !hasEquals || !value.equals(oldValue);\r\n if (changed) {\r\n this._hasClone = hasClone;\r\n this._hasEquals = hasEquals;\r\n this._value = !hasClone ? value : value.clone(this._value);\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nConstantProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof ConstantProperty && //\r\n ((!this._hasEquals && this._value === other._value) || //\r\n (this._hasEquals && this._value.equals(other._value))))\r\n );\r\n};\r\n\r\n/**\r\n * Gets this property's value.\r\n *\r\n * @returns {*} This property's value.\r\n */\r\nConstantProperty.prototype.valueOf = function () {\r\n return this._value;\r\n};\r\n\r\n/**\r\n * Creates a string representing this property's value.\r\n *\r\n * @returns {String} A string representing the property's value.\r\n */\r\nConstantProperty.prototype.toString = function () {\r\n return String(this._value);\r\n};\r\nexport default ConstantProperty;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport ConstantProperty from \"./ConstantProperty.js\";\r\n\r\nfunction createProperty(\r\n name,\r\n privateName,\r\n subscriptionName,\r\n configurable,\r\n createPropertyCallback\r\n) {\r\n return {\r\n configurable: configurable,\r\n get: function () {\r\n return this[privateName];\r\n },\r\n set: function (value) {\r\n var oldValue = this[privateName];\r\n var subscription = this[subscriptionName];\r\n if (defined(subscription)) {\r\n subscription();\r\n this[subscriptionName] = undefined;\r\n }\r\n\r\n var hasValue = value !== undefined;\r\n if (\r\n hasValue &&\r\n (!defined(value) || !defined(value.getValue)) &&\r\n defined(createPropertyCallback)\r\n ) {\r\n value = createPropertyCallback(value);\r\n }\r\n\r\n if (oldValue !== value) {\r\n this[privateName] = value;\r\n this._definitionChanged.raiseEvent(this, name, value, oldValue);\r\n }\r\n\r\n if (defined(value) && defined(value.definitionChanged)) {\r\n this[subscriptionName] = value.definitionChanged.addEventListener(\r\n function () {\r\n this._definitionChanged.raiseEvent(this, name, value, value);\r\n },\r\n this\r\n );\r\n }\r\n },\r\n };\r\n}\r\n\r\nfunction createConstantProperty(value) {\r\n return new ConstantProperty(value);\r\n}\r\n\r\n/**\r\n * Used to consistently define all DataSources graphics objects.\r\n * This is broken into two functions because the Chrome profiler does a better\r\n * job of optimizing lookups if it notices that the string is constant throughout the function.\r\n * @private\r\n */\r\nfunction createPropertyDescriptor(name, configurable, createPropertyCallback) {\r\n //Safari 8.0.3 has a JavaScript bug that causes it to confuse two variables and treat them as the same.\r\n //The two extra toString calls work around the issue.\r\n return createProperty(\r\n name,\r\n \"_\" + name.toString(),\r\n \"_\" + name.toString() + \"Subscription\",\r\n defaultValue(configurable, false),\r\n defaultValue(createPropertyCallback, createConstantProperty)\r\n );\r\n}\r\nexport default createPropertyDescriptor;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} BillboardGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the BillboardGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the billboard.\r\n * @property {Property | string | HTMLCanvasElement} [image] A Property specifying the Image, URI, or Canvas to use for the billboard.\r\n * @property {Property | number} [scale=1.0] A numeric Property specifying the scale to apply to the image size.\r\n * @property {Property | Cartesian2} [pixelOffset=Cartesian2.ZERO] A {@link Cartesian2} Property specifying the pixel offset.\r\n * @property {Property | Cartesian3} [eyeOffset=Cartesian3.ZERO] A {@link Cartesian3} Property specifying the eye offset.\r\n * @property {Property | HorizontalOrigin} [horizontalOrigin=HorizontalOrigin.CENTER] A Property specifying the {@link HorizontalOrigin}.\r\n * @property {Property | VerticalOrigin} [verticalOrigin=VerticalOrigin.CENTER] A Property specifying the {@link VerticalOrigin}.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height is relative to.\r\n * @property {Property | Color} [color=Color.WHITE] A Property specifying the tint {@link Color} of the image.\r\n * @property {Property | number} [rotation=0] A numeric Property specifying the rotation about the alignedAxis.\r\n * @property {Property | Cartesian3} [alignedAxis=Cartesian3.ZERO] A {@link Cartesian3} Property specifying the unit vector axis of rotation.\r\n * @property {Property | boolean} [sizeInMeters] A boolean Property specifying whether this billboard's size should be measured in meters.\r\n * @property {Property | number} [width] A numeric Property specifying the width of the billboard in pixels, overriding the native size.\r\n * @property {Property | number} [height] A numeric Property specifying the height of the billboard in pixels, overriding the native size.\r\n * @property {Property | NearFarScalar} [scaleByDistance] A {@link NearFarScalar} Property used to scale the point based on distance from the camera.\r\n * @property {Property | NearFarScalar} [translucencyByDistance] A {@link NearFarScalar} Property used to set translucency based on distance from the camera.\r\n * @property {Property | NearFarScalar} [pixelOffsetScaleByDistance] A {@link NearFarScalar} Property used to set pixelOffset based on distance from the camera.\r\n * @property {Property | BoundingRectangle} [imageSubRegion] A Property specifying a {@link BoundingRectangle} that defines a sub-region of the image to use for the billboard, rather than the entire image, measured in pixels from the bottom-left.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this billboard will be displayed.\r\n * @property {Property | number} [disableDepthTestDistance] A Property specifying the distance from the camera at which to disable the depth test to.\r\n */\r\n\r\n/**\r\n * Describes a two dimensional icon located at the position of the containing {@link Entity}.\r\n *

\r\n *

\r\n *
\r\n * Example billboards\r\n *
\r\n *

\r\n *\r\n * @alias BillboardGraphics\r\n * @constructor\r\n *\r\n * @param {BillboardGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Billboards.html|Cesium Sandcastle Billboard Demo}\r\n */\r\nfunction BillboardGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._image = undefined;\r\n this._imageSubscription = undefined;\r\n this._scale = undefined;\r\n this._scaleSubscription = undefined;\r\n this._pixelOffset = undefined;\r\n this._pixelOffsetSubscription = undefined;\r\n this._eyeOffset = undefined;\r\n this._eyeOffsetSubscription = undefined;\r\n this._horizontalOrigin = undefined;\r\n this._horizontalOriginSubscription = undefined;\r\n this._verticalOrigin = undefined;\r\n this._verticalOriginSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n this._rotation = undefined;\r\n this._rotationSubscription = undefined;\r\n this._alignedAxis = undefined;\r\n this._alignedAxisSubscription = undefined;\r\n this._sizeInMeters = undefined;\r\n this._sizeInMetersSubscription = undefined;\r\n this._width = undefined;\r\n this._widthSubscription = undefined;\r\n this._height = undefined;\r\n this._heightSubscription = undefined;\r\n this._scaleByDistance = undefined;\r\n this._scaleByDistanceSubscription = undefined;\r\n this._translucencyByDistance = undefined;\r\n this._translucencyByDistanceSubscription = undefined;\r\n this._pixelOffsetScaleByDistance = undefined;\r\n this._pixelOffsetScaleByDistanceSubscription = undefined;\r\n this._imageSubRegion = undefined;\r\n this._imageSubRegionSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n this._disableDepthTestDistance = undefined;\r\n this._disableDepthTestDistanceSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(BillboardGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof BillboardGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the billboard.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the Image, URI, or Canvas to use for the billboard.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n image: createPropertyDescriptor(\"image\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the uniform scale to apply to the image.\r\n * A scale greater than 1.0 enlarges the billboard while a scale less than 1.0 shrinks it.\r\n *

\r\n *

\r\n *
\r\n * From left to right in the above image, the scales are 0.5, 1.0, and 2.0.\r\n *
\r\n *

\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n scale: createPropertyDescriptor(\"scale\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying the billboard's pixel offset in screen space\r\n * from the origin of this billboard. This is commonly used to align multiple billboards and labels at\r\n * the same position, e.g., an image and text. The screen space origin is the top, left corner of the\r\n * canvas; x increases from left to right, and y increases from top to bottom.\r\n *

\r\n *

\r\n * \r\n * \r\n * \r\n *
default
b.pixeloffset = new Cartesian2(50, 25);
\r\n * The billboard's origin is indicated by the yellow point.\r\n *
\r\n *

\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Cartesian2.ZERO\r\n */\r\n pixelOffset: createPropertyDescriptor(\"pixelOffset\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian3} Property specifying the billboard's offset in eye coordinates.\r\n * Eye coordinates is a left-handed coordinate system, where x points towards the viewer's\r\n * right, y points up, and z points into the screen.\r\n *

\r\n * An eye offset is commonly used to arrange multiple billboards or objects at the same position, e.g., to\r\n * arrange a billboard above its corresponding 3D model.\r\n *

\r\n * Below, the billboard is positioned at the center of the Earth but an eye offset makes it always\r\n * appear on top of the Earth regardless of the viewer's or Earth's orientation.\r\n *

\r\n *

\r\n * \r\n * \r\n * \r\n *
\r\n * b.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);\r\n *
\r\n *

\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Cartesian3.ZERO\r\n */\r\n eyeOffset: createPropertyDescriptor(\"eyeOffset\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HorizontalOrigin}.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HorizontalOrigin.CENTER\r\n */\r\n horizontalOrigin: createPropertyDescriptor(\"horizontalOrigin\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link VerticalOrigin}.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default VerticalOrigin.CENTER\r\n */\r\n verticalOrigin: createPropertyDescriptor(\"verticalOrigin\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} that is multiplied with the image.\r\n * This has two common use cases. First, the same white texture may be used by many different billboards,\r\n * each with a different color, to create colored billboards. Second, the color's alpha component can be\r\n * used to make the billboard translucent as shown below. An alpha of 0.0 makes the billboard\r\n * transparent, and 1.0 makes the billboard opaque.\r\n *

\r\n *

\r\n * \r\n * \r\n * \r\n *
default
alpha : 0.5
\r\n *
\r\n *

\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the rotation of the image\r\n * counter clockwise from the alignedAxis.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0\r\n */\r\n rotation: createPropertyDescriptor(\"rotation\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian3} Property specifying the unit vector axis of rotation\r\n * in the fixed frame. When set to Cartesian3.ZERO the rotation is from the top of the screen.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Cartesian3.ZERO\r\n */\r\n alignedAxis: createPropertyDescriptor(\"alignedAxis\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying if this billboard's size will be measured in meters.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n sizeInMeters: createPropertyDescriptor(\"sizeInMeters\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the billboard in pixels.\r\n * When undefined, the native width is used.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n width: createPropertyDescriptor(\"width\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the height of the billboard in pixels.\r\n * When undefined, the native height is used.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n height: createPropertyDescriptor(\"height\"),\r\n\r\n /**\r\n * Gets or sets {@link NearFarScalar} Property specifying the scale of the billboard based on the distance from the camera.\r\n * A billboard's scale will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the billboard's scale remains clamped to the nearest bound.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n scaleByDistance: createPropertyDescriptor(\"scaleByDistance\"),\r\n\r\n /**\r\n * Gets or sets {@link NearFarScalar} Property specifying the translucency of the billboard based on the distance from the camera.\r\n * A billboard's translucency will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the billboard's translucency remains clamped to the nearest bound.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n translucencyByDistance: createPropertyDescriptor(\"translucencyByDistance\"),\r\n\r\n /**\r\n * Gets or sets {@link NearFarScalar} Property specifying the pixel offset of the billboard based on the distance from the camera.\r\n * A billboard's pixel offset will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the billboard's pixel offset remains clamped to the nearest bound.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n pixelOffsetScaleByDistance: createPropertyDescriptor(\r\n \"pixelOffsetScaleByDistance\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the Property specifying a {@link BoundingRectangle} that defines a\r\n * sub-region of the image to use for the billboard, rather than the entire image,\r\n * measured in pixels from the bottom-left.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n imageSubRegion: createPropertyDescriptor(\"imageSubRegion\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this billboard will be displayed.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.\r\n * When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.\r\n * @memberof BillboardGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n disableDepthTestDistance: createPropertyDescriptor(\r\n \"disableDepthTestDistance\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {BillboardGraphics} [result] The object onto which to store the result.\r\n * @returns {BillboardGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nBillboardGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new BillboardGraphics(this);\r\n }\r\n result.show = this._show;\r\n result.image = this._image;\r\n result.scale = this._scale;\r\n result.pixelOffset = this._pixelOffset;\r\n result.eyeOffset = this._eyeOffset;\r\n result.horizontalOrigin = this._horizontalOrigin;\r\n result.verticalOrigin = this._verticalOrigin;\r\n result.heightReference = this._heightReference;\r\n result.color = this._color;\r\n result.rotation = this._rotation;\r\n result.alignedAxis = this._alignedAxis;\r\n result.sizeInMeters = this._sizeInMeters;\r\n result.width = this._width;\r\n result.height = this._height;\r\n result.scaleByDistance = this._scaleByDistance;\r\n result.translucencyByDistance = this._translucencyByDistance;\r\n result.pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance;\r\n result.imageSubRegion = this._imageSubRegion;\r\n result.distanceDisplayCondition = this._distanceDisplayCondition;\r\n result.disableDepthTestDistance = this._disableDepthTestDistance;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {BillboardGraphics} source The object to be merged into this object.\r\n */\r\nBillboardGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this._show, source.show);\r\n this.image = defaultValue(this._image, source.image);\r\n this.scale = defaultValue(this._scale, source.scale);\r\n this.pixelOffset = defaultValue(this._pixelOffset, source.pixelOffset);\r\n this.eyeOffset = defaultValue(this._eyeOffset, source.eyeOffset);\r\n this.horizontalOrigin = defaultValue(\r\n this._horizontalOrigin,\r\n source.horizontalOrigin\r\n );\r\n this.verticalOrigin = defaultValue(\r\n this._verticalOrigin,\r\n source.verticalOrigin\r\n );\r\n this.heightReference = defaultValue(\r\n this._heightReference,\r\n source.heightReference\r\n );\r\n this.color = defaultValue(this._color, source.color);\r\n this.rotation = defaultValue(this._rotation, source.rotation);\r\n this.alignedAxis = defaultValue(this._alignedAxis, source.alignedAxis);\r\n this.sizeInMeters = defaultValue(this._sizeInMeters, source.sizeInMeters);\r\n this.width = defaultValue(this._width, source.width);\r\n this.height = defaultValue(this._height, source.height);\r\n this.scaleByDistance = defaultValue(\r\n this._scaleByDistance,\r\n source.scaleByDistance\r\n );\r\n this.translucencyByDistance = defaultValue(\r\n this._translucencyByDistance,\r\n source.translucencyByDistance\r\n );\r\n this.pixelOffsetScaleByDistance = defaultValue(\r\n this._pixelOffsetScaleByDistance,\r\n source.pixelOffsetScaleByDistance\r\n );\r\n this.imageSubRegion = defaultValue(\r\n this._imageSubRegion,\r\n source.imageSubRegion\r\n );\r\n this.distanceDisplayCondition = defaultValue(\r\n this._distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.disableDepthTestDistance = defaultValue(\r\n this._disableDepthTestDistance,\r\n source.disableDepthTestDistance\r\n );\r\n};\r\nexport default BillboardGraphics;\r\n","/**\r\n * Represents the position relative to the terrain.\r\n *\r\n * @enum {Number}\r\n */\r\nvar HeightReference = {\r\n /**\r\n * The position is absolute.\r\n * @type {Number}\r\n * @constant\r\n */\r\n NONE: 0,\r\n\r\n /**\r\n * The position is clamped to the terrain.\r\n * @type {Number}\r\n * @constant\r\n */\r\n CLAMP_TO_GROUND: 1,\r\n\r\n /**\r\n * The position height is the height above the terrain.\r\n * @type {Number}\r\n * @constant\r\n */\r\n RELATIVE_TO_GROUND: 2,\r\n};\r\nexport default Object.freeze(HeightReference);\r\n","/**\r\n * The horizontal location of an origin relative to an object, e.g., a {@link Billboard}\r\n * or {@link Label}. For example, setting the horizontal origin to LEFT\r\n * or RIGHT will display a billboard to the left or right (in screen space)\r\n * of the anchor position.\r\n *

\r\n *
\r\n *
\r\n *
\r\n *\r\n * @enum {Number}\r\n *\r\n * @see Billboard#horizontalOrigin\r\n * @see Label#horizontalOrigin\r\n */\r\nvar HorizontalOrigin = {\r\n /**\r\n * The origin is at the horizontal center of the object.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CENTER: 0,\r\n\r\n /**\r\n * The origin is on the left side of the object.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LEFT: 1,\r\n\r\n /**\r\n * The origin is on the right side of the object.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RIGHT: -1,\r\n};\r\nexport default Object.freeze(HorizontalOrigin);\r\n","/**\r\n * The vertical location of an origin relative to an object, e.g., a {@link Billboard}\r\n * or {@link Label}. For example, setting the vertical origin to TOP\r\n * or BOTTOM will display a billboard above or below (in screen space)\r\n * the anchor position.\r\n *

\r\n *
\r\n *
\r\n *
\r\n *\r\n * @enum {Number}\r\n *\r\n * @see Billboard#verticalOrigin\r\n * @see Label#verticalOrigin\r\n */\r\nvar VerticalOrigin = {\r\n /**\r\n * The origin is at the vertical center between BASELINE and TOP.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CENTER: 0,\r\n\r\n /**\r\n * The origin is at the bottom of the object.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n BOTTOM: 1,\r\n\r\n /**\r\n * If the object contains text, the origin is at the baseline of the text, else the origin is at the bottom of the object.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n BASELINE: 2,\r\n\r\n /**\r\n * The origin is at the top of the object.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n TOP: -1,\r\n};\r\nexport default Object.freeze(VerticalOrigin);\r\n","/**\r\n * The state of a BoundingSphere computation being performed by a {@link Visualizer}.\r\n * @enum {Number}\r\n * @private\r\n */\r\nvar BoundingSphereState = {\r\n /**\r\n * The BoundingSphere has been computed.\r\n * @type BoundingSphereState\r\n * @constant\r\n */\r\n DONE: 0,\r\n /**\r\n * The BoundingSphere is still being computed.\r\n * @type BoundingSphereState\r\n * @constant\r\n */\r\n PENDING: 1,\r\n /**\r\n * The BoundingSphere does not exist.\r\n * @type BoundingSphereState\r\n * @constant\r\n */\r\n FAILED: 2,\r\n};\r\nexport default Object.freeze(BoundingSphereState);\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\n\r\n/**\r\n * The interface for all properties, which represent a value that can optionally vary over time.\r\n * This type defines an interface and cannot be instantiated directly.\r\n *\r\n * @alias Property\r\n * @constructor\r\n * @abstract\r\n *\r\n * @see CompositeProperty\r\n * @see ConstantProperty\r\n * @see SampledProperty\r\n * @see TimeIntervalCollectionProperty\r\n * @see MaterialProperty\r\n * @see PositionProperty\r\n * @see ReferenceProperty\r\n */\r\nfunction Property() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\nObject.defineProperties(Property.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof Property.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof Property.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n * @function\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nProperty.prototype.getValue = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n * @function\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nProperty.prototype.equals = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * @private\r\n */\r\nProperty.equals = function (left, right) {\r\n return left === right || (defined(left) && left.equals(right));\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nProperty.arrayEquals = function (left, right) {\r\n if (left === right) {\r\n return true;\r\n }\r\n if (!defined(left) || !defined(right) || left.length !== right.length) {\r\n return false;\r\n }\r\n var length = left.length;\r\n for (var i = 0; i < length; i++) {\r\n if (!Property.equals(left[i], right[i])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nProperty.isConstant = function (property) {\r\n return !defined(property) || property.isConstant;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nProperty.getValueOrUndefined = function (property, time, result) {\r\n return defined(property) ? property.getValue(time, result) : undefined;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nProperty.getValueOrDefault = function (property, time, valueDefault, result) {\r\n return defined(property)\r\n ? defaultValue(property.getValue(time, result), valueDefault)\r\n : valueDefault;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nProperty.getValueOrClonedDefault = function (\r\n property,\r\n time,\r\n valueDefault,\r\n result\r\n) {\r\n var value;\r\n if (defined(property)) {\r\n value = property.getValue(time, result);\r\n }\r\n if (!defined(value)) {\r\n value = valueDefault.clone(value);\r\n }\r\n return value;\r\n};\r\nexport default Property;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport NearFarScalar from \"../Core/NearFarScalar.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport HorizontalOrigin from \"../Scene/HorizontalOrigin.js\";\r\nimport VerticalOrigin from \"../Scene/VerticalOrigin.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultColor = Color.WHITE;\r\nvar defaultEyeOffset = Cartesian3.ZERO;\r\nvar defaultHeightReference = HeightReference.NONE;\r\nvar defaultPixelOffset = Cartesian2.ZERO;\r\nvar defaultScale = 1.0;\r\nvar defaultRotation = 0.0;\r\nvar defaultAlignedAxis = Cartesian3.ZERO;\r\nvar defaultHorizontalOrigin = HorizontalOrigin.CENTER;\r\nvar defaultVerticalOrigin = VerticalOrigin.CENTER;\r\nvar defaultSizeInMeters = false;\r\n\r\nvar positionScratch = new Cartesian3();\r\nvar colorScratch = new Color();\r\nvar eyeOffsetScratch = new Cartesian3();\r\nvar pixelOffsetScratch = new Cartesian2();\r\nvar scaleByDistanceScratch = new NearFarScalar();\r\nvar translucencyByDistanceScratch = new NearFarScalar();\r\nvar pixelOffsetScaleByDistanceScratch = new NearFarScalar();\r\nvar boundingRectangleScratch = new BoundingRectangle();\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\n\r\nfunction EntityData(entity) {\r\n this.entity = entity;\r\n this.billboard = undefined;\r\n this.textureValue = undefined;\r\n}\r\n\r\n/**\r\n * A {@link Visualizer} which maps {@link Entity#billboard} to a {@link Billboard}.\r\n * @alias BillboardVisualizer\r\n * @constructor\r\n *\r\n * @param {EntityCluster} entityCluster The entity cluster to manage the collection of billboards and optionally cluster with other entities.\r\n * @param {EntityCollection} entityCollection The entityCollection to visualize.\r\n */\r\nfunction BillboardVisualizer(entityCluster, entityCollection) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entityCluster)) {\r\n throw new DeveloperError(\"entityCluster is required.\");\r\n }\r\n if (!defined(entityCollection)) {\r\n throw new DeveloperError(\"entityCollection is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n entityCollection.collectionChanged.addEventListener(\r\n BillboardVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n\r\n this._cluster = entityCluster;\r\n this._entityCollection = entityCollection;\r\n this._items = new AssociativeArray();\r\n this._onCollectionChanged(entityCollection, entityCollection.values, [], []);\r\n}\r\n\r\n/**\r\n * Updates the primitives created by this visualizer to match their\r\n * Entity counterpart at the given time.\r\n *\r\n * @param {JulianDate} time The time to update to.\r\n * @returns {Boolean} This function always returns true.\r\n */\r\nBillboardVisualizer.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var items = this._items.values;\r\n var cluster = this._cluster;\r\n\r\n for (var i = 0, len = items.length; i < len; i++) {\r\n var item = items[i];\r\n var entity = item.entity;\r\n var billboardGraphics = entity._billboard;\r\n var textureValue;\r\n var billboard = item.billboard;\r\n var show =\r\n entity.isShowing &&\r\n entity.isAvailable(time) &&\r\n Property.getValueOrDefault(billboardGraphics._show, time, true);\r\n var position;\r\n if (show) {\r\n position = Property.getValueOrUndefined(\r\n entity._position,\r\n time,\r\n positionScratch\r\n );\r\n textureValue = Property.getValueOrUndefined(\r\n billboardGraphics._image,\r\n time\r\n );\r\n show = defined(position) && defined(textureValue);\r\n }\r\n\r\n if (!show) {\r\n //don't bother creating or updating anything else\r\n returnPrimitive(item, entity, cluster);\r\n continue;\r\n }\r\n\r\n if (!Property.isConstant(entity._position)) {\r\n cluster._clusterDirty = true;\r\n }\r\n\r\n if (!defined(billboard)) {\r\n billboard = cluster.getBillboard(entity);\r\n billboard.id = entity;\r\n billboard.image = undefined;\r\n item.billboard = billboard;\r\n }\r\n\r\n billboard.show = show;\r\n if (!defined(billboard.image) || item.textureValue !== textureValue) {\r\n billboard.image = textureValue;\r\n item.textureValue = textureValue;\r\n }\r\n billboard.position = position;\r\n billboard.color = Property.getValueOrDefault(\r\n billboardGraphics._color,\r\n time,\r\n defaultColor,\r\n colorScratch\r\n );\r\n billboard.eyeOffset = Property.getValueOrDefault(\r\n billboardGraphics._eyeOffset,\r\n time,\r\n defaultEyeOffset,\r\n eyeOffsetScratch\r\n );\r\n billboard.heightReference = Property.getValueOrDefault(\r\n billboardGraphics._heightReference,\r\n time,\r\n defaultHeightReference\r\n );\r\n billboard.pixelOffset = Property.getValueOrDefault(\r\n billboardGraphics._pixelOffset,\r\n time,\r\n defaultPixelOffset,\r\n pixelOffsetScratch\r\n );\r\n billboard.scale = Property.getValueOrDefault(\r\n billboardGraphics._scale,\r\n time,\r\n defaultScale\r\n );\r\n billboard.rotation = Property.getValueOrDefault(\r\n billboardGraphics._rotation,\r\n time,\r\n defaultRotation\r\n );\r\n billboard.alignedAxis = Property.getValueOrDefault(\r\n billboardGraphics._alignedAxis,\r\n time,\r\n defaultAlignedAxis\r\n );\r\n billboard.horizontalOrigin = Property.getValueOrDefault(\r\n billboardGraphics._horizontalOrigin,\r\n time,\r\n defaultHorizontalOrigin\r\n );\r\n billboard.verticalOrigin = Property.getValueOrDefault(\r\n billboardGraphics._verticalOrigin,\r\n time,\r\n defaultVerticalOrigin\r\n );\r\n billboard.width = Property.getValueOrUndefined(\r\n billboardGraphics._width,\r\n time\r\n );\r\n billboard.height = Property.getValueOrUndefined(\r\n billboardGraphics._height,\r\n time\r\n );\r\n billboard.scaleByDistance = Property.getValueOrUndefined(\r\n billboardGraphics._scaleByDistance,\r\n time,\r\n scaleByDistanceScratch\r\n );\r\n billboard.translucencyByDistance = Property.getValueOrUndefined(\r\n billboardGraphics._translucencyByDistance,\r\n time,\r\n translucencyByDistanceScratch\r\n );\r\n billboard.pixelOffsetScaleByDistance = Property.getValueOrUndefined(\r\n billboardGraphics._pixelOffsetScaleByDistance,\r\n time,\r\n pixelOffsetScaleByDistanceScratch\r\n );\r\n billboard.sizeInMeters = Property.getValueOrDefault(\r\n billboardGraphics._sizeInMeters,\r\n time,\r\n defaultSizeInMeters\r\n );\r\n billboard.distanceDisplayCondition = Property.getValueOrUndefined(\r\n billboardGraphics._distanceDisplayCondition,\r\n time,\r\n distanceDisplayConditionScratch\r\n );\r\n billboard.disableDepthTestDistance = Property.getValueOrUndefined(\r\n billboardGraphics._disableDepthTestDistance,\r\n time\r\n );\r\n\r\n var subRegion = Property.getValueOrUndefined(\r\n billboardGraphics._imageSubRegion,\r\n time,\r\n boundingRectangleScratch\r\n );\r\n if (defined(subRegion)) {\r\n billboard.setImageSubRegion(billboard._imageId, subRegion);\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n *\r\n * @param {Entity} entity The entity whose bounding sphere to compute.\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nBillboardVisualizer.prototype.getBoundingSphere = function (entity, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entity)) {\r\n throw new DeveloperError(\"entity is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var item = this._items.get(entity.id);\r\n if (!defined(item) || !defined(item.billboard)) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n var billboard = item.billboard;\r\n if (billboard.heightReference === HeightReference.NONE) {\r\n result.center = Cartesian3.clone(billboard.position, result.center);\r\n } else {\r\n if (!defined(billboard._clampedPosition)) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n result.center = Cartesian3.clone(billboard._clampedPosition, result.center);\r\n }\r\n result.radius = 0;\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nBillboardVisualizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys all primitives created by this instance.\r\n */\r\nBillboardVisualizer.prototype.destroy = function () {\r\n this._entityCollection.collectionChanged.removeEventListener(\r\n BillboardVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n var entities = this._entityCollection.values;\r\n for (var i = 0; i < entities.length; i++) {\r\n this._cluster.removeBillboard(entities[i]);\r\n }\r\n return destroyObject(this);\r\n};\r\n\r\nBillboardVisualizer.prototype._onCollectionChanged = function (\r\n entityCollection,\r\n added,\r\n removed,\r\n changed\r\n) {\r\n var i;\r\n var entity;\r\n var items = this._items;\r\n var cluster = this._cluster;\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n if (defined(entity._billboard) && defined(entity._position)) {\r\n items.set(entity.id, new EntityData(entity));\r\n }\r\n }\r\n\r\n for (i = changed.length - 1; i > -1; i--) {\r\n entity = changed[i];\r\n if (defined(entity._billboard) && defined(entity._position)) {\r\n if (!items.contains(entity.id)) {\r\n items.set(entity.id, new EntityData(entity));\r\n }\r\n } else {\r\n returnPrimitive(items.get(entity.id), entity, cluster);\r\n items.remove(entity.id);\r\n }\r\n }\r\n\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n returnPrimitive(items.get(entity.id), entity, cluster);\r\n items.remove(entity.id);\r\n }\r\n};\r\n\r\nfunction returnPrimitive(item, entity, cluster) {\r\n if (defined(item)) {\r\n item.billboard = undefined;\r\n cluster.removeBillboard(entity);\r\n }\r\n}\r\nexport default BillboardVisualizer;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec3 v_positionEC;\\n\\\nvarying vec3 v_normalEC;\\n\\\nvarying vec3 v_tangentEC;\\n\\\nvarying vec3 v_bitangentEC;\\n\\\nvarying vec2 v_st;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec3 positionToEyeEC = -v_positionEC;\\n\\\nmat3 tangentToEyeMatrix = czm_tangentToEyeSpaceMatrix(v_normalEC, v_tangentEC, v_bitangentEC);\\n\\\nvec3 normalEC = normalize(v_normalEC);\\n\\\n#ifdef FACE_FORWARD\\n\\\nnormalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\\n\\\n#endif\\n\\\nczm_materialInput materialInput;\\n\\\nmaterialInput.normalEC = normalEC;\\n\\\nmaterialInput.tangentToEyeMatrix = tangentToEyeMatrix;\\n\\\nmaterialInput.positionToEyeEC = positionToEyeEC;\\n\\\nmaterialInput.st = v_st;\\n\\\nczm_material material = czm_getMaterial(materialInput);\\n\\\n#ifdef FLAT\\n\\\ngl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\\n\\\n#else\\n\\\ngl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec3 normal;\\n\\\nattribute vec3 tangent;\\n\\\nattribute vec3 bitangent;\\n\\\nattribute vec2 st;\\n\\\nattribute float batchId;\\n\\\nvarying vec3 v_positionEC;\\n\\\nvarying vec3 v_normalEC;\\n\\\nvarying vec3 v_tangentEC;\\n\\\nvarying vec3 v_bitangentEC;\\n\\\nvarying vec2 v_st;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec4 p = czm_computePosition();\\n\\\nv_positionEC = (czm_modelViewRelativeToEye * p).xyz;\\n\\\nv_normalEC = czm_normal * normal;\\n\\\nv_tangentEC = czm_normal * tangent;\\n\\\nv_bitangentEC = czm_normal * bitangent;\\n\\\nv_st = st;\\n\\\ngl_Position = czm_modelViewProjectionRelativeToEye * p;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec3 v_positionEC;\\n\\\nvarying vec3 v_normalEC;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec3 positionToEyeEC = -v_positionEC;\\n\\\nvec3 normalEC = normalize(v_normalEC);\\n\\\n#ifdef FACE_FORWARD\\n\\\nnormalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\\n\\\n#endif\\n\\\nczm_materialInput materialInput;\\n\\\nmaterialInput.normalEC = normalEC;\\n\\\nmaterialInput.positionToEyeEC = positionToEyeEC;\\n\\\nczm_material material = czm_getMaterial(materialInput);\\n\\\n#ifdef FLAT\\n\\\ngl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\\n\\\n#else\\n\\\ngl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec3 normal;\\n\\\nattribute float batchId;\\n\\\nvarying vec3 v_positionEC;\\n\\\nvarying vec3 v_normalEC;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec4 p = czm_computePosition();\\n\\\nv_positionEC = (czm_modelViewRelativeToEye * p).xyz;\\n\\\nv_normalEC = czm_normal * normal;\\n\\\ngl_Position = czm_modelViewProjectionRelativeToEye * p;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec3 v_positionEC;\\n\\\nvarying vec3 v_normalEC;\\n\\\nvarying vec2 v_st;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec3 positionToEyeEC = -v_positionEC;\\n\\\nvec3 normalEC = normalize(v_normalEC);\\n\\\n#ifdef FACE_FORWARD\\n\\\nnormalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\\n\\\n#endif\\n\\\nczm_materialInput materialInput;\\n\\\nmaterialInput.normalEC = normalEC;\\n\\\nmaterialInput.positionToEyeEC = positionToEyeEC;\\n\\\nmaterialInput.st = v_st;\\n\\\nczm_material material = czm_getMaterial(materialInput);\\n\\\n#ifdef FLAT\\n\\\ngl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\\n\\\n#else\\n\\\ngl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec3 normal;\\n\\\nattribute vec2 st;\\n\\\nattribute float batchId;\\n\\\nvarying vec3 v_positionEC;\\n\\\nvarying vec3 v_normalEC;\\n\\\nvarying vec2 v_st;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec4 p = czm_computePosition();\\n\\\nv_positionEC = (czm_modelViewRelativeToEye * p).xyz;\\n\\\nv_normalEC = czm_normal * normal;\\n\\\nv_st = st;\\n\\\ngl_Position = czm_modelViewProjectionRelativeToEye * p;\\n\\\n}\\n\\\n\";\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * Determines how two pixels' values are combined.\r\n *\r\n * @enum {Number}\r\n */\r\nvar BlendEquation = {\r\n /**\r\n * Pixel values are added componentwise. This is used in additive blending for translucency.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ADD: WebGLConstants.FUNC_ADD,\r\n\r\n /**\r\n * Pixel values are subtracted componentwise (source - destination). This is used in alpha blending for translucency.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SUBTRACT: WebGLConstants.FUNC_SUBTRACT,\r\n\r\n /**\r\n * Pixel values are subtracted componentwise (destination - source).\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n REVERSE_SUBTRACT: WebGLConstants.FUNC_REVERSE_SUBTRACT,\r\n\r\n /**\r\n * Pixel values are given to the minimum function (min(source, destination)).\r\n *\r\n * This equation operates on each pixel color component.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MIN: WebGLConstants.MIN,\r\n\r\n /**\r\n * Pixel values are given to the maximum function (max(source, destination)).\r\n *\r\n * This equation operates on each pixel color component.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MAX: WebGLConstants.MAX,\r\n};\r\nexport default Object.freeze(BlendEquation);\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * Determines how blending factors are computed.\r\n *\r\n * @enum {Number}\r\n */\r\nvar BlendFunction = {\r\n /**\r\n * The blend factor is zero.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ZERO: WebGLConstants.ZERO,\r\n\r\n /**\r\n * The blend factor is one.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ONE: WebGLConstants.ONE,\r\n\r\n /**\r\n * The blend factor is the source color.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SOURCE_COLOR: WebGLConstants.SRC_COLOR,\r\n\r\n /**\r\n * The blend factor is one minus the source color.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ONE_MINUS_SOURCE_COLOR: WebGLConstants.ONE_MINUS_SRC_COLOR,\r\n\r\n /**\r\n * The blend factor is the destination color.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n DESTINATION_COLOR: WebGLConstants.DST_COLOR,\r\n\r\n /**\r\n * The blend factor is one minus the destination color.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ONE_MINUS_DESTINATION_COLOR: WebGLConstants.ONE_MINUS_DST_COLOR,\r\n\r\n /**\r\n * The blend factor is the source alpha.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SOURCE_ALPHA: WebGLConstants.SRC_ALPHA,\r\n\r\n /**\r\n * The blend factor is one minus the source alpha.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ONE_MINUS_SOURCE_ALPHA: WebGLConstants.ONE_MINUS_SRC_ALPHA,\r\n\r\n /**\r\n * The blend factor is the destination alpha.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n DESTINATION_ALPHA: WebGLConstants.DST_ALPHA,\r\n\r\n /**\r\n * The blend factor is one minus the destination alpha.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ONE_MINUS_DESTINATION_ALPHA: WebGLConstants.ONE_MINUS_DST_ALPHA,\r\n\r\n /**\r\n * The blend factor is the constant color.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CONSTANT_COLOR: WebGLConstants.CONSTANT_COLOR,\r\n\r\n /**\r\n * The blend factor is one minus the constant color.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ONE_MINUS_CONSTANT_COLOR: WebGLConstants.ONE_MINUS_CONSTANT_COLOR,\r\n\r\n /**\r\n * The blend factor is the constant alpha.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CONSTANT_ALPHA: WebGLConstants.CONSTANT_ALPHA,\r\n\r\n /**\r\n * The blend factor is one minus the constant alpha.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ONE_MINUS_CONSTANT_ALPHA: WebGLConstants.ONE_MINUS_CONSTANT_ALPHA,\r\n\r\n /**\r\n * The blend factor is the saturated source alpha.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SOURCE_ALPHA_SATURATE: WebGLConstants.SRC_ALPHA_SATURATE,\r\n};\r\nexport default Object.freeze(BlendFunction);\r\n","import BlendEquation from \"./BlendEquation.js\";\r\nimport BlendFunction from \"./BlendFunction.js\";\r\n\r\n/**\r\n * The blending state combines {@link BlendEquation} and {@link BlendFunction} and the\r\n * enabled flag to define the full blending state for combining source and\r\n * destination fragments when rendering.\r\n *

\r\n * This is a helper when using custom render states with {@link Appearance#renderState}.\r\n *

\r\n *\r\n * @namespace\r\n */\r\nvar BlendingState = {\r\n /**\r\n * Blending is disabled.\r\n *\r\n * @type {Object}\r\n * @constant\r\n */\r\n DISABLED: Object.freeze({\r\n enabled: false,\r\n }),\r\n\r\n /**\r\n * Blending is enabled using alpha blending, source(source.alpha) + destination(1 - source.alpha).\r\n *\r\n * @type {Object}\r\n * @constant\r\n */\r\n ALPHA_BLEND: Object.freeze({\r\n enabled: true,\r\n equationRgb: BlendEquation.ADD,\r\n equationAlpha: BlendEquation.ADD,\r\n functionSourceRgb: BlendFunction.SOURCE_ALPHA,\r\n functionSourceAlpha: BlendFunction.ONE,\r\n functionDestinationRgb: BlendFunction.ONE_MINUS_SOURCE_ALPHA,\r\n functionDestinationAlpha: BlendFunction.ONE_MINUS_SOURCE_ALPHA,\r\n }),\r\n\r\n /**\r\n * Blending is enabled using alpha blending with premultiplied alpha, source + destination(1 - source.alpha).\r\n *\r\n * @type {Object}\r\n * @constant\r\n */\r\n PRE_MULTIPLIED_ALPHA_BLEND: Object.freeze({\r\n enabled: true,\r\n equationRgb: BlendEquation.ADD,\r\n equationAlpha: BlendEquation.ADD,\r\n functionSourceRgb: BlendFunction.ONE,\r\n functionSourceAlpha: BlendFunction.ONE,\r\n functionDestinationRgb: BlendFunction.ONE_MINUS_SOURCE_ALPHA,\r\n functionDestinationAlpha: BlendFunction.ONE_MINUS_SOURCE_ALPHA,\r\n }),\r\n\r\n /**\r\n * Blending is enabled using additive blending, source(source.alpha) + destination.\r\n *\r\n * @type {Object}\r\n * @constant\r\n */\r\n ADDITIVE_BLEND: Object.freeze({\r\n enabled: true,\r\n equationRgb: BlendEquation.ADD,\r\n equationAlpha: BlendEquation.ADD,\r\n functionSourceRgb: BlendFunction.SOURCE_ALPHA,\r\n functionSourceAlpha: BlendFunction.ONE,\r\n functionDestinationRgb: BlendFunction.ONE,\r\n functionDestinationAlpha: BlendFunction.ONE,\r\n }),\r\n};\r\nexport default Object.freeze(BlendingState);\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * Determines which triangles, if any, are culled.\r\n *\r\n * @enum {Number}\r\n */\r\nvar CullFace = {\r\n /**\r\n * Front-facing triangles are culled.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n FRONT: WebGLConstants.FRONT,\r\n\r\n /**\r\n * Back-facing triangles are culled.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n BACK: WebGLConstants.BACK,\r\n\r\n /**\r\n * Both front-facing and back-facing triangles are culled.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n FRONT_AND_BACK: WebGLConstants.FRONT_AND_BACK,\r\n};\r\nexport default Object.freeze(CullFace);\r\n","import clone from \"../Core/clone.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport CullFace from \"./CullFace.js\";\r\n\r\n/**\r\n * An appearance defines the full GLSL vertex and fragment shaders and the\r\n * render state used to draw a {@link Primitive}. All appearances implement\r\n * this base Appearance interface.\r\n *\r\n * @alias Appearance\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.translucent=true] When true, the geometry is expected to appear translucent so {@link Appearance#renderState} has alpha blending enabled.\r\n * @param {Boolean} [options.closed=false] When true, the geometry is expected to be closed so {@link Appearance#renderState} has backface culling enabled.\r\n * @param {Material} [options.material=Material.ColorType] The material used to determine the fragment color.\r\n * @param {String} [options.vertexShaderSource] Optional GLSL vertex shader source to override the default vertex shader.\r\n * @param {String} [options.fragmentShaderSource] Optional GLSL fragment shader source to override the default fragment shader.\r\n * @param {Object} [options.renderState] Optional render state to override the default render state.\r\n *\r\n * @see MaterialAppearance\r\n * @see EllipsoidSurfaceAppearance\r\n * @see PerInstanceColorAppearance\r\n * @see DebugAppearance\r\n * @see PolylineColorAppearance\r\n * @see PolylineMaterialAppearance\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Geometry%20and%20Appearances.html|Geometry and Appearances Demo}\r\n */\r\nfunction Appearance(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * The material used to determine the fragment color. Unlike other {@link Appearance}\r\n * properties, this is not read-only, so an appearance's material can change on the fly.\r\n *\r\n * @type Material\r\n *\r\n * @see {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}\r\n */\r\n this.material = options.material;\r\n\r\n /**\r\n * When true, the geometry is expected to appear translucent.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.translucent = defaultValue(options.translucent, true);\r\n\r\n this._vertexShaderSource = options.vertexShaderSource;\r\n this._fragmentShaderSource = options.fragmentShaderSource;\r\n this._renderState = options.renderState;\r\n this._closed = defaultValue(options.closed, false);\r\n}\r\n\r\nObject.defineProperties(Appearance.prototype, {\r\n /**\r\n * The GLSL source code for the vertex shader.\r\n *\r\n * @memberof Appearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n vertexShaderSource: {\r\n get: function () {\r\n return this._vertexShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The GLSL source code for the fragment shader. The full fragment shader\r\n * source is built procedurally taking into account the {@link Appearance#material}.\r\n * Use {@link Appearance#getFragmentShaderSource} to get the full source.\r\n *\r\n * @memberof Appearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n fragmentShaderSource: {\r\n get: function () {\r\n return this._fragmentShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The WebGL fixed-function state to use when rendering the geometry.\r\n *\r\n * @memberof Appearance.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n renderState: {\r\n get: function () {\r\n return this._renderState;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the geometry is expected to be closed.\r\n *\r\n * @memberof Appearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n closed: {\r\n get: function () {\r\n return this._closed;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Procedurally creates the full GLSL fragment shader source for this appearance\r\n * taking into account {@link Appearance#fragmentShaderSource} and {@link Appearance#material}.\r\n *\r\n * @returns {String} The full GLSL fragment shader source.\r\n */\r\nAppearance.prototype.getFragmentShaderSource = function () {\r\n var parts = [];\r\n if (this.flat) {\r\n parts.push(\"#define FLAT\");\r\n }\r\n if (this.faceForward) {\r\n parts.push(\"#define FACE_FORWARD\");\r\n }\r\n if (defined(this.material)) {\r\n parts.push(this.material.shaderSource);\r\n }\r\n parts.push(this.fragmentShaderSource);\r\n\r\n return parts.join(\"\\n\");\r\n};\r\n\r\n/**\r\n * Determines if the geometry is translucent based on {@link Appearance#translucent} and {@link Material#isTranslucent}.\r\n *\r\n * @returns {Boolean} true if the appearance is translucent.\r\n */\r\nAppearance.prototype.isTranslucent = function () {\r\n return (\r\n (defined(this.material) && this.material.isTranslucent()) ||\r\n (!defined(this.material) && this.translucent)\r\n );\r\n};\r\n\r\n/**\r\n * Creates a render state. This is not the final render state instance; instead,\r\n * it can contain a subset of render state properties identical to the render state\r\n * created in the context.\r\n *\r\n * @returns {Object} The render state.\r\n */\r\nAppearance.prototype.getRenderState = function () {\r\n var translucent = this.isTranslucent();\r\n var rs = clone(this.renderState, false);\r\n if (translucent) {\r\n rs.depthMask = false;\r\n rs.blending = BlendingState.ALPHA_BLEND;\r\n } else {\r\n rs.depthMask = true;\r\n }\r\n return rs;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nAppearance.getDefaultRenderState = function (translucent, closed, existing) {\r\n var rs = {\r\n depthTest: {\r\n enabled: true,\r\n },\r\n };\r\n\r\n if (translucent) {\r\n rs.depthMask = false;\r\n rs.blending = BlendingState.ALPHA_BLEND;\r\n }\r\n\r\n if (closed) {\r\n rs.cull = {\r\n enabled: true,\r\n face: CullFace.BACK,\r\n };\r\n }\r\n\r\n if (defined(existing)) {\r\n rs = combine(existing, rs, true);\r\n }\r\n\r\n return rs;\r\n};\r\nexport default Appearance;\r\n","/**\r\n * @private\r\n */\r\nvar ContextLimits = {\r\n _maximumCombinedTextureImageUnits: 0,\r\n _maximumCubeMapSize: 0,\r\n _maximumFragmentUniformVectors: 0,\r\n _maximumTextureImageUnits: 0,\r\n _maximumRenderbufferSize: 0,\r\n _maximumTextureSize: 0,\r\n _maximumVaryingVectors: 0,\r\n _maximumVertexAttributes: 0,\r\n _maximumVertexTextureImageUnits: 0,\r\n _maximumVertexUniformVectors: 0,\r\n _minimumAliasedLineWidth: 0,\r\n _maximumAliasedLineWidth: 0,\r\n _minimumAliasedPointSize: 0,\r\n _maximumAliasedPointSize: 0,\r\n _maximumViewportWidth: 0,\r\n _maximumViewportHeight: 0,\r\n _maximumTextureFilterAnisotropy: 0,\r\n _maximumDrawBuffers: 0,\r\n _maximumColorAttachments: 0,\r\n _highpFloatSupported: false,\r\n _highpIntSupported: false,\r\n};\r\n\r\nObject.defineProperties(ContextLimits, {\r\n /**\r\n * The maximum number of texture units that can be used from the vertex and fragment\r\n * shader with this WebGL implementation. The minimum is eight. If both shaders access the\r\n * same texture unit, this counts as two texture units.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_COMBINED_TEXTURE_IMAGE_UNITS.\r\n */\r\n maximumCombinedTextureImageUnits: {\r\n get: function () {\r\n return ContextLimits._maximumCombinedTextureImageUnits;\r\n },\r\n },\r\n\r\n /**\r\n * The approximate maximum cube mape width and height supported by this WebGL implementation.\r\n * The minimum is 16, but most desktop and laptop implementations will support much larger sizes like 8,192.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_CUBE_MAP_TEXTURE_SIZE.\r\n */\r\n maximumCubeMapSize: {\r\n get: function () {\r\n return ContextLimits._maximumCubeMapSize;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum number of vec4, ivec4, and bvec4\r\n * uniforms that can be used by a fragment shader with this WebGL implementation. The minimum is 16.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_FRAGMENT_UNIFORM_VECTORS.\r\n */\r\n maximumFragmentUniformVectors: {\r\n get: function () {\r\n return ContextLimits._maximumFragmentUniformVectors;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum number of texture units that can be used from the fragment shader with this WebGL implementation. The minimum is eight.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_TEXTURE_IMAGE_UNITS.\r\n */\r\n maximumTextureImageUnits: {\r\n get: function () {\r\n return ContextLimits._maximumTextureImageUnits;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum renderbuffer width and height supported by this WebGL implementation.\r\n * The minimum is 16, but most desktop and laptop implementations will support much larger sizes like 8,192.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_RENDERBUFFER_SIZE.\r\n */\r\n maximumRenderbufferSize: {\r\n get: function () {\r\n return ContextLimits._maximumRenderbufferSize;\r\n },\r\n },\r\n\r\n /**\r\n * The approximate maximum texture width and height supported by this WebGL implementation.\r\n * The minimum is 64, but most desktop and laptop implementations will support much larger sizes like 8,192.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_TEXTURE_SIZE.\r\n */\r\n maximumTextureSize: {\r\n get: function () {\r\n return ContextLimits._maximumTextureSize;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum number of vec4 varying variables supported by this WebGL implementation.\r\n * The minimum is eight. Matrices and arrays count as multiple vec4s.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VARYING_VECTORS.\r\n */\r\n maximumVaryingVectors: {\r\n get: function () {\r\n return ContextLimits._maximumVaryingVectors;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum number of vec4 vertex attributes supported by this WebGL implementation. The minimum is eight.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VERTEX_ATTRIBS.\r\n */\r\n maximumVertexAttributes: {\r\n get: function () {\r\n return ContextLimits._maximumVertexAttributes;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum number of texture units that can be used from the vertex shader with this WebGL implementation.\r\n * The minimum is zero, which means the GL does not support vertex texture fetch.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VERTEX_TEXTURE_IMAGE_UNITS.\r\n */\r\n maximumVertexTextureImageUnits: {\r\n get: function () {\r\n return ContextLimits._maximumVertexTextureImageUnits;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum number of vec4, ivec4, and bvec4\r\n * uniforms that can be used by a vertex shader with this WebGL implementation. The minimum is 16.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VERTEX_UNIFORM_VECTORS.\r\n */\r\n maximumVertexUniformVectors: {\r\n get: function () {\r\n return ContextLimits._maximumVertexUniformVectors;\r\n },\r\n },\r\n\r\n /**\r\n * The minimum aliased line width, in pixels, supported by this WebGL implementation. It will be at most one.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_LINE_WIDTH_RANGE.\r\n */\r\n minimumAliasedLineWidth: {\r\n get: function () {\r\n return ContextLimits._minimumAliasedLineWidth;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum aliased line width, in pixels, supported by this WebGL implementation. It will be at least one.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_LINE_WIDTH_RANGE.\r\n */\r\n maximumAliasedLineWidth: {\r\n get: function () {\r\n return ContextLimits._maximumAliasedLineWidth;\r\n },\r\n },\r\n\r\n /**\r\n * The minimum aliased point size, in pixels, supported by this WebGL implementation. It will be at most one.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_POINT_SIZE_RANGE.\r\n */\r\n minimumAliasedPointSize: {\r\n get: function () {\r\n return ContextLimits._minimumAliasedPointSize;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum aliased point size, in pixels, supported by this WebGL implementation. It will be at least one.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with ALIASED_POINT_SIZE_RANGE.\r\n */\r\n maximumAliasedPointSize: {\r\n get: function () {\r\n return ContextLimits._maximumAliasedPointSize;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum supported width of the viewport. It will be at least as large as the visible width of the associated canvas.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VIEWPORT_DIMS.\r\n */\r\n maximumViewportWidth: {\r\n get: function () {\r\n return ContextLimits._maximumViewportWidth;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum supported height of the viewport. It will be at least as large as the visible height of the associated canvas.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with MAX_VIEWPORT_DIMS.\r\n */\r\n maximumViewportHeight: {\r\n get: function () {\r\n return ContextLimits._maximumViewportHeight;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum degree of anisotropy for texture filtering\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n */\r\n maximumTextureFilterAnisotropy: {\r\n get: function () {\r\n return ContextLimits._maximumTextureFilterAnisotropy;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum number of simultaneous outputs that may be written in a fragment shader.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n */\r\n maximumDrawBuffers: {\r\n get: function () {\r\n return ContextLimits._maximumDrawBuffers;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum number of color attachments supported.\r\n * @memberof ContextLimits\r\n * @type {Number}\r\n */\r\n maximumColorAttachments: {\r\n get: function () {\r\n return ContextLimits._maximumColorAttachments;\r\n },\r\n },\r\n\r\n /**\r\n * High precision float supported (highp) in fragment shaders.\r\n * @memberof ContextLimits\r\n * @type {Boolean}\r\n */\r\n highpFloatSupported: {\r\n get: function () {\r\n return ContextLimits._highpFloatSupported;\r\n },\r\n },\r\n\r\n /**\r\n * High precision int supported (highp) in fragment shaders.\r\n * @memberof ContextLimits\r\n * @type {Boolean}\r\n */\r\n highpIntSupported: {\r\n get: function () {\r\n return ContextLimits._highpIntSupported;\r\n },\r\n },\r\n});\r\nexport default ContextLimits;\r\n","import Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport PixelDatatype from \"./PixelDatatype.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction CubeMapFace(\r\n context,\r\n texture,\r\n textureTarget,\r\n targetFace,\r\n internalFormat,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n preMultiplyAlpha,\r\n flipY,\r\n initialized\r\n) {\r\n this._context = context;\r\n this._texture = texture;\r\n this._textureTarget = textureTarget;\r\n this._targetFace = targetFace;\r\n this._pixelDatatype = pixelDatatype;\r\n this._internalFormat = internalFormat;\r\n this._pixelFormat = pixelFormat;\r\n this._size = size;\r\n this._preMultiplyAlpha = preMultiplyAlpha;\r\n this._flipY = flipY;\r\n this._initialized = initialized;\r\n}\r\n\r\nObject.defineProperties(CubeMapFace.prototype, {\r\n pixelFormat: {\r\n get: function () {\r\n return this._pixelFormat;\r\n },\r\n },\r\n pixelDatatype: {\r\n get: function () {\r\n return this._pixelDatatype;\r\n },\r\n },\r\n _target: {\r\n get: function () {\r\n return this._targetFace;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Copies texels from the source to the cubemap's face.\r\n *\r\n * @param {Object} source The source ImageData, HTMLImageElement, HTMLCanvasElement, HTMLVideoElement, or an object with a width, height, and typed array as shown in the example.\r\n * @param {Number} [xOffset=0] An offset in the x direction in the cubemap where copying begins.\r\n * @param {Number} [yOffset=0] An offset in the y direction in the cubemap where copying begins.\r\n *\r\n * @exception {DeveloperError} xOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} yOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} xOffset + source.width must be less than or equal to width.\r\n * @exception {DeveloperError} yOffset + source.height must be less than or equal to height.\r\n * @exception {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * // Create a cubemap with 1x1 faces, and make the +x face red.\r\n * var cubeMap = new CubeMap({\r\n * context : context\r\n * width : 1,\r\n * height : 1\r\n * });\r\n * cubeMap.positiveX.copyFrom({\r\n * width : 1,\r\n * height : 1,\r\n * arrayBufferView : new Uint8Array([255, 0, 0, 255])\r\n * });\r\n */\r\nCubeMapFace.prototype.copyFrom = function (source, xOffset, yOffset) {\r\n xOffset = defaultValue(xOffset, 0);\r\n yOffset = defaultValue(yOffset, 0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"source\", source);\r\n Check.typeOf.number.greaterThanOrEquals(\"xOffset\", xOffset, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\"yOffset\", yOffset, 0);\r\n if (xOffset + source.width > this._size) {\r\n throw new DeveloperError(\r\n \"xOffset + source.width must be less than or equal to width.\"\r\n );\r\n }\r\n if (yOffset + source.height > this._size) {\r\n throw new DeveloperError(\r\n \"yOffset + source.height must be less than or equal to height.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var gl = this._context._gl;\r\n var target = this._textureTarget;\r\n var targetFace = this._targetFace;\r\n\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(target, this._texture);\r\n\r\n var width = source.width;\r\n var height = source.height;\r\n var arrayBufferView = source.arrayBufferView;\r\n\r\n var size = this._size;\r\n var pixelFormat = this._pixelFormat;\r\n var internalFormat = this._internalFormat;\r\n var pixelDatatype = this._pixelDatatype;\r\n\r\n var preMultiplyAlpha = this._preMultiplyAlpha;\r\n var flipY = this._flipY;\r\n\r\n var unpackAlignment = 4;\r\n if (defined(arrayBufferView)) {\r\n unpackAlignment = PixelFormat.alignmentInBytes(\r\n pixelFormat,\r\n pixelDatatype,\r\n width\r\n );\r\n }\r\n\r\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);\r\n\r\n var uploaded = false;\r\n if (!this._initialized) {\r\n if (xOffset === 0 && yOffset === 0 && width === size && height === size) {\r\n // initialize the entire texture\r\n if (defined(arrayBufferView)) {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n if (flipY) {\r\n arrayBufferView = PixelFormat.flipY(\r\n arrayBufferView,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n size\r\n );\r\n }\r\n gl.texImage2D(\r\n targetFace,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, this._context),\r\n arrayBufferView\r\n );\r\n } else {\r\n // Only valid for DOM-Element uploads\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);\r\n\r\n gl.texImage2D(\r\n targetFace,\r\n 0,\r\n internalFormat,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, this._context),\r\n source\r\n );\r\n }\r\n uploaded = true;\r\n } else {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n // initialize the entire texture to zero\r\n var bufferView = PixelFormat.createTypedArray(\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n size\r\n );\r\n gl.texImage2D(\r\n targetFace,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, this._context),\r\n bufferView\r\n );\r\n }\r\n this._initialized = true;\r\n }\r\n\r\n if (!uploaded) {\r\n if (defined(arrayBufferView)) {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n if (flipY) {\r\n arrayBufferView = PixelFormat.flipY(\r\n arrayBufferView,\r\n pixelFormat,\r\n pixelDatatype,\r\n width,\r\n height\r\n );\r\n }\r\n gl.texSubImage2D(\r\n targetFace,\r\n 0,\r\n xOffset,\r\n yOffset,\r\n width,\r\n height,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, this._context),\r\n arrayBufferView\r\n );\r\n } else {\r\n // Only valid for DOM-Element uploads\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);\r\n\r\n // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement\r\n gl.texSubImage2D(\r\n targetFace,\r\n 0,\r\n xOffset,\r\n yOffset,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, this._context),\r\n source\r\n );\r\n }\r\n }\r\n\r\n gl.bindTexture(target, null);\r\n};\r\n\r\n/**\r\n * Copies texels from the framebuffer to the cubemap's face.\r\n *\r\n * @param {Number} [xOffset=0] An offset in the x direction in the cubemap where copying begins.\r\n * @param {Number} [yOffset=0] An offset in the y direction in the cubemap where copying begins.\r\n * @param {Number} [framebufferXOffset=0] An offset in the x direction in the framebuffer where copying begins from.\r\n * @param {Number} [framebufferYOffset=0] An offset in the y direction in the framebuffer where copying begins from.\r\n * @param {Number} [width=CubeMap's width] The width of the subimage to copy.\r\n * @param {Number} [height=CubeMap's height] The height of the subimage to copy.\r\n *\r\n * @exception {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.\r\n * @exception {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.\r\n * @exception {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.\r\n * @exception {DeveloperError} xOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} yOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} framebufferXOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} framebufferYOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} xOffset + source.width must be less than or equal to width.\r\n * @exception {DeveloperError} yOffset + source.height must be less than or equal to height.\r\n * @exception {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * // Copy the framebuffer contents to the +x cube map face.\r\n * cubeMap.positiveX.copyFromFramebuffer();\r\n */\r\nCubeMapFace.prototype.copyFromFramebuffer = function (\r\n xOffset,\r\n yOffset,\r\n framebufferXOffset,\r\n framebufferYOffset,\r\n width,\r\n height\r\n) {\r\n xOffset = defaultValue(xOffset, 0);\r\n yOffset = defaultValue(yOffset, 0);\r\n framebufferXOffset = defaultValue(framebufferXOffset, 0);\r\n framebufferYOffset = defaultValue(framebufferYOffset, 0);\r\n width = defaultValue(width, this._size);\r\n height = defaultValue(height, this._size);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"xOffset\", xOffset, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\"yOffset\", yOffset, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"framebufferXOffset\",\r\n framebufferXOffset,\r\n 0\r\n );\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"framebufferYOffset\",\r\n framebufferYOffset,\r\n 0\r\n );\r\n if (xOffset + width > this._size) {\r\n throw new DeveloperError(\r\n \"xOffset + source.width must be less than or equal to width.\"\r\n );\r\n }\r\n if (yOffset + height > this._size) {\r\n throw new DeveloperError(\r\n \"yOffset + source.height must be less than or equal to height.\"\r\n );\r\n }\r\n if (this._pixelDatatype === PixelDatatype.FLOAT) {\r\n throw new DeveloperError(\r\n \"Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.\"\r\n );\r\n }\r\n if (this._pixelDatatype === PixelDatatype.HALF_FLOAT) {\r\n throw new DeveloperError(\r\n \"Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var gl = this._context._gl;\r\n var target = this._textureTarget;\r\n\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(target, this._texture);\r\n gl.copyTexSubImage2D(\r\n this._targetFace,\r\n 0,\r\n xOffset,\r\n yOffset,\r\n framebufferXOffset,\r\n framebufferYOffset,\r\n width,\r\n height\r\n );\r\n gl.bindTexture(target, null);\r\n this._initialized = true;\r\n};\r\nexport default CubeMapFace;\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar MipmapHint = {\r\n DONT_CARE: WebGLConstants.DONT_CARE,\r\n FASTEST: WebGLConstants.FASTEST,\r\n NICEST: WebGLConstants.NICEST,\r\n\r\n validate: function (mipmapHint) {\r\n return (\r\n mipmapHint === MipmapHint.DONT_CARE ||\r\n mipmapHint === MipmapHint.FASTEST ||\r\n mipmapHint === MipmapHint.NICEST\r\n );\r\n },\r\n};\r\nexport default Object.freeze(MipmapHint);\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * Enumerates all possible filters used when magnifying WebGL textures.\r\n *\r\n * @enum {Number}\r\n *\r\n * @see TextureMinificationFilter\r\n */\r\nvar TextureMagnificationFilter = {\r\n /**\r\n * Samples the texture by returning the closest pixel.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NEAREST: WebGLConstants.NEAREST,\r\n /**\r\n * Samples the texture through bi-linear interpolation of the four nearest pixels. This produces smoother results than NEAREST filtering.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LINEAR: WebGLConstants.LINEAR,\r\n};\r\n\r\n/**\r\n * Validates the given textureMinificationFilter with respect to the possible enum values.\r\n * @param textureMagnificationFilter\r\n * @returns {Boolean} true if textureMagnificationFilter is valid.\r\n *\r\n * @private\r\n */\r\nTextureMagnificationFilter.validate = function (textureMagnificationFilter) {\r\n return (\r\n textureMagnificationFilter === TextureMagnificationFilter.NEAREST ||\r\n textureMagnificationFilter === TextureMagnificationFilter.LINEAR\r\n );\r\n};\r\n\r\nexport default Object.freeze(TextureMagnificationFilter);\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * Enumerates all possible filters used when minifying WebGL textures.\r\n *\r\n * @enum {Number}\r\n *\r\n * @see TextureMagnificationFilter\r\n */\r\nvar TextureMinificationFilter = {\r\n /**\r\n * Samples the texture by returning the closest pixel.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NEAREST: WebGLConstants.NEAREST,\r\n /**\r\n * Samples the texture through bi-linear interpolation of the four nearest pixels. This produces smoother results than NEAREST filtering.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LINEAR: WebGLConstants.LINEAR,\r\n /**\r\n * Selects the nearest mip level and applies nearest sampling within that level.\r\n *

\r\n * Requires that the texture has a mipmap. The mip level is chosen by the view angle and screen-space size of the texture.\r\n *

\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NEAREST_MIPMAP_NEAREST: WebGLConstants.NEAREST_MIPMAP_NEAREST,\r\n /**\r\n * Selects the nearest mip level and applies linear sampling within that level.\r\n *

\r\n * Requires that the texture has a mipmap. The mip level is chosen by the view angle and screen-space size of the texture.\r\n *

\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LINEAR_MIPMAP_NEAREST: WebGLConstants.LINEAR_MIPMAP_NEAREST,\r\n /**\r\n * Read texture values with nearest sampling from two adjacent mip levels and linearly interpolate the results.\r\n *

\r\n * This option provides a good balance of visual quality and speed when sampling from a mipmapped texture.\r\n *

\r\n *

\r\n * Requires that the texture has a mipmap. The mip level is chosen by the view angle and screen-space size of the texture.\r\n *

\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NEAREST_MIPMAP_LINEAR: WebGLConstants.NEAREST_MIPMAP_LINEAR,\r\n /**\r\n * Read texture values with linear sampling from two adjacent mip levels and linearly interpolate the results.\r\n *

\r\n * This option provides a good balance of visual quality and speed when sampling from a mipmapped texture.\r\n *

\r\n *

\r\n * Requires that the texture has a mipmap. The mip level is chosen by the view angle and screen-space size of the texture.\r\n *

\r\n * @type {Number}\r\n * @constant\r\n */\r\n LINEAR_MIPMAP_LINEAR: WebGLConstants.LINEAR_MIPMAP_LINEAR,\r\n};\r\n\r\n/**\r\n * Validates the given textureMinificationFilter with respect to the possible enum values.\r\n *\r\n * @private\r\n *\r\n * @param textureMinificationFilter\r\n * @returns {Boolean} true if textureMinificationFilter is valid.\r\n */\r\nTextureMinificationFilter.validate = function (textureMinificationFilter) {\r\n return (\r\n textureMinificationFilter === TextureMinificationFilter.NEAREST ||\r\n textureMinificationFilter === TextureMinificationFilter.LINEAR ||\r\n textureMinificationFilter ===\r\n TextureMinificationFilter.NEAREST_MIPMAP_NEAREST ||\r\n textureMinificationFilter ===\r\n TextureMinificationFilter.LINEAR_MIPMAP_NEAREST ||\r\n textureMinificationFilter ===\r\n TextureMinificationFilter.NEAREST_MIPMAP_LINEAR ||\r\n textureMinificationFilter === TextureMinificationFilter.LINEAR_MIPMAP_LINEAR\r\n );\r\n};\r\n\r\nexport default Object.freeze(TextureMinificationFilter);\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar TextureWrap = {\r\n CLAMP_TO_EDGE: WebGLConstants.CLAMP_TO_EDGE,\r\n REPEAT: WebGLConstants.REPEAT,\r\n MIRRORED_REPEAT: WebGLConstants.MIRRORED_REPEAT,\r\n\r\n validate: function (textureWrap) {\r\n return (\r\n textureWrap === TextureWrap.CLAMP_TO_EDGE ||\r\n textureWrap === TextureWrap.REPEAT ||\r\n textureWrap === TextureWrap.MIRRORED_REPEAT\r\n );\r\n },\r\n};\r\nexport default Object.freeze(TextureWrap);\r\n","import Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport TextureMagnificationFilter from \"./TextureMagnificationFilter.js\";\r\nimport TextureMinificationFilter from \"./TextureMinificationFilter.js\";\r\nimport TextureWrap from \"./TextureWrap.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Sampler(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var wrapS = defaultValue(options.wrapS, TextureWrap.CLAMP_TO_EDGE);\r\n var wrapT = defaultValue(options.wrapT, TextureWrap.CLAMP_TO_EDGE);\r\n var minificationFilter = defaultValue(\r\n options.minificationFilter,\r\n TextureMinificationFilter.LINEAR\r\n );\r\n var magnificationFilter = defaultValue(\r\n options.magnificationFilter,\r\n TextureMagnificationFilter.LINEAR\r\n );\r\n var maximumAnisotropy = defined(options.maximumAnisotropy)\r\n ? options.maximumAnisotropy\r\n : 1.0;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!TextureWrap.validate(wrapS)) {\r\n throw new DeveloperError(\"Invalid sampler.wrapS.\");\r\n }\r\n\r\n if (!TextureWrap.validate(wrapT)) {\r\n throw new DeveloperError(\"Invalid sampler.wrapT.\");\r\n }\r\n\r\n if (!TextureMinificationFilter.validate(minificationFilter)) {\r\n throw new DeveloperError(\"Invalid sampler.minificationFilter.\");\r\n }\r\n\r\n if (!TextureMagnificationFilter.validate(magnificationFilter)) {\r\n throw new DeveloperError(\"Invalid sampler.magnificationFilter.\");\r\n }\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"maximumAnisotropy\",\r\n maximumAnisotropy,\r\n 1.0\r\n );\r\n //>>includeEnd('debug');\r\n\r\n this._wrapS = wrapS;\r\n this._wrapT = wrapT;\r\n this._minificationFilter = minificationFilter;\r\n this._magnificationFilter = magnificationFilter;\r\n this._maximumAnisotropy = maximumAnisotropy;\r\n}\r\n\r\nObject.defineProperties(Sampler.prototype, {\r\n wrapS: {\r\n get: function () {\r\n return this._wrapS;\r\n },\r\n },\r\n wrapT: {\r\n get: function () {\r\n return this._wrapT;\r\n },\r\n },\r\n minificationFilter: {\r\n get: function () {\r\n return this._minificationFilter;\r\n },\r\n },\r\n magnificationFilter: {\r\n get: function () {\r\n return this._magnificationFilter;\r\n },\r\n },\r\n maximumAnisotropy: {\r\n get: function () {\r\n return this._maximumAnisotropy;\r\n },\r\n },\r\n});\r\n\r\nSampler.equals = function (left, right) {\r\n return (\r\n left === right ||\r\n (defined(left) &&\r\n defined(right) &&\r\n left._wrapS === right._wrapS &&\r\n left._wrapT === right._wrapT &&\r\n left._minificationFilter === right._minificationFilter &&\r\n left._magnificationFilter === right._magnificationFilter &&\r\n left._maximumAnisotropy === right._maximumAnisotropy)\r\n );\r\n};\r\n\r\nSampler.NEAREST = Object.freeze(\r\n new Sampler({\r\n wrapS: TextureWrap.CLAMP_TO_EDGE,\r\n wrapT: TextureWrap.CLAMP_TO_EDGE,\r\n minificationFilter: TextureMinificationFilter.NEAREST,\r\n magnificationFilter: TextureMagnificationFilter.NEAREST,\r\n })\r\n);\r\nexport default Sampler;\r\n","import Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport ContextLimits from \"./ContextLimits.js\";\r\nimport CubeMapFace from \"./CubeMapFace.js\";\r\nimport MipmapHint from \"./MipmapHint.js\";\r\nimport PixelDatatype from \"./PixelDatatype.js\";\r\nimport Sampler from \"./Sampler.js\";\r\nimport TextureMagnificationFilter from \"./TextureMagnificationFilter.js\";\r\nimport TextureMinificationFilter from \"./TextureMinificationFilter.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction CubeMap(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n //>>includeEnd('debug');\r\n\r\n var context = options.context;\r\n var source = options.source;\r\n var width;\r\n var height;\r\n\r\n if (defined(source)) {\r\n var faces = [\r\n source.positiveX,\r\n source.negativeX,\r\n source.positiveY,\r\n source.negativeY,\r\n source.positiveZ,\r\n source.negativeZ,\r\n ];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !faces[0] ||\r\n !faces[1] ||\r\n !faces[2] ||\r\n !faces[3] ||\r\n !faces[4] ||\r\n !faces[5]\r\n ) {\r\n throw new DeveloperError(\r\n \"options.source requires positiveX, negativeX, positiveY, negativeY, positiveZ, and negativeZ faces.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n width = faces[0].width;\r\n height = faces[0].height;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n for (var i = 1; i < 6; ++i) {\r\n if (\r\n Number(faces[i].width) !== width ||\r\n Number(faces[i].height) !== height\r\n ) {\r\n throw new DeveloperError(\r\n \"Each face in options.source must have the same width and height.\"\r\n );\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n } else {\r\n width = options.width;\r\n height = options.height;\r\n }\r\n\r\n var size = width;\r\n var pixelDatatype = defaultValue(\r\n options.pixelDatatype,\r\n PixelDatatype.UNSIGNED_BYTE\r\n );\r\n var pixelFormat = defaultValue(options.pixelFormat, PixelFormat.RGBA);\r\n var internalFormat = PixelFormat.toInternalFormat(\r\n pixelFormat,\r\n pixelDatatype,\r\n context\r\n );\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(width) || !defined(height)) {\r\n throw new DeveloperError(\r\n \"options requires a source field to create an initialized cube map or width and height fields to create a blank cube map.\"\r\n );\r\n }\r\n\r\n if (width !== height) {\r\n throw new DeveloperError(\"Width must equal height.\");\r\n }\r\n\r\n if (size <= 0) {\r\n throw new DeveloperError(\"Width and height must be greater than zero.\");\r\n }\r\n\r\n if (size > ContextLimits.maximumCubeMapSize) {\r\n throw new DeveloperError(\r\n \"Width and height must be less than or equal to the maximum cube map size (\" +\r\n ContextLimits.maximumCubeMapSize +\r\n \"). Check maximumCubeMapSize.\"\r\n );\r\n }\r\n\r\n if (!PixelFormat.validate(pixelFormat)) {\r\n throw new DeveloperError(\"Invalid options.pixelFormat.\");\r\n }\r\n\r\n if (PixelFormat.isDepthFormat(pixelFormat)) {\r\n throw new DeveloperError(\r\n \"options.pixelFormat cannot be DEPTH_COMPONENT or DEPTH_STENCIL.\"\r\n );\r\n }\r\n\r\n if (!PixelDatatype.validate(pixelDatatype)) {\r\n throw new DeveloperError(\"Invalid options.pixelDatatype.\");\r\n }\r\n\r\n if (pixelDatatype === PixelDatatype.FLOAT && !context.floatingPointTexture) {\r\n throw new DeveloperError(\r\n \"When options.pixelDatatype is FLOAT, this WebGL implementation must support the OES_texture_float extension.\"\r\n );\r\n }\r\n\r\n if (\r\n pixelDatatype === PixelDatatype.HALF_FLOAT &&\r\n !context.halfFloatingPointTexture\r\n ) {\r\n throw new DeveloperError(\r\n \"When options.pixelDatatype is HALF_FLOAT, this WebGL implementation must support the OES_texture_half_float extension.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var sizeInBytes =\r\n PixelFormat.textureSizeInBytes(pixelFormat, pixelDatatype, size, size) * 6;\r\n\r\n // Use premultiplied alpha for opaque textures should perform better on Chrome:\r\n // http://media.tojicode.com/webglCamp4/#20\r\n var preMultiplyAlpha =\r\n options.preMultiplyAlpha ||\r\n pixelFormat === PixelFormat.RGB ||\r\n pixelFormat === PixelFormat.LUMINANCE;\r\n var flipY = defaultValue(options.flipY, true);\r\n\r\n var gl = context._gl;\r\n var textureTarget = gl.TEXTURE_CUBE_MAP;\r\n var texture = gl.createTexture();\r\n\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(textureTarget, texture);\r\n\r\n function createFace(target, sourceFace, preMultiplyAlpha, flipY) {\r\n var arrayBufferView = sourceFace.arrayBufferView;\r\n if (!defined(arrayBufferView)) {\r\n arrayBufferView = sourceFace.bufferView;\r\n }\r\n\r\n var unpackAlignment = 4;\r\n if (defined(arrayBufferView)) {\r\n unpackAlignment = PixelFormat.alignmentInBytes(\r\n pixelFormat,\r\n pixelDatatype,\r\n width\r\n );\r\n }\r\n\r\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);\r\n\r\n if (defined(arrayBufferView)) {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n if (flipY) {\r\n arrayBufferView = PixelFormat.flipY(\r\n arrayBufferView,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n size\r\n );\r\n }\r\n gl.texImage2D(\r\n target,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n arrayBufferView\r\n );\r\n } else {\r\n // Only valid for DOM-Element uploads\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);\r\n\r\n // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement\r\n gl.texImage2D(\r\n target,\r\n 0,\r\n internalFormat,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n sourceFace\r\n );\r\n }\r\n }\r\n\r\n if (defined(source)) {\r\n createFace(\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_X,\r\n source.positiveX,\r\n preMultiplyAlpha,\r\n flipY\r\n );\r\n createFace(\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\r\n source.negativeX,\r\n preMultiplyAlpha,\r\n flipY\r\n );\r\n createFace(\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\r\n source.positiveY,\r\n preMultiplyAlpha,\r\n flipY\r\n );\r\n createFace(\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\r\n source.negativeY,\r\n preMultiplyAlpha,\r\n flipY\r\n );\r\n createFace(\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\r\n source.positiveZ,\r\n preMultiplyAlpha,\r\n flipY\r\n );\r\n createFace(\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\r\n source.negativeZ,\r\n preMultiplyAlpha,\r\n flipY\r\n );\r\n } else {\r\n gl.texImage2D(\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_X,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n null\r\n );\r\n gl.texImage2D(\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n null\r\n );\r\n gl.texImage2D(\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n null\r\n );\r\n gl.texImage2D(\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n null\r\n );\r\n gl.texImage2D(\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n null\r\n );\r\n gl.texImage2D(\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\r\n 0,\r\n internalFormat,\r\n size,\r\n size,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n null\r\n );\r\n }\r\n gl.bindTexture(textureTarget, null);\r\n\r\n this._context = context;\r\n this._textureFilterAnisotropic = context._textureFilterAnisotropic;\r\n this._textureTarget = textureTarget;\r\n this._texture = texture;\r\n this._pixelFormat = pixelFormat;\r\n this._pixelDatatype = pixelDatatype;\r\n this._size = size;\r\n this._hasMipmap = false;\r\n this._sizeInBytes = sizeInBytes;\r\n this._preMultiplyAlpha = preMultiplyAlpha;\r\n this._flipY = flipY;\r\n this._sampler = undefined;\r\n\r\n var initialized = defined(source);\r\n this._positiveX = new CubeMapFace(\r\n context,\r\n texture,\r\n textureTarget,\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_X,\r\n internalFormat,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n preMultiplyAlpha,\r\n flipY,\r\n initialized\r\n );\r\n this._negativeX = new CubeMapFace(\r\n context,\r\n texture,\r\n textureTarget,\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_X,\r\n internalFormat,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n preMultiplyAlpha,\r\n flipY,\r\n initialized\r\n );\r\n this._positiveY = new CubeMapFace(\r\n context,\r\n texture,\r\n textureTarget,\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_Y,\r\n internalFormat,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n preMultiplyAlpha,\r\n flipY,\r\n initialized\r\n );\r\n this._negativeY = new CubeMapFace(\r\n context,\r\n texture,\r\n textureTarget,\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Y,\r\n internalFormat,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n preMultiplyAlpha,\r\n flipY,\r\n initialized\r\n );\r\n this._positiveZ = new CubeMapFace(\r\n context,\r\n texture,\r\n textureTarget,\r\n gl.TEXTURE_CUBE_MAP_POSITIVE_Z,\r\n internalFormat,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n preMultiplyAlpha,\r\n flipY,\r\n initialized\r\n );\r\n this._negativeZ = new CubeMapFace(\r\n context,\r\n texture,\r\n textureTarget,\r\n gl.TEXTURE_CUBE_MAP_NEGATIVE_Z,\r\n internalFormat,\r\n pixelFormat,\r\n pixelDatatype,\r\n size,\r\n preMultiplyAlpha,\r\n flipY,\r\n initialized\r\n );\r\n\r\n this.sampler = defined(options.sampler) ? options.sampler : new Sampler();\r\n}\r\n\r\nObject.defineProperties(CubeMap.prototype, {\r\n positiveX: {\r\n get: function () {\r\n return this._positiveX;\r\n },\r\n },\r\n negativeX: {\r\n get: function () {\r\n return this._negativeX;\r\n },\r\n },\r\n positiveY: {\r\n get: function () {\r\n return this._positiveY;\r\n },\r\n },\r\n negativeY: {\r\n get: function () {\r\n return this._negativeY;\r\n },\r\n },\r\n positiveZ: {\r\n get: function () {\r\n return this._positiveZ;\r\n },\r\n },\r\n negativeZ: {\r\n get: function () {\r\n return this._negativeZ;\r\n },\r\n },\r\n sampler: {\r\n get: function () {\r\n return this._sampler;\r\n },\r\n set: function (sampler) {\r\n var minificationFilter = sampler.minificationFilter;\r\n var magnificationFilter = sampler.magnificationFilter;\r\n\r\n var mipmap =\r\n minificationFilter ===\r\n TextureMinificationFilter.NEAREST_MIPMAP_NEAREST ||\r\n minificationFilter ===\r\n TextureMinificationFilter.NEAREST_MIPMAP_LINEAR ||\r\n minificationFilter ===\r\n TextureMinificationFilter.LINEAR_MIPMAP_NEAREST ||\r\n minificationFilter === TextureMinificationFilter.LINEAR_MIPMAP_LINEAR;\r\n\r\n var context = this._context;\r\n var pixelDatatype = this._pixelDatatype;\r\n\r\n // float textures only support nearest filtering unless the linear extensions are supported, so override the sampler's settings\r\n if (\r\n (pixelDatatype === PixelDatatype.FLOAT &&\r\n !context.textureFloatLinear) ||\r\n (pixelDatatype === PixelDatatype.HALF_FLOAT &&\r\n !context.textureHalfFloatLinear)\r\n ) {\r\n minificationFilter = mipmap\r\n ? TextureMinificationFilter.NEAREST_MIPMAP_NEAREST\r\n : TextureMinificationFilter.NEAREST;\r\n magnificationFilter = TextureMagnificationFilter.NEAREST;\r\n }\r\n\r\n var gl = context._gl;\r\n var target = this._textureTarget;\r\n\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(target, this._texture);\r\n gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, minificationFilter);\r\n gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, magnificationFilter);\r\n gl.texParameteri(target, gl.TEXTURE_WRAP_S, sampler.wrapS);\r\n gl.texParameteri(target, gl.TEXTURE_WRAP_T, sampler.wrapT);\r\n if (defined(this._textureFilterAnisotropic)) {\r\n gl.texParameteri(\r\n target,\r\n this._textureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT,\r\n sampler.maximumAnisotropy\r\n );\r\n }\r\n gl.bindTexture(target, null);\r\n\r\n this._sampler = sampler;\r\n },\r\n },\r\n pixelFormat: {\r\n get: function () {\r\n return this._pixelFormat;\r\n },\r\n },\r\n pixelDatatype: {\r\n get: function () {\r\n return this._pixelDatatype;\r\n },\r\n },\r\n width: {\r\n get: function () {\r\n return this._size;\r\n },\r\n },\r\n height: {\r\n get: function () {\r\n return this._size;\r\n },\r\n },\r\n sizeInBytes: {\r\n get: function () {\r\n if (this._hasMipmap) {\r\n return Math.floor((this._sizeInBytes * 4) / 3);\r\n }\r\n return this._sizeInBytes;\r\n },\r\n },\r\n preMultiplyAlpha: {\r\n get: function () {\r\n return this._preMultiplyAlpha;\r\n },\r\n },\r\n flipY: {\r\n get: function () {\r\n return this._flipY;\r\n },\r\n },\r\n\r\n _target: {\r\n get: function () {\r\n return this._textureTarget;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Generates a complete mipmap chain for each cubemap face.\r\n *\r\n * @param {MipmapHint} [hint=MipmapHint.DONT_CARE] A performance vs. quality hint.\r\n *\r\n * @exception {DeveloperError} hint is invalid.\r\n * @exception {DeveloperError} This CubeMap's width must be a power of two to call generateMipmap().\r\n * @exception {DeveloperError} This CubeMap's height must be a power of two to call generateMipmap().\r\n * @exception {DeveloperError} This CubeMap was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * // Generate mipmaps, and then set the sampler so mipmaps are used for\r\n * // minification when the cube map is sampled.\r\n * cubeMap.generateMipmap();\r\n * cubeMap.sampler = new Sampler({\r\n * minificationFilter : Cesium.TextureMinificationFilter.NEAREST_MIPMAP_LINEAR\r\n * });\r\n */\r\nCubeMap.prototype.generateMipmap = function (hint) {\r\n hint = defaultValue(hint, MipmapHint.DONT_CARE);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (this._size > 1 && !CesiumMath.isPowerOfTwo(this._size)) {\r\n throw new DeveloperError(\r\n \"width and height must be a power of two to call generateMipmap().\"\r\n );\r\n }\r\n if (!MipmapHint.validate(hint)) {\r\n throw new DeveloperError(\"hint is invalid.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._hasMipmap = true;\r\n\r\n var gl = this._context._gl;\r\n var target = this._textureTarget;\r\n gl.hint(gl.GENERATE_MIPMAP_HINT, hint);\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(target, this._texture);\r\n gl.generateMipmap(target);\r\n gl.bindTexture(target, null);\r\n};\r\n\r\nCubeMap.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nCubeMap.prototype.destroy = function () {\r\n this._context._gl.deleteTexture(this._texture);\r\n this._positiveX = destroyObject(this._positiveX);\r\n this._negativeX = destroyObject(this._negativeX);\r\n this._positiveY = destroyObject(this._positiveY);\r\n this._negativeY = destroyObject(this._negativeY);\r\n this._positiveZ = destroyObject(this._positiveZ);\r\n this._negativeZ = destroyObject(this._negativeZ);\r\n return destroyObject(this);\r\n};\r\nexport default CubeMap;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport ContextLimits from \"./ContextLimits.js\";\r\nimport MipmapHint from \"./MipmapHint.js\";\r\nimport PixelDatatype from \"./PixelDatatype.js\";\r\nimport Sampler from \"./Sampler.js\";\r\nimport TextureMagnificationFilter from \"./TextureMagnificationFilter.js\";\r\nimport TextureMinificationFilter from \"./TextureMinificationFilter.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Texture(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n //>>includeEnd('debug');\r\n\r\n var context = options.context;\r\n var width = options.width;\r\n var height = options.height;\r\n var source = options.source;\r\n\r\n if (defined(source)) {\r\n if (!defined(width)) {\r\n width = defaultValue(source.videoWidth, source.width);\r\n }\r\n if (!defined(height)) {\r\n height = defaultValue(source.videoHeight, source.height);\r\n }\r\n }\r\n\r\n var pixelFormat = defaultValue(options.pixelFormat, PixelFormat.RGBA);\r\n var pixelDatatype = defaultValue(\r\n options.pixelDatatype,\r\n PixelDatatype.UNSIGNED_BYTE\r\n );\r\n var internalFormat = PixelFormat.toInternalFormat(\r\n pixelFormat,\r\n pixelDatatype,\r\n context\r\n );\r\n\r\n var isCompressed = PixelFormat.isCompressedFormat(internalFormat);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(width) || !defined(height)) {\r\n throw new DeveloperError(\r\n \"options requires a source field to create an initialized texture or width and height fields to create a blank texture.\"\r\n );\r\n }\r\n\r\n Check.typeOf.number.greaterThan(\"width\", width, 0);\r\n\r\n if (width > ContextLimits.maximumTextureSize) {\r\n throw new DeveloperError(\r\n \"Width must be less than or equal to the maximum texture size (\" +\r\n ContextLimits.maximumTextureSize +\r\n \"). Check maximumTextureSize.\"\r\n );\r\n }\r\n\r\n Check.typeOf.number.greaterThan(\"height\", height, 0);\r\n\r\n if (height > ContextLimits.maximumTextureSize) {\r\n throw new DeveloperError(\r\n \"Height must be less than or equal to the maximum texture size (\" +\r\n ContextLimits.maximumTextureSize +\r\n \"). Check maximumTextureSize.\"\r\n );\r\n }\r\n\r\n if (!PixelFormat.validate(pixelFormat)) {\r\n throw new DeveloperError(\"Invalid options.pixelFormat.\");\r\n }\r\n\r\n if (!isCompressed && !PixelDatatype.validate(pixelDatatype)) {\r\n throw new DeveloperError(\"Invalid options.pixelDatatype.\");\r\n }\r\n\r\n if (\r\n pixelFormat === PixelFormat.DEPTH_COMPONENT &&\r\n pixelDatatype !== PixelDatatype.UNSIGNED_SHORT &&\r\n pixelDatatype !== PixelDatatype.UNSIGNED_INT\r\n ) {\r\n throw new DeveloperError(\r\n \"When options.pixelFormat is DEPTH_COMPONENT, options.pixelDatatype must be UNSIGNED_SHORT or UNSIGNED_INT.\"\r\n );\r\n }\r\n\r\n if (\r\n pixelFormat === PixelFormat.DEPTH_STENCIL &&\r\n pixelDatatype !== PixelDatatype.UNSIGNED_INT_24_8\r\n ) {\r\n throw new DeveloperError(\r\n \"When options.pixelFormat is DEPTH_STENCIL, options.pixelDatatype must be UNSIGNED_INT_24_8.\"\r\n );\r\n }\r\n\r\n if (pixelDatatype === PixelDatatype.FLOAT && !context.floatingPointTexture) {\r\n throw new DeveloperError(\r\n \"When options.pixelDatatype is FLOAT, this WebGL implementation must support the OES_texture_float extension. Check context.floatingPointTexture.\"\r\n );\r\n }\r\n\r\n if (\r\n pixelDatatype === PixelDatatype.HALF_FLOAT &&\r\n !context.halfFloatingPointTexture\r\n ) {\r\n throw new DeveloperError(\r\n \"When options.pixelDatatype is HALF_FLOAT, this WebGL implementation must support the OES_texture_half_float extension. Check context.halfFloatingPointTexture.\"\r\n );\r\n }\r\n\r\n if (PixelFormat.isDepthFormat(pixelFormat)) {\r\n if (defined(source)) {\r\n throw new DeveloperError(\r\n \"When options.pixelFormat is DEPTH_COMPONENT or DEPTH_STENCIL, source cannot be provided.\"\r\n );\r\n }\r\n\r\n if (!context.depthTexture) {\r\n throw new DeveloperError(\r\n \"When options.pixelFormat is DEPTH_COMPONENT or DEPTH_STENCIL, this WebGL implementation must support WEBGL_depth_texture. Check context.depthTexture.\"\r\n );\r\n }\r\n }\r\n\r\n if (isCompressed) {\r\n if (!defined(source) || !defined(source.arrayBufferView)) {\r\n throw new DeveloperError(\r\n \"When options.pixelFormat is compressed, options.source.arrayBufferView must be defined.\"\r\n );\r\n }\r\n\r\n if (PixelFormat.isDXTFormat(internalFormat) && !context.s3tc) {\r\n throw new DeveloperError(\r\n \"When options.pixelFormat is S3TC compressed, this WebGL implementation must support the WEBGL_texture_compression_s3tc extension. Check context.s3tc.\"\r\n );\r\n } else if (PixelFormat.isPVRTCFormat(internalFormat) && !context.pvrtc) {\r\n throw new DeveloperError(\r\n \"When options.pixelFormat is PVRTC compressed, this WebGL implementation must support the WEBGL_texture_compression_pvrtc extension. Check context.pvrtc.\"\r\n );\r\n } else if (PixelFormat.isETC1Format(internalFormat) && !context.etc1) {\r\n throw new DeveloperError(\r\n \"When options.pixelFormat is ETC1 compressed, this WebGL implementation must support the WEBGL_texture_compression_etc1 extension. Check context.etc1.\"\r\n );\r\n }\r\n\r\n if (\r\n PixelFormat.compressedTextureSizeInBytes(\r\n internalFormat,\r\n width,\r\n height\r\n ) !== source.arrayBufferView.byteLength\r\n ) {\r\n throw new DeveloperError(\r\n \"The byte length of the array buffer is invalid for the compressed texture with the given width and height.\"\r\n );\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Use premultiplied alpha for opaque textures should perform better on Chrome:\r\n // http://media.tojicode.com/webglCamp4/#20\r\n var preMultiplyAlpha =\r\n options.preMultiplyAlpha ||\r\n pixelFormat === PixelFormat.RGB ||\r\n pixelFormat === PixelFormat.LUMINANCE;\r\n var flipY = defaultValue(options.flipY, true);\r\n\r\n var initialized = true;\r\n\r\n var gl = context._gl;\r\n var textureTarget = gl.TEXTURE_2D;\r\n var texture = gl.createTexture();\r\n\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(textureTarget, texture);\r\n\r\n var unpackAlignment = 4;\r\n if (defined(source) && defined(source.arrayBufferView) && !isCompressed) {\r\n unpackAlignment = PixelFormat.alignmentInBytes(\r\n pixelFormat,\r\n pixelDatatype,\r\n width\r\n );\r\n }\r\n\r\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);\r\n\r\n if (defined(source)) {\r\n if (defined(source.arrayBufferView)) {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n // Source: typed array\r\n var arrayBufferView = source.arrayBufferView;\r\n if (isCompressed) {\r\n gl.compressedTexImage2D(\r\n textureTarget,\r\n 0,\r\n internalFormat,\r\n width,\r\n height,\r\n 0,\r\n arrayBufferView\r\n );\r\n } else {\r\n if (flipY) {\r\n arrayBufferView = PixelFormat.flipY(\r\n arrayBufferView,\r\n pixelFormat,\r\n pixelDatatype,\r\n width,\r\n height\r\n );\r\n }\r\n gl.texImage2D(\r\n textureTarget,\r\n 0,\r\n internalFormat,\r\n width,\r\n height,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n arrayBufferView\r\n );\r\n\r\n if (defined(source.mipLevels)) {\r\n var mipWidth = width;\r\n var mipHeight = height;\r\n for (var i = 0; i < source.mipLevels.length; ++i) {\r\n mipWidth = Math.floor(mipWidth / 2) | 0;\r\n if (mipWidth < 1) {\r\n mipWidth = 1;\r\n }\r\n mipHeight = Math.floor(mipHeight / 2) | 0;\r\n if (mipHeight < 1) {\r\n mipHeight = 1;\r\n }\r\n gl.texImage2D(\r\n textureTarget,\r\n i + 1,\r\n internalFormat,\r\n mipWidth,\r\n mipHeight,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n source.mipLevels[i]\r\n );\r\n }\r\n }\r\n }\r\n } else if (defined(source.framebuffer)) {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n // Source: framebuffer\r\n if (source.framebuffer !== context.defaultFramebuffer) {\r\n source.framebuffer._bind();\r\n }\r\n\r\n gl.copyTexImage2D(\r\n textureTarget,\r\n 0,\r\n internalFormat,\r\n source.xOffset,\r\n source.yOffset,\r\n width,\r\n height,\r\n 0\r\n );\r\n\r\n if (source.framebuffer !== context.defaultFramebuffer) {\r\n source.framebuffer._unBind();\r\n }\r\n } else {\r\n // Only valid for DOM-Element uploads\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);\r\n\r\n // Source: ImageData, HTMLImageElement, HTMLCanvasElement, or HTMLVideoElement\r\n gl.texImage2D(\r\n textureTarget,\r\n 0,\r\n internalFormat,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n source\r\n );\r\n }\r\n } else {\r\n gl.texImage2D(\r\n textureTarget,\r\n 0,\r\n internalFormat,\r\n width,\r\n height,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n null\r\n );\r\n initialized = false;\r\n }\r\n gl.bindTexture(textureTarget, null);\r\n\r\n var sizeInBytes;\r\n if (isCompressed) {\r\n sizeInBytes = PixelFormat.compressedTextureSizeInBytes(\r\n pixelFormat,\r\n width,\r\n height\r\n );\r\n } else {\r\n sizeInBytes = PixelFormat.textureSizeInBytes(\r\n pixelFormat,\r\n pixelDatatype,\r\n width,\r\n height\r\n );\r\n }\r\n\r\n this._id = createGuid();\r\n this._context = context;\r\n this._textureFilterAnisotropic = context._textureFilterAnisotropic;\r\n this._textureTarget = textureTarget;\r\n this._texture = texture;\r\n this._internalFormat = internalFormat;\r\n this._pixelFormat = pixelFormat;\r\n this._pixelDatatype = pixelDatatype;\r\n this._width = width;\r\n this._height = height;\r\n this._dimensions = new Cartesian2(width, height);\r\n this._hasMipmap = false;\r\n this._sizeInBytes = sizeInBytes;\r\n this._preMultiplyAlpha = preMultiplyAlpha;\r\n this._flipY = flipY;\r\n this._initialized = initialized;\r\n this._sampler = undefined;\r\n\r\n this.sampler = defined(options.sampler) ? options.sampler : new Sampler();\r\n}\r\n\r\n/**\r\n * This function is identical to using the Texture constructor except that it can be\r\n * replaced with a mock/spy in tests.\r\n * @private\r\n */\r\nTexture.create = function (options) {\r\n return new Texture(options);\r\n};\r\n\r\n/**\r\n * Creates a texture, and copies a subimage of the framebuffer to it. When called without arguments,\r\n * the texture is the same width and height as the framebuffer and contains its contents.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Context} options.context The context in which the Texture gets created.\r\n * @param {PixelFormat} [options.pixelFormat=PixelFormat.RGB] The texture's internal pixel format.\r\n * @param {Number} [options.framebufferXOffset=0] An offset in the x direction in the framebuffer where copying begins from.\r\n * @param {Number} [options.framebufferYOffset=0] An offset in the y direction in the framebuffer where copying begins from.\r\n * @param {Number} [options.width=canvas.clientWidth] The width of the texture in texels.\r\n * @param {Number} [options.height=canvas.clientHeight] The height of the texture in texels.\r\n * @param {Framebuffer} [options.framebuffer=defaultFramebuffer] The framebuffer from which to create the texture. If this\r\n * parameter is not specified, the default framebuffer is used.\r\n * @returns {Texture} A texture with contents from the framebuffer.\r\n *\r\n * @exception {DeveloperError} Invalid pixelFormat.\r\n * @exception {DeveloperError} pixelFormat cannot be DEPTH_COMPONENT, DEPTH_STENCIL or a compressed format.\r\n * @exception {DeveloperError} framebufferXOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} framebufferYOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} framebufferXOffset + width must be less than or equal to canvas.clientWidth.\r\n * @exception {DeveloperError} framebufferYOffset + height must be less than or equal to canvas.clientHeight.\r\n *\r\n *\r\n * @example\r\n * // Create a texture with the contents of the framebuffer.\r\n * var t = Texture.fromFramebuffer({\r\n * context : context\r\n * });\r\n *\r\n * @see Sampler\r\n *\r\n * @private\r\n */\r\nTexture.fromFramebuffer = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n //>>includeEnd('debug');\r\n\r\n var context = options.context;\r\n var gl = context._gl;\r\n\r\n var pixelFormat = defaultValue(options.pixelFormat, PixelFormat.RGB);\r\n var framebufferXOffset = defaultValue(options.framebufferXOffset, 0);\r\n var framebufferYOffset = defaultValue(options.framebufferYOffset, 0);\r\n var width = defaultValue(options.width, gl.drawingBufferWidth);\r\n var height = defaultValue(options.height, gl.drawingBufferHeight);\r\n var framebuffer = options.framebuffer;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!PixelFormat.validate(pixelFormat)) {\r\n throw new DeveloperError(\"Invalid pixelFormat.\");\r\n }\r\n if (\r\n PixelFormat.isDepthFormat(pixelFormat) ||\r\n PixelFormat.isCompressedFormat(pixelFormat)\r\n ) {\r\n throw new DeveloperError(\r\n \"pixelFormat cannot be DEPTH_COMPONENT, DEPTH_STENCIL or a compressed format.\"\r\n );\r\n }\r\n Check.defined(\"options.context\", options.context);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"framebufferXOffset\",\r\n framebufferXOffset,\r\n 0\r\n );\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"framebufferYOffset\",\r\n framebufferYOffset,\r\n 0\r\n );\r\n if (framebufferXOffset + width > gl.drawingBufferWidth) {\r\n throw new DeveloperError(\r\n \"framebufferXOffset + width must be less than or equal to drawingBufferWidth\"\r\n );\r\n }\r\n if (framebufferYOffset + height > gl.drawingBufferHeight) {\r\n throw new DeveloperError(\r\n \"framebufferYOffset + height must be less than or equal to drawingBufferHeight.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var texture = new Texture({\r\n context: context,\r\n width: width,\r\n height: height,\r\n pixelFormat: pixelFormat,\r\n source: {\r\n framebuffer: defined(framebuffer)\r\n ? framebuffer\r\n : context.defaultFramebuffer,\r\n xOffset: framebufferXOffset,\r\n yOffset: framebufferYOffset,\r\n width: width,\r\n height: height,\r\n },\r\n });\r\n\r\n return texture;\r\n};\r\n\r\nObject.defineProperties(Texture.prototype, {\r\n /**\r\n * A unique id for the texture\r\n * @memberof Texture.prototype\r\n * @type {String}\r\n * @readonly\r\n * @private\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n /**\r\n * The sampler to use when sampling this texture.\r\n * Create a sampler by calling {@link Sampler}. If this\r\n * parameter is not specified, a default sampler is used. The default sampler clamps texture\r\n * coordinates in both directions, uses linear filtering for both magnification and minification,\r\n * and uses a maximum anisotropy of 1.0.\r\n * @memberof Texture.prototype\r\n * @type {Object}\r\n */\r\n sampler: {\r\n get: function () {\r\n return this._sampler;\r\n },\r\n set: function (sampler) {\r\n var minificationFilter = sampler.minificationFilter;\r\n var magnificationFilter = sampler.magnificationFilter;\r\n var context = this._context;\r\n var pixelFormat = this._pixelFormat;\r\n var pixelDatatype = this._pixelDatatype;\r\n\r\n var mipmap =\r\n minificationFilter ===\r\n TextureMinificationFilter.NEAREST_MIPMAP_NEAREST ||\r\n minificationFilter ===\r\n TextureMinificationFilter.NEAREST_MIPMAP_LINEAR ||\r\n minificationFilter ===\r\n TextureMinificationFilter.LINEAR_MIPMAP_NEAREST ||\r\n minificationFilter === TextureMinificationFilter.LINEAR_MIPMAP_LINEAR;\r\n\r\n // float textures only support nearest filtering unless the linear extensions are supported, so override the sampler's settings\r\n if (\r\n (pixelDatatype === PixelDatatype.FLOAT &&\r\n !context.textureFloatLinear) ||\r\n (pixelDatatype === PixelDatatype.HALF_FLOAT &&\r\n !context.textureHalfFloatLinear)\r\n ) {\r\n minificationFilter = mipmap\r\n ? TextureMinificationFilter.NEAREST_MIPMAP_NEAREST\r\n : TextureMinificationFilter.NEAREST;\r\n magnificationFilter = TextureMagnificationFilter.NEAREST;\r\n }\r\n\r\n // WebGL 2 depth texture only support nearest filtering. See section 3.8.13 OpenGL ES 3 spec\r\n if (context.webgl2) {\r\n if (PixelFormat.isDepthFormat(pixelFormat)) {\r\n minificationFilter = TextureMinificationFilter.NEAREST;\r\n magnificationFilter = TextureMagnificationFilter.NEAREST;\r\n }\r\n }\r\n\r\n var gl = context._gl;\r\n var target = this._textureTarget;\r\n\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(target, this._texture);\r\n gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, minificationFilter);\r\n gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, magnificationFilter);\r\n gl.texParameteri(target, gl.TEXTURE_WRAP_S, sampler.wrapS);\r\n gl.texParameteri(target, gl.TEXTURE_WRAP_T, sampler.wrapT);\r\n if (defined(this._textureFilterAnisotropic)) {\r\n gl.texParameteri(\r\n target,\r\n this._textureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT,\r\n sampler.maximumAnisotropy\r\n );\r\n }\r\n gl.bindTexture(target, null);\r\n\r\n this._sampler = sampler;\r\n },\r\n },\r\n pixelFormat: {\r\n get: function () {\r\n return this._pixelFormat;\r\n },\r\n },\r\n pixelDatatype: {\r\n get: function () {\r\n return this._pixelDatatype;\r\n },\r\n },\r\n dimensions: {\r\n get: function () {\r\n return this._dimensions;\r\n },\r\n },\r\n preMultiplyAlpha: {\r\n get: function () {\r\n return this._preMultiplyAlpha;\r\n },\r\n },\r\n flipY: {\r\n get: function () {\r\n return this._flipY;\r\n },\r\n },\r\n width: {\r\n get: function () {\r\n return this._width;\r\n },\r\n },\r\n height: {\r\n get: function () {\r\n return this._height;\r\n },\r\n },\r\n sizeInBytes: {\r\n get: function () {\r\n if (this._hasMipmap) {\r\n return Math.floor((this._sizeInBytes * 4) / 3);\r\n }\r\n return this._sizeInBytes;\r\n },\r\n },\r\n _target: {\r\n get: function () {\r\n return this._textureTarget;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Copy new image data into this texture, from a source {@link ImageData}, {@link HTMLImageElement}, {@link HTMLCanvasElement}, or {@link HTMLVideoElement}.\r\n * or an object with width, height, and arrayBufferView properties.\r\n *\r\n * @param {Object} source The source {@link ImageData}, {@link HTMLImageElement}, {@link HTMLCanvasElement}, or {@link HTMLVideoElement},\r\n * or an object with width, height, and arrayBufferView properties.\r\n * @param {Number} [xOffset=0] The offset in the x direction within the texture to copy into.\r\n * @param {Number} [yOffset=0] The offset in the y direction within the texture to copy into.\r\n *\r\n * @exception {DeveloperError} Cannot call copyFrom when the texture pixel format is DEPTH_COMPONENT or DEPTH_STENCIL.\r\n * @exception {DeveloperError} Cannot call copyFrom with a compressed texture pixel format.\r\n * @exception {DeveloperError} xOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} yOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} xOffset + source.width must be less than or equal to width.\r\n * @exception {DeveloperError} yOffset + source.height must be less than or equal to height.\r\n * @exception {DeveloperError} This texture was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * texture.copyFrom({\r\n * width : 1,\r\n * height : 1,\r\n * arrayBufferView : new Uint8Array([255, 0, 0, 255])\r\n * });\r\n */\r\nTexture.prototype.copyFrom = function (source, xOffset, yOffset) {\r\n xOffset = defaultValue(xOffset, 0);\r\n yOffset = defaultValue(yOffset, 0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"source\", source);\r\n if (PixelFormat.isDepthFormat(this._pixelFormat)) {\r\n throw new DeveloperError(\r\n \"Cannot call copyFrom when the texture pixel format is DEPTH_COMPONENT or DEPTH_STENCIL.\"\r\n );\r\n }\r\n if (PixelFormat.isCompressedFormat(this._pixelFormat)) {\r\n throw new DeveloperError(\r\n \"Cannot call copyFrom with a compressed texture pixel format.\"\r\n );\r\n }\r\n Check.typeOf.number.greaterThanOrEquals(\"xOffset\", xOffset, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\"yOffset\", yOffset, 0);\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"xOffset + source.width\",\r\n xOffset + source.width,\r\n this._width\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"yOffset + source.height\",\r\n yOffset + source.height,\r\n this._height\r\n );\r\n //>>includeEnd('debug');\r\n\r\n var context = this._context;\r\n var gl = context._gl;\r\n var target = this._textureTarget;\r\n\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(target, this._texture);\r\n\r\n var width = source.width;\r\n var height = source.height;\r\n var arrayBufferView = source.arrayBufferView;\r\n\r\n var textureWidth = this._width;\r\n var textureHeight = this._height;\r\n var internalFormat = this._internalFormat;\r\n var pixelFormat = this._pixelFormat;\r\n var pixelDatatype = this._pixelDatatype;\r\n\r\n var preMultiplyAlpha = this._preMultiplyAlpha;\r\n var flipY = this._flipY;\r\n\r\n var unpackAlignment = 4;\r\n if (defined(arrayBufferView)) {\r\n unpackAlignment = PixelFormat.alignmentInBytes(\r\n pixelFormat,\r\n pixelDatatype,\r\n width\r\n );\r\n }\r\n\r\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, unpackAlignment);\r\n\r\n var uploaded = false;\r\n if (!this._initialized) {\r\n if (\r\n xOffset === 0 &&\r\n yOffset === 0 &&\r\n width === textureWidth &&\r\n height === textureHeight\r\n ) {\r\n // initialize the entire texture\r\n if (defined(arrayBufferView)) {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n if (flipY) {\r\n arrayBufferView = PixelFormat.flipY(\r\n arrayBufferView,\r\n pixelFormat,\r\n pixelDatatype,\r\n textureWidth,\r\n textureHeight\r\n );\r\n }\r\n gl.texImage2D(\r\n target,\r\n 0,\r\n internalFormat,\r\n textureWidth,\r\n textureHeight,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n arrayBufferView\r\n );\r\n } else {\r\n // Only valid for DOM-Element uploads\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);\r\n\r\n gl.texImage2D(\r\n target,\r\n 0,\r\n internalFormat,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n source\r\n );\r\n }\r\n uploaded = true;\r\n } else {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n // initialize the entire texture to zero\r\n var bufferView = PixelFormat.createTypedArray(\r\n pixelFormat,\r\n pixelDatatype,\r\n textureWidth,\r\n textureHeight\r\n );\r\n gl.texImage2D(\r\n target,\r\n 0,\r\n internalFormat,\r\n textureWidth,\r\n textureHeight,\r\n 0,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n bufferView\r\n );\r\n }\r\n this._initialized = true;\r\n }\r\n\r\n if (!uploaded) {\r\n if (defined(arrayBufferView)) {\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\r\n\r\n if (flipY) {\r\n arrayBufferView = PixelFormat.flipY(\r\n arrayBufferView,\r\n pixelFormat,\r\n pixelDatatype,\r\n width,\r\n height\r\n );\r\n }\r\n gl.texSubImage2D(\r\n target,\r\n 0,\r\n xOffset,\r\n yOffset,\r\n width,\r\n height,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n arrayBufferView\r\n );\r\n } else {\r\n // Only valid for DOM-Element uploads\r\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, preMultiplyAlpha);\r\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY);\r\n\r\n gl.texSubImage2D(\r\n target,\r\n 0,\r\n xOffset,\r\n yOffset,\r\n pixelFormat,\r\n PixelDatatype.toWebGLConstant(pixelDatatype, context),\r\n source\r\n );\r\n }\r\n }\r\n\r\n gl.bindTexture(target, null);\r\n};\r\n\r\n/**\r\n * @param {Number} [xOffset=0] The offset in the x direction within the texture to copy into.\r\n * @param {Number} [yOffset=0] The offset in the y direction within the texture to copy into.\r\n * @param {Number} [framebufferXOffset=0] optional\r\n * @param {Number} [framebufferYOffset=0] optional\r\n * @param {Number} [width=width] optional\r\n * @param {Number} [height=height] optional\r\n *\r\n * @exception {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel format is DEPTH_COMPONENT or DEPTH_STENCIL.\r\n * @exception {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.\r\n * @exception {DeveloperError} Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.\r\n * @exception {DeveloperError} Cannot call copyFrom with a compressed texture pixel format.\r\n * @exception {DeveloperError} This texture was destroyed, i.e., destroy() was called.\r\n * @exception {DeveloperError} xOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} yOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} framebufferXOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} framebufferYOffset must be greater than or equal to zero.\r\n * @exception {DeveloperError} xOffset + width must be less than or equal to width.\r\n * @exception {DeveloperError} yOffset + height must be less than or equal to height.\r\n */\r\nTexture.prototype.copyFromFramebuffer = function (\r\n xOffset,\r\n yOffset,\r\n framebufferXOffset,\r\n framebufferYOffset,\r\n width,\r\n height\r\n) {\r\n xOffset = defaultValue(xOffset, 0);\r\n yOffset = defaultValue(yOffset, 0);\r\n framebufferXOffset = defaultValue(framebufferXOffset, 0);\r\n framebufferYOffset = defaultValue(framebufferYOffset, 0);\r\n width = defaultValue(width, this._width);\r\n height = defaultValue(height, this._height);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (PixelFormat.isDepthFormat(this._pixelFormat)) {\r\n throw new DeveloperError(\r\n \"Cannot call copyFromFramebuffer when the texture pixel format is DEPTH_COMPONENT or DEPTH_STENCIL.\"\r\n );\r\n }\r\n if (this._pixelDatatype === PixelDatatype.FLOAT) {\r\n throw new DeveloperError(\r\n \"Cannot call copyFromFramebuffer when the texture pixel data type is FLOAT.\"\r\n );\r\n }\r\n if (this._pixelDatatype === PixelDatatype.HALF_FLOAT) {\r\n throw new DeveloperError(\r\n \"Cannot call copyFromFramebuffer when the texture pixel data type is HALF_FLOAT.\"\r\n );\r\n }\r\n if (PixelFormat.isCompressedFormat(this._pixelFormat)) {\r\n throw new DeveloperError(\r\n \"Cannot call copyFrom with a compressed texture pixel format.\"\r\n );\r\n }\r\n\r\n Check.typeOf.number.greaterThanOrEquals(\"xOffset\", xOffset, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\"yOffset\", yOffset, 0);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"framebufferXOffset\",\r\n framebufferXOffset,\r\n 0\r\n );\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"framebufferYOffset\",\r\n framebufferYOffset,\r\n 0\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"xOffset + width\",\r\n xOffset + width,\r\n this._width\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"yOffset + height\",\r\n yOffset + height,\r\n this._height\r\n );\r\n //>>includeEnd('debug');\r\n\r\n var gl = this._context._gl;\r\n var target = this._textureTarget;\r\n\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(target, this._texture);\r\n gl.copyTexSubImage2D(\r\n target,\r\n 0,\r\n xOffset,\r\n yOffset,\r\n framebufferXOffset,\r\n framebufferYOffset,\r\n width,\r\n height\r\n );\r\n gl.bindTexture(target, null);\r\n this._initialized = true;\r\n};\r\n\r\n/**\r\n * @param {MipmapHint} [hint=MipmapHint.DONT_CARE] optional.\r\n *\r\n * @exception {DeveloperError} Cannot call generateMipmap when the texture pixel format is DEPTH_COMPONENT or DEPTH_STENCIL.\r\n * @exception {DeveloperError} Cannot call generateMipmap when the texture pixel format is a compressed format.\r\n * @exception {DeveloperError} hint is invalid.\r\n * @exception {DeveloperError} This texture's width must be a power of two to call generateMipmap().\r\n * @exception {DeveloperError} This texture's height must be a power of two to call generateMipmap().\r\n * @exception {DeveloperError} This texture was destroyed, i.e., destroy() was called.\r\n */\r\nTexture.prototype.generateMipmap = function (hint) {\r\n hint = defaultValue(hint, MipmapHint.DONT_CARE);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (PixelFormat.isDepthFormat(this._pixelFormat)) {\r\n throw new DeveloperError(\r\n \"Cannot call generateMipmap when the texture pixel format is DEPTH_COMPONENT or DEPTH_STENCIL.\"\r\n );\r\n }\r\n if (PixelFormat.isCompressedFormat(this._pixelFormat)) {\r\n throw new DeveloperError(\r\n \"Cannot call generateMipmap with a compressed pixel format.\"\r\n );\r\n }\r\n if (this._width > 1 && !CesiumMath.isPowerOfTwo(this._width)) {\r\n throw new DeveloperError(\r\n \"width must be a power of two to call generateMipmap().\"\r\n );\r\n }\r\n if (this._height > 1 && !CesiumMath.isPowerOfTwo(this._height)) {\r\n throw new DeveloperError(\r\n \"height must be a power of two to call generateMipmap().\"\r\n );\r\n }\r\n if (!MipmapHint.validate(hint)) {\r\n throw new DeveloperError(\"hint is invalid.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._hasMipmap = true;\r\n\r\n var gl = this._context._gl;\r\n var target = this._textureTarget;\r\n\r\n gl.hint(gl.GENERATE_MIPMAP_HINT, hint);\r\n gl.activeTexture(gl.TEXTURE0);\r\n gl.bindTexture(target, this._texture);\r\n gl.generateMipmap(target);\r\n gl.bindTexture(target, null);\r\n};\r\n\r\nTexture.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nTexture.prototype.destroy = function () {\r\n this._context._gl.deleteTexture(this._texture);\r\n return destroyObject(this);\r\n};\r\nexport default Texture;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform sampler2D image;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec4 rampColor = texture2D(image, vec2(materialInput.aspect / (2.0 * czm_pi), 0.5));\\n\\\nrampColor = czm_gammaCorrect(rampColor);\\n\\\nmaterial.diffuse = rampColor.rgb;\\n\\\nmaterial.alpha = rampColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform sampler2D image;\\n\\\nuniform float strength;\\n\\\nuniform vec2 repeat;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec2 st = materialInput.st;\\n\\\nvec2 centerPixel = fract(repeat * st);\\n\\\nfloat centerBump = texture2D(image, centerPixel).channel;\\n\\\nfloat imageWidth = float(imageDimensions.x);\\n\\\nvec2 rightPixel = fract(repeat * (st + vec2(1.0 / imageWidth, 0.0)));\\n\\\nfloat rightBump = texture2D(image, rightPixel).channel;\\n\\\nfloat imageHeight = float(imageDimensions.y);\\n\\\nvec2 leftPixel = fract(repeat * (st + vec2(0.0, 1.0 / imageHeight)));\\n\\\nfloat topBump = texture2D(image, leftPixel).channel;\\n\\\nvec3 normalTangentSpace = normalize(vec3(centerBump - rightBump, centerBump - topBump, clamp(1.0 - strength, 0.1, 1.0)));\\n\\\nvec3 normalEC = materialInput.tangentToEyeMatrix * normalTangentSpace;\\n\\\nmaterial.normal = normalEC;\\n\\\nmaterial.diffuse = vec3(0.01);\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 lightColor;\\n\\\nuniform vec4 darkColor;\\n\\\nuniform vec2 repeat;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec2 st = materialInput.st;\\n\\\nfloat b = mod(floor(repeat.s * st.s) + floor(repeat.t * st.t), 2.0);\\n\\\nfloat scaledWidth = fract(repeat.s * st.s);\\n\\\nscaledWidth = abs(scaledWidth - floor(scaledWidth + 0.5));\\n\\\nfloat scaledHeight = fract(repeat.t * st.t);\\n\\\nscaledHeight = abs(scaledHeight - floor(scaledHeight + 0.5));\\n\\\nfloat value = min(scaledWidth, scaledHeight);\\n\\\nvec4 currentColor = mix(lightColor, darkColor, b);\\n\\\nvec4 color = czm_antialias(lightColor, darkColor, currentColor, value, 0.03);\\n\\\ncolor = czm_gammaCorrect(color);\\n\\\nmaterial.diffuse = color.rgb;\\n\\\nmaterial.alpha = color.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 lightColor;\\n\\\nuniform vec4 darkColor;\\n\\\nuniform vec2 repeat;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nfloat b = smoothstep(0.3, 0.32, length(fract(repeat * materialInput.st) - 0.5));\\n\\\nvec4 color = mix(lightColor, darkColor, b);\\n\\\ncolor = czm_gammaCorrect(color);\\n\\\nmaterial.diffuse = color.rgb;\\n\\\nmaterial.alpha = color.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform sampler2D heights;\\n\\\nuniform sampler2D colors;\\n\\\nfloat getHeight(int idx, float invTexSize)\\n\\\n{\\n\\\nvec2 uv = vec2((float(idx) + 0.5) * invTexSize, 0.5);\\n\\\n#ifdef OES_texture_float\\n\\\nreturn texture2D(heights, uv).x;\\n\\\n#else\\n\\\nreturn czm_unpackFloat(texture2D(heights, uv));\\n\\\n#endif\\n\\\n}\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nfloat height = materialInput.height;\\n\\\nfloat invTexSize = 1.0 / float(heightsDimensions.x);\\n\\\nfloat minHeight = getHeight(0, invTexSize);\\n\\\nfloat maxHeight = getHeight(heightsDimensions.x - 1, invTexSize);\\n\\\nif (height < minHeight || height > maxHeight) {\\n\\\nmaterial.diffuse = vec3(0.0);\\n\\\nmaterial.alpha = 0.0;\\n\\\nreturn material;\\n\\\n}\\n\\\nint idxBelow = 0;\\n\\\nint idxAbove = heightsDimensions.x;\\n\\\nfloat heightBelow = minHeight;\\n\\\nfloat heightAbove = maxHeight;\\n\\\nconst int maxIterations = 16;\\n\\\nfor (int i = 0; i < maxIterations; i++) {\\n\\\nif (idxBelow >= idxAbove - 1) {\\n\\\nbreak;\\n\\\n}\\n\\\nint idxMid = (idxBelow + idxAbove) / 2;\\n\\\nfloat heightTex = getHeight(idxMid, invTexSize);\\n\\\nif (height > heightTex) {\\n\\\nidxBelow = idxMid;\\n\\\nheightBelow = heightTex;\\n\\\n} else {\\n\\\nidxAbove = idxMid;\\n\\\nheightAbove = heightTex;\\n\\\n}\\n\\\n}\\n\\\nfloat lerper = heightBelow == heightAbove ? 1.0 : (height - heightBelow) / (heightAbove - heightBelow);\\n\\\nvec2 colorUv = vec2(invTexSize * (float(idxBelow) + 0.5 + lerper), 0.5);\\n\\\nvec4 color = texture2D(colors, colorUv);\\n\\\nif (color.a > 0.0)\\n\\\n{\\n\\\ncolor.rgb /= color.a;\\n\\\n}\\n\\\ncolor.rgb = czm_gammaCorrect(color.rgb);\\n\\\nmaterial.diffuse = color.rgb;\\n\\\nmaterial.alpha = color.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef GL_OES_standard_derivatives\\n\\\n#extension GL_OES_standard_derivatives : enable\\n\\\n#endif\\n\\\nuniform vec4 color;\\n\\\nuniform float spacing;\\n\\\nuniform float width;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nfloat distanceToContour = mod(materialInput.height, spacing);\\n\\\n#ifdef GL_OES_standard_derivatives\\n\\\nfloat dxc = abs(dFdx(materialInput.height));\\n\\\nfloat dyc = abs(dFdy(materialInput.height));\\n\\\nfloat dF = max(dxc, dyc) * czm_pixelRatio * width;\\n\\\nfloat alpha = (distanceToContour < dF) ? 1.0 : 0.0;\\n\\\n#else\\n\\\nfloat alpha = (distanceToContour < (czm_pixelRatio * width)) ? 1.0 : 0.0;\\n\\\n#endif\\n\\\nvec4 outColor = czm_gammaCorrect(vec4(color.rgb, alpha * color.a));\\n\\\nmaterial.diffuse = outColor.rgb;\\n\\\nmaterial.alpha = outColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform sampler2D image;\\n\\\nuniform float minimumHeight;\\n\\\nuniform float maximumHeight;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nfloat scaledHeight = clamp((materialInput.height - minimumHeight) / (maximumHeight - minimumHeight), 0.0, 1.0);\\n\\\nvec4 rampColor = texture2D(image, vec2(scaledHeight, 0.5));\\n\\\nrampColor = czm_gammaCorrect(rampColor);\\n\\\nmaterial.diffuse = rampColor.rgb;\\n\\\nmaterial.alpha = rampColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 fadeInColor;\\n\\\nuniform vec4 fadeOutColor;\\n\\\nuniform float maximumDistance;\\n\\\nuniform bool repeat;\\n\\\nuniform vec2 fadeDirection;\\n\\\nuniform vec2 time;\\n\\\nfloat getTime(float t, float coord)\\n\\\n{\\n\\\nfloat scalar = 1.0 / maximumDistance;\\n\\\nfloat q = distance(t, coord) * scalar;\\n\\\nif (repeat)\\n\\\n{\\n\\\nfloat r = distance(t, coord + 1.0) * scalar;\\n\\\nfloat s = distance(t, coord - 1.0) * scalar;\\n\\\nq = min(min(r, s), q);\\n\\\n}\\n\\\nreturn clamp(q, 0.0, 1.0);\\n\\\n}\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec2 st = materialInput.st;\\n\\\nfloat s = getTime(time.x, st.s) * fadeDirection.s;\\n\\\nfloat t = getTime(time.y, st.t) * fadeDirection.t;\\n\\\nfloat u = length(vec2(s, t));\\n\\\nvec4 color = mix(fadeInColor, fadeOutColor, u);\\n\\\ncolor = czm_gammaCorrect(color);\\n\\\nmaterial.emission = color.rgb;\\n\\\nmaterial.alpha = color.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef GL_OES_standard_derivatives\\n\\\n#extension GL_OES_standard_derivatives : enable\\n\\\n#endif\\n\\\nuniform vec4 color;\\n\\\nuniform float cellAlpha;\\n\\\nuniform vec2 lineCount;\\n\\\nuniform vec2 lineThickness;\\n\\\nuniform vec2 lineOffset;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec2 st = materialInput.st;\\n\\\nfloat scaledWidth = fract(lineCount.s * st.s - lineOffset.s);\\n\\\nscaledWidth = abs(scaledWidth - floor(scaledWidth + 0.5));\\n\\\nfloat scaledHeight = fract(lineCount.t * st.t - lineOffset.t);\\n\\\nscaledHeight = abs(scaledHeight - floor(scaledHeight + 0.5));\\n\\\nfloat value;\\n\\\n#ifdef GL_OES_standard_derivatives\\n\\\nconst float fuzz = 1.2;\\n\\\nvec2 thickness = (lineThickness * czm_pixelRatio) - 1.0;\\n\\\nvec2 dx = abs(dFdx(st));\\n\\\nvec2 dy = abs(dFdy(st));\\n\\\nvec2 dF = vec2(max(dx.s, dy.s), max(dx.t, dy.t)) * lineCount;\\n\\\nvalue = min(\\n\\\nsmoothstep(dF.s * thickness.s, dF.s * (fuzz + thickness.s), scaledWidth),\\n\\\nsmoothstep(dF.t * thickness.t, dF.t * (fuzz + thickness.t), scaledHeight));\\n\\\n#else\\n\\\nconst float fuzz = 0.05;\\n\\\nvec2 range = 0.5 - (lineThickness * 0.05);\\n\\\nvalue = min(\\n\\\n1.0 - smoothstep(range.s, range.s + fuzz, scaledWidth),\\n\\\n1.0 - smoothstep(range.t, range.t + fuzz, scaledHeight));\\n\\\n#endif\\n\\\nfloat dRim = 1.0 - abs(dot(materialInput.normalEC, normalize(materialInput.positionToEyeEC)));\\n\\\nfloat sRim = smoothstep(0.8, 1.0, dRim);\\n\\\nvalue *= (1.0 - sRim);\\n\\\nvec4 halfColor;\\n\\\nhalfColor.rgb = color.rgb * 0.5;\\n\\\nhalfColor.a = color.a * (1.0 - ((1.0 - cellAlpha) * value));\\n\\\nhalfColor = czm_gammaCorrect(halfColor);\\n\\\nmaterial.diffuse = halfColor.rgb;\\n\\\nmaterial.emission = halfColor.rgb;\\n\\\nmaterial.alpha = halfColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform sampler2D image;\\n\\\nuniform float strength;\\n\\\nuniform vec2 repeat;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec4 textureValue = texture2D(image, fract(repeat * materialInput.st));\\n\\\nvec3 normalTangentSpace = textureValue.channels;\\n\\\nnormalTangentSpace.xy = normalTangentSpace.xy * 2.0 - 1.0;\\n\\\nnormalTangentSpace.z = clamp(1.0 - strength, 0.1, 1.0);\\n\\\nnormalTangentSpace = normalize(normalTangentSpace);\\n\\\nvec3 normalEC = materialInput.tangentToEyeMatrix * normalTangentSpace;\\n\\\nmaterial.normal = normalEC;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef GL_OES_standard_derivatives\\n\\\n#extension GL_OES_standard_derivatives : enable\\n\\\n#endif\\n\\\nuniform vec4 color;\\n\\\nfloat getPointOnLine(vec2 p0, vec2 p1, float x)\\n\\\n{\\n\\\nfloat slope = (p0.y - p1.y) / (p0.x - p1.x);\\n\\\nreturn slope * (x - p0.x) + p0.y;\\n\\\n}\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec2 st = materialInput.st;\\n\\\n#ifdef GL_OES_standard_derivatives\\n\\\nfloat base = 1.0 - abs(fwidth(st.s)) * 10.0 * czm_pixelRatio;\\n\\\n#else\\n\\\nfloat base = 0.975;\\n\\\n#endif\\n\\\nvec2 center = vec2(1.0, 0.5);\\n\\\nfloat ptOnUpperLine = getPointOnLine(vec2(base, 1.0), center, st.s);\\n\\\nfloat ptOnLowerLine = getPointOnLine(vec2(base, 0.0), center, st.s);\\n\\\nfloat halfWidth = 0.15;\\n\\\nfloat s = step(0.5 - halfWidth, st.t);\\n\\\ns *= 1.0 - step(0.5 + halfWidth, st.t);\\n\\\ns *= 1.0 - step(base, st.s);\\n\\\nfloat t = step(base, materialInput.st.s);\\n\\\nt *= 1.0 - step(ptOnUpperLine, st.t);\\n\\\nt *= step(ptOnLowerLine, st.t);\\n\\\nfloat dist;\\n\\\nif (st.s < base)\\n\\\n{\\n\\\nfloat d1 = abs(st.t - (0.5 - halfWidth));\\n\\\nfloat d2 = abs(st.t - (0.5 + halfWidth));\\n\\\ndist = min(d1, d2);\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nfloat d1 = czm_infinity;\\n\\\nif (st.t < 0.5 - halfWidth && st.t > 0.5 + halfWidth)\\n\\\n{\\n\\\nd1 = abs(st.s - base);\\n\\\n}\\n\\\nfloat d2 = abs(st.t - ptOnUpperLine);\\n\\\nfloat d3 = abs(st.t - ptOnLowerLine);\\n\\\ndist = min(min(d1, d2), d3);\\n\\\n}\\n\\\nvec4 outsideColor = vec4(0.0);\\n\\\nvec4 currentColor = mix(outsideColor, color, clamp(s + t, 0.0, 1.0));\\n\\\nvec4 outColor = czm_antialias(outsideColor, color, currentColor, dist);\\n\\\noutColor = czm_gammaCorrect(outColor);\\n\\\nmaterial.diffuse = outColor.rgb;\\n\\\nmaterial.alpha = outColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 color;\\n\\\nuniform vec4 gapColor;\\n\\\nuniform float dashLength;\\n\\\nuniform float dashPattern;\\n\\\nvarying float v_polylineAngle;\\n\\\nconst float maskLength = 16.0;\\n\\\nmat2 rotate(float rad) {\\n\\\nfloat c = cos(rad);\\n\\\nfloat s = sin(rad);\\n\\\nreturn mat2(\\n\\\nc, s,\\n\\\n-s, c\\n\\\n);\\n\\\n}\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec2 pos = rotate(v_polylineAngle) * gl_FragCoord.xy;\\n\\\nfloat dashPosition = fract(pos.x / (dashLength * czm_pixelRatio));\\n\\\nfloat maskIndex = floor(dashPosition * maskLength);\\n\\\nfloat maskTest = floor(dashPattern / pow(2.0, maskIndex));\\n\\\nvec4 fragColor = (mod(maskTest, 2.0) < 1.0) ? gapColor : color;\\n\\\nif (fragColor.a < 0.005) {\\n\\\ndiscard;\\n\\\n}\\n\\\nfragColor = czm_gammaCorrect(fragColor);\\n\\\nmaterial.emission = fragColor.rgb;\\n\\\nmaterial.alpha = fragColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 color;\\n\\\nuniform float glowPower;\\n\\\nuniform float taperPower;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec2 st = materialInput.st;\\n\\\nfloat glow = glowPower / abs(st.t - 0.5) - (glowPower / 0.5);\\n\\\nif (taperPower <= 0.99999) {\\n\\\nglow *= min(1.0, taperPower / (0.5 - st.s * 0.5) - (taperPower / 0.5));\\n\\\n}\\n\\\nvec4 fragColor;\\n\\\nfragColor.rgb = max(vec3(glow - 1.0 + color.rgb), color.rgb);\\n\\\nfragColor.a = clamp(0.0, 1.0, glow) * color.a;\\n\\\nfragColor = czm_gammaCorrect(fragColor);\\n\\\nmaterial.emission = fragColor.rgb;\\n\\\nmaterial.alpha = fragColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 color;\\n\\\nuniform vec4 outlineColor;\\n\\\nuniform float outlineWidth;\\n\\\nvarying float v_width;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec2 st = materialInput.st;\\n\\\nfloat halfInteriorWidth = 0.5 * (v_width - outlineWidth) / v_width;\\n\\\nfloat b = step(0.5 - halfInteriorWidth, st.t);\\n\\\nb *= 1.0 - step(0.5 + halfInteriorWidth, st.t);\\n\\\nfloat d1 = abs(st.t - (0.5 - halfInteriorWidth));\\n\\\nfloat d2 = abs(st.t - (0.5 + halfInteriorWidth));\\n\\\nfloat dist = min(d1, d2);\\n\\\nvec4 currentColor = mix(outlineColor, color, b);\\n\\\nvec4 outColor = czm_antialias(outlineColor, color, currentColor, dist);\\n\\\noutColor = czm_gammaCorrect(outColor);\\n\\\nmaterial.diffuse = outColor.rgb;\\n\\\nmaterial.alpha = outColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 color;\\n\\\nuniform vec4 rimColor;\\n\\\nuniform float width;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nfloat d = 1.0 - dot(materialInput.normalEC, normalize(materialInput.positionToEyeEC));\\n\\\nfloat s = smoothstep(1.0 - width, 1.0, d);\\n\\\nvec4 outColor = czm_gammaCorrect(color);\\n\\\nvec4 outRimColor = czm_gammaCorrect(rimColor);\\n\\\nmaterial.diffuse = outColor.rgb;\\n\\\nmaterial.emission = outRimColor.rgb * s;\\n\\\nmaterial.alpha = mix(outColor.a, outRimColor.a, s);\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform sampler2D image;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nvec4 rampColor = texture2D(image, vec2(materialInput.slope / (czm_pi / 2.0), 0.5));\\n\\\nrampColor = czm_gammaCorrect(rampColor);\\n\\\nmaterial.diffuse = rampColor.rgb;\\n\\\nmaterial.alpha = rampColor.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 evenColor;\\n\\\nuniform vec4 oddColor;\\n\\\nuniform float offset;\\n\\\nuniform float repeat;\\n\\\nuniform bool horizontal;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nfloat coord = mix(materialInput.st.s, materialInput.st.t, float(horizontal));\\n\\\nfloat value = fract((coord - offset) * (repeat * 0.5));\\n\\\nfloat dist = min(value, min(abs(value - 0.5), 1.0 - value));\\n\\\nvec4 currentColor = mix(evenColor, oddColor, step(0.5, value));\\n\\\nvec4 color = czm_antialias(evenColor, oddColor, currentColor, dist);\\n\\\ncolor = czm_gammaCorrect(color);\\n\\\nmaterial.diffuse = color.rgb;\\n\\\nmaterial.alpha = color.a;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform sampler2D specularMap;\\n\\\nuniform sampler2D normalMap;\\n\\\nuniform vec4 baseWaterColor;\\n\\\nuniform vec4 blendColor;\\n\\\nuniform float frequency;\\n\\\nuniform float animationSpeed;\\n\\\nuniform float amplitude;\\n\\\nuniform float specularIntensity;\\n\\\nuniform float fadeFactor;\\n\\\nczm_material czm_getMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nfloat time = czm_frameNumber * animationSpeed;\\n\\\nfloat fade = max(1.0, (length(materialInput.positionToEyeEC) / 10000000000.0) * frequency * fadeFactor);\\n\\\nfloat specularMapValue = texture2D(specularMap, materialInput.st).r;\\n\\\nvec4 noise = czm_getWaterNoise(normalMap, materialInput.st * frequency, time, 0.0);\\n\\\nvec3 normalTangentSpace = noise.xyz * vec3(1.0, 1.0, (1.0 / amplitude));\\n\\\nnormalTangentSpace.xy /= fade;\\n\\\nnormalTangentSpace = mix(vec3(0.0, 0.0, 50.0), normalTangentSpace, specularMapValue);\\n\\\nnormalTangentSpace = normalize(normalTangentSpace);\\n\\\nfloat tsPerturbationRatio = clamp(dot(normalTangentSpace, vec3(0.0, 0.0, 1.0)), 0.0, 1.0);\\n\\\nmaterial.alpha = mix(blendColor.a, baseWaterColor.a, specularMapValue) * specularMapValue;\\n\\\nmaterial.diffuse = mix(blendColor.rgb, baseWaterColor.rgb, specularMapValue);\\n\\\nmaterial.diffuse += (0.1 * tsPerturbationRatio);\\n\\\nmaterial.diffuse = material.diffuse;\\n\\\nmaterial.normal = normalize(materialInput.tangentToEyeMatrix * normalTangentSpace);\\n\\\nmaterial.specular = specularIntensity;\\n\\\nmaterial.shininess = 10.0;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport clone from \"../Core/clone.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport loadCRN from \"../Core/loadCRN.js\";\r\nimport loadKTX from \"../Core/loadKTX.js\";\r\nimport Matrix2 from \"../Core/Matrix2.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport CubeMap from \"../Renderer/CubeMap.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport AspectRampMaterial from \"../Shaders/Materials/AspectRampMaterial.js\";\r\nimport BumpMapMaterial from \"../Shaders/Materials/BumpMapMaterial.js\";\r\nimport CheckerboardMaterial from \"../Shaders/Materials/CheckerboardMaterial.js\";\r\nimport DotMaterial from \"../Shaders/Materials/DotMaterial.js\";\r\nimport ElevationBandMaterial from \"../Shaders/Materials/ElevationBandMaterial.js\";\r\nimport ElevationContourMaterial from \"../Shaders/Materials/ElevationContourMaterial.js\";\r\nimport ElevationRampMaterial from \"../Shaders/Materials/ElevationRampMaterial.js\";\r\nimport FadeMaterial from \"../Shaders/Materials/FadeMaterial.js\";\r\nimport GridMaterial from \"../Shaders/Materials/GridMaterial.js\";\r\nimport NormalMapMaterial from \"../Shaders/Materials/NormalMapMaterial.js\";\r\nimport PolylineArrowMaterial from \"../Shaders/Materials/PolylineArrowMaterial.js\";\r\nimport PolylineDashMaterial from \"../Shaders/Materials/PolylineDashMaterial.js\";\r\nimport PolylineGlowMaterial from \"../Shaders/Materials/PolylineGlowMaterial.js\";\r\nimport PolylineOutlineMaterial from \"../Shaders/Materials/PolylineOutlineMaterial.js\";\r\nimport RimLightingMaterial from \"../Shaders/Materials/RimLightingMaterial.js\";\r\nimport Sampler from \"../Renderer/Sampler.js\";\r\nimport SlopeRampMaterial from \"../Shaders/Materials/SlopeRampMaterial.js\";\r\nimport StripeMaterial from \"../Shaders/Materials/StripeMaterial.js\";\r\nimport TextureMagnificationFilter from \"../Renderer/TextureMagnificationFilter.js\";\r\nimport TextureMinificationFilter from \"../Renderer/TextureMinificationFilter.js\";\r\nimport WaterMaterial from \"../Shaders/Materials/Water.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\n\r\n/**\r\n * A Material defines surface appearance through a combination of diffuse, specular,\r\n * normal, emission, and alpha components. These values are specified using a\r\n * JSON schema called Fabric which gets parsed and assembled into glsl shader code\r\n * behind-the-scenes. Check out the {@link https://github.com/CesiumGS/cesium/wiki/Fabric|wiki page}\r\n * for more details on Fabric.\r\n *

\r\n * \r\n *\r\n * Base material types and their uniforms:\r\n *
\r\n *
    \r\n *
  • Color
  • \r\n *
      \r\n *
    • color: rgba color object.
    • \r\n *
    \r\n *
  • Image
  • \r\n *
      \r\n *
    • image: path to image.
    • \r\n *
    • repeat: Object with x and y values specifying the number of times to repeat the image.
    • \r\n *
    \r\n *
  • DiffuseMap
  • \r\n *
      \r\n *
    • image: path to image.
    • \r\n *
    • channels: Three character string containing any combination of r, g, b, and a for selecting the desired image channels.
    • \r\n *
    • repeat: Object with x and y values specifying the number of times to repeat the image.
    • \r\n *
    \r\n *
  • AlphaMap
  • \r\n *
      \r\n *
    • image: path to image.
    • \r\n *
    • channel: One character string containing r, g, b, or a for selecting the desired image channel.
    • \r\n *
    • repeat: Object with x and y values specifying the number of times to repeat the image.
    • \r\n *
    \r\n *
  • SpecularMap
  • \r\n *
      \r\n *
    • image: path to image.
    • \r\n *
    • channel: One character string containing r, g, b, or a for selecting the desired image channel.
    • \r\n *
    • repeat: Object with x and y values specifying the number of times to repeat the image.
    • \r\n *
    \r\n *
  • EmissionMap
  • \r\n *
      \r\n *
    • image: path to image.
    • \r\n *
    • channels: Three character string containing any combination of r, g, b, and a for selecting the desired image channels.
    • \r\n *
    • repeat: Object with x and y values specifying the number of times to repeat the image.
    • \r\n *
    \r\n *
  • BumpMap
  • \r\n *
      \r\n *
    • image: path to image.
    • \r\n *
    • channel: One character string containing r, g, b, or a for selecting the desired image channel.
    • \r\n *
    • repeat: Object with x and y values specifying the number of times to repeat the image.
    • \r\n *
    • strength: Bump strength value between 0.0 and 1.0 where 0.0 is small bumps and 1.0 is large bumps.
    • \r\n *
    \r\n *
  • NormalMap
  • \r\n *
      \r\n *
    • image: path to image.
    • \r\n *
    • channels: Three character string containing any combination of r, g, b, and a for selecting the desired image channels.
    • \r\n *
    • repeat: Object with x and y values specifying the number of times to repeat the image.
    • \r\n *
    • strength: Bump strength value between 0.0 and 1.0 where 0.0 is small bumps and 1.0 is large bumps.
    • \r\n *
    \r\n *
  • Grid
  • \r\n *
      \r\n *
    • color: rgba color object for the whole material.
    • \r\n *
    • cellAlpha: Alpha value for the cells between grid lines. This will be combined with color.alpha.
    • \r\n *
    • lineCount: Object with x and y values specifying the number of columns and rows respectively.
    • \r\n *
    • lineThickness: Object with x and y values specifying the thickness of grid lines (in pixels where available).
    • \r\n *
    • lineOffset: Object with x and y values specifying the offset of grid lines (range is 0 to 1).
    • \r\n *
    \r\n *
  • Stripe
  • \r\n *
      \r\n *
    • horizontal: Boolean that determines if the stripes are horizontal or vertical.
    • \r\n *
    • evenColor: rgba color object for the stripe's first color.
    • \r\n *
    • oddColor: rgba color object for the stripe's second color.
    • \r\n *
    • offset: Number that controls at which point into the pattern to begin drawing; with 0.0 being the beginning of the even color, 1.0 the beginning of the odd color, 2.0 being the even color again, and any multiple or fractional values being in between.
    • \r\n *
    • repeat: Number that controls the total number of stripes, half light and half dark.
    • \r\n *
    \r\n *
  • Checkerboard
  • \r\n *
      \r\n *
    • lightColor: rgba color object for the checkerboard's light alternating color.
    • \r\n *
    • darkColor: rgba color object for the checkerboard's dark alternating color.
    • \r\n *
    • repeat: Object with x and y values specifying the number of columns and rows respectively.
    • \r\n *
    \r\n *
  • Dot
  • \r\n *
      \r\n *
    • lightColor: rgba color object for the dot color.
    • \r\n *
    • darkColor: rgba color object for the background color.
    • \r\n *
    • repeat: Object with x and y values specifying the number of columns and rows of dots respectively.
    • \r\n *
    \r\n *
  • Water
  • \r\n *
      \r\n *
    • baseWaterColor: rgba color object base color of the water.
    • \r\n *
    • blendColor: rgba color object used when blending from water to non-water areas.
    • \r\n *
    • specularMap: Single channel texture used to indicate areas of water.
    • \r\n *
    • normalMap: Normal map for water normal perturbation.
    • \r\n *
    • frequency: Number that controls the number of waves.
    • \r\n *
    • normalMap: Normal map for water normal perturbation.
    • \r\n *
    • animationSpeed: Number that controls the animations speed of the water.
    • \r\n *
    • amplitude: Number that controls the amplitude of water waves.
    • \r\n *
    • specularIntensity: Number that controls the intensity of specular reflections.
    • \r\n *
    \r\n *
  • RimLighting
  • \r\n *
      \r\n *
    • color: diffuse color and alpha.
    • \r\n *
    • rimColor: diffuse color and alpha of the rim.
    • \r\n *
    • width: Number that determines the rim's width.
    • \r\n *
    \r\n *
  • Fade
  • \r\n *
      \r\n *
    • fadeInColor: diffuse color and alpha at time
    • \r\n *
    • fadeOutColor: diffuse color and alpha at maximumDistance from time
    • \r\n *
    • maximumDistance: Number between 0.0 and 1.0 where the fadeInColor becomes the fadeOutColor. A value of 0.0 gives the entire material a color of fadeOutColor and a value of 1.0 gives the the entire material a color of fadeInColor
    • \r\n *
    • repeat: true if the fade should wrap around the texture coodinates.
    • \r\n *
    • fadeDirection: Object with x and y values specifying if the fade should be in the x and y directions.
    • \r\n *
    • time: Object with x and y values between 0.0 and 1.0 of the fadeInColor position
    • \r\n *
    \r\n *
  • PolylineArrow
  • \r\n *
      \r\n *
    • color: diffuse color and alpha.
    • \r\n *
    \r\n *
  • PolylineDash
  • \r\n *
      \r\n *
    • color: color for the line.
    • \r\n *
    • gapColor: color for the gaps in the line.
    • \r\n *
    • dashLength: Dash length in pixels.
    • \r\n *
    • dashPattern: The 16 bit stipple pattern for the line..
    • \r\n *
    \r\n *
  • PolylineGlow
  • \r\n *
      \r\n *
    • color: color and maximum alpha for the glow on the line.
    • \r\n *
    • glowPower: strength of the glow, as a percentage of the total line width (less than 1.0).
    • \r\n *
    • taperPower: strength of the tapering effect, as a percentage of the total line length. If 1.0 or higher, no taper effect is used.
    • \r\n *
    \r\n *
  • PolylineOutline
  • \r\n *
      \r\n *
    • color: diffuse color and alpha for the interior of the line.
    • \r\n *
    • outlineColor: diffuse color and alpha for the outline.
    • \r\n *
    • outlineWidth: width of the outline in pixels.
    • \r\n *
    \r\n *
  • ElevationContour
  • \r\n *
      \r\n *
    • color: color and alpha for the contour line.
    • \r\n *
    • spacing: spacing for contour lines in meters.
    • \r\n *
    • width: Number specifying the width of the grid lines in pixels.
    • \r\n *
    \r\n *
  • ElevationRamp
  • \r\n *
      \r\n *
    • image: color ramp image to use for coloring the terrain.
    • \r\n *
    • minimumHeight: minimum height for the ramp.
    • \r\n *
    • maximumHeight: maximum height for the ramp.
    • \r\n *
    \r\n *
  • SlopeRamp
  • \r\n *
      \r\n *
    • image: color ramp image to use for coloring the terrain by slope.
    • \r\n *
    \r\n *
  • AspectRamp
  • \r\n *
      \r\n *
    • image: color ramp image to use for color the terrain by aspect.
    • \r\n *
    \r\n *
  • ElevationBand
  • \r\n *
      \r\n *
    • heights: image of heights sorted from lowest to highest.
    • \r\n *
    • colors: image of colors at the corresponding heights.
    • \r\n *
    \r\n *
\r\n * \r\n *
\r\n *\r\n * @alias Material\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.strict=false] Throws errors for issues that would normally be ignored, including unused uniforms or materials.\r\n * @param {Boolean|Function} [options.translucent=true] When true or a function that returns true, the geometry\r\n * with this material is expected to appear translucent.\r\n * @param {TextureMinificationFilter} [options.minificationFilter=TextureMinificationFilter.LINEAR] The {@link TextureMinificationFilter} to apply to this material's textures.\r\n * @param {TextureMagnificationFilter} [options.magnificationFilter=TextureMagnificationFilter.LINEAR] The {@link TextureMagnificationFilter} to apply to this material's textures.\r\n * @param {Object} options.fabric The fabric JSON used to generate the material.\r\n *\r\n * @constructor\r\n *\r\n * @exception {DeveloperError} fabric: uniform has invalid type.\r\n * @exception {DeveloperError} fabric: uniforms and materials cannot share the same property.\r\n * @exception {DeveloperError} fabric: cannot have source and components in the same section.\r\n * @exception {DeveloperError} fabric: property name is not valid. It should be 'type', 'materials', 'uniforms', 'components', or 'source'.\r\n * @exception {DeveloperError} fabric: property name is not valid. It should be 'diffuse', 'specular', 'shininess', 'normal', 'emission', or 'alpha'.\r\n * @exception {DeveloperError} strict: shader source does not use string.\r\n * @exception {DeveloperError} strict: shader source does not use uniform.\r\n * @exception {DeveloperError} strict: shader source does not use material.\r\n *\r\n * @see {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric wiki page} for a more detailed options of Fabric.\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Materials.html|Cesium Sandcastle Materials Demo}\r\n *\r\n * @example\r\n * // Create a color material with fromType:\r\n * polygon.material = Cesium.Material.fromType('Color');\r\n * polygon.material.uniforms.color = new Cesium.Color(1.0, 1.0, 0.0, 1.0);\r\n *\r\n * // Create the default material:\r\n * polygon.material = new Cesium.Material();\r\n *\r\n * // Create a color material with full Fabric notation:\r\n * polygon.material = new Cesium.Material({\r\n * fabric : {\r\n * type : 'Color',\r\n * uniforms : {\r\n * color : new Cesium.Color(1.0, 1.0, 0.0, 1.0)\r\n * }\r\n * }\r\n * });\r\n */\r\nfunction Material(options) {\r\n /**\r\n * The material type. Can be an existing type or a new type. If no type is specified in fabric, type is a GUID.\r\n * @type {String}\r\n * @default undefined\r\n */\r\n this.type = undefined;\r\n\r\n /**\r\n * The glsl shader source for this material.\r\n * @type {String}\r\n * @default undefined\r\n */\r\n this.shaderSource = undefined;\r\n\r\n /**\r\n * Maps sub-material names to Material objects.\r\n * @type {Object}\r\n * @default undefined\r\n */\r\n this.materials = undefined;\r\n\r\n /**\r\n * Maps uniform names to their values.\r\n * @type {Object}\r\n * @default undefined\r\n */\r\n this.uniforms = undefined;\r\n this._uniforms = undefined;\r\n\r\n /**\r\n * When true or a function that returns true,\r\n * the geometry is expected to appear translucent.\r\n * @type {Boolean|Function}\r\n * @default undefined\r\n */\r\n this.translucent = undefined;\r\n\r\n this._minificationFilter = defaultValue(\r\n options.minificationFilter,\r\n TextureMinificationFilter.LINEAR\r\n );\r\n this._magnificationFilter = defaultValue(\r\n options.magnificationFilter,\r\n TextureMagnificationFilter.LINEAR\r\n );\r\n\r\n this._strict = undefined;\r\n this._template = undefined;\r\n this._count = undefined;\r\n\r\n this._texturePaths = {};\r\n this._loadedImages = [];\r\n this._loadedCubeMaps = [];\r\n\r\n this._textures = {};\r\n\r\n this._updateFunctions = [];\r\n\r\n this._defaultTexture = undefined;\r\n\r\n initializeMaterial(options, this);\r\n Object.defineProperties(this, {\r\n type: {\r\n value: this.type,\r\n writable: false,\r\n },\r\n });\r\n\r\n if (!defined(Material._uniformList[this.type])) {\r\n Material._uniformList[this.type] = Object.keys(this._uniforms);\r\n }\r\n}\r\n\r\n// Cached list of combined uniform names indexed by type.\r\n// Used to get the list of uniforms in the same order.\r\nMaterial._uniformList = {};\r\n\r\n/**\r\n * Creates a new material using an existing material type.\r\n *

\r\n * Shorthand for: new Material({fabric : {type : type}});\r\n *\r\n * @param {String} type The base material type.\r\n * @param {Object} [uniforms] Overrides for the default uniforms.\r\n * @returns {Material} New material object.\r\n *\r\n * @exception {DeveloperError} material with that type does not exist.\r\n *\r\n * @example\r\n * var material = Cesium.Material.fromType('Color', {\r\n * color : new Cesium.Color(1.0, 0.0, 0.0, 1.0)\r\n * });\r\n */\r\nMaterial.fromType = function (type, uniforms) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(Material._materialCache.getMaterial(type))) {\r\n throw new DeveloperError(\r\n \"material with type '\" + type + \"' does not exist.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var material = new Material({\r\n fabric: {\r\n type: type,\r\n },\r\n });\r\n\r\n if (defined(uniforms)) {\r\n for (var name in uniforms) {\r\n if (uniforms.hasOwnProperty(name)) {\r\n material.uniforms[name] = uniforms[name];\r\n }\r\n }\r\n }\r\n\r\n return material;\r\n};\r\n\r\n/**\r\n * Gets whether or not this material is translucent.\r\n * @returns {Boolean} true if this material is translucent, false otherwise.\r\n */\r\nMaterial.prototype.isTranslucent = function () {\r\n if (defined(this.translucent)) {\r\n if (typeof this.translucent === \"function\") {\r\n return this.translucent();\r\n }\r\n\r\n return this.translucent;\r\n }\r\n\r\n var translucent = true;\r\n var funcs = this._translucentFunctions;\r\n var length = funcs.length;\r\n for (var i = 0; i < length; ++i) {\r\n var func = funcs[i];\r\n if (typeof func === \"function\") {\r\n translucent = translucent && func();\r\n } else {\r\n translucent = translucent && func;\r\n }\r\n\r\n if (!translucent) {\r\n break;\r\n }\r\n }\r\n return translucent;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nMaterial.prototype.update = function (context) {\r\n var i;\r\n var uniformId;\r\n\r\n var loadedImages = this._loadedImages;\r\n var length = loadedImages.length;\r\n\r\n for (i = 0; i < length; ++i) {\r\n var loadedImage = loadedImages[i];\r\n uniformId = loadedImage.id;\r\n var image = loadedImage.image;\r\n\r\n var sampler = new Sampler({\r\n minificationFilter: this._minificationFilter,\r\n magnificationFilter: this._magnificationFilter,\r\n });\r\n\r\n var texture;\r\n if (defined(image.internalFormat)) {\r\n texture = new Texture({\r\n context: context,\r\n pixelFormat: image.internalFormat,\r\n width: image.width,\r\n height: image.height,\r\n source: {\r\n arrayBufferView: image.bufferView,\r\n },\r\n sampler: sampler,\r\n });\r\n } else {\r\n texture = new Texture({\r\n context: context,\r\n source: image,\r\n sampler: sampler,\r\n });\r\n }\r\n\r\n this._textures[uniformId] = texture;\r\n\r\n var uniformDimensionsName = uniformId + \"Dimensions\";\r\n if (this.uniforms.hasOwnProperty(uniformDimensionsName)) {\r\n var uniformDimensions = this.uniforms[uniformDimensionsName];\r\n uniformDimensions.x = texture._width;\r\n uniformDimensions.y = texture._height;\r\n }\r\n }\r\n\r\n loadedImages.length = 0;\r\n\r\n var loadedCubeMaps = this._loadedCubeMaps;\r\n length = loadedCubeMaps.length;\r\n\r\n for (i = 0; i < length; ++i) {\r\n var loadedCubeMap = loadedCubeMaps[i];\r\n uniformId = loadedCubeMap.id;\r\n var images = loadedCubeMap.images;\r\n\r\n var cubeMap = new CubeMap({\r\n context: context,\r\n source: {\r\n positiveX: images[0],\r\n negativeX: images[1],\r\n positiveY: images[2],\r\n negativeY: images[3],\r\n positiveZ: images[4],\r\n negativeZ: images[5],\r\n },\r\n sampler: new Sampler({\r\n minificationFilter: this._minificationFilter,\r\n magnificationFilter: this._magnificationFilter,\r\n }),\r\n });\r\n\r\n this._textures[uniformId] = cubeMap;\r\n }\r\n\r\n loadedCubeMaps.length = 0;\r\n\r\n var updateFunctions = this._updateFunctions;\r\n length = updateFunctions.length;\r\n for (i = 0; i < length; ++i) {\r\n updateFunctions[i](this, context);\r\n }\r\n\r\n var subMaterials = this.materials;\r\n for (var name in subMaterials) {\r\n if (subMaterials.hasOwnProperty(name)) {\r\n subMaterials[name].update(context);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n *\r\n * @see Material#destroy\r\n */\r\nMaterial.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * material = material && material.destroy();\r\n *\r\n * @see Material#isDestroyed\r\n */\r\nMaterial.prototype.destroy = function () {\r\n var textures = this._textures;\r\n for (var texture in textures) {\r\n if (textures.hasOwnProperty(texture)) {\r\n var instance = textures[texture];\r\n if (instance !== this._defaultTexture) {\r\n instance.destroy();\r\n }\r\n }\r\n }\r\n\r\n var materials = this.materials;\r\n for (var material in materials) {\r\n if (materials.hasOwnProperty(material)) {\r\n materials[material].destroy();\r\n }\r\n }\r\n return destroyObject(this);\r\n};\r\n\r\nfunction initializeMaterial(options, result) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n result._strict = defaultValue(options.strict, false);\r\n result._count = defaultValue(options.count, 0);\r\n result._template = clone(\r\n defaultValue(options.fabric, defaultValue.EMPTY_OBJECT)\r\n );\r\n result._template.uniforms = clone(\r\n defaultValue(result._template.uniforms, defaultValue.EMPTY_OBJECT)\r\n );\r\n result._template.materials = clone(\r\n defaultValue(result._template.materials, defaultValue.EMPTY_OBJECT)\r\n );\r\n\r\n result.type = defined(result._template.type)\r\n ? result._template.type\r\n : createGuid();\r\n\r\n result.shaderSource = \"\";\r\n result.materials = {};\r\n result.uniforms = {};\r\n result._uniforms = {};\r\n result._translucentFunctions = [];\r\n\r\n var translucent;\r\n\r\n // If the cache contains this material type, build the material template off of the stored template.\r\n var cachedMaterial = Material._materialCache.getMaterial(result.type);\r\n if (defined(cachedMaterial)) {\r\n var template = clone(cachedMaterial.fabric, true);\r\n result._template = combine(result._template, template, true);\r\n translucent = cachedMaterial.translucent;\r\n }\r\n\r\n // Make sure the template has no obvious errors. More error checking happens later.\r\n checkForTemplateErrors(result);\r\n\r\n // If the material has a new type, add it to the cache.\r\n if (!defined(cachedMaterial)) {\r\n Material._materialCache.addMaterial(result.type, result);\r\n }\r\n\r\n createMethodDefinition(result);\r\n createUniforms(result);\r\n createSubMaterials(result);\r\n\r\n var defaultTranslucent =\r\n result._translucentFunctions.length === 0 ? true : undefined;\r\n translucent = defaultValue(translucent, defaultTranslucent);\r\n translucent = defaultValue(options.translucent, translucent);\r\n\r\n if (defined(translucent)) {\r\n if (typeof translucent === \"function\") {\r\n var wrappedTranslucent = function () {\r\n return translucent(result);\r\n };\r\n result._translucentFunctions.push(wrappedTranslucent);\r\n } else {\r\n result._translucentFunctions.push(translucent);\r\n }\r\n }\r\n}\r\n\r\nfunction checkForValidProperties(object, properties, result, throwNotFound) {\r\n if (defined(object)) {\r\n for (var property in object) {\r\n if (object.hasOwnProperty(property)) {\r\n var hasProperty = properties.indexOf(property) !== -1;\r\n if (\r\n (throwNotFound && !hasProperty) ||\r\n (!throwNotFound && hasProperty)\r\n ) {\r\n result(property, properties);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction invalidNameError(property, properties) {\r\n //>>includeStart('debug', pragmas.debug);\r\n var errorString =\r\n \"fabric: property name '\" + property + \"' is not valid. It should be \";\r\n for (var i = 0; i < properties.length; i++) {\r\n var propertyName = \"'\" + properties[i] + \"'\";\r\n errorString +=\r\n i === properties.length - 1\r\n ? \"or \" + propertyName + \".\"\r\n : propertyName + \", \";\r\n }\r\n throw new DeveloperError(errorString);\r\n //>>includeEnd('debug');\r\n}\r\n\r\nfunction duplicateNameError(property, properties) {\r\n //>>includeStart('debug', pragmas.debug);\r\n var errorString =\r\n \"fabric: uniforms and materials cannot share the same property '\" +\r\n property +\r\n \"'\";\r\n throw new DeveloperError(errorString);\r\n //>>includeEnd('debug');\r\n}\r\n\r\nvar templateProperties = [\r\n \"type\",\r\n \"materials\",\r\n \"uniforms\",\r\n \"components\",\r\n \"source\",\r\n];\r\nvar componentProperties = [\r\n \"diffuse\",\r\n \"specular\",\r\n \"shininess\",\r\n \"normal\",\r\n \"emission\",\r\n \"alpha\",\r\n];\r\n\r\nfunction checkForTemplateErrors(material) {\r\n var template = material._template;\r\n var uniforms = template.uniforms;\r\n var materials = template.materials;\r\n var components = template.components;\r\n\r\n // Make sure source and components do not exist in the same template.\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(components) && defined(template.source)) {\r\n throw new DeveloperError(\r\n \"fabric: cannot have source and components in the same template.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Make sure all template and components properties are valid.\r\n checkForValidProperties(template, templateProperties, invalidNameError, true);\r\n checkForValidProperties(\r\n components,\r\n componentProperties,\r\n invalidNameError,\r\n true\r\n );\r\n\r\n // Make sure uniforms and materials do not share any of the same names.\r\n var materialNames = [];\r\n for (var property in materials) {\r\n if (materials.hasOwnProperty(property)) {\r\n materialNames.push(property);\r\n }\r\n }\r\n checkForValidProperties(uniforms, materialNames, duplicateNameError, false);\r\n}\r\n\r\nfunction isMaterialFused(shaderComponent, material) {\r\n var materials = material._template.materials;\r\n for (var subMaterialId in materials) {\r\n if (materials.hasOwnProperty(subMaterialId)) {\r\n if (shaderComponent.indexOf(subMaterialId) > -1) {\r\n return true;\r\n }\r\n }\r\n }\r\n\r\n return false;\r\n}\r\n\r\n// Create the czm_getMaterial method body using source or components.\r\nfunction createMethodDefinition(material) {\r\n var components = material._template.components;\r\n var source = material._template.source;\r\n if (defined(source)) {\r\n material.shaderSource += source + \"\\n\";\r\n } else {\r\n material.shaderSource +=\r\n \"czm_material czm_getMaterial(czm_materialInput materialInput)\\n{\\n\";\r\n material.shaderSource +=\r\n \"czm_material material = czm_getDefaultMaterial(materialInput);\\n\";\r\n if (defined(components)) {\r\n var isMultiMaterial =\r\n Object.keys(material._template.materials).length > 0;\r\n for (var component in components) {\r\n if (components.hasOwnProperty(component)) {\r\n if (component === \"diffuse\" || component === \"emission\") {\r\n var isFusion =\r\n isMultiMaterial &&\r\n isMaterialFused(components[component], material);\r\n var componentSource = isFusion\r\n ? components[component]\r\n : \"czm_gammaCorrect(\" + components[component] + \")\";\r\n material.shaderSource +=\r\n \"material.\" + component + \" = \" + componentSource + \"; \\n\";\r\n } else if (component === \"alpha\") {\r\n material.shaderSource +=\r\n \"material.alpha = \" + components.alpha + \"; \\n\";\r\n } else {\r\n material.shaderSource +=\r\n \"material.\" + component + \" = \" + components[component] + \";\\n\";\r\n }\r\n }\r\n }\r\n }\r\n material.shaderSource += \"return material;\\n}\\n\";\r\n }\r\n}\r\n\r\nvar matrixMap = {\r\n mat2: Matrix2,\r\n mat3: Matrix3,\r\n mat4: Matrix4,\r\n};\r\n\r\nvar ktxRegex = /\\.ktx$/i;\r\nvar crnRegex = /\\.crn$/i;\r\n\r\nfunction createTexture2DUpdateFunction(uniformId) {\r\n var oldUniformValue;\r\n return function (material, context) {\r\n var uniforms = material.uniforms;\r\n var uniformValue = uniforms[uniformId];\r\n var uniformChanged = oldUniformValue !== uniformValue;\r\n oldUniformValue = uniformValue;\r\n var texture = material._textures[uniformId];\r\n\r\n var uniformDimensionsName;\r\n var uniformDimensions;\r\n\r\n if (uniformValue instanceof HTMLVideoElement) {\r\n // HTMLVideoElement.readyState >=2 means we have enough data for the current frame.\r\n // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState\r\n if (uniformValue.readyState >= 2) {\r\n if (uniformChanged && defined(texture)) {\r\n if (texture !== context.defaultTexture) {\r\n texture.destroy();\r\n }\r\n texture = undefined;\r\n }\r\n\r\n if (!defined(texture) || texture === context.defaultTexture) {\r\n var sampler = new Sampler({\r\n minificationFilter: material._minificationFilter,\r\n magnificationFilter: material._magnificationFilter,\r\n });\r\n texture = new Texture({\r\n context: context,\r\n source: uniformValue,\r\n sampler: sampler,\r\n });\r\n material._textures[uniformId] = texture;\r\n return;\r\n }\r\n\r\n texture.copyFrom(uniformValue);\r\n } else if (!defined(texture)) {\r\n material._textures[uniformId] = context.defaultTexture;\r\n }\r\n return;\r\n }\r\n\r\n if (uniformValue instanceof Texture && uniformValue !== texture) {\r\n material._texturePaths[uniformId] = undefined;\r\n var tmp = material._textures[uniformId];\r\n if (tmp !== material._defaultTexture) {\r\n tmp.destroy();\r\n }\r\n material._textures[uniformId] = uniformValue;\r\n\r\n uniformDimensionsName = uniformId + \"Dimensions\";\r\n if (uniforms.hasOwnProperty(uniformDimensionsName)) {\r\n uniformDimensions = uniforms[uniformDimensionsName];\r\n uniformDimensions.x = uniformValue._width;\r\n uniformDimensions.y = uniformValue._height;\r\n }\r\n\r\n return;\r\n }\r\n\r\n if (!defined(texture)) {\r\n material._texturePaths[uniformId] = undefined;\r\n if (!defined(material._defaultTexture)) {\r\n material._defaultTexture = context.defaultTexture;\r\n }\r\n texture = material._textures[uniformId] = material._defaultTexture;\r\n\r\n uniformDimensionsName = uniformId + \"Dimensions\";\r\n if (uniforms.hasOwnProperty(uniformDimensionsName)) {\r\n uniformDimensions = uniforms[uniformDimensionsName];\r\n uniformDimensions.x = texture._width;\r\n uniformDimensions.y = texture._height;\r\n }\r\n }\r\n\r\n if (uniformValue === Material.DefaultImageId) {\r\n return;\r\n }\r\n\r\n // When using the entity layer, the Resource objects get recreated on getValue because\r\n // they are clonable. That's why we check the url property for Resources\r\n // because the instances aren't the same and we keep trying to load the same\r\n // image if it fails to load.\r\n var isResource = uniformValue instanceof Resource;\r\n if (\r\n !defined(material._texturePaths[uniformId]) ||\r\n (isResource &&\r\n uniformValue.url !== material._texturePaths[uniformId].url) ||\r\n (!isResource && uniformValue !== material._texturePaths[uniformId])\r\n ) {\r\n if (typeof uniformValue === \"string\" || isResource) {\r\n var resource = isResource\r\n ? uniformValue\r\n : Resource.createIfNeeded(uniformValue);\r\n\r\n var promise;\r\n if (ktxRegex.test(resource.url)) {\r\n promise = loadKTX(resource);\r\n } else if (crnRegex.test(resource.url)) {\r\n promise = loadCRN(resource);\r\n } else {\r\n promise = resource.fetchImage();\r\n }\r\n when(promise, function (image) {\r\n material._loadedImages.push({\r\n id: uniformId,\r\n image: image,\r\n });\r\n });\r\n } else if (\r\n uniformValue instanceof HTMLCanvasElement ||\r\n uniformValue instanceof HTMLImageElement\r\n ) {\r\n material._loadedImages.push({\r\n id: uniformId,\r\n image: uniformValue,\r\n });\r\n }\r\n\r\n material._texturePaths[uniformId] = uniformValue;\r\n }\r\n };\r\n}\r\n\r\nfunction createCubeMapUpdateFunction(uniformId) {\r\n return function (material, context) {\r\n var uniformValue = material.uniforms[uniformId];\r\n\r\n if (uniformValue instanceof CubeMap) {\r\n var tmp = material._textures[uniformId];\r\n if (tmp !== material._defaultTexture) {\r\n tmp.destroy();\r\n }\r\n material._texturePaths[uniformId] = undefined;\r\n material._textures[uniformId] = uniformValue;\r\n return;\r\n }\r\n\r\n if (!defined(material._textures[uniformId])) {\r\n material._texturePaths[uniformId] = undefined;\r\n material._textures[uniformId] = context.defaultCubeMap;\r\n }\r\n\r\n if (uniformValue === Material.DefaultCubeMapId) {\r\n return;\r\n }\r\n\r\n var path =\r\n uniformValue.positiveX +\r\n uniformValue.negativeX +\r\n uniformValue.positiveY +\r\n uniformValue.negativeY +\r\n uniformValue.positiveZ +\r\n uniformValue.negativeZ;\r\n\r\n if (path !== material._texturePaths[uniformId]) {\r\n var promises = [\r\n Resource.createIfNeeded(uniformValue.positiveX).fetchImage(),\r\n Resource.createIfNeeded(uniformValue.negativeX).fetchImage(),\r\n Resource.createIfNeeded(uniformValue.positiveY).fetchImage(),\r\n Resource.createIfNeeded(uniformValue.negativeY).fetchImage(),\r\n Resource.createIfNeeded(uniformValue.positiveZ).fetchImage(),\r\n Resource.createIfNeeded(uniformValue.negativeZ).fetchImage(),\r\n ];\r\n\r\n when.all(promises).then(function (images) {\r\n material._loadedCubeMaps.push({\r\n id: uniformId,\r\n images: images,\r\n });\r\n });\r\n\r\n material._texturePaths[uniformId] = path;\r\n }\r\n };\r\n}\r\n\r\nfunction createUniforms(material) {\r\n var uniforms = material._template.uniforms;\r\n for (var uniformId in uniforms) {\r\n if (uniforms.hasOwnProperty(uniformId)) {\r\n createUniform(material, uniformId);\r\n }\r\n }\r\n}\r\n\r\n// Writes uniform declarations to the shader file and connects uniform values with\r\n// corresponding material properties through the returnUniforms function.\r\nfunction createUniform(material, uniformId) {\r\n var strict = material._strict;\r\n var materialUniforms = material._template.uniforms;\r\n var uniformValue = materialUniforms[uniformId];\r\n var uniformType = getUniformType(uniformValue);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(uniformType)) {\r\n throw new DeveloperError(\r\n \"fabric: uniform '\" + uniformId + \"' has invalid type.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var replacedTokenCount;\r\n if (uniformType === \"channels\") {\r\n replacedTokenCount = replaceToken(material, uniformId, uniformValue, false);\r\n //>>includeStart('debug', pragmas.debug);\r\n if (replacedTokenCount === 0 && strict) {\r\n throw new DeveloperError(\r\n \"strict: shader source does not use channels '\" + uniformId + \"'.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n } else {\r\n // Since webgl doesn't allow texture dimension queries in glsl, create a uniform to do it.\r\n // Check if the shader source actually uses texture dimensions before creating the uniform.\r\n if (uniformType === \"sampler2D\") {\r\n var imageDimensionsUniformName = uniformId + \"Dimensions\";\r\n if (getNumberOfTokens(material, imageDimensionsUniformName) > 0) {\r\n materialUniforms[imageDimensionsUniformName] = {\r\n type: \"ivec3\",\r\n x: 1,\r\n y: 1,\r\n };\r\n createUniform(material, imageDimensionsUniformName);\r\n }\r\n }\r\n\r\n // Add uniform declaration to source code.\r\n var uniformDeclarationRegex = new RegExp(\r\n \"uniform\\\\s+\" + uniformType + \"\\\\s+\" + uniformId + \"\\\\s*;\"\r\n );\r\n if (!uniformDeclarationRegex.test(material.shaderSource)) {\r\n var uniformDeclaration = \"uniform \" + uniformType + \" \" + uniformId + \";\";\r\n material.shaderSource = uniformDeclaration + material.shaderSource;\r\n }\r\n\r\n var newUniformId = uniformId + \"_\" + material._count++;\r\n replacedTokenCount = replaceToken(material, uniformId, newUniformId);\r\n //>>includeStart('debug', pragmas.debug);\r\n if (replacedTokenCount === 1 && strict) {\r\n throw new DeveloperError(\r\n \"strict: shader source does not use uniform '\" + uniformId + \"'.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Set uniform value\r\n material.uniforms[uniformId] = uniformValue;\r\n\r\n if (uniformType === \"sampler2D\") {\r\n material._uniforms[newUniformId] = function () {\r\n return material._textures[uniformId];\r\n };\r\n material._updateFunctions.push(createTexture2DUpdateFunction(uniformId));\r\n } else if (uniformType === \"samplerCube\") {\r\n material._uniforms[newUniformId] = function () {\r\n return material._textures[uniformId];\r\n };\r\n material._updateFunctions.push(createCubeMapUpdateFunction(uniformId));\r\n } else if (uniformType.indexOf(\"mat\") !== -1) {\r\n var scratchMatrix = new matrixMap[uniformType]();\r\n material._uniforms[newUniformId] = function () {\r\n return matrixMap[uniformType].fromColumnMajorArray(\r\n material.uniforms[uniformId],\r\n scratchMatrix\r\n );\r\n };\r\n } else {\r\n material._uniforms[newUniformId] = function () {\r\n return material.uniforms[uniformId];\r\n };\r\n }\r\n }\r\n}\r\n\r\n// Determines the uniform type based on the uniform in the template.\r\nfunction getUniformType(uniformValue) {\r\n var uniformType = uniformValue.type;\r\n if (!defined(uniformType)) {\r\n var type = typeof uniformValue;\r\n if (type === \"number\") {\r\n uniformType = \"float\";\r\n } else if (type === \"boolean\") {\r\n uniformType = \"bool\";\r\n } else if (\r\n type === \"string\" ||\r\n uniformValue instanceof Resource ||\r\n uniformValue instanceof HTMLCanvasElement ||\r\n uniformValue instanceof HTMLImageElement\r\n ) {\r\n if (/^([rgba]){1,4}$/i.test(uniformValue)) {\r\n uniformType = \"channels\";\r\n } else if (uniformValue === Material.DefaultCubeMapId) {\r\n uniformType = \"samplerCube\";\r\n } else {\r\n uniformType = \"sampler2D\";\r\n }\r\n } else if (type === \"object\") {\r\n if (Array.isArray(uniformValue)) {\r\n if (\r\n uniformValue.length === 4 ||\r\n uniformValue.length === 9 ||\r\n uniformValue.length === 16\r\n ) {\r\n uniformType = \"mat\" + Math.sqrt(uniformValue.length);\r\n }\r\n } else {\r\n var numAttributes = 0;\r\n for (var attribute in uniformValue) {\r\n if (uniformValue.hasOwnProperty(attribute)) {\r\n numAttributes += 1;\r\n }\r\n }\r\n if (numAttributes >= 2 && numAttributes <= 4) {\r\n uniformType = \"vec\" + numAttributes;\r\n } else if (numAttributes === 6) {\r\n uniformType = \"samplerCube\";\r\n }\r\n }\r\n }\r\n }\r\n return uniformType;\r\n}\r\n\r\n// Create all sub-materials by combining source and uniforms together.\r\nfunction createSubMaterials(material) {\r\n var strict = material._strict;\r\n var subMaterialTemplates = material._template.materials;\r\n for (var subMaterialId in subMaterialTemplates) {\r\n if (subMaterialTemplates.hasOwnProperty(subMaterialId)) {\r\n // Construct the sub-material.\r\n var subMaterial = new Material({\r\n strict: strict,\r\n fabric: subMaterialTemplates[subMaterialId],\r\n count: material._count,\r\n });\r\n\r\n material._count = subMaterial._count;\r\n material._uniforms = combine(\r\n material._uniforms,\r\n subMaterial._uniforms,\r\n true\r\n );\r\n material.materials[subMaterialId] = subMaterial;\r\n material._translucentFunctions = material._translucentFunctions.concat(\r\n subMaterial._translucentFunctions\r\n );\r\n\r\n // Make the material's czm_getMaterial unique by appending the sub-material type.\r\n var originalMethodName = \"czm_getMaterial\";\r\n var newMethodName = originalMethodName + \"_\" + material._count++;\r\n replaceToken(subMaterial, originalMethodName, newMethodName);\r\n material.shaderSource = subMaterial.shaderSource + material.shaderSource;\r\n\r\n // Replace each material id with an czm_getMaterial method call.\r\n var materialMethodCall = newMethodName + \"(materialInput)\";\r\n var tokensReplacedCount = replaceToken(\r\n material,\r\n subMaterialId,\r\n materialMethodCall\r\n );\r\n //>>includeStart('debug', pragmas.debug);\r\n if (tokensReplacedCount === 0 && strict) {\r\n throw new DeveloperError(\r\n \"strict: shader source does not use material '\" + subMaterialId + \"'.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n }\r\n }\r\n}\r\n\r\n// Used for searching or replacing a token in a material's shader source with something else.\r\n// If excludePeriod is true, do not accept tokens that are preceded by periods.\r\n// http://stackoverflow.com/questions/641407/javascript-negative-lookbehind-equivalent\r\nfunction replaceToken(material, token, newToken, excludePeriod) {\r\n excludePeriod = defaultValue(excludePeriod, true);\r\n var count = 0;\r\n var suffixChars = \"([\\\\w])?\";\r\n var prefixChars = \"([\\\\w\" + (excludePeriod ? \".\" : \"\") + \"])?\";\r\n var regExp = new RegExp(prefixChars + token + suffixChars, \"g\");\r\n material.shaderSource = material.shaderSource.replace(regExp, function (\r\n $0,\r\n $1,\r\n $2\r\n ) {\r\n if ($1 || $2) {\r\n return $0;\r\n }\r\n count += 1;\r\n return newToken;\r\n });\r\n return count;\r\n}\r\n\r\nfunction getNumberOfTokens(material, token, excludePeriod) {\r\n return replaceToken(material, token, token, excludePeriod);\r\n}\r\n\r\nMaterial._materialCache = {\r\n _materials: {},\r\n addMaterial: function (type, materialTemplate) {\r\n this._materials[type] = materialTemplate;\r\n },\r\n getMaterial: function (type) {\r\n return this._materials[type];\r\n },\r\n};\r\n\r\n/**\r\n * Gets or sets the default texture uniform value.\r\n * @type {String}\r\n */\r\nMaterial.DefaultImageId = \"czm_defaultImage\";\r\n\r\n/**\r\n * Gets or sets the default cube map texture uniform value.\r\n * @type {String}\r\n */\r\nMaterial.DefaultCubeMapId = \"czm_defaultCubeMap\";\r\n\r\n/**\r\n * Gets the name of the color material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.ColorType = \"Color\";\r\nMaterial._materialCache.addMaterial(Material.ColorType, {\r\n fabric: {\r\n type: Material.ColorType,\r\n uniforms: {\r\n color: new Color(1.0, 0.0, 0.0, 0.5),\r\n },\r\n components: {\r\n diffuse: \"color.rgb\",\r\n alpha: \"color.a\",\r\n },\r\n },\r\n translucent: function (material) {\r\n return material.uniforms.color.alpha < 1.0;\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the image material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.ImageType = \"Image\";\r\nMaterial._materialCache.addMaterial(Material.ImageType, {\r\n fabric: {\r\n type: Material.ImageType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n repeat: new Cartesian2(1.0, 1.0),\r\n color: new Color(1.0, 1.0, 1.0, 1.0),\r\n },\r\n components: {\r\n diffuse:\r\n \"texture2D(image, fract(repeat * materialInput.st)).rgb * color.rgb\",\r\n alpha: \"texture2D(image, fract(repeat * materialInput.st)).a * color.a\",\r\n },\r\n },\r\n translucent: function (material) {\r\n return material.uniforms.color.alpha < 1.0;\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the diffuce map material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.DiffuseMapType = \"DiffuseMap\";\r\nMaterial._materialCache.addMaterial(Material.DiffuseMapType, {\r\n fabric: {\r\n type: Material.DiffuseMapType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n channels: \"rgb\",\r\n repeat: new Cartesian2(1.0, 1.0),\r\n },\r\n components: {\r\n diffuse: \"texture2D(image, fract(repeat * materialInput.st)).channels\",\r\n },\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the alpha map material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.AlphaMapType = \"AlphaMap\";\r\nMaterial._materialCache.addMaterial(Material.AlphaMapType, {\r\n fabric: {\r\n type: Material.AlphaMapType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n channel: \"a\",\r\n repeat: new Cartesian2(1.0, 1.0),\r\n },\r\n components: {\r\n alpha: \"texture2D(image, fract(repeat * materialInput.st)).channel\",\r\n },\r\n },\r\n translucent: true,\r\n});\r\n\r\n/**\r\n * Gets the name of the specular map material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.SpecularMapType = \"SpecularMap\";\r\nMaterial._materialCache.addMaterial(Material.SpecularMapType, {\r\n fabric: {\r\n type: Material.SpecularMapType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n channel: \"r\",\r\n repeat: new Cartesian2(1.0, 1.0),\r\n },\r\n components: {\r\n specular: \"texture2D(image, fract(repeat * materialInput.st)).channel\",\r\n },\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the emmision map material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.EmissionMapType = \"EmissionMap\";\r\nMaterial._materialCache.addMaterial(Material.EmissionMapType, {\r\n fabric: {\r\n type: Material.EmissionMapType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n channels: \"rgb\",\r\n repeat: new Cartesian2(1.0, 1.0),\r\n },\r\n components: {\r\n emission: \"texture2D(image, fract(repeat * materialInput.st)).channels\",\r\n },\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the bump map material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.BumpMapType = \"BumpMap\";\r\nMaterial._materialCache.addMaterial(Material.BumpMapType, {\r\n fabric: {\r\n type: Material.BumpMapType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n channel: \"r\",\r\n strength: 0.8,\r\n repeat: new Cartesian2(1.0, 1.0),\r\n },\r\n source: BumpMapMaterial,\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the normal map material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.NormalMapType = \"NormalMap\";\r\nMaterial._materialCache.addMaterial(Material.NormalMapType, {\r\n fabric: {\r\n type: Material.NormalMapType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n channels: \"rgb\",\r\n strength: 0.8,\r\n repeat: new Cartesian2(1.0, 1.0),\r\n },\r\n source: NormalMapMaterial,\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the grid material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.GridType = \"Grid\";\r\nMaterial._materialCache.addMaterial(Material.GridType, {\r\n fabric: {\r\n type: Material.GridType,\r\n uniforms: {\r\n color: new Color(0.0, 1.0, 0.0, 1.0),\r\n cellAlpha: 0.1,\r\n lineCount: new Cartesian2(8.0, 8.0),\r\n lineThickness: new Cartesian2(1.0, 1.0),\r\n lineOffset: new Cartesian2(0.0, 0.0),\r\n },\r\n source: GridMaterial,\r\n },\r\n translucent: function (material) {\r\n var uniforms = material.uniforms;\r\n return uniforms.color.alpha < 1.0 || uniforms.cellAlpha < 1.0;\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the stripe material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.StripeType = \"Stripe\";\r\nMaterial._materialCache.addMaterial(Material.StripeType, {\r\n fabric: {\r\n type: Material.StripeType,\r\n uniforms: {\r\n horizontal: true,\r\n evenColor: new Color(1.0, 1.0, 1.0, 0.5),\r\n oddColor: new Color(0.0, 0.0, 1.0, 0.5),\r\n offset: 0.0,\r\n repeat: 5.0,\r\n },\r\n source: StripeMaterial,\r\n },\r\n translucent: function (material) {\r\n var uniforms = material.uniforms;\r\n return uniforms.evenColor.alpha < 1.0 || uniforms.oddColor.alpha < 1.0;\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the checkerboard material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.CheckerboardType = \"Checkerboard\";\r\nMaterial._materialCache.addMaterial(Material.CheckerboardType, {\r\n fabric: {\r\n type: Material.CheckerboardType,\r\n uniforms: {\r\n lightColor: new Color(1.0, 1.0, 1.0, 0.5),\r\n darkColor: new Color(0.0, 0.0, 0.0, 0.5),\r\n repeat: new Cartesian2(5.0, 5.0),\r\n },\r\n source: CheckerboardMaterial,\r\n },\r\n translucent: function (material) {\r\n var uniforms = material.uniforms;\r\n return uniforms.lightColor.alpha < 1.0 || uniforms.darkColor.alpha < 1.0;\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the dot material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.DotType = \"Dot\";\r\nMaterial._materialCache.addMaterial(Material.DotType, {\r\n fabric: {\r\n type: Material.DotType,\r\n uniforms: {\r\n lightColor: new Color(1.0, 1.0, 0.0, 0.75),\r\n darkColor: new Color(0.0, 1.0, 1.0, 0.75),\r\n repeat: new Cartesian2(5.0, 5.0),\r\n },\r\n source: DotMaterial,\r\n },\r\n translucent: function (material) {\r\n var uniforms = material.uniforms;\r\n return uniforms.lightColor.alpha < 1.0 || uniforms.darkColor.alpha < 1.0;\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the water material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.WaterType = \"Water\";\r\nMaterial._materialCache.addMaterial(Material.WaterType, {\r\n fabric: {\r\n type: Material.WaterType,\r\n uniforms: {\r\n baseWaterColor: new Color(0.2, 0.3, 0.6, 1.0),\r\n blendColor: new Color(0.0, 1.0, 0.699, 1.0),\r\n specularMap: Material.DefaultImageId,\r\n normalMap: Material.DefaultImageId,\r\n frequency: 10.0,\r\n animationSpeed: 0.01,\r\n amplitude: 1.0,\r\n specularIntensity: 0.5,\r\n fadeFactor: 1.0,\r\n },\r\n source: WaterMaterial,\r\n },\r\n translucent: function (material) {\r\n var uniforms = material.uniforms;\r\n return (\r\n uniforms.baseWaterColor.alpha < 1.0 || uniforms.blendColor.alpha < 1.0\r\n );\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the rim lighting material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.RimLightingType = \"RimLighting\";\r\nMaterial._materialCache.addMaterial(Material.RimLightingType, {\r\n fabric: {\r\n type: Material.RimLightingType,\r\n uniforms: {\r\n color: new Color(1.0, 0.0, 0.0, 0.7),\r\n rimColor: new Color(1.0, 1.0, 1.0, 0.4),\r\n width: 0.3,\r\n },\r\n source: RimLightingMaterial,\r\n },\r\n translucent: function (material) {\r\n var uniforms = material.uniforms;\r\n return uniforms.color.alpha < 1.0 || uniforms.rimColor.alpha < 1.0;\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the fade material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.FadeType = \"Fade\";\r\nMaterial._materialCache.addMaterial(Material.FadeType, {\r\n fabric: {\r\n type: Material.FadeType,\r\n uniforms: {\r\n fadeInColor: new Color(1.0, 0.0, 0.0, 1.0),\r\n fadeOutColor: new Color(0.0, 0.0, 0.0, 0.0),\r\n maximumDistance: 0.5,\r\n repeat: true,\r\n fadeDirection: {\r\n x: true,\r\n y: true,\r\n },\r\n time: new Cartesian2(0.5, 0.5),\r\n },\r\n source: FadeMaterial,\r\n },\r\n translucent: function (material) {\r\n var uniforms = material.uniforms;\r\n return (\r\n uniforms.fadeInColor.alpha < 1.0 || uniforms.fadeOutColor.alpha < 1.0\r\n );\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the polyline arrow material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.PolylineArrowType = \"PolylineArrow\";\r\nMaterial._materialCache.addMaterial(Material.PolylineArrowType, {\r\n fabric: {\r\n type: Material.PolylineArrowType,\r\n uniforms: {\r\n color: new Color(1.0, 1.0, 1.0, 1.0),\r\n },\r\n source: PolylineArrowMaterial,\r\n },\r\n translucent: true,\r\n});\r\n\r\n/**\r\n * Gets the name of the polyline glow material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.PolylineDashType = \"PolylineDash\";\r\nMaterial._materialCache.addMaterial(Material.PolylineDashType, {\r\n fabric: {\r\n type: Material.PolylineDashType,\r\n uniforms: {\r\n color: new Color(1.0, 0.0, 1.0, 1.0),\r\n gapColor: new Color(0.0, 0.0, 0.0, 0.0),\r\n dashLength: 16.0,\r\n dashPattern: 255.0,\r\n },\r\n source: PolylineDashMaterial,\r\n },\r\n translucent: true,\r\n});\r\n\r\n/**\r\n * Gets the name of the polyline glow material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.PolylineGlowType = \"PolylineGlow\";\r\nMaterial._materialCache.addMaterial(Material.PolylineGlowType, {\r\n fabric: {\r\n type: Material.PolylineGlowType,\r\n uniforms: {\r\n color: new Color(0.0, 0.5, 1.0, 1.0),\r\n glowPower: 0.25,\r\n taperPower: 1.0,\r\n },\r\n source: PolylineGlowMaterial,\r\n },\r\n translucent: true,\r\n});\r\n\r\n/**\r\n * Gets the name of the polyline outline material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.PolylineOutlineType = \"PolylineOutline\";\r\nMaterial._materialCache.addMaterial(Material.PolylineOutlineType, {\r\n fabric: {\r\n type: Material.PolylineOutlineType,\r\n uniforms: {\r\n color: new Color(1.0, 1.0, 1.0, 1.0),\r\n outlineColor: new Color(1.0, 0.0, 0.0, 1.0),\r\n outlineWidth: 1.0,\r\n },\r\n source: PolylineOutlineMaterial,\r\n },\r\n translucent: function (material) {\r\n var uniforms = material.uniforms;\r\n return uniforms.color.alpha < 1.0 || uniforms.outlineColor.alpha < 1.0;\r\n },\r\n});\r\n\r\n/**\r\n * Gets the name of the elevation contour material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.ElevationContourType = \"ElevationContour\";\r\nMaterial._materialCache.addMaterial(Material.ElevationContourType, {\r\n fabric: {\r\n type: Material.ElevationContourType,\r\n uniforms: {\r\n spacing: 100.0,\r\n color: new Color(1.0, 0.0, 0.0, 1.0),\r\n width: 1.0,\r\n },\r\n source: ElevationContourMaterial,\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the elevation contour material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.ElevationRampType = \"ElevationRamp\";\r\nMaterial._materialCache.addMaterial(Material.ElevationRampType, {\r\n fabric: {\r\n type: Material.ElevationRampType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n minimumHeight: 0.0,\r\n maximumHeight: 10000.0,\r\n },\r\n source: ElevationRampMaterial,\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the slope ramp material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.SlopeRampMaterialType = \"SlopeRamp\";\r\nMaterial._materialCache.addMaterial(Material.SlopeRampMaterialType, {\r\n fabric: {\r\n type: Material.SlopeRampMaterialType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n },\r\n source: SlopeRampMaterial,\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the aspect ramp material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.AspectRampMaterialType = \"AspectRamp\";\r\nMaterial._materialCache.addMaterial(Material.AspectRampMaterialType, {\r\n fabric: {\r\n type: Material.AspectRampMaterialType,\r\n uniforms: {\r\n image: Material.DefaultImageId,\r\n },\r\n source: AspectRampMaterial,\r\n },\r\n translucent: false,\r\n});\r\n\r\n/**\r\n * Gets the name of the elevation band material.\r\n * @type {String}\r\n * @readonly\r\n */\r\nMaterial.ElevationBandType = \"ElevationBand\";\r\nMaterial._materialCache.addMaterial(Material.ElevationBandType, {\r\n fabric: {\r\n type: Material.ElevationBandType,\r\n uniforms: {\r\n heights: Material.DefaultImageId,\r\n colors: Material.DefaultImageId,\r\n },\r\n source: ElevationBandMaterial,\r\n },\r\n translucent: true,\r\n});\r\n\r\nexport default Material;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport VertexFormat from \"../Core/VertexFormat.js\";\r\nimport AllMaterialAppearanceFS from \"../Shaders/Appearances/AllMaterialAppearanceFS.js\";\r\nimport AllMaterialAppearanceVS from \"../Shaders/Appearances/AllMaterialAppearanceVS.js\";\r\nimport BasicMaterialAppearanceFS from \"../Shaders/Appearances/BasicMaterialAppearanceFS.js\";\r\nimport BasicMaterialAppearanceVS from \"../Shaders/Appearances/BasicMaterialAppearanceVS.js\";\r\nimport TexturedMaterialAppearanceFS from \"../Shaders/Appearances/TexturedMaterialAppearanceFS.js\";\r\nimport TexturedMaterialAppearanceVS from \"../Shaders/Appearances/TexturedMaterialAppearanceVS.js\";\r\nimport Appearance from \"./Appearance.js\";\r\nimport Material from \"./Material.js\";\r\n\r\n/**\r\n * An appearance for arbitrary geometry (as opposed to {@link EllipsoidSurfaceAppearance}, for example)\r\n * that supports shading with materials.\r\n *\r\n * @alias MaterialAppearance\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.flat=false] When true, flat shading is used in the fragment shader, which means lighting is not taking into account.\r\n * @param {Boolean} [options.faceForward=!options.closed] When true, the fragment shader flips the surface normal as needed to ensure that the normal faces the viewer to avoid dark spots. This is useful when both sides of a geometry should be shaded like {@link WallGeometry}.\r\n * @param {Boolean} [options.translucent=true] When true, the geometry is expected to appear translucent so {@link MaterialAppearance#renderState} has alpha blending enabled.\r\n * @param {Boolean} [options.closed=false] When true, the geometry is expected to be closed so {@link MaterialAppearance#renderState} has backface culling enabled.\r\n * @param {MaterialAppearance.MaterialSupportType} [options.materialSupport=MaterialAppearance.MaterialSupport.TEXTURED] The type of materials that will be supported.\r\n * @param {Material} [options.material=Material.ColorType] The material used to determine the fragment color.\r\n * @param {String} [options.vertexShaderSource] Optional GLSL vertex shader source to override the default vertex shader.\r\n * @param {String} [options.fragmentShaderSource] Optional GLSL fragment shader source to override the default fragment shader.\r\n * @param {Object} [options.renderState] Optional render state to override the default render state.\r\n *\r\n * @see {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Materials.html|Cesium Sandcastle Material Appearance Demo}\r\n *\r\n * @example\r\n * var primitive = new Cesium.Primitive({\r\n * geometryInstances : new Cesium.GeometryInstance({\r\n * geometry : new Cesium.WallGeometry({\r\n materialSupport : Cesium.MaterialAppearance.MaterialSupport.BASIC.vertexFormat,\r\n * // ...\r\n * })\r\n * }),\r\n * appearance : new Cesium.MaterialAppearance({\r\n * material : Cesium.Material.fromType('Color'),\r\n * faceForward : true\r\n * })\r\n *\r\n * });\r\n */\r\nfunction MaterialAppearance(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var translucent = defaultValue(options.translucent, true);\r\n var closed = defaultValue(options.closed, false);\r\n var materialSupport = defaultValue(\r\n options.materialSupport,\r\n MaterialAppearance.MaterialSupport.TEXTURED\r\n );\r\n\r\n /**\r\n * The material used to determine the fragment color. Unlike other {@link MaterialAppearance}\r\n * properties, this is not read-only, so an appearance's material can change on the fly.\r\n *\r\n * @type Material\r\n *\r\n * @default {@link Material.ColorType}\r\n *\r\n * @see {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}\r\n */\r\n this.material = defined(options.material)\r\n ? options.material\r\n : Material.fromType(Material.ColorType);\r\n\r\n /**\r\n * When true, the geometry is expected to appear translucent.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.translucent = translucent;\r\n\r\n this._vertexShaderSource = defaultValue(\r\n options.vertexShaderSource,\r\n materialSupport.vertexShaderSource\r\n );\r\n this._fragmentShaderSource = defaultValue(\r\n options.fragmentShaderSource,\r\n materialSupport.fragmentShaderSource\r\n );\r\n this._renderState = Appearance.getDefaultRenderState(\r\n translucent,\r\n closed,\r\n options.renderState\r\n );\r\n this._closed = closed;\r\n\r\n // Non-derived members\r\n\r\n this._materialSupport = materialSupport;\r\n this._vertexFormat = materialSupport.vertexFormat;\r\n this._flat = defaultValue(options.flat, false);\r\n this._faceForward = defaultValue(options.faceForward, !closed);\r\n}\r\n\r\nObject.defineProperties(MaterialAppearance.prototype, {\r\n /**\r\n * The GLSL source code for the vertex shader.\r\n *\r\n * @memberof MaterialAppearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n vertexShaderSource: {\r\n get: function () {\r\n return this._vertexShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The GLSL source code for the fragment shader. The full fragment shader\r\n * source is built procedurally taking into account {@link MaterialAppearance#material},\r\n * {@link MaterialAppearance#flat}, and {@link MaterialAppearance#faceForward}.\r\n * Use {@link MaterialAppearance#getFragmentShaderSource} to get the full source.\r\n *\r\n * @memberof MaterialAppearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n fragmentShaderSource: {\r\n get: function () {\r\n return this._fragmentShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The WebGL fixed-function state to use when rendering the geometry.\r\n *

\r\n * The render state can be explicitly defined when constructing a {@link MaterialAppearance}\r\n * instance, or it is set implicitly via {@link MaterialAppearance#translucent}\r\n * and {@link MaterialAppearance#closed}.\r\n *

\r\n *\r\n * @memberof MaterialAppearance.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n renderState: {\r\n get: function () {\r\n return this._renderState;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the geometry is expected to be closed so\r\n * {@link MaterialAppearance#renderState} has backface culling enabled.\r\n * If the viewer enters the geometry, it will not be visible.\r\n *\r\n * @memberof MaterialAppearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n closed: {\r\n get: function () {\r\n return this._closed;\r\n },\r\n },\r\n\r\n /**\r\n * The type of materials supported by this instance. This impacts the required\r\n * {@link VertexFormat} and the complexity of the vertex and fragment shaders.\r\n *\r\n * @memberof MaterialAppearance.prototype\r\n *\r\n * @type {MaterialAppearance.MaterialSupportType}\r\n * @readonly\r\n *\r\n * @default {@link MaterialAppearance.MaterialSupport.TEXTURED}\r\n */\r\n materialSupport: {\r\n get: function () {\r\n return this._materialSupport;\r\n },\r\n },\r\n\r\n /**\r\n * The {@link VertexFormat} that this appearance instance is compatible with.\r\n * A geometry can have more vertex attributes and still be compatible - at a\r\n * potential performance cost - but it can't have less.\r\n *\r\n * @memberof MaterialAppearance.prototype\r\n *\r\n * @type VertexFormat\r\n * @readonly\r\n *\r\n * @default {@link MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat}\r\n */\r\n vertexFormat: {\r\n get: function () {\r\n return this._vertexFormat;\r\n },\r\n },\r\n\r\n /**\r\n * When true, flat shading is used in the fragment shader,\r\n * which means lighting is not taking into account.\r\n *\r\n * @memberof MaterialAppearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n flat: {\r\n get: function () {\r\n return this._flat;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the fragment shader flips the surface normal\r\n * as needed to ensure that the normal faces the viewer to avoid\r\n * dark spots. This is useful when both sides of a geometry should be\r\n * shaded like {@link WallGeometry}.\r\n *\r\n * @memberof MaterialAppearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n faceForward: {\r\n get: function () {\r\n return this._faceForward;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Procedurally creates the full GLSL fragment shader source. For {@link MaterialAppearance},\r\n * this is derived from {@link MaterialAppearance#fragmentShaderSource}, {@link MaterialAppearance#material},\r\n * {@link MaterialAppearance#flat}, and {@link MaterialAppearance#faceForward}.\r\n *\r\n * @function\r\n *\r\n * @returns {String} The full GLSL fragment shader source.\r\n */\r\nMaterialAppearance.prototype.getFragmentShaderSource =\r\n Appearance.prototype.getFragmentShaderSource;\r\n\r\n/**\r\n * Determines if the geometry is translucent based on {@link MaterialAppearance#translucent} and {@link Material#isTranslucent}.\r\n *\r\n * @function\r\n *\r\n * @returns {Boolean} true if the appearance is translucent.\r\n */\r\nMaterialAppearance.prototype.isTranslucent = Appearance.prototype.isTranslucent;\r\n\r\n/**\r\n * Creates a render state. This is not the final render state instance; instead,\r\n * it can contain a subset of render state properties identical to the render state\r\n * created in the context.\r\n *\r\n * @function\r\n *\r\n * @returns {Object} The render state.\r\n */\r\nMaterialAppearance.prototype.getRenderState =\r\n Appearance.prototype.getRenderState;\r\n\r\n/**\r\n * @typedef MaterialAppearance.MaterialSupportType\r\n * @type {Object}\r\n * @property {VertexFormat} vertexFormat\r\n * @property {String} vertexShaderSource\r\n * @property {String} fragmentShaderSource\r\n */\r\n\r\n/**\r\n * Determines the type of {@link Material} that is supported by a\r\n * {@link MaterialAppearance} instance. This is a trade-off between\r\n * flexibility (a wide array of materials) and memory/performance\r\n * (required vertex format and GLSL shader complexity.\r\n * @namespace\r\n */\r\nMaterialAppearance.MaterialSupport = {\r\n /**\r\n * Only basic materials, which require just position and\r\n * normal vertex attributes, are supported.\r\n *\r\n * @type {MaterialAppearance.MaterialSupportType}\r\n * @constant\r\n */\r\n BASIC: Object.freeze({\r\n vertexFormat: VertexFormat.POSITION_AND_NORMAL,\r\n vertexShaderSource: BasicMaterialAppearanceVS,\r\n fragmentShaderSource: BasicMaterialAppearanceFS,\r\n }),\r\n /**\r\n * Materials with textures, which require position,\r\n * normal, and st vertex attributes,\r\n * are supported. The vast majority of materials fall into this category.\r\n *\r\n * @type {MaterialAppearance.MaterialSupportType}\r\n * @constant\r\n */\r\n TEXTURED: Object.freeze({\r\n vertexFormat: VertexFormat.POSITION_NORMAL_AND_ST,\r\n vertexShaderSource: TexturedMaterialAppearanceVS,\r\n fragmentShaderSource: TexturedMaterialAppearanceFS,\r\n }),\r\n /**\r\n * All materials, including those that work in tangent space, are supported.\r\n * This requires position, normal, st,\r\n * tangent, and bitangent vertex attributes.\r\n *\r\n * @type {MaterialAppearance.MaterialSupportType}\r\n * @constant\r\n */\r\n ALL: Object.freeze({\r\n vertexFormat: VertexFormat.ALL,\r\n vertexShaderSource: AllMaterialAppearanceVS,\r\n fragmentShaderSource: AllMaterialAppearanceFS,\r\n }),\r\n};\r\nexport default MaterialAppearance;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec3 v_positionEC;\\n\\\nvarying vec3 v_normalEC;\\n\\\nvarying vec4 v_color;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec3 positionToEyeEC = -v_positionEC;\\n\\\nvec3 normalEC = normalize(v_normalEC);\\n\\\n#ifdef FACE_FORWARD\\n\\\nnormalEC = faceforward(normalEC, vec3(0.0, 0.0, 1.0), -normalEC);\\n\\\n#endif\\n\\\nvec4 color = czm_gammaCorrect(v_color);\\n\\\nczm_materialInput materialInput;\\n\\\nmaterialInput.normalEC = normalEC;\\n\\\nmaterialInput.positionToEyeEC = positionToEyeEC;\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nmaterial.diffuse = color.rgb;\\n\\\nmaterial.alpha = color.a;\\n\\\ngl_FragColor = czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec3 normal;\\n\\\nattribute vec4 color;\\n\\\nattribute float batchId;\\n\\\nvarying vec3 v_positionEC;\\n\\\nvarying vec3 v_normalEC;\\n\\\nvarying vec4 v_color;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec4 p = czm_computePosition();\\n\\\nv_positionEC = (czm_modelViewRelativeToEye * p).xyz;\\n\\\nv_normalEC = czm_normal * normal;\\n\\\nv_color = color;\\n\\\ngl_Position = czm_modelViewProjectionRelativeToEye * p;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec4 v_color;\\n\\\nvoid main()\\n\\\n{\\n\\\ngl_FragColor = czm_gammaCorrect(v_color);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec4 color;\\n\\\nattribute float batchId;\\n\\\nvarying vec4 v_color;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec4 p = czm_computePosition();\\n\\\nv_color = color;\\n\\\ngl_Position = czm_modelViewProjectionRelativeToEye * p;\\n\\\n}\\n\\\n\";\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport VertexFormat from \"../Core/VertexFormat.js\";\r\nimport PerInstanceColorAppearanceFS from \"../Shaders/Appearances/PerInstanceColorAppearanceFS.js\";\r\nimport PerInstanceColorAppearanceVS from \"../Shaders/Appearances/PerInstanceColorAppearanceVS.js\";\r\nimport PerInstanceFlatColorAppearanceFS from \"../Shaders/Appearances/PerInstanceFlatColorAppearanceFS.js\";\r\nimport PerInstanceFlatColorAppearanceVS from \"../Shaders/Appearances/PerInstanceFlatColorAppearanceVS.js\";\r\nimport Appearance from \"./Appearance.js\";\r\n\r\n/**\r\n * An appearance for {@link GeometryInstance} instances with color attributes.\r\n * This allows several geometry instances, each with a different color, to\r\n * be drawn with the same {@link Primitive} as shown in the second example below.\r\n *\r\n * @alias PerInstanceColorAppearance\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.flat=false] When true, flat shading is used in the fragment shader, which means lighting is not taking into account.\r\n * @param {Boolean} [options.faceForward=!options.closed] When true, the fragment shader flips the surface normal as needed to ensure that the normal faces the viewer to avoid dark spots. This is useful when both sides of a geometry should be shaded like {@link WallGeometry}.\r\n * @param {Boolean} [options.translucent=true] When true, the geometry is expected to appear translucent so {@link PerInstanceColorAppearance#renderState} has alpha blending enabled.\r\n * @param {Boolean} [options.closed=false] When true, the geometry is expected to be closed so {@link PerInstanceColorAppearance#renderState} has backface culling enabled.\r\n * @param {String} [options.vertexShaderSource] Optional GLSL vertex shader source to override the default vertex shader.\r\n * @param {String} [options.fragmentShaderSource] Optional GLSL fragment shader source to override the default fragment shader.\r\n * @param {Object} [options.renderState] Optional render state to override the default render state.\r\n *\r\n * @example\r\n * // A solid white line segment\r\n * var primitive = new Cesium.Primitive({\r\n * geometryInstances : new Cesium.GeometryInstance({\r\n * geometry : new Cesium.SimplePolylineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * 0.0, 0.0,\r\n * 5.0, 0.0\r\n * ])\r\n * }),\r\n * attributes : {\r\n * color : Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 1.0, 1.0))\r\n * }\r\n * }),\r\n * appearance : new Cesium.PerInstanceColorAppearance({\r\n * flat : true,\r\n * translucent : false\r\n * })\r\n * });\r\n *\r\n * // Two rectangles in a primitive, each with a different color\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.RectangleGeometry({\r\n * rectangle : Cesium.Rectangle.fromDegrees(0.0, 20.0, 10.0, 30.0)\r\n * }),\r\n * attributes : {\r\n * color : new Cesium.ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 0.5)\r\n * }\r\n * });\r\n *\r\n * var anotherInstance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.RectangleGeometry({\r\n * rectangle : Cesium.Rectangle.fromDegrees(0.0, 40.0, 10.0, 50.0)\r\n * }),\r\n * attributes : {\r\n * color : new Cesium.ColorGeometryInstanceAttribute(0.0, 0.0, 1.0, 0.5)\r\n * }\r\n * });\r\n *\r\n * var rectanglePrimitive = new Cesium.Primitive({\r\n * geometryInstances : [instance, anotherInstance],\r\n * appearance : new Cesium.PerInstanceColorAppearance()\r\n * });\r\n */\r\nfunction PerInstanceColorAppearance(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var translucent = defaultValue(options.translucent, true);\r\n var closed = defaultValue(options.closed, false);\r\n var flat = defaultValue(options.flat, false);\r\n var vs = flat\r\n ? PerInstanceFlatColorAppearanceVS\r\n : PerInstanceColorAppearanceVS;\r\n var fs = flat\r\n ? PerInstanceFlatColorAppearanceFS\r\n : PerInstanceColorAppearanceFS;\r\n var vertexFormat = flat\r\n ? PerInstanceColorAppearance.FLAT_VERTEX_FORMAT\r\n : PerInstanceColorAppearance.VERTEX_FORMAT;\r\n\r\n /**\r\n * This property is part of the {@link Appearance} interface, but is not\r\n * used by {@link PerInstanceColorAppearance} since a fully custom fragment shader is used.\r\n *\r\n * @type Material\r\n *\r\n * @default undefined\r\n */\r\n this.material = undefined;\r\n\r\n /**\r\n * When true, the geometry is expected to appear translucent so\r\n * {@link PerInstanceColorAppearance#renderState} has alpha blending enabled.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.translucent = translucent;\r\n\r\n this._vertexShaderSource = defaultValue(options.vertexShaderSource, vs);\r\n this._fragmentShaderSource = defaultValue(options.fragmentShaderSource, fs);\r\n this._renderState = Appearance.getDefaultRenderState(\r\n translucent,\r\n closed,\r\n options.renderState\r\n );\r\n this._closed = closed;\r\n\r\n // Non-derived members\r\n\r\n this._vertexFormat = vertexFormat;\r\n this._flat = flat;\r\n this._faceForward = defaultValue(options.faceForward, !closed);\r\n}\r\n\r\nObject.defineProperties(PerInstanceColorAppearance.prototype, {\r\n /**\r\n * The GLSL source code for the vertex shader.\r\n *\r\n * @memberof PerInstanceColorAppearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n vertexShaderSource: {\r\n get: function () {\r\n return this._vertexShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The GLSL source code for the fragment shader.\r\n *\r\n * @memberof PerInstanceColorAppearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n fragmentShaderSource: {\r\n get: function () {\r\n return this._fragmentShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The WebGL fixed-function state to use when rendering the geometry.\r\n *

\r\n * The render state can be explicitly defined when constructing a {@link PerInstanceColorAppearance}\r\n * instance, or it is set implicitly via {@link PerInstanceColorAppearance#translucent}\r\n * and {@link PerInstanceColorAppearance#closed}.\r\n *

\r\n *\r\n * @memberof PerInstanceColorAppearance.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n renderState: {\r\n get: function () {\r\n return this._renderState;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the geometry is expected to be closed so\r\n * {@link PerInstanceColorAppearance#renderState} has backface culling enabled.\r\n * If the viewer enters the geometry, it will not be visible.\r\n *\r\n * @memberof PerInstanceColorAppearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n closed: {\r\n get: function () {\r\n return this._closed;\r\n },\r\n },\r\n\r\n /**\r\n * The {@link VertexFormat} that this appearance instance is compatible with.\r\n * A geometry can have more vertex attributes and still be compatible - at a\r\n * potential performance cost - but it can't have less.\r\n *\r\n * @memberof PerInstanceColorAppearance.prototype\r\n *\r\n * @type VertexFormat\r\n * @readonly\r\n */\r\n vertexFormat: {\r\n get: function () {\r\n return this._vertexFormat;\r\n },\r\n },\r\n\r\n /**\r\n * When true, flat shading is used in the fragment shader,\r\n * which means lighting is not taking into account.\r\n *\r\n * @memberof PerInstanceColorAppearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n flat: {\r\n get: function () {\r\n return this._flat;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the fragment shader flips the surface normal\r\n * as needed to ensure that the normal faces the viewer to avoid\r\n * dark spots. This is useful when both sides of a geometry should be\r\n * shaded like {@link WallGeometry}.\r\n *\r\n * @memberof PerInstanceColorAppearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n faceForward: {\r\n get: function () {\r\n return this._faceForward;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * The {@link VertexFormat} that all {@link PerInstanceColorAppearance} instances\r\n * are compatible with. This requires only position and normal\r\n * attributes.\r\n *\r\n * @type VertexFormat\r\n *\r\n * @constant\r\n */\r\nPerInstanceColorAppearance.VERTEX_FORMAT = VertexFormat.POSITION_AND_NORMAL;\r\n\r\n/**\r\n * The {@link VertexFormat} that all {@link PerInstanceColorAppearance} instances\r\n * are compatible with when {@link PerInstanceColorAppearance#flat} is true.\r\n * This requires only a position attribute.\r\n *\r\n * @type VertexFormat\r\n *\r\n * @constant\r\n */\r\nPerInstanceColorAppearance.FLAT_VERTEX_FORMAT = VertexFormat.POSITION_ONLY;\r\n\r\n/**\r\n * Procedurally creates the full GLSL fragment shader source. For {@link PerInstanceColorAppearance},\r\n * this is derived from {@link PerInstanceColorAppearance#fragmentShaderSource}, {@link PerInstanceColorAppearance#flat},\r\n * and {@link PerInstanceColorAppearance#faceForward}.\r\n *\r\n * @function\r\n *\r\n * @returns {String} The full GLSL fragment shader source.\r\n */\r\nPerInstanceColorAppearance.prototype.getFragmentShaderSource =\r\n Appearance.prototype.getFragmentShaderSource;\r\n\r\n/**\r\n * Determines if the geometry is translucent based on {@link PerInstanceColorAppearance#translucent}.\r\n *\r\n * @function\r\n *\r\n * @returns {Boolean} true if the appearance is translucent.\r\n */\r\nPerInstanceColorAppearance.prototype.isTranslucent =\r\n Appearance.prototype.isTranslucent;\r\n\r\n/**\r\n * Creates a render state. This is not the final render state instance; instead,\r\n * it can contain a subset of render state properties identical to the render state\r\n * created in the context.\r\n *\r\n * @function\r\n *\r\n * @returns {Object} The render state.\r\n */\r\nPerInstanceColorAppearance.prototype.getRenderState =\r\n Appearance.prototype.getRenderState;\r\nexport default PerInstanceColorAppearance;\r\n","import Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to solid color {@link Material} uniforms.\r\n *\r\n * @param {Property|Color} [color=Color.WHITE] The {@link Color} Property to be used.\r\n *\r\n * @alias ColorMaterialProperty\r\n * @constructor\r\n */\r\nfunction ColorMaterialProperty(color) {\r\n this._definitionChanged = new Event();\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n\r\n this.color = color;\r\n}\r\n\r\nObject.defineProperties(ColorMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof ColorMaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return Property.isConstant(this._color);\r\n },\r\n },\r\n\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof ColorMaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the {@link Color} {@link Property}.\r\n * @memberof ColorMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nColorMaterialProperty.prototype.getType = function (time) {\r\n return \"Color\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nColorMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n result.color = Property.getValueOrClonedDefault(\r\n this._color,\r\n time,\r\n Color.WHITE,\r\n result.color\r\n );\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nColorMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof ColorMaterialProperty && //\r\n Property.equals(this._color, other._color))\r\n );\r\n};\r\nexport default ColorMaterialProperty;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport PrimitiveType from \"../Core/PrimitiveType.js\";\r\n\r\n/**\r\n * Represents a command to the renderer for drawing.\r\n *\r\n * @private\r\n */\r\nfunction DrawCommand(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._boundingVolume = options.boundingVolume;\r\n this._orientedBoundingBox = options.orientedBoundingBox;\r\n this._cull = defaultValue(options.cull, true);\r\n this._occlude = defaultValue(options.occlude, true);\r\n this._modelMatrix = options.modelMatrix;\r\n this._primitiveType = defaultValue(\r\n options.primitiveType,\r\n PrimitiveType.TRIANGLES\r\n );\r\n this._vertexArray = options.vertexArray;\r\n this._count = options.count;\r\n this._offset = defaultValue(options.offset, 0);\r\n this._instanceCount = defaultValue(options.instanceCount, 0);\r\n this._shaderProgram = options.shaderProgram;\r\n this._uniformMap = options.uniformMap;\r\n this._renderState = options.renderState;\r\n this._framebuffer = options.framebuffer;\r\n this._pass = options.pass;\r\n this._executeInClosestFrustum = defaultValue(\r\n options.executeInClosestFrustum,\r\n false\r\n );\r\n this._owner = options.owner;\r\n this._debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n this._debugOverlappingFrustums = 0;\r\n this._castShadows = defaultValue(options.castShadows, false);\r\n this._receiveShadows = defaultValue(options.receiveShadows, false);\r\n this._pickId = options.pickId;\r\n this._pickOnly = defaultValue(options.pickOnly, false);\r\n\r\n this._depthForTranslucentClassification = defaultValue(\r\n options.depthForTranslucentClassification,\r\n false\r\n );\r\n\r\n this.dirty = true;\r\n this.lastDirtyTime = 0;\r\n\r\n /**\r\n * @private\r\n */\r\n this.derivedCommands = {};\r\n}\r\n\r\nObject.defineProperties(DrawCommand.prototype, {\r\n /**\r\n * The bounding volume of the geometry in world space. This is used for culling and frustum selection.\r\n *

\r\n * For best rendering performance, use the tightest possible bounding volume. Although\r\n * undefined is allowed, always try to provide a bounding volume to\r\n * allow the tightest possible near and far planes to be computed for the scene, and\r\n * minimize the number of frustums needed.\r\n *

\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Object}\r\n * @default undefined\r\n *\r\n * @see DrawCommand#debugShowBoundingVolume\r\n */\r\n boundingVolume: {\r\n get: function () {\r\n return this._boundingVolume;\r\n },\r\n set: function (value) {\r\n if (this._boundingVolume !== value) {\r\n this._boundingVolume = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The oriented bounding box of the geometry in world space. If this is defined, it is used instead of\r\n * {@link DrawCommand#boundingVolume} for plane intersection testing.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {OrientedBoundingBox}\r\n * @default undefined\r\n *\r\n * @see DrawCommand#debugShowBoundingVolume\r\n */\r\n orientedBoundingBox: {\r\n get: function () {\r\n return this._orientedBoundingBox;\r\n },\r\n set: function (value) {\r\n if (this._orientedBoundingBox !== value) {\r\n this._orientedBoundingBox = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * When true, the renderer frustum and horizon culls the command based on its {@link DrawCommand#boundingVolume}.\r\n * If the command was already culled, set this to false for a performance improvement.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n cull: {\r\n get: function () {\r\n return this._cull;\r\n },\r\n set: function (value) {\r\n if (this._cull !== value) {\r\n this._cull = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * When true, the horizon culls the command based on its {@link DrawCommand#boundingVolume}.\r\n * {@link DrawCommand#cull} must also be true in order for the command to be culled.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n occlude: {\r\n get: function () {\r\n return this._occlude;\r\n },\r\n set: function (value) {\r\n if (this._occlude !== value) {\r\n this._occlude = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The transformation from the geometry in model space to world space.\r\n *

\r\n * When undefined, the geometry is assumed to be defined in world space.\r\n *

\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Matrix4}\r\n * @default undefined\r\n */\r\n modelMatrix: {\r\n get: function () {\r\n return this._modelMatrix;\r\n },\r\n set: function (value) {\r\n if (this._modelMatrix !== value) {\r\n this._modelMatrix = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The type of geometry in the vertex array.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {PrimitiveType}\r\n * @default PrimitiveType.TRIANGLES\r\n */\r\n primitiveType: {\r\n get: function () {\r\n return this._primitiveType;\r\n },\r\n set: function (value) {\r\n if (this._primitiveType !== value) {\r\n this._primitiveType = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The vertex array.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {VertexArray}\r\n * @default undefined\r\n */\r\n vertexArray: {\r\n get: function () {\r\n return this._vertexArray;\r\n },\r\n set: function (value) {\r\n if (this._vertexArray !== value) {\r\n this._vertexArray = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The number of vertices to draw in the vertex array.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Number}\r\n * @default undefined\r\n */\r\n count: {\r\n get: function () {\r\n return this._count;\r\n },\r\n set: function (value) {\r\n if (this._count !== value) {\r\n this._count = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The offset to start drawing in the vertex array.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Number}\r\n * @default 0\r\n */\r\n offset: {\r\n get: function () {\r\n return this._offset;\r\n },\r\n set: function (value) {\r\n if (this._offset !== value) {\r\n this._offset = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The number of instances to draw.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Number}\r\n * @default 0\r\n */\r\n instanceCount: {\r\n get: function () {\r\n return this._instanceCount;\r\n },\r\n set: function (value) {\r\n if (this._instanceCount !== value) {\r\n this._instanceCount = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The shader program to apply.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {ShaderProgram}\r\n * @default undefined\r\n */\r\n shaderProgram: {\r\n get: function () {\r\n return this._shaderProgram;\r\n },\r\n set: function (value) {\r\n if (this._shaderProgram !== value) {\r\n this._shaderProgram = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Whether this command should cast shadows when shadowing is enabled.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n castShadows: {\r\n get: function () {\r\n return this._castShadows;\r\n },\r\n set: function (value) {\r\n if (this._castShadows !== value) {\r\n this._castShadows = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Whether this command should receive shadows when shadowing is enabled.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n receiveShadows: {\r\n get: function () {\r\n return this._receiveShadows;\r\n },\r\n set: function (value) {\r\n if (this._receiveShadows !== value) {\r\n this._receiveShadows = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * An object with functions whose names match the uniforms in the shader program\r\n * and return values to set those uniforms.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Object}\r\n * @default undefined\r\n */\r\n uniformMap: {\r\n get: function () {\r\n return this._uniformMap;\r\n },\r\n set: function (value) {\r\n if (this._uniformMap !== value) {\r\n this._uniformMap = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The render state.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {RenderState}\r\n * @default undefined\r\n */\r\n renderState: {\r\n get: function () {\r\n return this._renderState;\r\n },\r\n set: function (value) {\r\n if (this._renderState !== value) {\r\n this._renderState = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The framebuffer to draw to.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Framebuffer}\r\n * @default undefined\r\n */\r\n framebuffer: {\r\n get: function () {\r\n return this._framebuffer;\r\n },\r\n set: function (value) {\r\n if (this._framebuffer !== value) {\r\n this._framebuffer = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The pass when to render.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Pass}\r\n * @default undefined\r\n */\r\n pass: {\r\n get: function () {\r\n return this._pass;\r\n },\r\n set: function (value) {\r\n if (this._pass !== value) {\r\n this._pass = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Specifies if this command is only to be executed in the frustum closest\r\n * to the eye containing the bounding volume. Defaults to false.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n executeInClosestFrustum: {\r\n get: function () {\r\n return this._executeInClosestFrustum;\r\n },\r\n set: function (value) {\r\n if (this._executeInClosestFrustum !== value) {\r\n this._executeInClosestFrustum = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The object who created this command. This is useful for debugging command\r\n * execution; it allows us to see who created a command when we only have a\r\n * reference to the command, and can be used to selectively execute commands\r\n * with {@link Scene#debugCommandFilter}.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Object}\r\n * @default undefined\r\n *\r\n * @see Scene#debugCommandFilter\r\n */\r\n owner: {\r\n get: function () {\r\n return this._owner;\r\n },\r\n set: function (value) {\r\n if (this._owner !== value) {\r\n this._owner = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the {@link DrawCommand#boundingVolume} for this command, assuming it is a sphere, when the command executes.\r\n *

\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Boolean}\r\n * @default false\r\n *\r\n * @see DrawCommand#boundingVolume\r\n */\r\n debugShowBoundingVolume: {\r\n get: function () {\r\n return this._debugShowBoundingVolume;\r\n },\r\n set: function (value) {\r\n if (this._debugShowBoundingVolume !== value) {\r\n this._debugShowBoundingVolume = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Used to implement Scene.debugShowFrustums.\r\n * @private\r\n */\r\n debugOverlappingFrustums: {\r\n get: function () {\r\n return this._debugOverlappingFrustums;\r\n },\r\n set: function (value) {\r\n if (this._debugOverlappingFrustums !== value) {\r\n this._debugOverlappingFrustums = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n /**\r\n * A GLSL string that will evaluate to a pick id. When undefined, the command will only draw depth\r\n * during the pick pass.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {String}\r\n * @default undefined\r\n */\r\n pickId: {\r\n get: function () {\r\n return this._pickId;\r\n },\r\n set: function (value) {\r\n if (this._pickId !== value) {\r\n this._pickId = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n /**\r\n * Whether this command should be executed in the pick pass only.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n pickOnly: {\r\n get: function () {\r\n return this._pickOnly;\r\n },\r\n set: function (value) {\r\n if (this._pickOnly !== value) {\r\n this._pickOnly = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n /**\r\n * Whether this command should be derived to draw depth for classification of translucent primitives.\r\n *\r\n * @memberof DrawCommand.prototype\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n depthForTranslucentClassification: {\r\n get: function () {\r\n return this._depthForTranslucentClassification;\r\n },\r\n set: function (value) {\r\n if (this._depthForTranslucentClassification !== value) {\r\n this._depthForTranslucentClassification = value;\r\n this.dirty = true;\r\n }\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @private\r\n */\r\nDrawCommand.shallowClone = function (command, result) {\r\n if (!defined(command)) {\r\n return undefined;\r\n }\r\n if (!defined(result)) {\r\n result = new DrawCommand();\r\n }\r\n\r\n result._boundingVolume = command._boundingVolume;\r\n result._orientedBoundingBox = command._orientedBoundingBox;\r\n result._cull = command._cull;\r\n result._occlude = command._occlude;\r\n result._modelMatrix = command._modelMatrix;\r\n result._primitiveType = command._primitiveType;\r\n result._vertexArray = command._vertexArray;\r\n result._count = command._count;\r\n result._offset = command._offset;\r\n result._instanceCount = command._instanceCount;\r\n result._shaderProgram = command._shaderProgram;\r\n result._uniformMap = command._uniformMap;\r\n result._renderState = command._renderState;\r\n result._framebuffer = command._framebuffer;\r\n result._pass = command._pass;\r\n result._executeInClosestFrustum = command._executeInClosestFrustum;\r\n result._owner = command._owner;\r\n result._debugShowBoundingVolume = command._debugShowBoundingVolume;\r\n result._debugOverlappingFrustums = command._debugOverlappingFrustums;\r\n result._castShadows = command._castShadows;\r\n result._receiveShadows = command._receiveShadows;\r\n result._pickId = command._pickId;\r\n result._pickOnly = command._pickOnly;\r\n result._depthForTranslucentClassification =\r\n command._depthForTranslucentClassification;\r\n\r\n result.dirty = true;\r\n result.lastDirtyTime = 0;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Executes the draw command.\r\n *\r\n * @param {Context} context The renderer context in which to draw.\r\n * @param {PassState} [passState] The state for the current render pass.\r\n */\r\nDrawCommand.prototype.execute = function (context, passState) {\r\n context.draw(this, passState);\r\n};\r\nexport default DrawCommand;\r\n","/**\r\n * The render pass for a command.\r\n *\r\n * @private\r\n */\r\nvar Pass = {\r\n // If you add/modify/remove Pass constants, also change the automatic GLSL constants\r\n // that start with 'czm_pass'\r\n //\r\n // Commands are executed in order by pass up to the translucent pass.\r\n // Translucent geometry needs special handling (sorting/OIT). The compute pass\r\n // is executed first and the overlay pass is executed last. Both are not sorted\r\n // by frustum.\r\n ENVIRONMENT: 0,\r\n COMPUTE: 1,\r\n GLOBE: 2,\r\n TERRAIN_CLASSIFICATION: 3,\r\n CESIUM_3D_TILE: 4,\r\n CESIUM_3D_TILE_CLASSIFICATION: 5,\r\n CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW: 6,\r\n OPAQUE: 7,\r\n TRANSLUCENT: 8,\r\n OVERLAY: 9,\r\n NUMBER_OF_PASSES: 10,\r\n};\r\nexport default Object.freeze(Pass);\r\n","/**\r\n * Returns frozen renderState as well as all of the object literal properties. This function is deep object freeze\r\n * function ignoring properties named \"_applyFunctions\".\r\n *\r\n * @private\r\n *\r\n * @param {Object} renderState\r\n * @returns {Object} Returns frozen renderState.\r\n *\r\n */\r\nfunction freezeRenderState(renderState) {\r\n if (typeof renderState !== \"object\" || renderState === null) {\r\n return renderState;\r\n }\r\n\r\n var propName;\r\n var propNames = Object.keys(renderState);\r\n\r\n for (var i = 0; i < propNames.length; i++) {\r\n propName = propNames[i];\r\n if (\r\n renderState.hasOwnProperty(propName) &&\r\n propName !== \"_applyFunctions\"\r\n ) {\r\n renderState[propName] = freezeRenderState(renderState[propName]);\r\n }\r\n }\r\n return Object.freeze(renderState);\r\n}\r\nexport default freezeRenderState;\r\n","import BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport WindingOrder from \"../Core/WindingOrder.js\";\r\nimport ContextLimits from \"./ContextLimits.js\";\r\nimport freezeRenderState from \"./freezeRenderState.js\";\r\n\r\nfunction validateBlendEquation(blendEquation) {\r\n return (\r\n blendEquation === WebGLConstants.FUNC_ADD ||\r\n blendEquation === WebGLConstants.FUNC_SUBTRACT ||\r\n blendEquation === WebGLConstants.FUNC_REVERSE_SUBTRACT ||\r\n blendEquation === WebGLConstants.MIN ||\r\n blendEquation === WebGLConstants.MAX\r\n );\r\n}\r\n\r\nfunction validateBlendFunction(blendFunction) {\r\n return (\r\n blendFunction === WebGLConstants.ZERO ||\r\n blendFunction === WebGLConstants.ONE ||\r\n blendFunction === WebGLConstants.SRC_COLOR ||\r\n blendFunction === WebGLConstants.ONE_MINUS_SRC_COLOR ||\r\n blendFunction === WebGLConstants.DST_COLOR ||\r\n blendFunction === WebGLConstants.ONE_MINUS_DST_COLOR ||\r\n blendFunction === WebGLConstants.SRC_ALPHA ||\r\n blendFunction === WebGLConstants.ONE_MINUS_SRC_ALPHA ||\r\n blendFunction === WebGLConstants.DST_ALPHA ||\r\n blendFunction === WebGLConstants.ONE_MINUS_DST_ALPHA ||\r\n blendFunction === WebGLConstants.CONSTANT_COLOR ||\r\n blendFunction === WebGLConstants.ONE_MINUS_CONSTANT_COLOR ||\r\n blendFunction === WebGLConstants.CONSTANT_ALPHA ||\r\n blendFunction === WebGLConstants.ONE_MINUS_CONSTANT_ALPHA ||\r\n blendFunction === WebGLConstants.SRC_ALPHA_SATURATE\r\n );\r\n}\r\n\r\nfunction validateCullFace(cullFace) {\r\n return (\r\n cullFace === WebGLConstants.FRONT ||\r\n cullFace === WebGLConstants.BACK ||\r\n cullFace === WebGLConstants.FRONT_AND_BACK\r\n );\r\n}\r\n\r\nfunction validateDepthFunction(depthFunction) {\r\n return (\r\n depthFunction === WebGLConstants.NEVER ||\r\n depthFunction === WebGLConstants.LESS ||\r\n depthFunction === WebGLConstants.EQUAL ||\r\n depthFunction === WebGLConstants.LEQUAL ||\r\n depthFunction === WebGLConstants.GREATER ||\r\n depthFunction === WebGLConstants.NOTEQUAL ||\r\n depthFunction === WebGLConstants.GEQUAL ||\r\n depthFunction === WebGLConstants.ALWAYS\r\n );\r\n}\r\n\r\nfunction validateStencilFunction(stencilFunction) {\r\n return (\r\n stencilFunction === WebGLConstants.NEVER ||\r\n stencilFunction === WebGLConstants.LESS ||\r\n stencilFunction === WebGLConstants.EQUAL ||\r\n stencilFunction === WebGLConstants.LEQUAL ||\r\n stencilFunction === WebGLConstants.GREATER ||\r\n stencilFunction === WebGLConstants.NOTEQUAL ||\r\n stencilFunction === WebGLConstants.GEQUAL ||\r\n stencilFunction === WebGLConstants.ALWAYS\r\n );\r\n}\r\n\r\nfunction validateStencilOperation(stencilOperation) {\r\n return (\r\n stencilOperation === WebGLConstants.ZERO ||\r\n stencilOperation === WebGLConstants.KEEP ||\r\n stencilOperation === WebGLConstants.REPLACE ||\r\n stencilOperation === WebGLConstants.INCR ||\r\n stencilOperation === WebGLConstants.DECR ||\r\n stencilOperation === WebGLConstants.INVERT ||\r\n stencilOperation === WebGLConstants.INCR_WRAP ||\r\n stencilOperation === WebGLConstants.DECR_WRAP\r\n );\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction RenderState(renderState) {\r\n var rs = defaultValue(renderState, defaultValue.EMPTY_OBJECT);\r\n var cull = defaultValue(rs.cull, defaultValue.EMPTY_OBJECT);\r\n var polygonOffset = defaultValue(rs.polygonOffset, defaultValue.EMPTY_OBJECT);\r\n var scissorTest = defaultValue(rs.scissorTest, defaultValue.EMPTY_OBJECT);\r\n var scissorTestRectangle = defaultValue(\r\n scissorTest.rectangle,\r\n defaultValue.EMPTY_OBJECT\r\n );\r\n var depthRange = defaultValue(rs.depthRange, defaultValue.EMPTY_OBJECT);\r\n var depthTest = defaultValue(rs.depthTest, defaultValue.EMPTY_OBJECT);\r\n var colorMask = defaultValue(rs.colorMask, defaultValue.EMPTY_OBJECT);\r\n var blending = defaultValue(rs.blending, defaultValue.EMPTY_OBJECT);\r\n var blendingColor = defaultValue(blending.color, defaultValue.EMPTY_OBJECT);\r\n var stencilTest = defaultValue(rs.stencilTest, defaultValue.EMPTY_OBJECT);\r\n var stencilTestFrontOperation = defaultValue(\r\n stencilTest.frontOperation,\r\n defaultValue.EMPTY_OBJECT\r\n );\r\n var stencilTestBackOperation = defaultValue(\r\n stencilTest.backOperation,\r\n defaultValue.EMPTY_OBJECT\r\n );\r\n var sampleCoverage = defaultValue(\r\n rs.sampleCoverage,\r\n defaultValue.EMPTY_OBJECT\r\n );\r\n var viewport = rs.viewport;\r\n\r\n this.frontFace = defaultValue(rs.frontFace, WindingOrder.COUNTER_CLOCKWISE);\r\n this.cull = {\r\n enabled: defaultValue(cull.enabled, false),\r\n face: defaultValue(cull.face, WebGLConstants.BACK),\r\n };\r\n this.lineWidth = defaultValue(rs.lineWidth, 1.0);\r\n this.polygonOffset = {\r\n enabled: defaultValue(polygonOffset.enabled, false),\r\n factor: defaultValue(polygonOffset.factor, 0),\r\n units: defaultValue(polygonOffset.units, 0),\r\n };\r\n this.scissorTest = {\r\n enabled: defaultValue(scissorTest.enabled, false),\r\n rectangle: BoundingRectangle.clone(scissorTestRectangle),\r\n };\r\n this.depthRange = {\r\n near: defaultValue(depthRange.near, 0),\r\n far: defaultValue(depthRange.far, 1),\r\n };\r\n this.depthTest = {\r\n enabled: defaultValue(depthTest.enabled, false),\r\n func: defaultValue(depthTest.func, WebGLConstants.LESS), // func, because function is a JavaScript keyword\r\n };\r\n this.colorMask = {\r\n red: defaultValue(colorMask.red, true),\r\n green: defaultValue(colorMask.green, true),\r\n blue: defaultValue(colorMask.blue, true),\r\n alpha: defaultValue(colorMask.alpha, true),\r\n };\r\n this.depthMask = defaultValue(rs.depthMask, true);\r\n this.stencilMask = defaultValue(rs.stencilMask, ~0);\r\n this.blending = {\r\n enabled: defaultValue(blending.enabled, false),\r\n color: new Color(\r\n defaultValue(blendingColor.red, 0.0),\r\n defaultValue(blendingColor.green, 0.0),\r\n defaultValue(blendingColor.blue, 0.0),\r\n defaultValue(blendingColor.alpha, 0.0)\r\n ),\r\n equationRgb: defaultValue(blending.equationRgb, WebGLConstants.FUNC_ADD),\r\n equationAlpha: defaultValue(\r\n blending.equationAlpha,\r\n WebGLConstants.FUNC_ADD\r\n ),\r\n functionSourceRgb: defaultValue(\r\n blending.functionSourceRgb,\r\n WebGLConstants.ONE\r\n ),\r\n functionSourceAlpha: defaultValue(\r\n blending.functionSourceAlpha,\r\n WebGLConstants.ONE\r\n ),\r\n functionDestinationRgb: defaultValue(\r\n blending.functionDestinationRgb,\r\n WebGLConstants.ZERO\r\n ),\r\n functionDestinationAlpha: defaultValue(\r\n blending.functionDestinationAlpha,\r\n WebGLConstants.ZERO\r\n ),\r\n };\r\n this.stencilTest = {\r\n enabled: defaultValue(stencilTest.enabled, false),\r\n frontFunction: defaultValue(\r\n stencilTest.frontFunction,\r\n WebGLConstants.ALWAYS\r\n ),\r\n backFunction: defaultValue(stencilTest.backFunction, WebGLConstants.ALWAYS),\r\n reference: defaultValue(stencilTest.reference, 0),\r\n mask: defaultValue(stencilTest.mask, ~0),\r\n frontOperation: {\r\n fail: defaultValue(stencilTestFrontOperation.fail, WebGLConstants.KEEP),\r\n zFail: defaultValue(stencilTestFrontOperation.zFail, WebGLConstants.KEEP),\r\n zPass: defaultValue(stencilTestFrontOperation.zPass, WebGLConstants.KEEP),\r\n },\r\n backOperation: {\r\n fail: defaultValue(stencilTestBackOperation.fail, WebGLConstants.KEEP),\r\n zFail: defaultValue(stencilTestBackOperation.zFail, WebGLConstants.KEEP),\r\n zPass: defaultValue(stencilTestBackOperation.zPass, WebGLConstants.KEEP),\r\n },\r\n };\r\n this.sampleCoverage = {\r\n enabled: defaultValue(sampleCoverage.enabled, false),\r\n value: defaultValue(sampleCoverage.value, 1.0),\r\n invert: defaultValue(sampleCoverage.invert, false),\r\n };\r\n this.viewport = defined(viewport)\r\n ? new BoundingRectangle(\r\n viewport.x,\r\n viewport.y,\r\n viewport.width,\r\n viewport.height\r\n )\r\n : undefined;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n this.lineWidth < ContextLimits.minimumAliasedLineWidth ||\r\n this.lineWidth > ContextLimits.maximumAliasedLineWidth\r\n ) {\r\n throw new DeveloperError(\r\n \"renderState.lineWidth is out of range. Check minimumAliasedLineWidth and maximumAliasedLineWidth.\"\r\n );\r\n }\r\n if (!WindingOrder.validate(this.frontFace)) {\r\n throw new DeveloperError(\"Invalid renderState.frontFace.\");\r\n }\r\n if (!validateCullFace(this.cull.face)) {\r\n throw new DeveloperError(\"Invalid renderState.cull.face.\");\r\n }\r\n if (\r\n this.scissorTest.rectangle.width < 0 ||\r\n this.scissorTest.rectangle.height < 0\r\n ) {\r\n throw new DeveloperError(\r\n \"renderState.scissorTest.rectangle.width and renderState.scissorTest.rectangle.height must be greater than or equal to zero.\"\r\n );\r\n }\r\n if (this.depthRange.near > this.depthRange.far) {\r\n // WebGL specific - not an error in GL ES\r\n throw new DeveloperError(\r\n \"renderState.depthRange.near can not be greater than renderState.depthRange.far.\"\r\n );\r\n }\r\n if (this.depthRange.near < 0) {\r\n // Would be clamped by GL\r\n throw new DeveloperError(\r\n \"renderState.depthRange.near must be greater than or equal to zero.\"\r\n );\r\n }\r\n if (this.depthRange.far > 1) {\r\n // Would be clamped by GL\r\n throw new DeveloperError(\r\n \"renderState.depthRange.far must be less than or equal to one.\"\r\n );\r\n }\r\n if (!validateDepthFunction(this.depthTest.func)) {\r\n throw new DeveloperError(\"Invalid renderState.depthTest.func.\");\r\n }\r\n if (\r\n this.blending.color.red < 0.0 ||\r\n this.blending.color.red > 1.0 ||\r\n this.blending.color.green < 0.0 ||\r\n this.blending.color.green > 1.0 ||\r\n this.blending.color.blue < 0.0 ||\r\n this.blending.color.blue > 1.0 ||\r\n this.blending.color.alpha < 0.0 ||\r\n this.blending.color.alpha > 1.0\r\n ) {\r\n // Would be clamped by GL\r\n throw new DeveloperError(\r\n \"renderState.blending.color components must be greater than or equal to zero and less than or equal to one.\"\r\n );\r\n }\r\n if (!validateBlendEquation(this.blending.equationRgb)) {\r\n throw new DeveloperError(\"Invalid renderState.blending.equationRgb.\");\r\n }\r\n if (!validateBlendEquation(this.blending.equationAlpha)) {\r\n throw new DeveloperError(\"Invalid renderState.blending.equationAlpha.\");\r\n }\r\n if (!validateBlendFunction(this.blending.functionSourceRgb)) {\r\n throw new DeveloperError(\"Invalid renderState.blending.functionSourceRgb.\");\r\n }\r\n if (!validateBlendFunction(this.blending.functionSourceAlpha)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.blending.functionSourceAlpha.\"\r\n );\r\n }\r\n if (!validateBlendFunction(this.blending.functionDestinationRgb)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.blending.functionDestinationRgb.\"\r\n );\r\n }\r\n if (!validateBlendFunction(this.blending.functionDestinationAlpha)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.blending.functionDestinationAlpha.\"\r\n );\r\n }\r\n if (!validateStencilFunction(this.stencilTest.frontFunction)) {\r\n throw new DeveloperError(\"Invalid renderState.stencilTest.frontFunction.\");\r\n }\r\n if (!validateStencilFunction(this.stencilTest.backFunction)) {\r\n throw new DeveloperError(\"Invalid renderState.stencilTest.backFunction.\");\r\n }\r\n if (!validateStencilOperation(this.stencilTest.frontOperation.fail)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.stencilTest.frontOperation.fail.\"\r\n );\r\n }\r\n if (!validateStencilOperation(this.stencilTest.frontOperation.zFail)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.stencilTest.frontOperation.zFail.\"\r\n );\r\n }\r\n if (!validateStencilOperation(this.stencilTest.frontOperation.zPass)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.stencilTest.frontOperation.zPass.\"\r\n );\r\n }\r\n if (!validateStencilOperation(this.stencilTest.backOperation.fail)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.stencilTest.backOperation.fail.\"\r\n );\r\n }\r\n if (!validateStencilOperation(this.stencilTest.backOperation.zFail)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.stencilTest.backOperation.zFail.\"\r\n );\r\n }\r\n if (!validateStencilOperation(this.stencilTest.backOperation.zPass)) {\r\n throw new DeveloperError(\r\n \"Invalid renderState.stencilTest.backOperation.zPass.\"\r\n );\r\n }\r\n\r\n if (defined(this.viewport)) {\r\n if (this.viewport.width < 0) {\r\n throw new DeveloperError(\r\n \"renderState.viewport.width must be greater than or equal to zero.\"\r\n );\r\n }\r\n if (this.viewport.height < 0) {\r\n throw new DeveloperError(\r\n \"renderState.viewport.height must be greater than or equal to zero.\"\r\n );\r\n }\r\n\r\n if (this.viewport.width > ContextLimits.maximumViewportWidth) {\r\n throw new DeveloperError(\r\n \"renderState.viewport.width must be less than or equal to the maximum viewport width (\" +\r\n ContextLimits.maximumViewportWidth.toString() +\r\n \"). Check maximumViewportWidth.\"\r\n );\r\n }\r\n if (this.viewport.height > ContextLimits.maximumViewportHeight) {\r\n throw new DeveloperError(\r\n \"renderState.viewport.height must be less than or equal to the maximum viewport height (\" +\r\n ContextLimits.maximumViewportHeight.toString() +\r\n \"). Check maximumViewportHeight.\"\r\n );\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.id = 0;\r\n this._applyFunctions = [];\r\n}\r\n\r\nvar nextRenderStateId = 0;\r\nvar renderStateCache = {};\r\n\r\n/**\r\n * Validates and then finds or creates an immutable render state, which defines the pipeline\r\n * state for a {@link DrawCommand} or {@link ClearCommand}. All inputs states are optional. Omitted states\r\n * use the defaults shown in the example below.\r\n *\r\n * @param {Object} [renderState] The states defining the render state as shown in the example below.\r\n *\r\n * @exception {RuntimeError} renderState.lineWidth is out of range.\r\n * @exception {DeveloperError} Invalid renderState.frontFace.\r\n * @exception {DeveloperError} Invalid renderState.cull.face.\r\n * @exception {DeveloperError} scissorTest.rectangle.width and scissorTest.rectangle.height must be greater than or equal to zero.\r\n * @exception {DeveloperError} renderState.depthRange.near can't be greater than renderState.depthRange.far.\r\n * @exception {DeveloperError} renderState.depthRange.near must be greater than or equal to zero.\r\n * @exception {DeveloperError} renderState.depthRange.far must be less than or equal to zero.\r\n * @exception {DeveloperError} Invalid renderState.depthTest.func.\r\n * @exception {DeveloperError} renderState.blending.color components must be greater than or equal to zero and less than or equal to one\r\n * @exception {DeveloperError} Invalid renderState.blending.equationRgb.\r\n * @exception {DeveloperError} Invalid renderState.blending.equationAlpha.\r\n * @exception {DeveloperError} Invalid renderState.blending.functionSourceRgb.\r\n * @exception {DeveloperError} Invalid renderState.blending.functionSourceAlpha.\r\n * @exception {DeveloperError} Invalid renderState.blending.functionDestinationRgb.\r\n * @exception {DeveloperError} Invalid renderState.blending.functionDestinationAlpha.\r\n * @exception {DeveloperError} Invalid renderState.stencilTest.frontFunction.\r\n * @exception {DeveloperError} Invalid renderState.stencilTest.backFunction.\r\n * @exception {DeveloperError} Invalid renderState.stencilTest.frontOperation.fail.\r\n * @exception {DeveloperError} Invalid renderState.stencilTest.frontOperation.zFail.\r\n * @exception {DeveloperError} Invalid renderState.stencilTest.frontOperation.zPass.\r\n * @exception {DeveloperError} Invalid renderState.stencilTest.backOperation.fail.\r\n * @exception {DeveloperError} Invalid renderState.stencilTest.backOperation.zFail.\r\n * @exception {DeveloperError} Invalid renderState.stencilTest.backOperation.zPass.\r\n * @exception {DeveloperError} renderState.viewport.width must be greater than or equal to zero.\r\n * @exception {DeveloperError} renderState.viewport.width must be less than or equal to the maximum viewport width.\r\n * @exception {DeveloperError} renderState.viewport.height must be greater than or equal to zero.\r\n * @exception {DeveloperError} renderState.viewport.height must be less than or equal to the maximum viewport height.\r\n *\r\n *\r\n * @example\r\n * var defaults = {\r\n * frontFace : WindingOrder.COUNTER_CLOCKWISE,\r\n * cull : {\r\n * enabled : false,\r\n * face : CullFace.BACK\r\n * },\r\n * lineWidth : 1,\r\n * polygonOffset : {\r\n * enabled : false,\r\n * factor : 0,\r\n * units : 0\r\n * },\r\n * scissorTest : {\r\n * enabled : false,\r\n * rectangle : {\r\n * x : 0,\r\n * y : 0,\r\n * width : 0,\r\n * height : 0\r\n * }\r\n * },\r\n * depthRange : {\r\n * near : 0,\r\n * far : 1\r\n * },\r\n * depthTest : {\r\n * enabled : false,\r\n * func : DepthFunction.LESS\r\n * },\r\n * colorMask : {\r\n * red : true,\r\n * green : true,\r\n * blue : true,\r\n * alpha : true\r\n * },\r\n * depthMask : true,\r\n * stencilMask : ~0,\r\n * blending : {\r\n * enabled : false,\r\n * color : {\r\n * red : 0.0,\r\n * green : 0.0,\r\n * blue : 0.0,\r\n * alpha : 0.0\r\n * },\r\n * equationRgb : BlendEquation.ADD,\r\n * equationAlpha : BlendEquation.ADD,\r\n * functionSourceRgb : BlendFunction.ONE,\r\n * functionSourceAlpha : BlendFunction.ONE,\r\n * functionDestinationRgb : BlendFunction.ZERO,\r\n * functionDestinationAlpha : BlendFunction.ZERO\r\n * },\r\n * stencilTest : {\r\n * enabled : false,\r\n * frontFunction : StencilFunction.ALWAYS,\r\n * backFunction : StencilFunction.ALWAYS,\r\n * reference : 0,\r\n * mask : ~0,\r\n * frontOperation : {\r\n * fail : StencilOperation.KEEP,\r\n * zFail : StencilOperation.KEEP,\r\n * zPass : StencilOperation.KEEP\r\n * },\r\n * backOperation : {\r\n * fail : StencilOperation.KEEP,\r\n * zFail : StencilOperation.KEEP,\r\n * zPass : StencilOperation.KEEP\r\n * }\r\n * },\r\n * sampleCoverage : {\r\n * enabled : false,\r\n * value : 1.0,\r\n * invert : false\r\n * }\r\n * };\r\n *\r\n * var rs = RenderState.fromCache(defaults);\r\n *\r\n * @see DrawCommand\r\n * @see ClearCommand\r\n *\r\n * @private\r\n */\r\nRenderState.fromCache = function (renderState) {\r\n var partialKey = JSON.stringify(renderState);\r\n var cachedState = renderStateCache[partialKey];\r\n if (defined(cachedState)) {\r\n ++cachedState.referenceCount;\r\n return cachedState.state;\r\n }\r\n\r\n // Cache miss. Fully define render state and try again.\r\n var states = new RenderState(renderState);\r\n var fullKey = JSON.stringify(states);\r\n cachedState = renderStateCache[fullKey];\r\n if (!defined(cachedState)) {\r\n states.id = nextRenderStateId++;\r\n //>>includeStart('debug', pragmas.debug);\r\n states = freezeRenderState(states);\r\n //>>includeEnd('debug');\r\n cachedState = {\r\n referenceCount: 0,\r\n state: states,\r\n };\r\n\r\n // Cache full render state. Multiple partially defined render states may map to this.\r\n renderStateCache[fullKey] = cachedState;\r\n }\r\n\r\n ++cachedState.referenceCount;\r\n\r\n // Cache partial render state so we can skip validation on a cache hit for a partially defined render state\r\n renderStateCache[partialKey] = {\r\n referenceCount: 1,\r\n state: cachedState.state,\r\n };\r\n\r\n return cachedState.state;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nRenderState.removeFromCache = function (renderState) {\r\n var states = new RenderState(renderState);\r\n var fullKey = JSON.stringify(states);\r\n var fullCachedState = renderStateCache[fullKey];\r\n\r\n // decrement partial key reference count\r\n var partialKey = JSON.stringify(renderState);\r\n var cachedState = renderStateCache[partialKey];\r\n if (defined(cachedState)) {\r\n --cachedState.referenceCount;\r\n\r\n if (cachedState.referenceCount === 0) {\r\n // remove partial key\r\n delete renderStateCache[partialKey];\r\n\r\n // decrement full key reference count\r\n if (defined(fullCachedState)) {\r\n --fullCachedState.referenceCount;\r\n }\r\n }\r\n }\r\n\r\n // remove full key if reference count is zero\r\n if (defined(fullCachedState) && fullCachedState.referenceCount === 0) {\r\n delete renderStateCache[fullKey];\r\n }\r\n};\r\n\r\n/**\r\n * This function is for testing purposes only.\r\n * @private\r\n */\r\nRenderState.getCache = function () {\r\n return renderStateCache;\r\n};\r\n\r\n/**\r\n * This function is for testing purposes only.\r\n * @private\r\n */\r\nRenderState.clearCache = function () {\r\n renderStateCache = {};\r\n};\r\n\r\nfunction enableOrDisable(gl, glEnum, enable) {\r\n if (enable) {\r\n gl.enable(glEnum);\r\n } else {\r\n gl.disable(glEnum);\r\n }\r\n}\r\n\r\nfunction applyFrontFace(gl, renderState) {\r\n gl.frontFace(renderState.frontFace);\r\n}\r\n\r\nfunction applyCull(gl, renderState) {\r\n var cull = renderState.cull;\r\n var enabled = cull.enabled;\r\n\r\n enableOrDisable(gl, gl.CULL_FACE, enabled);\r\n\r\n if (enabled) {\r\n gl.cullFace(cull.face);\r\n }\r\n}\r\n\r\nfunction applyLineWidth(gl, renderState) {\r\n gl.lineWidth(renderState.lineWidth);\r\n}\r\n\r\nfunction applyPolygonOffset(gl, renderState) {\r\n var polygonOffset = renderState.polygonOffset;\r\n var enabled = polygonOffset.enabled;\r\n\r\n enableOrDisable(gl, gl.POLYGON_OFFSET_FILL, enabled);\r\n\r\n if (enabled) {\r\n gl.polygonOffset(polygonOffset.factor, polygonOffset.units);\r\n }\r\n}\r\n\r\nfunction applyScissorTest(gl, renderState, passState) {\r\n var scissorTest = renderState.scissorTest;\r\n var enabled = defined(passState.scissorTest)\r\n ? passState.scissorTest.enabled\r\n : scissorTest.enabled;\r\n\r\n enableOrDisable(gl, gl.SCISSOR_TEST, enabled);\r\n\r\n if (enabled) {\r\n var rectangle = defined(passState.scissorTest)\r\n ? passState.scissorTest.rectangle\r\n : scissorTest.rectangle;\r\n gl.scissor(rectangle.x, rectangle.y, rectangle.width, rectangle.height);\r\n }\r\n}\r\n\r\nfunction applyDepthRange(gl, renderState) {\r\n var depthRange = renderState.depthRange;\r\n gl.depthRange(depthRange.near, depthRange.far);\r\n}\r\n\r\nfunction applyDepthTest(gl, renderState) {\r\n var depthTest = renderState.depthTest;\r\n var enabled = depthTest.enabled;\r\n\r\n enableOrDisable(gl, gl.DEPTH_TEST, enabled);\r\n\r\n if (enabled) {\r\n gl.depthFunc(depthTest.func);\r\n }\r\n}\r\n\r\nfunction applyColorMask(gl, renderState) {\r\n var colorMask = renderState.colorMask;\r\n gl.colorMask(colorMask.red, colorMask.green, colorMask.blue, colorMask.alpha);\r\n}\r\n\r\nfunction applyDepthMask(gl, renderState) {\r\n gl.depthMask(renderState.depthMask);\r\n}\r\n\r\nfunction applyStencilMask(gl, renderState) {\r\n gl.stencilMask(renderState.stencilMask);\r\n}\r\n\r\nfunction applyBlendingColor(gl, color) {\r\n gl.blendColor(color.red, color.green, color.blue, color.alpha);\r\n}\r\n\r\nfunction applyBlending(gl, renderState, passState) {\r\n var blending = renderState.blending;\r\n var enabled = defined(passState.blendingEnabled)\r\n ? passState.blendingEnabled\r\n : blending.enabled;\r\n\r\n enableOrDisable(gl, gl.BLEND, enabled);\r\n\r\n if (enabled) {\r\n applyBlendingColor(gl, blending.color);\r\n gl.blendEquationSeparate(blending.equationRgb, blending.equationAlpha);\r\n gl.blendFuncSeparate(\r\n blending.functionSourceRgb,\r\n blending.functionDestinationRgb,\r\n blending.functionSourceAlpha,\r\n blending.functionDestinationAlpha\r\n );\r\n }\r\n}\r\n\r\nfunction applyStencilTest(gl, renderState) {\r\n var stencilTest = renderState.stencilTest;\r\n var enabled = stencilTest.enabled;\r\n\r\n enableOrDisable(gl, gl.STENCIL_TEST, enabled);\r\n\r\n if (enabled) {\r\n var frontFunction = stencilTest.frontFunction;\r\n var backFunction = stencilTest.backFunction;\r\n var reference = stencilTest.reference;\r\n var mask = stencilTest.mask;\r\n\r\n // Section 6.8 of the WebGL spec requires the reference and masks to be the same for\r\n // front- and back-face tests. This call prevents invalid operation errors when calling\r\n // stencilFuncSeparate on Firefox. Perhaps they should delay validation to avoid requiring this.\r\n gl.stencilFunc(frontFunction, reference, mask);\r\n gl.stencilFuncSeparate(gl.BACK, backFunction, reference, mask);\r\n gl.stencilFuncSeparate(gl.FRONT, frontFunction, reference, mask);\r\n\r\n var frontOperation = stencilTest.frontOperation;\r\n var frontOperationFail = frontOperation.fail;\r\n var frontOperationZFail = frontOperation.zFail;\r\n var frontOperationZPass = frontOperation.zPass;\r\n\r\n gl.stencilOpSeparate(\r\n gl.FRONT,\r\n frontOperationFail,\r\n frontOperationZFail,\r\n frontOperationZPass\r\n );\r\n\r\n var backOperation = stencilTest.backOperation;\r\n var backOperationFail = backOperation.fail;\r\n var backOperationZFail = backOperation.zFail;\r\n var backOperationZPass = backOperation.zPass;\r\n\r\n gl.stencilOpSeparate(\r\n gl.BACK,\r\n backOperationFail,\r\n backOperationZFail,\r\n backOperationZPass\r\n );\r\n }\r\n}\r\n\r\nfunction applySampleCoverage(gl, renderState) {\r\n var sampleCoverage = renderState.sampleCoverage;\r\n var enabled = sampleCoverage.enabled;\r\n\r\n enableOrDisable(gl, gl.SAMPLE_COVERAGE, enabled);\r\n\r\n if (enabled) {\r\n gl.sampleCoverage(sampleCoverage.value, sampleCoverage.invert);\r\n }\r\n}\r\n\r\nvar scratchViewport = new BoundingRectangle();\r\n\r\nfunction applyViewport(gl, renderState, passState) {\r\n var viewport = defaultValue(renderState.viewport, passState.viewport);\r\n if (!defined(viewport)) {\r\n viewport = scratchViewport;\r\n viewport.width = passState.context.drawingBufferWidth;\r\n viewport.height = passState.context.drawingBufferHeight;\r\n }\r\n\r\n passState.context.uniformState.viewport = viewport;\r\n gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);\r\n}\r\n\r\nRenderState.apply = function (gl, renderState, passState) {\r\n applyFrontFace(gl, renderState);\r\n applyCull(gl, renderState);\r\n applyLineWidth(gl, renderState);\r\n applyPolygonOffset(gl, renderState);\r\n applyDepthRange(gl, renderState);\r\n applyDepthTest(gl, renderState);\r\n applyColorMask(gl, renderState);\r\n applyDepthMask(gl, renderState);\r\n applyStencilMask(gl, renderState);\r\n applyStencilTest(gl, renderState);\r\n applySampleCoverage(gl, renderState);\r\n applyScissorTest(gl, renderState, passState);\r\n applyBlending(gl, renderState, passState);\r\n applyViewport(gl, renderState, passState);\r\n};\r\n\r\nfunction createFuncs(previousState, nextState) {\r\n var funcs = [];\r\n\r\n if (previousState.frontFace !== nextState.frontFace) {\r\n funcs.push(applyFrontFace);\r\n }\r\n\r\n if (\r\n previousState.cull.enabled !== nextState.cull.enabled ||\r\n previousState.cull.face !== nextState.cull.face\r\n ) {\r\n funcs.push(applyCull);\r\n }\r\n\r\n if (previousState.lineWidth !== nextState.lineWidth) {\r\n funcs.push(applyLineWidth);\r\n }\r\n\r\n if (\r\n previousState.polygonOffset.enabled !== nextState.polygonOffset.enabled ||\r\n previousState.polygonOffset.factor !== nextState.polygonOffset.factor ||\r\n previousState.polygonOffset.units !== nextState.polygonOffset.units\r\n ) {\r\n funcs.push(applyPolygonOffset);\r\n }\r\n\r\n if (\r\n previousState.depthRange.near !== nextState.depthRange.near ||\r\n previousState.depthRange.far !== nextState.depthRange.far\r\n ) {\r\n funcs.push(applyDepthRange);\r\n }\r\n\r\n if (\r\n previousState.depthTest.enabled !== nextState.depthTest.enabled ||\r\n previousState.depthTest.func !== nextState.depthTest.func\r\n ) {\r\n funcs.push(applyDepthTest);\r\n }\r\n\r\n if (\r\n previousState.colorMask.red !== nextState.colorMask.red ||\r\n previousState.colorMask.green !== nextState.colorMask.green ||\r\n previousState.colorMask.blue !== nextState.colorMask.blue ||\r\n previousState.colorMask.alpha !== nextState.colorMask.alpha\r\n ) {\r\n funcs.push(applyColorMask);\r\n }\r\n\r\n if (previousState.depthMask !== nextState.depthMask) {\r\n funcs.push(applyDepthMask);\r\n }\r\n\r\n if (previousState.stencilMask !== nextState.stencilMask) {\r\n funcs.push(applyStencilMask);\r\n }\r\n\r\n if (\r\n previousState.stencilTest.enabled !== nextState.stencilTest.enabled ||\r\n previousState.stencilTest.frontFunction !==\r\n nextState.stencilTest.frontFunction ||\r\n previousState.stencilTest.backFunction !==\r\n nextState.stencilTest.backFunction ||\r\n previousState.stencilTest.reference !== nextState.stencilTest.reference ||\r\n previousState.stencilTest.mask !== nextState.stencilTest.mask ||\r\n previousState.stencilTest.frontOperation.fail !==\r\n nextState.stencilTest.frontOperation.fail ||\r\n previousState.stencilTest.frontOperation.zFail !==\r\n nextState.stencilTest.frontOperation.zFail ||\r\n previousState.stencilTest.backOperation.fail !==\r\n nextState.stencilTest.backOperation.fail ||\r\n previousState.stencilTest.backOperation.zFail !==\r\n nextState.stencilTest.backOperation.zFail ||\r\n previousState.stencilTest.backOperation.zPass !==\r\n nextState.stencilTest.backOperation.zPass\r\n ) {\r\n funcs.push(applyStencilTest);\r\n }\r\n\r\n if (\r\n previousState.sampleCoverage.enabled !== nextState.sampleCoverage.enabled ||\r\n previousState.sampleCoverage.value !== nextState.sampleCoverage.value ||\r\n previousState.sampleCoverage.invert !== nextState.sampleCoverage.invert\r\n ) {\r\n funcs.push(applySampleCoverage);\r\n }\r\n\r\n return funcs;\r\n}\r\n\r\nRenderState.partialApply = function (\r\n gl,\r\n previousRenderState,\r\n renderState,\r\n previousPassState,\r\n passState,\r\n clear\r\n) {\r\n if (previousRenderState !== renderState) {\r\n // When a new render state is applied, instead of making WebGL calls for all the states or first\r\n // comparing the states one-by-one with the previous state (basically a linear search), we take\r\n // advantage of RenderState's immutability, and store a dynamically populated sparse data structure\r\n // containing functions that make the minimum number of WebGL calls when transitioning from one state\r\n // to the other. In practice, this works well since state-to-state transitions generally only require a\r\n // few WebGL calls, especially if commands are stored by state.\r\n var funcs = renderState._applyFunctions[previousRenderState.id];\r\n if (!defined(funcs)) {\r\n funcs = createFuncs(previousRenderState, renderState);\r\n renderState._applyFunctions[previousRenderState.id] = funcs;\r\n }\r\n\r\n var len = funcs.length;\r\n for (var i = 0; i < len; ++i) {\r\n funcs[i](gl, renderState);\r\n }\r\n }\r\n\r\n var previousScissorTest = defined(previousPassState.scissorTest)\r\n ? previousPassState.scissorTest\r\n : previousRenderState.scissorTest;\r\n var scissorTest = defined(passState.scissorTest)\r\n ? passState.scissorTest\r\n : renderState.scissorTest;\r\n\r\n // Our scissor rectangle can get out of sync with the GL scissor rectangle on clears.\r\n // Seems to be a problem only on ANGLE. See https://github.com/CesiumGS/cesium/issues/2994\r\n if (previousScissorTest !== scissorTest || clear) {\r\n applyScissorTest(gl, renderState, passState);\r\n }\r\n\r\n var previousBlendingEnabled = defined(previousPassState.blendingEnabled)\r\n ? previousPassState.blendingEnabled\r\n : previousRenderState.blending.enabled;\r\n var blendingEnabled = defined(passState.blendingEnabled)\r\n ? passState.blendingEnabled\r\n : renderState.blending.enabled;\r\n if (\r\n previousBlendingEnabled !== blendingEnabled ||\r\n (blendingEnabled && previousRenderState.blending !== renderState.blending)\r\n ) {\r\n applyBlending(gl, renderState, passState);\r\n }\r\n\r\n if (\r\n previousRenderState !== renderState ||\r\n previousPassState !== passState ||\r\n previousPassState.context !== passState.context\r\n ) {\r\n applyViewport(gl, renderState, passState);\r\n }\r\n};\r\n\r\nRenderState.getState = function (renderState) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(renderState)) {\r\n throw new DeveloperError(\"renderState is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return {\r\n frontFace: renderState.frontFace,\r\n cull: {\r\n enabled: renderState.cull.enabled,\r\n face: renderState.cull.face,\r\n },\r\n lineWidth: renderState.lineWidth,\r\n polygonOffset: {\r\n enabled: renderState.polygonOffset.enabled,\r\n factor: renderState.polygonOffset.factor,\r\n units: renderState.polygonOffset.units,\r\n },\r\n scissorTest: {\r\n enabled: renderState.scissorTest.enabled,\r\n rectangle: BoundingRectangle.clone(renderState.scissorTest.rectangle),\r\n },\r\n depthRange: {\r\n near: renderState.depthRange.near,\r\n far: renderState.depthRange.far,\r\n },\r\n depthTest: {\r\n enabled: renderState.depthTest.enabled,\r\n func: renderState.depthTest.func,\r\n },\r\n colorMask: {\r\n red: renderState.colorMask.red,\r\n green: renderState.colorMask.green,\r\n blue: renderState.colorMask.blue,\r\n alpha: renderState.colorMask.alpha,\r\n },\r\n depthMask: renderState.depthMask,\r\n stencilMask: renderState.stencilMask,\r\n blending: {\r\n enabled: renderState.blending.enabled,\r\n color: Color.clone(renderState.blending.color),\r\n equationRgb: renderState.blending.equationRgb,\r\n equationAlpha: renderState.blending.equationAlpha,\r\n functionSourceRgb: renderState.blending.functionSourceRgb,\r\n functionSourceAlpha: renderState.blending.functionSourceAlpha,\r\n functionDestinationRgb: renderState.blending.functionDestinationRgb,\r\n functionDestinationAlpha: renderState.blending.functionDestinationAlpha,\r\n },\r\n stencilTest: {\r\n enabled: renderState.stencilTest.enabled,\r\n frontFunction: renderState.stencilTest.frontFunction,\r\n backFunction: renderState.stencilTest.backFunction,\r\n reference: renderState.stencilTest.reference,\r\n mask: renderState.stencilTest.mask,\r\n frontOperation: {\r\n fail: renderState.stencilTest.frontOperation.fail,\r\n zFail: renderState.stencilTest.frontOperation.zFail,\r\n zPass: renderState.stencilTest.frontOperation.zPass,\r\n },\r\n backOperation: {\r\n fail: renderState.stencilTest.backOperation.fail,\r\n zFail: renderState.stencilTest.backOperation.zFail,\r\n zPass: renderState.stencilTest.backOperation.zPass,\r\n },\r\n },\r\n sampleCoverage: {\r\n enabled: renderState.sampleCoverage.enabled,\r\n value: renderState.sampleCoverage.value,\r\n invert: renderState.sampleCoverage.invert,\r\n },\r\n viewport: defined(renderState.viewport)\r\n ? BoundingRectangle.clone(renderState.viewport)\r\n : undefined,\r\n };\r\n};\r\nexport default RenderState;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\nvar viewerPositionWCScratch = new Cartesian3();\r\n\r\nfunction AutomaticUniform(options) {\r\n this._size = options.size;\r\n this._datatype = options.datatype;\r\n this.getValue = options.getValue;\r\n}\r\n\r\nvar datatypeToGlsl = {};\r\ndatatypeToGlsl[WebGLConstants.FLOAT] = \"float\";\r\ndatatypeToGlsl[WebGLConstants.FLOAT_VEC2] = \"vec2\";\r\ndatatypeToGlsl[WebGLConstants.FLOAT_VEC3] = \"vec3\";\r\ndatatypeToGlsl[WebGLConstants.FLOAT_VEC4] = \"vec4\";\r\ndatatypeToGlsl[WebGLConstants.INT] = \"int\";\r\ndatatypeToGlsl[WebGLConstants.INT_VEC2] = \"ivec2\";\r\ndatatypeToGlsl[WebGLConstants.INT_VEC3] = \"ivec3\";\r\ndatatypeToGlsl[WebGLConstants.INT_VEC4] = \"ivec4\";\r\ndatatypeToGlsl[WebGLConstants.BOOL] = \"bool\";\r\ndatatypeToGlsl[WebGLConstants.BOOL_VEC2] = \"bvec2\";\r\ndatatypeToGlsl[WebGLConstants.BOOL_VEC3] = \"bvec3\";\r\ndatatypeToGlsl[WebGLConstants.BOOL_VEC4] = \"bvec4\";\r\ndatatypeToGlsl[WebGLConstants.FLOAT_MAT2] = \"mat2\";\r\ndatatypeToGlsl[WebGLConstants.FLOAT_MAT3] = \"mat3\";\r\ndatatypeToGlsl[WebGLConstants.FLOAT_MAT4] = \"mat4\";\r\ndatatypeToGlsl[WebGLConstants.SAMPLER_2D] = \"sampler2D\";\r\ndatatypeToGlsl[WebGLConstants.SAMPLER_CUBE] = \"samplerCube\";\r\n\r\nAutomaticUniform.prototype.getDeclaration = function (name) {\r\n var declaration = \"uniform \" + datatypeToGlsl[this._datatype] + \" \" + name;\r\n\r\n var size = this._size;\r\n if (size === 1) {\r\n declaration += \";\";\r\n } else {\r\n declaration += \"[\" + size.toString() + \"];\";\r\n }\r\n\r\n return declaration;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nvar AutomaticUniforms = {\r\n /**\r\n * An automatic GLSL uniform containing the viewport's x, y, width,\r\n * and height properties in an vec4's x, y, z,\r\n * and w components, respectively.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec4 czm_viewport;\r\n *\r\n * // Scale the window coordinate components to [0, 1] by dividing\r\n * // by the viewport's width and height.\r\n * vec2 v = gl_FragCoord.xy / czm_viewport.zw;\r\n *\r\n * @see Context#getViewport\r\n */\r\n czm_viewport: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC4,\r\n getValue: function (uniformState) {\r\n return uniformState.viewportCartesian4;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 orthographic projection matrix that\r\n * transforms window coordinates to clip coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output.\r\n *

\r\n * This transform is useful when a vertex shader inputs or manipulates window coordinates\r\n * as done by {@link BillboardCollection}.\r\n *

\r\n * Do not confuse {@link czm_viewportTransformation} with czm_viewportOrthographic.\r\n * The former transforms from normalized device coordinates to window coordinates; the later transforms\r\n * from window coordinates to clip coordinates, and is often used to assign to gl_Position.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_viewportOrthographic;\r\n *\r\n * // Example\r\n * gl_Position = czm_viewportOrthographic * vec4(windowPosition, 0.0, 1.0);\r\n *\r\n * @see UniformState#viewportOrthographic\r\n * @see czm_viewport\r\n * @see czm_viewportTransformation\r\n * @see BillboardCollection\r\n */\r\n czm_viewportOrthographic: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.viewportOrthographic;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 transformation matrix that\r\n * transforms normalized device coordinates to window coordinates. The context's\r\n * full viewport is used, and the depth range is assumed to be near = 0\r\n * and far = 1.\r\n *

\r\n * This transform is useful when there is a need to manipulate window coordinates\r\n * in a vertex shader as done by {@link BillboardCollection}. In many cases,\r\n * this matrix will not be used directly; instead, {@link czm_modelToWindowCoordinates}\r\n * will be used to transform directly from model to window coordinates.\r\n *

\r\n * Do not confuse czm_viewportTransformation with {@link czm_viewportOrthographic}.\r\n * The former transforms from normalized device coordinates to window coordinates; the later transforms\r\n * from window coordinates to clip coordinates, and is often used to assign to gl_Position.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_viewportTransformation;\r\n *\r\n * // Use czm_viewportTransformation as part of the\r\n * // transform from model to window coordinates.\r\n * vec4 q = czm_modelViewProjection * positionMC; // model to clip coordinates\r\n * q.xyz /= q.w; // clip to normalized device coordinates (ndc)\r\n * q.xyz = (czm_viewportTransformation * vec4(q.xyz, 1.0)).xyz; // ndc to window coordinates\r\n *\r\n * @see UniformState#viewportTransformation\r\n * @see czm_viewport\r\n * @see czm_viewportOrthographic\r\n * @see czm_modelToWindowCoordinates\r\n * @see BillboardCollection\r\n */\r\n czm_viewportTransformation: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.viewportTransformation;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the depth of the scene\r\n * after the globe pass and then updated after the 3D Tiles pass.\r\n * The depth is packed into an RGBA texture.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform sampler2D czm_globeDepthTexture;\r\n *\r\n * // Get the depth at the current fragment\r\n * vec2 coords = gl_FragCoord.xy / czm_viewport.zw;\r\n * float depth = czm_unpackDepth(texture2D(czm_globeDepthTexture, coords));\r\n */\r\n czm_globeDepthTexture: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.SAMPLER_2D,\r\n getValue: function (uniformState) {\r\n return uniformState.globeDepthTexture;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 model transformation matrix that\r\n * transforms model coordinates to world coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_model;\r\n *\r\n * // Example\r\n * vec4 worldPosition = czm_model * modelPosition;\r\n *\r\n * @see UniformState#model\r\n * @see czm_inverseModel\r\n * @see czm_modelView\r\n * @see czm_modelViewProjection\r\n */\r\n czm_model: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.model;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 model transformation matrix that\r\n * transforms world coordinates to model coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_inverseModel;\r\n *\r\n * // Example\r\n * vec4 modelPosition = czm_inverseModel * worldPosition;\r\n *\r\n * @see UniformState#inverseModel\r\n * @see czm_model\r\n * @see czm_inverseModelView\r\n */\r\n czm_inverseModel: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseModel;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 view transformation matrix that\r\n * transforms world coordinates to eye coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_view;\r\n *\r\n * // Example\r\n * vec4 eyePosition = czm_view * worldPosition;\r\n *\r\n * @see UniformState#view\r\n * @see czm_viewRotation\r\n * @see czm_modelView\r\n * @see czm_viewProjection\r\n * @see czm_modelViewProjection\r\n * @see czm_inverseView\r\n */\r\n czm_view: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.view;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 view transformation matrix that\r\n * transforms 3D world coordinates to eye coordinates. In 3D mode, this is identical to\r\n * {@link czm_view}, but in 2D and Columbus View it represents the view matrix\r\n * as if the camera were at an equivalent location in 3D mode. This is useful for lighting\r\n * 2D and Columbus View in the same way that 3D is lit.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_view3D;\r\n *\r\n * // Example\r\n * vec4 eyePosition3D = czm_view3D * worldPosition3D;\r\n *\r\n * @see UniformState#view3D\r\n * @see czm_view\r\n */\r\n czm_view3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.view3D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 view rotation matrix that\r\n * transforms vectors in world coordinates to eye coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_viewRotation;\r\n *\r\n * // Example\r\n * vec3 eyeVector = czm_viewRotation * worldVector;\r\n *\r\n * @see UniformState#viewRotation\r\n * @see czm_view\r\n * @see czm_inverseView\r\n * @see czm_inverseViewRotation\r\n */\r\n czm_viewRotation: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.viewRotation;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 view rotation matrix that\r\n * transforms vectors in 3D world coordinates to eye coordinates. In 3D mode, this is identical to\r\n * {@link czm_viewRotation}, but in 2D and Columbus View it represents the view matrix\r\n * as if the camera were at an equivalent location in 3D mode. This is useful for lighting\r\n * 2D and Columbus View in the same way that 3D is lit.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_viewRotation3D;\r\n *\r\n * // Example\r\n * vec3 eyeVector = czm_viewRotation3D * worldVector;\r\n *\r\n * @see UniformState#viewRotation3D\r\n * @see czm_viewRotation\r\n */\r\n czm_viewRotation3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.viewRotation3D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 transformation matrix that\r\n * transforms from eye coordinates to world coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_inverseView;\r\n *\r\n * // Example\r\n * vec4 worldPosition = czm_inverseView * eyePosition;\r\n *\r\n * @see UniformState#inverseView\r\n * @see czm_view\r\n * @see czm_inverseNormal\r\n */\r\n czm_inverseView: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseView;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 transformation matrix that\r\n * transforms from 3D eye coordinates to world coordinates. In 3D mode, this is identical to\r\n * {@link czm_inverseView}, but in 2D and Columbus View it represents the inverse view matrix\r\n * as if the camera were at an equivalent location in 3D mode. This is useful for lighting\r\n * 2D and Columbus View in the same way that 3D is lit.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_inverseView3D;\r\n *\r\n * // Example\r\n * vec4 worldPosition = czm_inverseView3D * eyePosition;\r\n *\r\n * @see UniformState#inverseView3D\r\n * @see czm_inverseView\r\n */\r\n czm_inverseView3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseView3D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 rotation matrix that\r\n * transforms vectors from eye coordinates to world coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_inverseViewRotation;\r\n *\r\n * // Example\r\n * vec4 worldVector = czm_inverseViewRotation * eyeVector;\r\n *\r\n * @see UniformState#inverseView\r\n * @see czm_view\r\n * @see czm_viewRotation\r\n * @see czm_inverseViewRotation\r\n */\r\n czm_inverseViewRotation: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseViewRotation;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 rotation matrix that\r\n * transforms vectors from 3D eye coordinates to world coordinates. In 3D mode, this is identical to\r\n * {@link czm_inverseViewRotation}, but in 2D and Columbus View it represents the inverse view matrix\r\n * as if the camera were at an equivalent location in 3D mode. This is useful for lighting\r\n * 2D and Columbus View in the same way that 3D is lit.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_inverseViewRotation3D;\r\n *\r\n * // Example\r\n * vec4 worldVector = czm_inverseViewRotation3D * eyeVector;\r\n *\r\n * @see UniformState#inverseView3D\r\n * @see czm_inverseViewRotation\r\n */\r\n czm_inverseViewRotation3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseViewRotation3D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 projection transformation matrix that\r\n * transforms eye coordinates to clip coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_projection;\r\n *\r\n * // Example\r\n * gl_Position = czm_projection * eyePosition;\r\n *\r\n * @see UniformState#projection\r\n * @see czm_viewProjection\r\n * @see czm_modelViewProjection\r\n * @see czm_infiniteProjection\r\n */\r\n czm_projection: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.projection;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 inverse projection transformation matrix that\r\n * transforms from clip coordinates to eye coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_inverseProjection;\r\n *\r\n * // Example\r\n * vec4 eyePosition = czm_inverseProjection * clipPosition;\r\n *\r\n * @see UniformState#inverseProjection\r\n * @see czm_projection\r\n */\r\n czm_inverseProjection: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseProjection;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 projection transformation matrix with the far plane at infinity,\r\n * that transforms eye coordinates to clip coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output. An infinite far plane is used\r\n * in algorithms like shadow volumes and GPU ray casting with proxy geometry to ensure that triangles\r\n * are not clipped by the far plane.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_infiniteProjection;\r\n *\r\n * // Example\r\n * gl_Position = czm_infiniteProjection * eyePosition;\r\n *\r\n * @see UniformState#infiniteProjection\r\n * @see czm_projection\r\n * @see czm_modelViewInfiniteProjection\r\n */\r\n czm_infiniteProjection: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.infiniteProjection;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that\r\n * transforms model coordinates to eye coordinates.\r\n *

\r\n * Positions should be transformed to eye coordinates using czm_modelView and\r\n * normals should be transformed using {@link czm_normal}.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_modelView;\r\n *\r\n * // Example\r\n * vec4 eyePosition = czm_modelView * modelPosition;\r\n *\r\n * // The above is equivalent to, but more efficient than:\r\n * vec4 eyePosition = czm_view * czm_model * modelPosition;\r\n *\r\n * @see UniformState#modelView\r\n * @see czm_model\r\n * @see czm_view\r\n * @see czm_modelViewProjection\r\n * @see czm_normal\r\n */\r\n czm_modelView: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.modelView;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that\r\n * transforms 3D model coordinates to eye coordinates. In 3D mode, this is identical to\r\n * {@link czm_modelView}, but in 2D and Columbus View it represents the model-view matrix\r\n * as if the camera were at an equivalent location in 3D mode. This is useful for lighting\r\n * 2D and Columbus View in the same way that 3D is lit.\r\n *

\r\n * Positions should be transformed to eye coordinates using czm_modelView3D and\r\n * normals should be transformed using {@link czm_normal3D}.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_modelView3D;\r\n *\r\n * // Example\r\n * vec4 eyePosition = czm_modelView3D * modelPosition;\r\n *\r\n * // The above is equivalent to, but more efficient than:\r\n * vec4 eyePosition = czm_view3D * czm_model * modelPosition;\r\n *\r\n * @see UniformState#modelView3D\r\n * @see czm_modelView\r\n */\r\n czm_modelView3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.modelView3D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 model-view transformation matrix that\r\n * transforms model coordinates, relative to the eye, to eye coordinates. This is used\r\n * in conjunction with {@link czm_translateRelativeToEye}.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_modelViewRelativeToEye;\r\n *\r\n * // Example\r\n * attribute vec3 positionHigh;\r\n * attribute vec3 positionLow;\r\n *\r\n * void main()\r\n * {\r\n * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);\r\n * gl_Position = czm_projection * (czm_modelViewRelativeToEye * p);\r\n * }\r\n *\r\n * @see czm_modelViewProjectionRelativeToEye\r\n * @see czm_translateRelativeToEye\r\n * @see EncodedCartesian3\r\n */\r\n czm_modelViewRelativeToEye: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.modelViewRelativeToEye;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 transformation matrix that\r\n * transforms from eye coordinates to model coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_inverseModelView;\r\n *\r\n * // Example\r\n * vec4 modelPosition = czm_inverseModelView * eyePosition;\r\n *\r\n * @see UniformState#inverseModelView\r\n * @see czm_modelView\r\n */\r\n czm_inverseModelView: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseModelView;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 transformation matrix that\r\n * transforms from eye coordinates to 3D model coordinates. In 3D mode, this is identical to\r\n * {@link czm_inverseModelView}, but in 2D and Columbus View it represents the inverse model-view matrix\r\n * as if the camera were at an equivalent location in 3D mode. This is useful for lighting\r\n * 2D and Columbus View in the same way that 3D is lit.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_inverseModelView3D;\r\n *\r\n * // Example\r\n * vec4 modelPosition = czm_inverseModelView3D * eyePosition;\r\n *\r\n * @see UniformState#inverseModelView\r\n * @see czm_inverseModelView\r\n * @see czm_modelView3D\r\n */\r\n czm_inverseModelView3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseModelView3D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that\r\n * transforms world coordinates to clip coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_viewProjection;\r\n *\r\n * // Example\r\n * vec4 gl_Position = czm_viewProjection * czm_model * modelPosition;\r\n *\r\n * // The above is equivalent to, but more efficient than:\r\n * gl_Position = czm_projection * czm_view * czm_model * modelPosition;\r\n *\r\n * @see UniformState#viewProjection\r\n * @see czm_view\r\n * @see czm_projection\r\n * @see czm_modelViewProjection\r\n * @see czm_inverseViewProjection\r\n */\r\n czm_viewProjection: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.viewProjection;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 view-projection transformation matrix that\r\n * transforms clip coordinates to world coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_inverseViewProjection;\r\n *\r\n * // Example\r\n * vec4 worldPosition = czm_inverseViewProjection * clipPosition;\r\n *\r\n * @see UniformState#inverseViewProjection\r\n * @see czm_viewProjection\r\n */\r\n czm_inverseViewProjection: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseViewProjection;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that\r\n * transforms model coordinates to clip coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_modelViewProjection;\r\n *\r\n * // Example\r\n * vec4 gl_Position = czm_modelViewProjection * modelPosition;\r\n *\r\n * // The above is equivalent to, but more efficient than:\r\n * gl_Position = czm_projection * czm_view * czm_model * modelPosition;\r\n *\r\n * @see UniformState#modelViewProjection\r\n * @see czm_model\r\n * @see czm_view\r\n * @see czm_projection\r\n * @see czm_modelView\r\n * @see czm_viewProjection\r\n * @see czm_modelViewInfiniteProjection\r\n * @see czm_inverseModelViewProjection\r\n */\r\n czm_modelViewProjection: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.modelViewProjection;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 inverse model-view-projection transformation matrix that\r\n * transforms clip coordinates to model coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_inverseModelViewProjection;\r\n *\r\n * // Example\r\n * vec4 modelPosition = czm_inverseModelViewProjection * clipPosition;\r\n *\r\n * @see UniformState#modelViewProjection\r\n * @see czm_modelViewProjection\r\n */\r\n czm_inverseModelViewProjection: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseModelViewProjection;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that\r\n * transforms model coordinates, relative to the eye, to clip coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output. This is used in\r\n * conjunction with {@link czm_translateRelativeToEye}.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_modelViewProjectionRelativeToEye;\r\n *\r\n * // Example\r\n * attribute vec3 positionHigh;\r\n * attribute vec3 positionLow;\r\n *\r\n * void main()\r\n * {\r\n * vec4 p = czm_translateRelativeToEye(positionHigh, positionLow);\r\n * gl_Position = czm_modelViewProjectionRelativeToEye * p;\r\n * }\r\n *\r\n * @see czm_modelViewRelativeToEye\r\n * @see czm_translateRelativeToEye\r\n * @see EncodedCartesian3\r\n */\r\n czm_modelViewProjectionRelativeToEye: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.modelViewProjectionRelativeToEye;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 4x4 model-view-projection transformation matrix that\r\n * transforms model coordinates to clip coordinates. Clip coordinates is the\r\n * coordinate system for a vertex shader's gl_Position output. The projection matrix places\r\n * the far plane at infinity. This is useful in algorithms like shadow volumes and GPU ray casting with\r\n * proxy geometry to ensure that triangles are not clipped by the far plane.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat4 czm_modelViewInfiniteProjection;\r\n *\r\n * // Example\r\n * vec4 gl_Position = czm_modelViewInfiniteProjection * modelPosition;\r\n *\r\n * // The above is equivalent to, but more efficient than:\r\n * gl_Position = czm_infiniteProjection * czm_view * czm_model * modelPosition;\r\n *\r\n * @see UniformState#modelViewInfiniteProjection\r\n * @see czm_model\r\n * @see czm_view\r\n * @see czm_infiniteProjection\r\n * @see czm_modelViewProjection\r\n */\r\n czm_modelViewInfiniteProjection: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT4,\r\n getValue: function (uniformState) {\r\n return uniformState.modelViewInfiniteProjection;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform that indicates if the current camera is orthographic in 3D.\r\n *\r\n * @see UniformState#orthographicIn3D\r\n */\r\n czm_orthographicIn3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.orthographicIn3D ? 1 : 0;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 normal transformation matrix that\r\n * transforms normal vectors in model coordinates to eye coordinates.\r\n *

\r\n * Positions should be transformed to eye coordinates using {@link czm_modelView} and\r\n * normals should be transformed using czm_normal.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_normal;\r\n *\r\n * // Example\r\n * vec3 eyeNormal = czm_normal * normal;\r\n *\r\n * @see UniformState#normal\r\n * @see czm_inverseNormal\r\n * @see czm_modelView\r\n */\r\n czm_normal: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.normal;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 normal transformation matrix that\r\n * transforms normal vectors in 3D model coordinates to eye coordinates.\r\n * In 3D mode, this is identical to\r\n * {@link czm_normal}, but in 2D and Columbus View it represents the normal transformation\r\n * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting\r\n * 2D and Columbus View in the same way that 3D is lit.\r\n *

\r\n * Positions should be transformed to eye coordinates using {@link czm_modelView3D} and\r\n * normals should be transformed using czm_normal3D.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_normal3D;\r\n *\r\n * // Example\r\n * vec3 eyeNormal = czm_normal3D * normal;\r\n *\r\n * @see UniformState#normal3D\r\n * @see czm_normal\r\n */\r\n czm_normal3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.normal3D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 normal transformation matrix that\r\n * transforms normal vectors in eye coordinates to model coordinates. This is\r\n * the opposite of the transform provided by {@link czm_normal}.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_inverseNormal;\r\n *\r\n * // Example\r\n * vec3 normalMC = czm_inverseNormal * normalEC;\r\n *\r\n * @see UniformState#inverseNormal\r\n * @see czm_normal\r\n * @see czm_modelView\r\n * @see czm_inverseView\r\n */\r\n czm_inverseNormal: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseNormal;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 normal transformation matrix that\r\n * transforms normal vectors in eye coordinates to 3D model coordinates. This is\r\n * the opposite of the transform provided by {@link czm_normal}.\r\n * In 3D mode, this is identical to\r\n * {@link czm_inverseNormal}, but in 2D and Columbus View it represents the inverse normal transformation\r\n * matrix as if the camera were at an equivalent location in 3D mode. This is useful for lighting\r\n * 2D and Columbus View in the same way that 3D is lit.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_inverseNormal3D;\r\n *\r\n * // Example\r\n * vec3 normalMC = czm_inverseNormal3D * normalEC;\r\n *\r\n * @see UniformState#inverseNormal3D\r\n * @see czm_inverseNormal\r\n */\r\n czm_inverseNormal3D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.inverseNormal3D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the height in meters of the\r\n * eye (camera) above or below the ellipsoid.\r\n *\r\n * @see UniformState#eyeHeight\r\n */\r\n czm_eyeHeight: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.eyeHeight;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing height (x) and height squared (y)\r\n * in meters of the eye (camera) above the 2D world plane. This uniform is only valid\r\n * when the {@link SceneMode} is SCENE2D.\r\n *\r\n * @see UniformState#eyeHeight2D\r\n */\r\n czm_eyeHeight2D: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC2,\r\n getValue: function (uniformState) {\r\n return uniformState.eyeHeight2D;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the near distance (x) and the far distance (y)\r\n * of the frustum defined by the camera. This is the largest possible frustum, not an individual\r\n * frustum used for multi-frustum rendering.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec2 czm_entireFrustum;\r\n *\r\n * // Example\r\n * float frustumLength = czm_entireFrustum.y - czm_entireFrustum.x;\r\n *\r\n * @see UniformState#entireFrustum\r\n * @see czm_currentFrustum\r\n */\r\n czm_entireFrustum: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC2,\r\n getValue: function (uniformState) {\r\n return uniformState.entireFrustum;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the near distance (x) and the far distance (y)\r\n * of the frustum defined by the camera. This is the individual\r\n * frustum used for multi-frustum rendering.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec2 czm_currentFrustum;\r\n *\r\n * // Example\r\n * float frustumLength = czm_currentFrustum.y - czm_currentFrustum.x;\r\n *\r\n * @see UniformState#currentFrustum\r\n * @see czm_entireFrustum\r\n */\r\n czm_currentFrustum: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC2,\r\n getValue: function (uniformState) {\r\n return uniformState.currentFrustum;\r\n },\r\n }),\r\n\r\n /**\r\n * The distances to the frustum planes. The top, bottom, left and right distances are\r\n * the x, y, z, and w components, respectively.\r\n */\r\n czm_frustumPlanes: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC4,\r\n getValue: function (uniformState) {\r\n return uniformState.frustumPlanes;\r\n },\r\n }),\r\n\r\n /**\r\n * Gets the far plane's distance from the near plane, plus 1.0.\r\n */\r\n czm_farDepthFromNearPlusOne: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.farDepthFromNearPlusOne;\r\n },\r\n }),\r\n\r\n /**\r\n * Gets the log2 of {@link AutomaticUniforms#czm_farDepthFromNearPlusOne}.\r\n */\r\n czm_log2FarDepthFromNearPlusOne: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.log2FarDepthFromNearPlusOne;\r\n },\r\n }),\r\n\r\n /**\r\n * Gets 1.0 divided by {@link AutomaticUniforms#czm_log2FarDepthFromNearPlusOne}.\r\n */\r\n czm_oneOverLog2FarDepthFromNearPlusOne: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.oneOverLog2FarDepthFromNearPlusOne;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the sun position in world coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_sunPositionWC;\r\n *\r\n * @see UniformState#sunPositionWC\r\n * @see czm_sunPositionColumbusView\r\n * @see czm_sunDirectionWC\r\n */\r\n czm_sunPositionWC: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.sunPositionWC;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the sun position in Columbus view world coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_sunPositionColumbusView;\r\n *\r\n * @see UniformState#sunPositionColumbusView\r\n * @see czm_sunPositionWC\r\n */\r\n czm_sunPositionColumbusView: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.sunPositionColumbusView;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the normalized direction to the sun in eye coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_sunDirectionEC;\r\n *\r\n * // Example\r\n * float diffuse = max(dot(czm_sunDirectionEC, normalEC), 0.0);\r\n *\r\n * @see UniformState#sunDirectionEC\r\n * @see czm_moonDirectionEC\r\n * @see czm_sunDirectionWC\r\n */\r\n czm_sunDirectionEC: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.sunDirectionEC;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the normalized direction to the sun in world coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_sunDirectionWC;\r\n *\r\n * // Example\r\n * float diffuse = max(dot(czm_sunDirectionWC, normalWC), 0.0);\r\n *\r\n * @see UniformState#sunDirectionWC\r\n * @see czm_sunPositionWC\r\n * @see czm_sunDirectionEC\r\n */\r\n czm_sunDirectionWC: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.sunDirectionWC;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the normalized direction to the moon in eye coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_moonDirectionEC;\r\n *\r\n * // Example\r\n * float diffuse = max(dot(czm_moonDirectionEC, normalEC), 0.0);\r\n *\r\n * @see UniformState#moonDirectionEC\r\n * @see czm_sunDirectionEC\r\n */\r\n czm_moonDirectionEC: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.moonDirectionEC;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the normalized direction to the scene's light source in eye coordinates.\r\n * This is commonly used for directional lighting computations.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_lightDirectionEC;\r\n *\r\n * // Example\r\n * float diffuse = max(dot(czm_lightDirectionEC, normalEC), 0.0);\r\n *\r\n * @see UniformState#lightDirectionEC\r\n * @see czm_lightDirectionWC\r\n */\r\n czm_lightDirectionEC: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.lightDirectionEC;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the normalized direction to the scene's light source in world coordinates.\r\n * This is commonly used for directional lighting computations.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_lightDirectionWC;\r\n *\r\n * // Example\r\n * float diffuse = max(dot(czm_lightDirectionWC, normalWC), 0.0);\r\n *\r\n * @see UniformState#lightDirectionWC\r\n * @see czm_lightDirectionEC\r\n */\r\n czm_lightDirectionWC: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.lightDirectionWC;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform that represents the color of light emitted by the scene's light source. This\r\n * is equivalent to the light color multiplied by the light intensity limited to a maximum luminance of 1.0\r\n * suitable for non-HDR lighting.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_lightColor;\r\n *\r\n * // Example\r\n * vec3 diffuseColor = czm_lightColor * max(dot(czm_lightDirectionWC, normalWC), 0.0);\r\n *\r\n * @see UniformState#lightColor\r\n * @see czm_lightColorHdr\r\n */\r\n czm_lightColor: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.lightColor;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform that represents the high dynamic range color of light emitted by the scene's light\r\n * source. This is equivalent to the light color multiplied by the light intensity suitable for HDR lighting.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_lightColorHdr;\r\n *\r\n * // Example\r\n * vec3 diffuseColor = czm_lightColorHdr * max(dot(czm_lightDirectionWC, normalWC), 0.0);\r\n *\r\n * @see UniformState#lightColorHdr\r\n * @see czm_lightColor\r\n */\r\n czm_lightColorHdr: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.lightColorHdr;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the high bits of the camera position in model\r\n * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering\r\n * as described in {@link http://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm|Precisions, Precisions}.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_encodedCameraPositionMCHigh;\r\n *\r\n * @see czm_encodedCameraPositionMCLow\r\n * @see czm_modelViewRelativeToEye\r\n * @see czm_modelViewProjectionRelativeToEye\r\n */\r\n czm_encodedCameraPositionMCHigh: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.encodedCameraPositionMCHigh;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the low bits of the camera position in model\r\n * coordinates. This is used for GPU RTE to eliminate jittering artifacts when rendering\r\n * as described in {@linkhttp://help.agi.com/AGIComponents/html/BlogPrecisionsPrecisions.htm|Precisions, Precisions}.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_encodedCameraPositionMCLow;\r\n *\r\n * @see czm_encodedCameraPositionMCHigh\r\n * @see czm_modelViewRelativeToEye\r\n * @see czm_modelViewProjectionRelativeToEye\r\n */\r\n czm_encodedCameraPositionMCLow: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.encodedCameraPositionMCLow;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the position of the viewer (camera) in world coordinates.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3 czm_viewerPositionWC;\r\n */\r\n czm_viewerPositionWC: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return Matrix4.getTranslation(\r\n uniformState.inverseView,\r\n viewerPositionWCScratch\r\n );\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the frame number. This uniform is automatically incremented\r\n * every frame.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform float czm_frameNumber;\r\n */\r\n czm_frameNumber: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.frameState.frameNumber;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the current morph transition time between\r\n * 2D/Columbus View and 3D, with 0.0 being 2D or Columbus View and 1.0 being 3D.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform float czm_morphTime;\r\n *\r\n * // Example\r\n * vec4 p = czm_columbusViewMorph(position2D, position3D, czm_morphTime);\r\n */\r\n czm_morphTime: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.frameState.morphTime;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the current {@link SceneMode}, expressed\r\n * as a float.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform float czm_sceneMode;\r\n *\r\n * // Example\r\n * if (czm_sceneMode == czm_sceneMode2D)\r\n * {\r\n * eyeHeightSq = czm_eyeHeight2D.y;\r\n * }\r\n *\r\n * @see czm_sceneMode2D\r\n * @see czm_sceneModeColumbusView\r\n * @see czm_sceneMode3D\r\n * @see czm_sceneModeMorphing\r\n */\r\n czm_sceneMode: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.frameState.mode;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the current rendering pass.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform float czm_pass;\r\n *\r\n * // Example\r\n * if ((czm_pass == czm_passTranslucent) && isOpaque())\r\n * {\r\n * gl_Position *= 0.0; // Cull opaque geometry in the translucent pass\r\n * }\r\n */\r\n czm_pass: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.pass;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the current scene background color.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec4 czm_backgroundColor;\r\n *\r\n * // Example: If the given color's RGB matches the background color, invert it.\r\n * vec4 adjustColorForContrast(vec4 color)\r\n * {\r\n * if (czm_backgroundColor.rgb == color.rgb)\r\n * {\r\n * color.rgb = vec3(1.0) - color.rgb;\r\n * }\r\n *\r\n * return color;\r\n * }\r\n */\r\n czm_backgroundColor: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC4,\r\n getValue: function (uniformState) {\r\n return uniformState.backgroundColor;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the BRDF look up texture used for image-based lighting computations.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform sampler2D czm_brdfLut;\r\n *\r\n * // Example: For a given roughness and NdotV value, find the material's BRDF information in the red and green channels\r\n * float roughness = 0.5;\r\n * float NdotV = dot(normal, view);\r\n * vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, 1.0 - roughness)).rg;\r\n */\r\n czm_brdfLut: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.SAMPLER_2D,\r\n getValue: function (uniformState) {\r\n return uniformState.brdfLut;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the environment map used within the scene.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform samplerCube czm_environmentMap;\r\n *\r\n * // Example: Create a perfect reflection of the environment map on a model\r\n * float reflected = reflect(view, normal);\r\n * vec4 reflectedColor = textureCube(czm_environmentMap, reflected);\r\n */\r\n czm_environmentMap: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.SAMPLER_CUBE,\r\n getValue: function (uniformState) {\r\n return uniformState.environmentMap;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the specular environment map atlas used within the scene.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform sampler2D czm_specularEnvironmentMaps;\r\n */\r\n czm_specularEnvironmentMaps: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.SAMPLER_2D,\r\n getValue: function (uniformState) {\r\n return uniformState.specularEnvironmentMaps;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the size of the specular environment map atlas used within the scene.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec2 czm_specularEnvironmentMapSize;\r\n */\r\n czm_specularEnvironmentMapSize: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC2,\r\n getValue: function (uniformState) {\r\n return uniformState.specularEnvironmentMapsDimensions;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the maximum level-of-detail of the specular environment map atlas used within the scene.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform float czm_specularEnvironmentMapsMaximumLOD;\r\n */\r\n czm_specularEnvironmentMapsMaximumLOD: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.specularEnvironmentMapsMaximumLOD;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform containing the spherical harmonic coefficients used within the scene.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform vec3[9] czm_sphericalHarmonicCoefficients;\r\n */\r\n czm_sphericalHarmonicCoefficients: new AutomaticUniform({\r\n size: 9,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.sphericalHarmonicCoefficients;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing a 3x3 rotation matrix that transforms\r\n * from True Equator Mean Equinox (TEME) axes to the pseudo-fixed axes at the current scene time.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform mat3 czm_temeToPseudoFixed;\r\n *\r\n * // Example\r\n * vec3 pseudoFixed = czm_temeToPseudoFixed * teme;\r\n *\r\n * @see UniformState#temeToPseudoFixedMatrix\r\n * @see Transforms.computeTemeToPseudoFixedMatrix\r\n */\r\n czm_temeToPseudoFixed: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_MAT3,\r\n getValue: function (uniformState) {\r\n return uniformState.temeToPseudoFixedMatrix;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the ratio of canvas coordinate space to canvas pixel space.\r\n *\r\n * @example\r\n * uniform float czm_pixelRatio;\r\n */\r\n czm_pixelRatio: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.pixelRatio;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform scalar used to mix a color with the fog color based on the distance to the camera.\r\n *\r\n * @see czm_fog\r\n */\r\n czm_fogDensity: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.fogDensity;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the splitter position to use when rendering imagery layers with a splitter.\r\n * This will be in pixel coordinates relative to the canvas.\r\n *\r\n * @example\r\n * // GLSL declaration\r\n * uniform float czm_imagerySplitPosition;\r\n */\r\n czm_imagerySplitPosition: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.imagerySplitPosition;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform scalar representing the geometric tolerance per meter\r\n */\r\n czm_geometricToleranceOverMeter: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.geometricToleranceOverMeter;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform representing the distance from the camera at which to disable the depth test of billboards, labels and points\r\n * to, for example, prevent clipping against terrain. When set to zero, the depth test should always be applied. When less than zero,\r\n * the depth test should never be applied.\r\n */\r\n czm_minimumDisableDepthTestDistance: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.minimumDisableDepthTestDistance;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform that will be the highlight color of unclassified 3D Tiles.\r\n */\r\n czm_invertClassificationColor: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC4,\r\n getValue: function (uniformState) {\r\n return uniformState.invertClassificationColor;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform that is used for gamma correction.\r\n */\r\n czm_gamma: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT,\r\n getValue: function (uniformState) {\r\n return uniformState.gamma;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform that stores the ellipsoid radii.\r\n */\r\n czm_ellipsoidRadii: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.ellipsoid.radii;\r\n },\r\n }),\r\n\r\n /**\r\n * An automatic GLSL uniform that stores the ellipsoid inverse radii.\r\n */\r\n czm_ellipsoidInverseRadii: new AutomaticUniform({\r\n size: 1,\r\n datatype: WebGLConstants.FLOAT_VEC3,\r\n getValue: function (uniformState) {\r\n return uniformState.ellipsoid.oneOverRadii;\r\n },\r\n }),\r\n};\r\nexport default AutomaticUniforms;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Matrix2 from \"../Core/Matrix2.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction createUniform(gl, activeUniform, uniformName, location) {\r\n switch (activeUniform.type) {\r\n case gl.FLOAT:\r\n return new UniformFloat(gl, activeUniform, uniformName, location);\r\n case gl.FLOAT_VEC2:\r\n return new UniformFloatVec2(gl, activeUniform, uniformName, location);\r\n case gl.FLOAT_VEC3:\r\n return new UniformFloatVec3(gl, activeUniform, uniformName, location);\r\n case gl.FLOAT_VEC4:\r\n return new UniformFloatVec4(gl, activeUniform, uniformName, location);\r\n case gl.SAMPLER_2D:\r\n case gl.SAMPLER_CUBE:\r\n return new UniformSampler(gl, activeUniform, uniformName, location);\r\n case gl.INT:\r\n case gl.BOOL:\r\n return new UniformInt(gl, activeUniform, uniformName, location);\r\n case gl.INT_VEC2:\r\n case gl.BOOL_VEC2:\r\n return new UniformIntVec2(gl, activeUniform, uniformName, location);\r\n case gl.INT_VEC3:\r\n case gl.BOOL_VEC3:\r\n return new UniformIntVec3(gl, activeUniform, uniformName, location);\r\n case gl.INT_VEC4:\r\n case gl.BOOL_VEC4:\r\n return new UniformIntVec4(gl, activeUniform, uniformName, location);\r\n case gl.FLOAT_MAT2:\r\n return new UniformMat2(gl, activeUniform, uniformName, location);\r\n case gl.FLOAT_MAT3:\r\n return new UniformMat3(gl, activeUniform, uniformName, location);\r\n case gl.FLOAT_MAT4:\r\n return new UniformMat4(gl, activeUniform, uniformName, location);\r\n default:\r\n throw new RuntimeError(\r\n \"Unrecognized uniform type: \" +\r\n activeUniform.type +\r\n ' for uniform \"' +\r\n uniformName +\r\n '\".'\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformFloat(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = 0.0;\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformFloat.prototype.set = function () {\r\n if (this.value !== this._value) {\r\n this._value = this.value;\r\n this._gl.uniform1f(this._location, this.value);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformFloatVec2(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = new Cartesian2();\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformFloatVec2.prototype.set = function () {\r\n var v = this.value;\r\n if (!Cartesian2.equals(v, this._value)) {\r\n Cartesian2.clone(v, this._value);\r\n this._gl.uniform2f(this._location, v.x, v.y);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformFloatVec3(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = undefined;\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformFloatVec3.prototype.set = function () {\r\n var v = this.value;\r\n\r\n if (defined(v.red)) {\r\n if (!Color.equals(v, this._value)) {\r\n this._value = Color.clone(v, this._value);\r\n this._gl.uniform3f(this._location, v.red, v.green, v.blue);\r\n }\r\n } else if (defined(v.x)) {\r\n if (!Cartesian3.equals(v, this._value)) {\r\n this._value = Cartesian3.clone(v, this._value);\r\n this._gl.uniform3f(this._location, v.x, v.y, v.z);\r\n }\r\n } else {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\r\n 'Invalid vec3 value for uniform \"' + this.name + '\".'\r\n );\r\n //>>includeEnd('debug');\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformFloatVec4(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = undefined;\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformFloatVec4.prototype.set = function () {\r\n var v = this.value;\r\n\r\n if (defined(v.red)) {\r\n if (!Color.equals(v, this._value)) {\r\n this._value = Color.clone(v, this._value);\r\n this._gl.uniform4f(this._location, v.red, v.green, v.blue, v.alpha);\r\n }\r\n } else if (defined(v.x)) {\r\n if (!Cartesian4.equals(v, this._value)) {\r\n this._value = Cartesian4.clone(v, this._value);\r\n this._gl.uniform4f(this._location, v.x, v.y, v.z, v.w);\r\n }\r\n } else {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\r\n 'Invalid vec4 value for uniform \"' + this.name + '\".'\r\n );\r\n //>>includeEnd('debug');\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformSampler(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n\r\n this.textureUnitIndex = undefined;\r\n}\r\n\r\nUniformSampler.prototype.set = function () {\r\n var gl = this._gl;\r\n gl.activeTexture(gl.TEXTURE0 + this.textureUnitIndex);\r\n\r\n var v = this.value;\r\n gl.bindTexture(v._target, v._texture);\r\n};\r\n\r\nUniformSampler.prototype._setSampler = function (textureUnitIndex) {\r\n this.textureUnitIndex = textureUnitIndex;\r\n this._gl.uniform1i(this._location, textureUnitIndex);\r\n return textureUnitIndex + 1;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformInt(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = 0.0;\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformInt.prototype.set = function () {\r\n if (this.value !== this._value) {\r\n this._value = this.value;\r\n this._gl.uniform1i(this._location, this.value);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformIntVec2(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = new Cartesian2();\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformIntVec2.prototype.set = function () {\r\n var v = this.value;\r\n if (!Cartesian2.equals(v, this._value)) {\r\n Cartesian2.clone(v, this._value);\r\n this._gl.uniform2i(this._location, v.x, v.y);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformIntVec3(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = new Cartesian3();\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformIntVec3.prototype.set = function () {\r\n var v = this.value;\r\n if (!Cartesian3.equals(v, this._value)) {\r\n Cartesian3.clone(v, this._value);\r\n this._gl.uniform3i(this._location, v.x, v.y, v.z);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformIntVec4(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = new Cartesian4();\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformIntVec4.prototype.set = function () {\r\n var v = this.value;\r\n if (!Cartesian4.equals(v, this._value)) {\r\n Cartesian4.clone(v, this._value);\r\n this._gl.uniform4i(this._location, v.x, v.y, v.z, v.w);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar scratchUniformArray = new Float32Array(4);\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformMat2(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = new Matrix2();\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformMat2.prototype.set = function () {\r\n if (!Matrix2.equalsArray(this.value, this._value, 0)) {\r\n Matrix2.clone(this.value, this._value);\r\n\r\n var array = Matrix2.toArray(this.value, scratchUniformArray);\r\n this._gl.uniformMatrix2fv(this._location, false, array);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar scratchMat3Array = new Float32Array(9);\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformMat3(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = new Matrix3();\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformMat3.prototype.set = function () {\r\n if (!Matrix3.equalsArray(this.value, this._value, 0)) {\r\n Matrix3.clone(this.value, this._value);\r\n\r\n var array = Matrix3.toArray(this.value, scratchMat3Array);\r\n this._gl.uniformMatrix3fv(this._location, false, array);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar scratchMat4Array = new Float32Array(16);\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformMat4(gl, activeUniform, uniformName, location) {\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = undefined;\r\n this._value = new Matrix4();\r\n\r\n this._gl = gl;\r\n this._location = location;\r\n}\r\n\r\nUniformMat4.prototype.set = function () {\r\n if (!Matrix4.equalsArray(this.value, this._value, 0)) {\r\n Matrix4.clone(this.value, this._value);\r\n\r\n var array = Matrix4.toArray(this.value, scratchMat4Array);\r\n this._gl.uniformMatrix4fv(this._location, false, array);\r\n }\r\n};\r\nexport default createUniform;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Matrix2 from \"../Core/Matrix2.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction createUniformArray(gl, activeUniform, uniformName, locations) {\r\n switch (activeUniform.type) {\r\n case gl.FLOAT:\r\n return new UniformArrayFloat(gl, activeUniform, uniformName, locations);\r\n case gl.FLOAT_VEC2:\r\n return new UniformArrayFloatVec2(\r\n gl,\r\n activeUniform,\r\n uniformName,\r\n locations\r\n );\r\n case gl.FLOAT_VEC3:\r\n return new UniformArrayFloatVec3(\r\n gl,\r\n activeUniform,\r\n uniformName,\r\n locations\r\n );\r\n case gl.FLOAT_VEC4:\r\n return new UniformArrayFloatVec4(\r\n gl,\r\n activeUniform,\r\n uniformName,\r\n locations\r\n );\r\n case gl.SAMPLER_2D:\r\n case gl.SAMPLER_CUBE:\r\n return new UniformArraySampler(gl, activeUniform, uniformName, locations);\r\n case gl.INT:\r\n case gl.BOOL:\r\n return new UniformArrayInt(gl, activeUniform, uniformName, locations);\r\n case gl.INT_VEC2:\r\n case gl.BOOL_VEC2:\r\n return new UniformArrayIntVec2(gl, activeUniform, uniformName, locations);\r\n case gl.INT_VEC3:\r\n case gl.BOOL_VEC3:\r\n return new UniformArrayIntVec3(gl, activeUniform, uniformName, locations);\r\n case gl.INT_VEC4:\r\n case gl.BOOL_VEC4:\r\n return new UniformArrayIntVec4(gl, activeUniform, uniformName, locations);\r\n case gl.FLOAT_MAT2:\r\n return new UniformArrayMat2(gl, activeUniform, uniformName, locations);\r\n case gl.FLOAT_MAT3:\r\n return new UniformArrayMat3(gl, activeUniform, uniformName, locations);\r\n case gl.FLOAT_MAT4:\r\n return new UniformArrayMat4(gl, activeUniform, uniformName, locations);\r\n default:\r\n throw new RuntimeError(\r\n \"Unrecognized uniform type: \" +\r\n activeUniform.type +\r\n ' for uniform \"' +\r\n uniformName +\r\n '\".'\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayFloat(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Float32Array(length);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayFloat.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (v !== arraybuffer[i]) {\r\n arraybuffer[i] = v;\r\n changed = true;\r\n }\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniform1fv(this._location, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayFloatVec2(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Float32Array(length * 2);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayFloatVec2.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (!Cartesian2.equalsArray(v, arraybuffer, j)) {\r\n Cartesian2.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n j += 2;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniform2fv(this._location, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayFloatVec3(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Float32Array(length * 3);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayFloatVec3.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (defined(v.red)) {\r\n if (\r\n v.red !== arraybuffer[j] ||\r\n v.green !== arraybuffer[j + 1] ||\r\n v.blue !== arraybuffer[j + 2]\r\n ) {\r\n arraybuffer[j] = v.red;\r\n arraybuffer[j + 1] = v.green;\r\n arraybuffer[j + 2] = v.blue;\r\n changed = true;\r\n }\r\n } else if (defined(v.x)) {\r\n if (!Cartesian3.equalsArray(v, arraybuffer, j)) {\r\n Cartesian3.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n } else {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\"Invalid vec3 value.\");\r\n //>>includeEnd('debug');\r\n }\r\n\r\n j += 3;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniform3fv(this._location, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayFloatVec4(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Float32Array(length * 4);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayFloatVec4.prototype.set = function () {\r\n // PERFORMANCE_IDEA: if it is a common case that only a few elements\r\n // in a uniform array change, we could use heuristics to determine\r\n // when it is better to call uniform4f for each element that changed\r\n // vs. call uniform4fv once to set the entire array. This applies\r\n // to all uniform array types, not just vec4. We might not care\r\n // once we have uniform buffers since that will be the fast path.\r\n\r\n // PERFORMANCE_IDEA: Micro-optimization (I bet it works though):\r\n // As soon as changed is true, break into a separate loop that\r\n // does the copy without the equals check.\r\n\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (defined(v.red)) {\r\n if (!Color.equalsArray(v, arraybuffer, j)) {\r\n Color.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n } else if (defined(v.x)) {\r\n if (!Cartesian4.equalsArray(v, arraybuffer, j)) {\r\n Cartesian4.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n } else {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\"Invalid vec4 value.\");\r\n //>>includeEnd('debug');\r\n }\r\n\r\n j += 4;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniform4fv(this._location, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArraySampler(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Float32Array(length);\r\n\r\n this._gl = gl;\r\n this._locations = locations;\r\n\r\n this.textureUnitIndex = undefined;\r\n}\r\n\r\nUniformArraySampler.prototype.set = function () {\r\n var gl = this._gl;\r\n var textureUnitIndex = gl.TEXTURE0 + this.textureUnitIndex;\r\n\r\n var value = this.value;\r\n var length = value.length;\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n gl.activeTexture(textureUnitIndex + i);\r\n gl.bindTexture(v._target, v._texture);\r\n }\r\n};\r\n\r\nUniformArraySampler.prototype._setSampler = function (textureUnitIndex) {\r\n this.textureUnitIndex = textureUnitIndex;\r\n\r\n var locations = this._locations;\r\n var length = locations.length;\r\n for (var i = 0; i < length; ++i) {\r\n var index = textureUnitIndex + i;\r\n this._gl.uniform1i(locations[i], index);\r\n }\r\n\r\n return textureUnitIndex + length;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayInt(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Int32Array(length);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayInt.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (v !== arraybuffer[i]) {\r\n arraybuffer[i] = v;\r\n changed = true;\r\n }\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniform1iv(this._location, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayIntVec2(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Int32Array(length * 2);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayIntVec2.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (!Cartesian2.equalsArray(v, arraybuffer, j)) {\r\n Cartesian2.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n j += 2;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniform2iv(this._location, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayIntVec3(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Int32Array(length * 3);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayIntVec3.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (!Cartesian3.equalsArray(v, arraybuffer, j)) {\r\n Cartesian3.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n j += 3;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniform3iv(this._location, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayIntVec4(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Int32Array(length * 4);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayIntVec4.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (!Cartesian4.equalsArray(v, arraybuffer, j)) {\r\n Cartesian4.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n j += 4;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniform4iv(this._location, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayMat2(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Float32Array(length * 4);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayMat2.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (!Matrix2.equalsArray(v, arraybuffer, j)) {\r\n Matrix2.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n j += 4;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniformMatrix2fv(this._location, false, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayMat3(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Float32Array(length * 9);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayMat3.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (!Matrix3.equalsArray(v, arraybuffer, j)) {\r\n Matrix3.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n j += 9;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniformMatrix3fv(this._location, false, arraybuffer);\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction UniformArrayMat4(gl, activeUniform, uniformName, locations) {\r\n var length = locations.length;\r\n\r\n /**\r\n * @type {String}\r\n * @readonly\r\n */\r\n this.name = uniformName;\r\n\r\n this.value = new Array(length);\r\n this._value = new Float32Array(length * 16);\r\n\r\n this._gl = gl;\r\n this._location = locations[0];\r\n}\r\n\r\nUniformArrayMat4.prototype.set = function () {\r\n var value = this.value;\r\n var length = value.length;\r\n var arraybuffer = this._value;\r\n var changed = false;\r\n var j = 0;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var v = value[i];\r\n\r\n if (!Matrix4.equalsArray(v, arraybuffer, j)) {\r\n Matrix4.pack(v, arraybuffer, j);\r\n changed = true;\r\n }\r\n j += 16;\r\n }\r\n\r\n if (changed) {\r\n this._gl.uniformMatrix4fv(this._location, false, arraybuffer);\r\n }\r\n};\r\nexport default createUniformArray;\r\n","import Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport AutomaticUniforms from \"./AutomaticUniforms.js\";\r\nimport ContextLimits from \"./ContextLimits.js\";\r\nimport createUniform from \"./createUniform.js\";\r\nimport createUniformArray from \"./createUniformArray.js\";\r\n\r\nvar nextShaderProgramId = 0;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction ShaderProgram(options) {\r\n var vertexShaderText = options.vertexShaderText;\r\n var fragmentShaderText = options.fragmentShaderText;\r\n\r\n if (typeof spector !== \"undefined\") {\r\n // The #line statements common in Cesium shaders interfere with the ability of the\r\n // SpectorJS to show errors on the correct line. So remove them when SpectorJS\r\n // is active.\r\n vertexShaderText = vertexShaderText.replace(/^#line/gm, \"//#line\");\r\n fragmentShaderText = fragmentShaderText.replace(/^#line/gm, \"//#line\");\r\n }\r\n\r\n var modifiedFS = handleUniformPrecisionMismatches(\r\n vertexShaderText,\r\n fragmentShaderText\r\n );\r\n\r\n this._gl = options.gl;\r\n this._logShaderCompilation = options.logShaderCompilation;\r\n this._debugShaders = options.debugShaders;\r\n this._attributeLocations = options.attributeLocations;\r\n\r\n this._program = undefined;\r\n this._numberOfVertexAttributes = undefined;\r\n this._vertexAttributes = undefined;\r\n this._uniformsByName = undefined;\r\n this._uniforms = undefined;\r\n this._automaticUniforms = undefined;\r\n this._manualUniforms = undefined;\r\n this._duplicateUniformNames = modifiedFS.duplicateUniformNames;\r\n this._cachedShader = undefined; // Used by ShaderCache\r\n\r\n /**\r\n * @private\r\n */\r\n this.maximumTextureUnitIndex = undefined;\r\n\r\n this._vertexShaderSource = options.vertexShaderSource;\r\n this._vertexShaderText = options.vertexShaderText;\r\n this._fragmentShaderSource = options.fragmentShaderSource;\r\n this._fragmentShaderText = modifiedFS.fragmentShaderText;\r\n\r\n /**\r\n * @private\r\n */\r\n this.id = nextShaderProgramId++;\r\n}\r\n\r\nShaderProgram.fromCache = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n //>>includeEnd('debug');\r\n\r\n return options.context.shaderCache.getShaderProgram(options);\r\n};\r\n\r\nShaderProgram.replaceCache = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n //>>includeEnd('debug');\r\n\r\n return options.context.shaderCache.replaceShaderProgram(options);\r\n};\r\n\r\nObject.defineProperties(ShaderProgram.prototype, {\r\n /**\r\n * GLSL source for the shader program's vertex shader.\r\n * @memberof ShaderProgram.prototype\r\n *\r\n * @type {ShaderSource}\r\n * @readonly\r\n */\r\n vertexShaderSource: {\r\n get: function () {\r\n return this._vertexShaderSource;\r\n },\r\n },\r\n /**\r\n * GLSL source for the shader program's fragment shader.\r\n * @memberof ShaderProgram.prototype\r\n *\r\n * @type {ShaderSource}\r\n * @readonly\r\n */\r\n fragmentShaderSource: {\r\n get: function () {\r\n return this._fragmentShaderSource;\r\n },\r\n },\r\n vertexAttributes: {\r\n get: function () {\r\n initialize(this);\r\n return this._vertexAttributes;\r\n },\r\n },\r\n numberOfVertexAttributes: {\r\n get: function () {\r\n initialize(this);\r\n return this._numberOfVertexAttributes;\r\n },\r\n },\r\n allUniforms: {\r\n get: function () {\r\n initialize(this);\r\n return this._uniformsByName;\r\n },\r\n },\r\n});\r\n\r\nfunction extractUniforms(shaderText) {\r\n var uniformNames = [];\r\n var uniformLines = shaderText.match(/uniform.*?(?![^{]*})(?=[=\\[;])/g);\r\n if (defined(uniformLines)) {\r\n var len = uniformLines.length;\r\n for (var i = 0; i < len; i++) {\r\n var line = uniformLines[i].trim();\r\n var name = line.slice(line.lastIndexOf(\" \") + 1);\r\n uniformNames.push(name);\r\n }\r\n }\r\n return uniformNames;\r\n}\r\n\r\nfunction handleUniformPrecisionMismatches(\r\n vertexShaderText,\r\n fragmentShaderText\r\n) {\r\n // If a uniform exists in both the vertex and fragment shader but with different precision qualifiers,\r\n // give the fragment shader uniform a different name. This fixes shader compilation errors on devices\r\n // that only support mediump in the fragment shader.\r\n var duplicateUniformNames = {};\r\n\r\n if (!ContextLimits.highpFloatSupported || !ContextLimits.highpIntSupported) {\r\n var i, j;\r\n var uniformName;\r\n var duplicateName;\r\n var vertexShaderUniforms = extractUniforms(vertexShaderText);\r\n var fragmentShaderUniforms = extractUniforms(fragmentShaderText);\r\n var vertexUniformsCount = vertexShaderUniforms.length;\r\n var fragmentUniformsCount = fragmentShaderUniforms.length;\r\n\r\n for (i = 0; i < vertexUniformsCount; i++) {\r\n for (j = 0; j < fragmentUniformsCount; j++) {\r\n if (vertexShaderUniforms[i] === fragmentShaderUniforms[j]) {\r\n uniformName = vertexShaderUniforms[i];\r\n duplicateName = \"czm_mediump_\" + uniformName;\r\n // Update fragmentShaderText with renamed uniforms\r\n var re = new RegExp(uniformName + \"\\\\b\", \"g\");\r\n fragmentShaderText = fragmentShaderText.replace(re, duplicateName);\r\n duplicateUniformNames[duplicateName] = uniformName;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n fragmentShaderText: fragmentShaderText,\r\n duplicateUniformNames: duplicateUniformNames,\r\n };\r\n}\r\n\r\nvar consolePrefix = \"[Cesium WebGL] \";\r\n\r\nfunction createAndLinkProgram(gl, shader) {\r\n var vsSource = shader._vertexShaderText;\r\n var fsSource = shader._fragmentShaderText;\r\n\r\n var vertexShader = gl.createShader(gl.VERTEX_SHADER);\r\n gl.shaderSource(vertexShader, vsSource);\r\n gl.compileShader(vertexShader);\r\n\r\n var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\r\n gl.shaderSource(fragmentShader, fsSource);\r\n gl.compileShader(fragmentShader);\r\n\r\n var program = gl.createProgram();\r\n gl.attachShader(program, vertexShader);\r\n gl.attachShader(program, fragmentShader);\r\n\r\n gl.deleteShader(vertexShader);\r\n gl.deleteShader(fragmentShader);\r\n\r\n var attributeLocations = shader._attributeLocations;\r\n if (defined(attributeLocations)) {\r\n for (var attribute in attributeLocations) {\r\n if (attributeLocations.hasOwnProperty(attribute)) {\r\n gl.bindAttribLocation(\r\n program,\r\n attributeLocations[attribute],\r\n attribute\r\n );\r\n }\r\n }\r\n }\r\n\r\n gl.linkProgram(program);\r\n\r\n var log;\r\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\r\n var debugShaders = shader._debugShaders;\r\n\r\n // For performance, only check compile errors if there is a linker error.\r\n if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {\r\n log = gl.getShaderInfoLog(fragmentShader);\r\n console.error(consolePrefix + \"Fragment shader compile log: \" + log);\r\n if (defined(debugShaders)) {\r\n var fragmentSourceTranslation = debugShaders.getTranslatedShaderSource(\r\n fragmentShader\r\n );\r\n if (fragmentSourceTranslation !== \"\") {\r\n console.error(\r\n consolePrefix +\r\n \"Translated fragment shader source:\\n\" +\r\n fragmentSourceTranslation\r\n );\r\n } else {\r\n console.error(consolePrefix + \"Fragment shader translation failed.\");\r\n }\r\n }\r\n\r\n gl.deleteProgram(program);\r\n throw new RuntimeError(\r\n \"Fragment shader failed to compile. Compile log: \" + log\r\n );\r\n }\r\n\r\n if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {\r\n log = gl.getShaderInfoLog(vertexShader);\r\n console.error(consolePrefix + \"Vertex shader compile log: \" + log);\r\n if (defined(debugShaders)) {\r\n var vertexSourceTranslation = debugShaders.getTranslatedShaderSource(\r\n vertexShader\r\n );\r\n if (vertexSourceTranslation !== \"\") {\r\n console.error(\r\n consolePrefix +\r\n \"Translated vertex shader source:\\n\" +\r\n vertexSourceTranslation\r\n );\r\n } else {\r\n console.error(consolePrefix + \"Vertex shader translation failed.\");\r\n }\r\n }\r\n\r\n gl.deleteProgram(program);\r\n throw new RuntimeError(\r\n \"Vertex shader failed to compile. Compile log: \" + log\r\n );\r\n }\r\n\r\n log = gl.getProgramInfoLog(program);\r\n console.error(consolePrefix + \"Shader program link log: \" + log);\r\n if (defined(debugShaders)) {\r\n console.error(\r\n consolePrefix +\r\n \"Translated vertex shader source:\\n\" +\r\n debugShaders.getTranslatedShaderSource(vertexShader)\r\n );\r\n console.error(\r\n consolePrefix +\r\n \"Translated fragment shader source:\\n\" +\r\n debugShaders.getTranslatedShaderSource(fragmentShader)\r\n );\r\n }\r\n\r\n gl.deleteProgram(program);\r\n throw new RuntimeError(\"Program failed to link. Link log: \" + log);\r\n }\r\n\r\n var logShaderCompilation = shader._logShaderCompilation;\r\n\r\n if (logShaderCompilation) {\r\n log = gl.getShaderInfoLog(vertexShader);\r\n if (defined(log) && log.length > 0) {\r\n console.log(consolePrefix + \"Vertex shader compile log: \" + log);\r\n }\r\n }\r\n\r\n if (logShaderCompilation) {\r\n log = gl.getShaderInfoLog(fragmentShader);\r\n if (defined(log) && log.length > 0) {\r\n console.log(consolePrefix + \"Fragment shader compile log: \" + log);\r\n }\r\n }\r\n\r\n if (logShaderCompilation) {\r\n log = gl.getProgramInfoLog(program);\r\n if (defined(log) && log.length > 0) {\r\n console.log(consolePrefix + \"Shader program link log: \" + log);\r\n }\r\n }\r\n\r\n return program;\r\n}\r\n\r\nfunction findVertexAttributes(gl, program, numberOfAttributes) {\r\n var attributes = {};\r\n for (var i = 0; i < numberOfAttributes; ++i) {\r\n var attr = gl.getActiveAttrib(program, i);\r\n var location = gl.getAttribLocation(program, attr.name);\r\n\r\n attributes[attr.name] = {\r\n name: attr.name,\r\n type: attr.type,\r\n index: location,\r\n };\r\n }\r\n\r\n return attributes;\r\n}\r\n\r\nfunction findUniforms(gl, program) {\r\n var uniformsByName = {};\r\n var uniforms = [];\r\n var samplerUniforms = [];\r\n\r\n var numberOfUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);\r\n\r\n for (var i = 0; i < numberOfUniforms; ++i) {\r\n var activeUniform = gl.getActiveUniform(program, i);\r\n var suffix = \"[0]\";\r\n var uniformName =\r\n activeUniform.name.indexOf(\r\n suffix,\r\n activeUniform.name.length - suffix.length\r\n ) !== -1\r\n ? activeUniform.name.slice(0, activeUniform.name.length - 3)\r\n : activeUniform.name;\r\n\r\n // Ignore GLSL built-in uniforms returned in Firefox.\r\n if (uniformName.indexOf(\"gl_\") !== 0) {\r\n if (activeUniform.name.indexOf(\"[\") < 0) {\r\n // Single uniform\r\n var location = gl.getUniformLocation(program, uniformName);\r\n\r\n // IE 11.0.9 needs this check since getUniformLocation can return null\r\n // if the uniform is not active (e.g., it is optimized out). Looks like\r\n // getActiveUniform() above returns uniforms that are not actually active.\r\n if (location !== null) {\r\n var uniform = createUniform(gl, activeUniform, uniformName, location);\r\n\r\n uniformsByName[uniformName] = uniform;\r\n uniforms.push(uniform);\r\n\r\n if (uniform._setSampler) {\r\n samplerUniforms.push(uniform);\r\n }\r\n }\r\n } else {\r\n // Uniform array\r\n\r\n var uniformArray;\r\n var locations;\r\n var value;\r\n var loc;\r\n\r\n // On some platforms - Nexus 4 in Firefox for one - an array of sampler2D ends up being represented\r\n // as separate uniforms, one for each array element. Check for and handle that case.\r\n var indexOfBracket = uniformName.indexOf(\"[\");\r\n if (indexOfBracket >= 0) {\r\n // We're assuming the array elements show up in numerical order - it seems to be true.\r\n uniformArray = uniformsByName[uniformName.slice(0, indexOfBracket)];\r\n\r\n // Nexus 4 with Android 4.3 needs this check, because it reports a uniform\r\n // with the strange name webgl_3467e0265d05c3c1[1] in our globe surface shader.\r\n if (!defined(uniformArray)) {\r\n continue;\r\n }\r\n\r\n locations = uniformArray._locations;\r\n\r\n // On the Nexus 4 in Chrome, we get one uniform per sampler, just like in Firefox,\r\n // but the size is not 1 like it is in Firefox. So if we push locations here,\r\n // we'll end up adding too many locations.\r\n if (locations.length <= 1) {\r\n value = uniformArray.value;\r\n loc = gl.getUniformLocation(program, uniformName);\r\n\r\n // Workaround for IE 11.0.9. See above.\r\n if (loc !== null) {\r\n locations.push(loc);\r\n value.push(gl.getUniform(program, loc));\r\n }\r\n }\r\n } else {\r\n locations = [];\r\n for (var j = 0; j < activeUniform.size; ++j) {\r\n loc = gl.getUniformLocation(program, uniformName + \"[\" + j + \"]\");\r\n\r\n // Workaround for IE 11.0.9. See above.\r\n if (loc !== null) {\r\n locations.push(loc);\r\n }\r\n }\r\n uniformArray = createUniformArray(\r\n gl,\r\n activeUniform,\r\n uniformName,\r\n locations\r\n );\r\n\r\n uniformsByName[uniformName] = uniformArray;\r\n uniforms.push(uniformArray);\r\n\r\n if (uniformArray._setSampler) {\r\n samplerUniforms.push(uniformArray);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n uniformsByName: uniformsByName,\r\n uniforms: uniforms,\r\n samplerUniforms: samplerUniforms,\r\n };\r\n}\r\n\r\nfunction partitionUniforms(shader, uniforms) {\r\n var automaticUniforms = [];\r\n var manualUniforms = [];\r\n\r\n for (var uniform in uniforms) {\r\n if (uniforms.hasOwnProperty(uniform)) {\r\n var uniformObject = uniforms[uniform];\r\n var uniformName = uniform;\r\n // if it's a duplicate uniform, use its original name so it is updated correctly\r\n var duplicateUniform = shader._duplicateUniformNames[uniformName];\r\n if (defined(duplicateUniform)) {\r\n uniformObject.name = duplicateUniform;\r\n uniformName = duplicateUniform;\r\n }\r\n var automaticUniform = AutomaticUniforms[uniformName];\r\n if (defined(automaticUniform)) {\r\n automaticUniforms.push({\r\n uniform: uniformObject,\r\n automaticUniform: automaticUniform,\r\n });\r\n } else {\r\n manualUniforms.push(uniformObject);\r\n }\r\n }\r\n }\r\n\r\n return {\r\n automaticUniforms: automaticUniforms,\r\n manualUniforms: manualUniforms,\r\n };\r\n}\r\n\r\nfunction setSamplerUniforms(gl, program, samplerUniforms) {\r\n gl.useProgram(program);\r\n\r\n var textureUnitIndex = 0;\r\n var length = samplerUniforms.length;\r\n for (var i = 0; i < length; ++i) {\r\n textureUnitIndex = samplerUniforms[i]._setSampler(textureUnitIndex);\r\n }\r\n\r\n gl.useProgram(null);\r\n\r\n return textureUnitIndex;\r\n}\r\n\r\nfunction initialize(shader) {\r\n if (defined(shader._program)) {\r\n return;\r\n }\r\n\r\n reinitialize(shader);\r\n}\r\n\r\nfunction reinitialize(shader) {\r\n var oldProgram = shader._program;\r\n\r\n var gl = shader._gl;\r\n var program = createAndLinkProgram(gl, shader, shader._debugShaders);\r\n var numberOfVertexAttributes = gl.getProgramParameter(\r\n program,\r\n gl.ACTIVE_ATTRIBUTES\r\n );\r\n var uniforms = findUniforms(gl, program);\r\n var partitionedUniforms = partitionUniforms(shader, uniforms.uniformsByName);\r\n\r\n shader._program = program;\r\n shader._numberOfVertexAttributes = numberOfVertexAttributes;\r\n shader._vertexAttributes = findVertexAttributes(\r\n gl,\r\n program,\r\n numberOfVertexAttributes\r\n );\r\n shader._uniformsByName = uniforms.uniformsByName;\r\n shader._uniforms = uniforms.uniforms;\r\n shader._automaticUniforms = partitionedUniforms.automaticUniforms;\r\n shader._manualUniforms = partitionedUniforms.manualUniforms;\r\n\r\n shader.maximumTextureUnitIndex = setSamplerUniforms(\r\n gl,\r\n program,\r\n uniforms.samplerUniforms\r\n );\r\n\r\n if (oldProgram) {\r\n shader._gl.deleteProgram(oldProgram);\r\n }\r\n\r\n // If SpectorJS is active, add the hook to make the shader editor work.\r\n // https://github.com/BabylonJS/Spector.js/blob/master/documentation/extension.md#shader-editor\r\n if (typeof spector !== \"undefined\") {\r\n shader._program.__SPECTOR_rebuildProgram = function (\r\n vertexSourceCode, // The new vertex shader source\r\n fragmentSourceCode, // The new fragment shader source\r\n onCompiled, // Callback triggered by your engine when the compilation is successful. It needs to send back the new linked program.\r\n onError // Callback triggered by your engine in case of error. It needs to send the WebGL error to allow the editor to display the error in the gutter.\r\n ) {\r\n var originalVS = shader._vertexShaderText;\r\n var originalFS = shader._fragmentShaderText;\r\n\r\n // SpectorJS likes to replace `!=` with `! =` for unknown reasons,\r\n // and that causes glsl compile failures. So fix that up.\r\n var regex = / ! = /g;\r\n shader._vertexShaderText = vertexSourceCode.replace(regex, \" != \");\r\n shader._fragmentShaderText = fragmentSourceCode.replace(regex, \" != \");\r\n\r\n try {\r\n reinitialize(shader);\r\n onCompiled(shader._program);\r\n } catch (e) {\r\n shader._vertexShaderText = originalVS;\r\n shader._fragmentShaderText = originalFS;\r\n\r\n // Only pass on the WebGL error:\r\n var errorMatcher = /(?:Compile|Link) error: ([^]*)/;\r\n var match = errorMatcher.exec(e.message);\r\n if (match) {\r\n onError(match[1]);\r\n } else {\r\n onError(e.message);\r\n }\r\n }\r\n };\r\n }\r\n}\r\n\r\nShaderProgram.prototype._bind = function () {\r\n initialize(this);\r\n this._gl.useProgram(this._program);\r\n};\r\n\r\nShaderProgram.prototype._setUniforms = function (\r\n uniformMap,\r\n uniformState,\r\n validate\r\n) {\r\n var len;\r\n var i;\r\n\r\n if (defined(uniformMap)) {\r\n var manualUniforms = this._manualUniforms;\r\n len = manualUniforms.length;\r\n for (i = 0; i < len; ++i) {\r\n var mu = manualUniforms[i];\r\n mu.value = uniformMap[mu.name]();\r\n }\r\n }\r\n\r\n var automaticUniforms = this._automaticUniforms;\r\n len = automaticUniforms.length;\r\n for (i = 0; i < len; ++i) {\r\n var au = automaticUniforms[i];\r\n au.uniform.value = au.automaticUniform.getValue(uniformState);\r\n }\r\n\r\n ///////////////////////////////////////////////////////////////////\r\n\r\n // It appears that assigning the uniform values above and then setting them here\r\n // (which makes the GL calls) is faster than removing this loop and making\r\n // the GL calls above. I suspect this is because each GL call pollutes the\r\n // L2 cache making our JavaScript and the browser/driver ping-pong cache lines.\r\n var uniforms = this._uniforms;\r\n len = uniforms.length;\r\n for (i = 0; i < len; ++i) {\r\n uniforms[i].set();\r\n }\r\n\r\n if (validate) {\r\n var gl = this._gl;\r\n var program = this._program;\r\n\r\n gl.validateProgram(program);\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) {\r\n throw new DeveloperError(\r\n \"Program validation failed. Program info log: \" +\r\n gl.getProgramInfoLog(program)\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n }\r\n};\r\n\r\nShaderProgram.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nShaderProgram.prototype.destroy = function () {\r\n this._cachedShader.cache.releaseShaderProgram(this);\r\n return undefined;\r\n};\r\n\r\nShaderProgram.prototype.finalDestroy = function () {\r\n this._gl.deleteProgram(this._program);\r\n return destroyObject(this);\r\n};\r\nexport default ShaderProgram;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\n\r\n/**\r\n * A function to port GLSL shaders from GLSL ES 1.00 to GLSL ES 3.00\r\n *\r\n * This function is nowhere near comprehensive or complete. It just\r\n * handles some common cases.\r\n *\r\n * Note that this function requires the presence of the\r\n * \"#define OUTPUT_DECLARATION\" line that is appended\r\n * by ShaderSource.\r\n *\r\n * @private\r\n */\r\nfunction modernizeShader(source, isFragmentShader) {\r\n var outputDeclarationRegex = /#define OUTPUT_DECLARATION/;\r\n var splitSource = source.split(\"\\n\");\r\n\r\n if (/#version 300 es/g.test(source)) {\r\n return source;\r\n }\r\n\r\n var outputDeclarationLine = -1;\r\n var i, line;\r\n for (i = 0; i < splitSource.length; ++i) {\r\n line = splitSource[i];\r\n if (outputDeclarationRegex.test(line)) {\r\n outputDeclarationLine = i;\r\n break;\r\n }\r\n }\r\n\r\n if (outputDeclarationLine === -1) {\r\n throw new DeveloperError(\"Could not find a #define OUTPUT_DECLARATION!\");\r\n }\r\n\r\n var outputVariables = [];\r\n\r\n for (i = 0; i < 10; i++) {\r\n var fragDataString = \"gl_FragData\\\\[\" + i + \"\\\\]\";\r\n var newOutput = \"czm_out\" + i;\r\n var regex = new RegExp(fragDataString, \"g\");\r\n if (regex.test(source)) {\r\n setAdd(newOutput, outputVariables);\r\n replaceInSourceString(fragDataString, newOutput, splitSource);\r\n splitSource.splice(\r\n outputDeclarationLine,\r\n 0,\r\n \"layout(location = \" + i + \") out vec4 \" + newOutput + \";\"\r\n );\r\n outputDeclarationLine += 1;\r\n }\r\n }\r\n\r\n var czmFragColor = \"czm_fragColor\";\r\n if (findInSource(\"gl_FragColor\", splitSource)) {\r\n setAdd(czmFragColor, outputVariables);\r\n replaceInSourceString(\"gl_FragColor\", czmFragColor, splitSource);\r\n splitSource.splice(\r\n outputDeclarationLine,\r\n 0,\r\n \"layout(location = 0) out vec4 czm_fragColor;\"\r\n );\r\n outputDeclarationLine += 1;\r\n }\r\n\r\n var variableMap = getVariablePreprocessorBranch(outputVariables, splitSource);\r\n var lineAdds = {};\r\n for (i = 0; i < splitSource.length; i++) {\r\n line = splitSource[i];\r\n for (var variable in variableMap) {\r\n if (variableMap.hasOwnProperty(variable)) {\r\n var matchVar = new RegExp(\r\n \"(layout)[^]+(out)[^]+(\" + variable + \")[^]+\",\r\n \"g\"\r\n );\r\n if (matchVar.test(line)) {\r\n lineAdds[line] = variable;\r\n }\r\n }\r\n }\r\n }\r\n\r\n for (var layoutDeclaration in lineAdds) {\r\n if (lineAdds.hasOwnProperty(layoutDeclaration)) {\r\n var variableName = lineAdds[layoutDeclaration];\r\n var lineNumber = splitSource.indexOf(layoutDeclaration);\r\n var entry = variableMap[variableName];\r\n var depth = entry.length;\r\n var d;\r\n for (d = 0; d < depth; d++) {\r\n splitSource.splice(lineNumber, 0, entry[d]);\r\n }\r\n lineNumber += depth + 1;\r\n for (d = depth - 1; d >= 0; d--) {\r\n splitSource.splice(lineNumber, 0, \"#endif //\" + entry[d]);\r\n }\r\n }\r\n }\r\n\r\n var webgl2UniqueID = \"WEBGL_2\";\r\n var webgl2DefineMacro = \"#define \" + webgl2UniqueID;\r\n var versionThree = \"#version 300 es\";\r\n var foundVersion = false;\r\n for (i = 0; i < splitSource.length; i++) {\r\n if (/#version/.test(splitSource[i])) {\r\n splitSource[i] = versionThree;\r\n foundVersion = true;\r\n break;\r\n }\r\n }\r\n\r\n if (!foundVersion) {\r\n splitSource.splice(0, 0, versionThree);\r\n }\r\n\r\n splitSource.splice(1, 0, webgl2DefineMacro);\r\n\r\n removeExtension(\"EXT_draw_buffers\", webgl2UniqueID, splitSource);\r\n removeExtension(\"EXT_frag_depth\", webgl2UniqueID, splitSource);\r\n removeExtension(\"OES_standard_derivatives\", webgl2UniqueID, splitSource);\r\n\r\n replaceInSourceString(\"texture2D\", \"texture\", splitSource);\r\n replaceInSourceString(\"texture3D\", \"texture\", splitSource);\r\n replaceInSourceString(\"textureCube\", \"texture\", splitSource);\r\n replaceInSourceString(\"gl_FragDepthEXT\", \"gl_FragDepth\", splitSource);\r\n\r\n if (isFragmentShader) {\r\n replaceInSourceString(\"varying\", \"in\", splitSource);\r\n } else {\r\n replaceInSourceString(\"attribute\", \"in\", splitSource);\r\n replaceInSourceString(\"varying\", \"out\", splitSource);\r\n }\r\n\r\n return compileSource(splitSource);\r\n}\r\n\r\n// Note that this fails if your string looks like\r\n// searchString[singleCharacter]searchString\r\nfunction replaceInSourceString(str, replacement, splitSource) {\r\n var regexStr = \"(^|[^\\\\w])(\" + str + \")($|[^\\\\w])\";\r\n var regex = new RegExp(regexStr, \"g\");\r\n\r\n var splitSourceLength = splitSource.length;\r\n for (var i = 0; i < splitSourceLength; ++i) {\r\n var line = splitSource[i];\r\n splitSource[i] = line.replace(regex, \"$1\" + replacement + \"$3\");\r\n }\r\n}\r\n\r\nfunction replaceInSourceRegex(regex, replacement, splitSource) {\r\n var splitSourceLength = splitSource.length;\r\n for (var i = 0; i < splitSourceLength; ++i) {\r\n var line = splitSource[i];\r\n splitSource[i] = line.replace(regex, replacement);\r\n }\r\n}\r\n\r\nfunction findInSource(str, splitSource) {\r\n var regexStr = \"(^|[^\\\\w])(\" + str + \")($|[^\\\\w])\";\r\n var regex = new RegExp(regexStr, \"g\");\r\n\r\n var splitSourceLength = splitSource.length;\r\n for (var i = 0; i < splitSourceLength; ++i) {\r\n var line = splitSource[i];\r\n if (regex.test(line)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nfunction compileSource(splitSource) {\r\n var wholeSource = \"\";\r\n\r\n var splitSourceLength = splitSource.length;\r\n for (var i = 0; i < splitSourceLength; ++i) {\r\n wholeSource += splitSource[i] + \"\\n\";\r\n }\r\n return wholeSource;\r\n}\r\n\r\nfunction setAdd(variable, set) {\r\n if (set.indexOf(variable) === -1) {\r\n set.push(variable);\r\n }\r\n}\r\n\r\nfunction getVariablePreprocessorBranch(layoutVariables, splitSource) {\r\n var variableMap = {};\r\n\r\n var numLayoutVariables = layoutVariables.length;\r\n\r\n var stack = [];\r\n for (var i = 0; i < splitSource.length; ++i) {\r\n var line = splitSource[i];\r\n var hasIF = /(#ifdef|#if)/g.test(line);\r\n var hasELSE = /#else/g.test(line);\r\n var hasENDIF = /#endif/g.test(line);\r\n\r\n if (hasIF) {\r\n stack.push(line);\r\n } else if (hasELSE) {\r\n var top = stack[stack.length - 1];\r\n var op = top.replace(\"ifdef\", \"ifndef\");\r\n if (/if/g.test(op)) {\r\n op = op.replace(/(#if\\s+)(\\S*)([^]*)/, \"$1!($2)$3\");\r\n }\r\n stack.pop();\r\n stack.push(op);\r\n } else if (hasENDIF) {\r\n stack.pop();\r\n } else if (!/layout/g.test(line)) {\r\n for (var varIndex = 0; varIndex < numLayoutVariables; ++varIndex) {\r\n var varName = layoutVariables[varIndex];\r\n if (line.indexOf(varName) !== -1) {\r\n if (!defined(variableMap[varName])) {\r\n variableMap[varName] = stack.slice();\r\n } else {\r\n variableMap[varName] = variableMap[varName].filter(function (x) {\r\n return stack.indexOf(x) >= 0;\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return variableMap;\r\n}\r\n\r\nfunction removeExtension(name, webgl2UniqueID, splitSource) {\r\n var regex = \"#extension\\\\s+GL_\" + name + \"\\\\s+:\\\\s+[a-zA-Z0-9]+\\\\s*$\";\r\n replaceInSourceRegex(new RegExp(regex, \"g\"), \"\", splitSource);\r\n\r\n // replace any possible directive #ifdef (GL_EXT_extension) with WEBGL_2 unique directive\r\n replaceInSourceString(\"GL_\" + name, webgl2UniqueID, splitSource);\r\n}\r\nexport default modernizeShader;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_degreesPerRadian = 57.29577951308232;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const czm_depthRangeStruct czm_depthRange = czm_depthRangeStruct(0.0, 1.0);\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_epsilon1 = 0.1;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_epsilon2 = 0.01;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_epsilon3 = 0.001;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_epsilon4 = 0.0001;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_epsilon5 = 0.00001;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_epsilon6 = 0.000001;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_epsilon7 = 0.0000001;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_infinity = 5906376272000.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_oneOverPi = 0.3183098861837907;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_oneOverTwoPi = 0.15915494309189535;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passCesium3DTile = 4.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passCesium3DTileClassification = 5.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passCesium3DTileClassificationIgnoreShow = 6.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passClassification = 7.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passCompute = 1.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passEnvironment = 0.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passGlobe = 2.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passOpaque = 7.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passOverlay = 9.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passTerrainClassification = 3.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_passTranslucent = 8.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_pi = 3.141592653589793;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_piOverFour = 0.7853981633974483;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_piOverSix = 0.5235987755982988;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_piOverThree = 1.0471975511965976;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_piOverTwo = 1.5707963267948966;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_radiansPerDegree = 0.017453292519943295;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_sceneMode2D = 2.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_sceneMode3D = 3.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_sceneModeColumbusView = 1.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_sceneModeMorphing = 0.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_solarRadius = 695500000.0;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_threePiOver2 = 4.71238898038469;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_twoPi = 6.283185307179586;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const float czm_webMercatorMaxLatitude = 1.4844222297453324;\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"struct czm_depthRangeStruct\\n\\\n{\\n\\\nfloat near;\\n\\\nfloat far;\\n\\\n};\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"struct czm_material\\n\\\n{\\n\\\nvec3 diffuse;\\n\\\nfloat specular;\\n\\\nfloat shininess;\\n\\\nvec3 normal;\\n\\\nvec3 emission;\\n\\\nfloat alpha;\\n\\\n};\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"struct czm_materialInput\\n\\\n{\\n\\\nfloat s;\\n\\\nvec2 st;\\n\\\nvec3 str;\\n\\\nvec3 normalEC;\\n\\\nmat3 tangentToEyeMatrix;\\n\\\nvec3 positionToEyeEC;\\n\\\nfloat height;\\n\\\nfloat slope;\\n\\\nfloat aspect;\\n\\\n};\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"struct czm_ray\\n\\\n{\\n\\\nvec3 origin;\\n\\\nvec3 direction;\\n\\\n};\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"struct czm_raySegment\\n\\\n{\\n\\\nfloat start;\\n\\\nfloat stop;\\n\\\n};\\n\\\nconst czm_raySegment czm_emptyRaySegment = czm_raySegment(-czm_infinity, -czm_infinity);\\n\\\nconst czm_raySegment czm_fullRaySegment = czm_raySegment(0.0, czm_infinity);\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"struct czm_shadowParameters\\n\\\n{\\n\\\n#ifdef USE_CUBE_MAP_SHADOW\\n\\\nvec3 texCoords;\\n\\\n#else\\n\\\nvec2 texCoords;\\n\\\n#endif\\n\\\nfloat depthBias;\\n\\\nfloat depth;\\n\\\nfloat nDotL;\\n\\\nvec2 texelStepSize;\\n\\\nfloat normalShadingSmooth;\\n\\\nfloat darkness;\\n\\\n};\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_acesTonemapping(vec3 color) {\\n\\\nfloat g = 0.985;\\n\\\nfloat a = 0.065;\\n\\\nfloat b = 0.0001;\\n\\\nfloat c = 0.433;\\n\\\nfloat d = 0.238;\\n\\\ncolor = (color * (color + a) - b) / (color * (g * color + c) + d);\\n\\\ncolor = clamp(color, 0.0, 1.0);\\n\\\nreturn color;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_alphaWeight(float a)\\n\\\n{\\n\\\nfloat z = (gl_FragCoord.z - czm_viewportTransformation[3][2]) / czm_viewportTransformation[2][2];\\n\\\nreturn pow(a + 0.01, 4.0) + max(1e-2, min(3.0 * 1e3, 0.003 / (1e-5 + pow(abs(z) / 200.0, 4.0))));\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_antialias(vec4 color1, vec4 color2, vec4 currentColor, float dist, float fuzzFactor)\\n\\\n{\\n\\\nfloat val1 = clamp(dist / fuzzFactor, 0.0, 1.0);\\n\\\nfloat val2 = clamp((dist - 0.5) / fuzzFactor, 0.0, 1.0);\\n\\\nval1 = val1 * (1.0 - val2);\\n\\\nval1 = val1 * val1 * (3.0 - (2.0 * val1));\\n\\\nval1 = pow(val1, 0.5);\\n\\\nvec4 midColor = (color1 + color2) * 0.5;\\n\\\nreturn mix(midColor, currentColor, val1);\\n\\\n}\\n\\\nvec4 czm_antialias(vec4 color1, vec4 color2, vec4 currentColor, float dist)\\n\\\n{\\n\\\nreturn czm_antialias(color1, color2, currentColor, dist, 0.1);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec2 czm_approximateSphericalCoordinates(vec3 normal) {\\n\\\nfloat latitudeApproximation = czm_fastApproximateAtan(sqrt(normal.x * normal.x + normal.y * normal.y), normal.z);\\n\\\nfloat longitudeApproximation = czm_fastApproximateAtan(normal.x, normal.y);\\n\\\nreturn vec2(latitudeApproximation, longitudeApproximation);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"bool czm_backFacing()\\n\\\n{\\n\\\nreturn gl_FrontFacing == false;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_branchFreeTernary(bool comparison, float a, float b) {\\n\\\nfloat useA = float(comparison);\\n\\\nreturn a * useA + b * (1.0 - useA);\\n\\\n}\\n\\\nvec2 czm_branchFreeTernary(bool comparison, vec2 a, vec2 b) {\\n\\\nfloat useA = float(comparison);\\n\\\nreturn a * useA + b * (1.0 - useA);\\n\\\n}\\n\\\nvec3 czm_branchFreeTernary(bool comparison, vec3 a, vec3 b) {\\n\\\nfloat useA = float(comparison);\\n\\\nreturn a * useA + b * (1.0 - useA);\\n\\\n}\\n\\\nvec4 czm_branchFreeTernary(bool comparison, vec4 a, vec4 b) {\\n\\\nfloat useA = float(comparison);\\n\\\nreturn a * useA + b * (1.0 - useA);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_cascadeColor(vec4 weights)\\n\\\n{\\n\\\nreturn vec4(1.0, 0.0, 0.0, 1.0) * weights.x +\\n\\\nvec4(0.0, 1.0, 0.0, 1.0) * weights.y +\\n\\\nvec4(0.0, 0.0, 1.0, 1.0) * weights.z +\\n\\\nvec4(1.0, 0.0, 1.0, 1.0) * weights.w;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 shadowMap_cascadeDistances;\\n\\\nfloat czm_cascadeDistance(vec4 weights)\\n\\\n{\\n\\\nreturn dot(shadowMap_cascadeDistances, weights);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform mat4 shadowMap_cascadeMatrices[4];\\n\\\nmat4 czm_cascadeMatrix(vec4 weights)\\n\\\n{\\n\\\nreturn shadowMap_cascadeMatrices[0] * weights.x +\\n\\\nshadowMap_cascadeMatrices[1] * weights.y +\\n\\\nshadowMap_cascadeMatrices[2] * weights.z +\\n\\\nshadowMap_cascadeMatrices[3] * weights.w;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform vec4 shadowMap_cascadeSplits[2];\\n\\\nvec4 czm_cascadeWeights(float depthEye)\\n\\\n{\\n\\\nvec4 near = step(shadowMap_cascadeSplits[0], vec4(depthEye));\\n\\\nvec4 far = step(depthEye, shadowMap_cascadeSplits[1]);\\n\\\nreturn near * far;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_columbusViewMorph(vec4 position2D, vec4 position3D, float time)\\n\\\n{\\n\\\nvec3 p = mix(position2D.xyz, position3D.xyz, time);\\n\\\nreturn vec4(p, 1.0);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_computePosition();\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec2 cordic(float angle)\\n\\\n{\\n\\\nvec2 vector = vec2(6.0725293500888267e-1, 0.0);\\n\\\nfloat sense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nmat2 rotation = mat2(1.0, sense, -sense, 1.0);\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 7.8539816339744828e-1;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfloat factor = sense * 5.0e-1;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 4.6364760900080609e-1;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 2.5e-1;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 2.4497866312686414e-1;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 1.25e-1;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 1.2435499454676144e-1;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 6.25e-2;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 6.2418809995957350e-2;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 3.125e-2;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 3.1239833430268277e-2;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 1.5625e-2;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 1.5623728620476831e-2;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 7.8125e-3;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 7.8123410601011111e-3;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 3.90625e-3;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 3.9062301319669718e-3;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 1.953125e-3;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 1.9531225164788188e-3;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 9.765625e-4;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 9.7656218955931946e-4;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 4.8828125e-4;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 4.8828121119489829e-4;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 2.44140625e-4;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 2.4414062014936177e-4;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 1.220703125e-4;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 1.2207031189367021e-4;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 6.103515625e-5;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 6.1035156174208773e-5;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 3.0517578125e-5;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 3.0517578115526096e-5;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 1.52587890625e-5;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 1.5258789061315762e-5;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 7.62939453125e-6;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 7.6293945311019700e-6;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 3.814697265625e-6;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 3.8146972656064961e-6;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 1.9073486328125e-6;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 1.9073486328101870e-6;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 9.5367431640625e-7;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 9.5367431640596084e-7;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 4.76837158203125e-7;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 4.7683715820308884e-7;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 2.384185791015625e-7;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nangle -= sense * 2.3841857910155797e-7;\\n\\\nsense = (angle < 0.0) ? -1.0 : 1.0;\\n\\\nfactor = sense * 1.1920928955078125e-7;\\n\\\nrotation[0][1] = factor;\\n\\\nrotation[1][0] = -factor;\\n\\\nvector = rotation * vector;\\n\\\nreturn vector;\\n\\\n}\\n\\\nvec2 czm_cosineAndSine(float angle)\\n\\\n{\\n\\\nif (angle < -czm_piOverTwo || angle > czm_piOverTwo)\\n\\\n{\\n\\\nif (angle < 0.0)\\n\\\n{\\n\\\nreturn -cordic(angle + czm_pi);\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nreturn -cordic(angle - czm_pi);\\n\\\n}\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nreturn cordic(angle);\\n\\\n}\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec2 czm_decompressTextureCoordinates(float encoded)\\n\\\n{\\n\\\nfloat temp = encoded / 4096.0;\\n\\\nfloat xZeroTo4095 = floor(temp);\\n\\\nfloat stx = xZeroTo4095 / 4095.0;\\n\\\nfloat sty = (encoded - xZeroTo4095 * 4096.0) / 4095.0;\\n\\\nreturn vec2(stx, sty);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#if defined(GL_EXT_frag_depth) && !defined(LOG_DEPTH)\\n\\\nvarying float v_WindowZ;\\n\\\n#endif\\n\\\nvec4 czm_depthClamp(vec4 coords)\\n\\\n{\\n\\\n#ifndef LOG_DEPTH\\n\\\n#ifdef GL_EXT_frag_depth\\n\\\nv_WindowZ = (0.5 * (coords.z / coords.w) + 0.5) * coords.w;\\n\\\ncoords.z = 0.0;\\n\\\n#else\\n\\\ncoords.z = min(coords.z, coords.w);\\n\\\n#endif\\n\\\n#endif\\n\\\nreturn coords;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"mat3 czm_eastNorthUpToEyeCoordinates(vec3 positionMC, vec3 normalEC)\\n\\\n{\\n\\\nvec3 tangentMC = normalize(vec3(-positionMC.y, positionMC.x, 0.0));\\n\\\nvec3 tangentEC = normalize(czm_normal3D * tangentMC);\\n\\\nvec3 bitangentEC = normalize(cross(normalEC, tangentEC));\\n\\\nreturn mat3(\\n\\\ntangentEC.x, tangentEC.y, tangentEC.z,\\n\\\nbitangentEC.x, bitangentEC.y, bitangentEC.z,\\n\\\nnormalEC.x, normalEC.y, normalEC.z);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"bool czm_ellipsoidContainsPoint(vec3 ellipsoid_inverseRadii, vec3 point)\\n\\\n{\\n\\\nvec3 scaled = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(point, 1.0)).xyz;\\n\\\nreturn (dot(scaled, scaled) <= 1.0);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec2 czm_ellipsoidWgs84TextureCoordinates(vec3 normal)\\n\\\n{\\n\\\nreturn vec2(atan(normal.y, normal.x) * czm_oneOverTwoPi + 0.5, asin(normal.z) * czm_oneOverPi + 0.5);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"bool czm_equalsEpsilon(vec4 left, vec4 right, float epsilon) {\\n\\\nreturn all(lessThanEqual(abs(left - right), vec4(epsilon)));\\n\\\n}\\n\\\nbool czm_equalsEpsilon(vec3 left, vec3 right, float epsilon) {\\n\\\nreturn all(lessThanEqual(abs(left - right), vec3(epsilon)));\\n\\\n}\\n\\\nbool czm_equalsEpsilon(vec2 left, vec2 right, float epsilon) {\\n\\\nreturn all(lessThanEqual(abs(left - right), vec2(epsilon)));\\n\\\n}\\n\\\nbool czm_equalsEpsilon(float left, float right, float epsilon) {\\n\\\nreturn (abs(left - right) <= epsilon);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_eyeOffset(vec4 positionEC, vec3 eyeOffset)\\n\\\n{\\n\\\nvec4 p = positionEC;\\n\\\nvec4 zEyeOffset = normalize(p) * eyeOffset.z;\\n\\\np.xy += eyeOffset.xy + zEyeOffset.xy;\\n\\\np.z += zEyeOffset.z;\\n\\\nreturn p;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_eyeToWindowCoordinates(vec4 positionEC)\\n\\\n{\\n\\\nvec4 q = czm_projection * positionEC;\\n\\\nq.xyz /= q.w;\\n\\\nq.xyz = (czm_viewportTransformation * vec4(q.xyz, 1.0)).xyz;\\n\\\nreturn q;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_fastApproximateAtan(float x) {\\n\\\nreturn x * (-0.1784 * x - 0.0663 * x * x + 1.0301);\\n\\\n}\\n\\\nfloat czm_fastApproximateAtan(float x, float y) {\\n\\\nfloat t = abs(x);\\n\\\nfloat opposite = abs(y);\\n\\\nfloat adjacent = max(t, opposite);\\n\\\nopposite = min(t, opposite);\\n\\\nt = czm_fastApproximateAtan(opposite / adjacent);\\n\\\nt = czm_branchFreeTernary(abs(y) > abs(x), czm_piOverTwo - t, t);\\n\\\nt = czm_branchFreeTernary(x < 0.0, czm_pi - t, t);\\n\\\nt = czm_branchFreeTernary(y < 0.0, -t, t);\\n\\\nreturn t;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_fog(float distanceToCamera, vec3 color, vec3 fogColor)\\n\\\n{\\n\\\nfloat scalar = distanceToCamera * czm_fogDensity;\\n\\\nfloat fog = 1.0 - exp(-(scalar * scalar));\\n\\\nreturn mix(color, fogColor, fog);\\n\\\n}\\n\\\nvec3 czm_fog(float distanceToCamera, vec3 color, vec3 fogColor, float fogModifierConstant)\\n\\\n{\\n\\\nfloat scalar = distanceToCamera * czm_fogDensity;\\n\\\nfloat fog = 1.0 - exp(-((fogModifierConstant * scalar + fogModifierConstant) * (scalar * (1.0 + fogModifierConstant))));\\n\\\nreturn mix(color, fogColor, fog);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_gammaCorrect(vec3 color) {\\n\\\n#ifdef HDR\\n\\\ncolor = pow(color, vec3(czm_gamma));\\n\\\n#endif\\n\\\nreturn color;\\n\\\n}\\n\\\nvec4 czm_gammaCorrect(vec4 color) {\\n\\\n#ifdef HDR\\n\\\ncolor.rgb = pow(color.rgb, vec3(czm_gamma));\\n\\\n#endif\\n\\\nreturn color;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_geodeticSurfaceNormal(vec3 positionOnEllipsoid, vec3 ellipsoidCenter, vec3 oneOverEllipsoidRadiiSquared)\\n\\\n{\\n\\\nreturn normalize((positionOnEllipsoid - ellipsoidCenter) * oneOverEllipsoidRadiiSquared);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"czm_material czm_getDefaultMaterial(czm_materialInput materialInput)\\n\\\n{\\n\\\nczm_material material;\\n\\\nmaterial.diffuse = vec3(0.0);\\n\\\nmaterial.specular = 0.0;\\n\\\nmaterial.shininess = 1.0;\\n\\\nmaterial.normal = materialInput.normalEC;\\n\\\nmaterial.emission = vec3(0.0);\\n\\\nmaterial.alpha = 1.0;\\n\\\nreturn material;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_getLambertDiffuse(vec3 lightDirectionEC, vec3 normalEC)\\n\\\n{\\n\\\nreturn max(dot(lightDirectionEC, normalEC), 0.0);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_getSpecular(vec3 lightDirectionEC, vec3 toEyeEC, vec3 normalEC, float shininess)\\n\\\n{\\n\\\nvec3 toReflectedLight = reflect(-lightDirectionEC, normalEC);\\n\\\nfloat specular = max(dot(toReflectedLight, toEyeEC), 0.0);\\n\\\nreturn pow(specular, max(shininess, czm_epsilon2));\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_getWaterNoise(sampler2D normalMap, vec2 uv, float time, float angleInRadians)\\n\\\n{\\n\\\nfloat cosAngle = cos(angleInRadians);\\n\\\nfloat sinAngle = sin(angleInRadians);\\n\\\nvec2 s0 = vec2(1.0/17.0, 0.0);\\n\\\nvec2 s1 = vec2(-1.0/29.0, 0.0);\\n\\\nvec2 s2 = vec2(1.0/101.0, 1.0/59.0);\\n\\\nvec2 s3 = vec2(-1.0/109.0, -1.0/57.0);\\n\\\ns0 = vec2((cosAngle * s0.x) - (sinAngle * s0.y), (sinAngle * s0.x) + (cosAngle * s0.y));\\n\\\ns1 = vec2((cosAngle * s1.x) - (sinAngle * s1.y), (sinAngle * s1.x) + (cosAngle * s1.y));\\n\\\ns2 = vec2((cosAngle * s2.x) - (sinAngle * s2.y), (sinAngle * s2.x) + (cosAngle * s2.y));\\n\\\ns3 = vec2((cosAngle * s3.x) - (sinAngle * s3.y), (sinAngle * s3.x) + (cosAngle * s3.y));\\n\\\nvec2 uv0 = (uv/103.0) + (time * s0);\\n\\\nvec2 uv1 = uv/107.0 + (time * s1) + vec2(0.23);\\n\\\nvec2 uv2 = uv/vec2(897.0, 983.0) + (time * s2) + vec2(0.51);\\n\\\nvec2 uv3 = uv/vec2(991.0, 877.0) + (time * s3) + vec2(0.71);\\n\\\nuv0 = fract(uv0);\\n\\\nuv1 = fract(uv1);\\n\\\nuv2 = fract(uv2);\\n\\\nuv3 = fract(uv3);\\n\\\nvec4 noise = (texture2D(normalMap, uv0)) +\\n\\\n(texture2D(normalMap, uv1)) +\\n\\\n(texture2D(normalMap, uv2)) +\\n\\\n(texture2D(normalMap, uv3));\\n\\\nreturn ((noise / 4.0) - 0.5) * 2.0;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const vec4 K_HSB2RGB = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\\n\\\nvec3 czm_HSBToRGB(vec3 hsb)\\n\\\n{\\n\\\nvec3 p = abs(fract(hsb.xxx + K_HSB2RGB.xyz) * 6.0 - K_HSB2RGB.www);\\n\\\nreturn hsb.z * mix(K_HSB2RGB.xxx, clamp(p - K_HSB2RGB.xxx, 0.0, 1.0), hsb.y);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 hueToRGB(float hue)\\n\\\n{\\n\\\nfloat r = abs(hue * 6.0 - 3.0) - 1.0;\\n\\\nfloat g = 2.0 - abs(hue * 6.0 - 2.0);\\n\\\nfloat b = 2.0 - abs(hue * 6.0 - 4.0);\\n\\\nreturn clamp(vec3(r, g, b), 0.0, 1.0);\\n\\\n}\\n\\\nvec3 czm_HSLToRGB(vec3 hsl)\\n\\\n{\\n\\\nvec3 rgb = hueToRGB(hsl.x);\\n\\\nfloat c = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;\\n\\\nreturn (rgb - 0.5) * c + hsl.z;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_hue(vec3 rgb, float adjustment)\\n\\\n{\\n\\\nconst mat3 toYIQ = mat3(0.299, 0.587, 0.114,\\n\\\n0.595716, -0.274453, -0.321263,\\n\\\n0.211456, -0.522591, 0.311135);\\n\\\nconst mat3 toRGB = mat3(1.0, 0.9563, 0.6210,\\n\\\n1.0, -0.2721, -0.6474,\\n\\\n1.0, -1.107, 1.7046);\\n\\\nvec3 yiq = toYIQ * rgb;\\n\\\nfloat hue = atan(yiq.z, yiq.y) + adjustment;\\n\\\nfloat chroma = sqrt(yiq.z * yiq.z + yiq.y * yiq.y);\\n\\\nvec3 color = vec3(yiq.x, chroma * cos(hue), chroma * sin(hue));\\n\\\nreturn toRGB * color;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_inverseGamma(vec3 color) {\\n\\\nreturn pow(color, vec3(1.0 / czm_gamma));\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"bool czm_isEmpty(czm_raySegment interval)\\n\\\n{\\n\\\nreturn (interval.stop < 0.0);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"bool czm_isFull(czm_raySegment interval)\\n\\\n{\\n\\\nreturn (interval.start == 0.0 && interval.stop == czm_infinity);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_latitudeToWebMercatorFraction(float latitude, float southMercatorY, float oneOverMercatorHeight)\\n\\\n{\\n\\\nfloat sinLatitude = sin(latitude);\\n\\\nfloat mercatorY = 0.5 * log((1.0 + sinLatitude) / (1.0 - sinLatitude));\\n\\\nreturn (mercatorY - southMercatorY) * oneOverMercatorHeight;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_lineDistance(vec2 point1, vec2 point2, vec2 point) {\\n\\\nreturn abs((point2.y - point1.y) * point.x - (point2.x - point1.x) * point.y + point2.x * point1.y - point2.y * point1.x) / distance(point2, point1);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_luminance(vec3 rgb)\\n\\\n{\\n\\\nconst vec3 W = vec3(0.2125, 0.7154, 0.0721);\\n\\\nreturn dot(rgb, W);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_metersPerPixel(vec4 positionEC, float pixelRatio)\\n\\\n{\\n\\\nfloat width = czm_viewport.z;\\n\\\nfloat height = czm_viewport.w;\\n\\\nfloat pixelWidth;\\n\\\nfloat pixelHeight;\\n\\\nfloat top = czm_frustumPlanes.x;\\n\\\nfloat bottom = czm_frustumPlanes.y;\\n\\\nfloat left = czm_frustumPlanes.z;\\n\\\nfloat right = czm_frustumPlanes.w;\\n\\\nif (czm_sceneMode == czm_sceneMode2D || czm_orthographicIn3D == 1.0)\\n\\\n{\\n\\\nfloat frustumWidth = right - left;\\n\\\nfloat frustumHeight = top - bottom;\\n\\\npixelWidth = frustumWidth / width;\\n\\\npixelHeight = frustumHeight / height;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nfloat distanceToPixel = -positionEC.z;\\n\\\nfloat inverseNear = 1.0 / czm_currentFrustum.x;\\n\\\nfloat tanTheta = top * inverseNear;\\n\\\npixelHeight = 2.0 * distanceToPixel * tanTheta / height;\\n\\\ntanTheta = right * inverseNear;\\n\\\npixelWidth = 2.0 * distanceToPixel * tanTheta / width;\\n\\\n}\\n\\\nreturn max(pixelWidth, pixelHeight) * pixelRatio;\\n\\\n}\\n\\\nfloat czm_metersPerPixel(vec4 positionEC)\\n\\\n{\\n\\\nreturn czm_metersPerPixel(positionEC, czm_pixelRatio);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_modelToWindowCoordinates(vec4 position)\\n\\\n{\\n\\\nvec4 q = czm_modelViewProjection * position;\\n\\\nq.xyz /= q.w;\\n\\\nq.xyz = (czm_viewportTransformation * vec4(q.xyz, 1.0)).xyz;\\n\\\nreturn q;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_multiplyWithColorBalance(vec3 left, vec3 right)\\n\\\n{\\n\\\nconst vec3 W = vec3(0.2125, 0.7154, 0.0721);\\n\\\nvec3 target = left * right;\\n\\\nfloat leftLuminance = dot(left, W);\\n\\\nfloat rightLuminance = dot(right, W);\\n\\\nfloat targetLuminance = dot(target, W);\\n\\\nreturn ((leftLuminance + rightLuminance) / (2.0 * targetLuminance)) * target;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_nearFarScalar(vec4 nearFarScalar, float cameraDistSq)\\n\\\n{\\n\\\nfloat valueAtMin = nearFarScalar.y;\\n\\\nfloat valueAtMax = nearFarScalar.w;\\n\\\nfloat nearDistanceSq = nearFarScalar.x * nearFarScalar.x;\\n\\\nfloat farDistanceSq = nearFarScalar.z * nearFarScalar.z;\\n\\\nfloat t = (cameraDistSq - nearDistanceSq) / (farDistanceSq - nearDistanceSq);\\n\\\nt = pow(clamp(t, 0.0, 1.0), 0.2);\\n\\\nreturn mix(valueAtMin, valueAtMax, t);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_octDecode(vec2 encoded, float range)\\n\\\n{\\n\\\nif (encoded.x == 0.0 && encoded.y == 0.0) {\\n\\\nreturn vec3(0.0, 0.0, 0.0);\\n\\\n}\\n\\\nencoded = encoded / range * 2.0 - 1.0;\\n\\\nvec3 v = vec3(encoded.x, encoded.y, 1.0 - abs(encoded.x) - abs(encoded.y));\\n\\\nif (v.z < 0.0)\\n\\\n{\\n\\\nv.xy = (1.0 - abs(v.yx)) * czm_signNotZero(v.xy);\\n\\\n}\\n\\\nreturn normalize(v);\\n\\\n}\\n\\\nvec3 czm_octDecode(vec2 encoded)\\n\\\n{\\n\\\nreturn czm_octDecode(encoded, 255.0);\\n\\\n}\\n\\\nvec3 czm_octDecode(float encoded)\\n\\\n{\\n\\\nfloat temp = encoded / 256.0;\\n\\\nfloat x = floor(temp);\\n\\\nfloat y = (temp - x) * 256.0;\\n\\\nreturn czm_octDecode(vec2(x, y));\\n\\\n}\\n\\\nvoid czm_octDecode(vec2 encoded, out vec3 vector1, out vec3 vector2, out vec3 vector3)\\n\\\n{\\n\\\nfloat temp = encoded.x / 65536.0;\\n\\\nfloat x = floor(temp);\\n\\\nfloat encodedFloat1 = (temp - x) * 65536.0;\\n\\\ntemp = encoded.y / 65536.0;\\n\\\nfloat y = floor(temp);\\n\\\nfloat encodedFloat2 = (temp - y) * 65536.0;\\n\\\nvector1 = czm_octDecode(encodedFloat1);\\n\\\nvector2 = czm_octDecode(encodedFloat2);\\n\\\nvector3 = czm_octDecode(vec2(x, y));\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_packDepth(float depth)\\n\\\n{\\n\\\nvec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * depth;\\n\\\nenc = fract(enc);\\n\\\nenc -= enc.yzww * vec4(1.0 / 255.0, 1.0 / 255.0, 1.0 / 255.0, 0.0);\\n\\\nreturn enc;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_private_getLambertDiffuseOfMaterial(vec3 lightDirectionEC, czm_material material)\\n\\\n{\\n\\\nreturn czm_getLambertDiffuse(lightDirectionEC, material.normal);\\n\\\n}\\n\\\nfloat czm_private_getSpecularOfMaterial(vec3 lightDirectionEC, vec3 toEyeEC, czm_material material)\\n\\\n{\\n\\\nreturn czm_getSpecular(lightDirectionEC, toEyeEC, material.normal, material.shininess);\\n\\\n}\\n\\\nvec4 czm_phong(vec3 toEye, czm_material material, vec3 lightDirectionEC)\\n\\\n{\\n\\\nfloat diffuse = czm_private_getLambertDiffuseOfMaterial(vec3(0.0, 0.0, 1.0), material);\\n\\\nif (czm_sceneMode == czm_sceneMode3D) {\\n\\\ndiffuse += czm_private_getLambertDiffuseOfMaterial(vec3(0.0, 1.0, 0.0), material);\\n\\\n}\\n\\\nfloat specular = czm_private_getSpecularOfMaterial(lightDirectionEC, toEye, material);\\n\\\nvec3 materialDiffuse = material.diffuse * 0.5;\\n\\\nvec3 ambient = materialDiffuse;\\n\\\nvec3 color = ambient + material.emission;\\n\\\ncolor += materialDiffuse * diffuse * czm_lightColor;\\n\\\ncolor += material.specular * specular * czm_lightColor;\\n\\\nreturn vec4(color, material.alpha);\\n\\\n}\\n\\\nvec4 czm_private_phong(vec3 toEye, czm_material material, vec3 lightDirectionEC)\\n\\\n{\\n\\\nfloat diffuse = czm_private_getLambertDiffuseOfMaterial(lightDirectionEC, material);\\n\\\nfloat specular = czm_private_getSpecularOfMaterial(lightDirectionEC, toEye, material);\\n\\\nvec3 ambient = vec3(0.0);\\n\\\nvec3 color = ambient + material.emission;\\n\\\ncolor += material.diffuse * diffuse * czm_lightColor;\\n\\\ncolor += material.specular * specular * czm_lightColor;\\n\\\nreturn vec4(color, material.alpha);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_planeDistance(vec4 plane, vec3 point) {\\n\\\nreturn (dot(plane.xyz, point) + plane.w);\\n\\\n}\\n\\\nfloat czm_planeDistance(vec3 planeNormal, float planeDistance, vec3 point) {\\n\\\nreturn (dot(planeNormal, point) + planeDistance);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_pointAlongRay(czm_ray ray, float time)\\n\\\n{\\n\\\nreturn ray.origin + (time * ray.direction);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"czm_raySegment czm_rayEllipsoidIntersectionInterval(czm_ray ray, vec3 ellipsoid_center, vec3 ellipsoid_inverseRadii)\\n\\\n{\\n\\\nvec3 q = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.origin, 1.0)).xyz;\\n\\\nvec3 w = ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ray.direction, 0.0)).xyz;\\n\\\nq = q - ellipsoid_inverseRadii * (czm_inverseModelView * vec4(ellipsoid_center, 1.0)).xyz;\\n\\\nfloat q2 = dot(q, q);\\n\\\nfloat qw = dot(q, w);\\n\\\nif (q2 > 1.0)\\n\\\n{\\n\\\nif (qw >= 0.0)\\n\\\n{\\n\\\nreturn czm_emptyRaySegment;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nfloat qw2 = qw * qw;\\n\\\nfloat difference = q2 - 1.0;\\n\\\nfloat w2 = dot(w, w);\\n\\\nfloat product = w2 * difference;\\n\\\nif (qw2 < product)\\n\\\n{\\n\\\nreturn czm_emptyRaySegment;\\n\\\n}\\n\\\nelse if (qw2 > product)\\n\\\n{\\n\\\nfloat discriminant = qw * qw - product;\\n\\\nfloat temp = -qw + sqrt(discriminant);\\n\\\nfloat root0 = temp / w2;\\n\\\nfloat root1 = difference / temp;\\n\\\nif (root0 < root1)\\n\\\n{\\n\\\nczm_raySegment i = czm_raySegment(root0, root1);\\n\\\nreturn i;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nczm_raySegment i = czm_raySegment(root1, root0);\\n\\\nreturn i;\\n\\\n}\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nfloat root = sqrt(difference / w2);\\n\\\nczm_raySegment i = czm_raySegment(root, root);\\n\\\nreturn i;\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\nelse if (q2 < 1.0)\\n\\\n{\\n\\\nfloat difference = q2 - 1.0;\\n\\\nfloat w2 = dot(w, w);\\n\\\nfloat product = w2 * difference;\\n\\\nfloat discriminant = qw * qw - product;\\n\\\nfloat temp = -qw + sqrt(discriminant);\\n\\\nczm_raySegment i = czm_raySegment(0.0, temp / w2);\\n\\\nreturn i;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nif (qw < 0.0)\\n\\\n{\\n\\\nfloat w2 = dot(w, w);\\n\\\nczm_raySegment i = czm_raySegment(0.0, -qw / w2);\\n\\\nreturn i;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nreturn czm_emptyRaySegment;\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_readDepth(sampler2D depthTexture, vec2 texCoords)\\n\\\n{\\n\\\nreturn czm_reverseLogDepth(texture2D(depthTexture, texCoords).r);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_readNonPerspective(float value, float oneOverW) {\\n\\\nreturn value * oneOverW;\\n\\\n}\\n\\\nvec2 czm_readNonPerspective(vec2 value, float oneOverW) {\\n\\\nreturn value * oneOverW;\\n\\\n}\\n\\\nvec3 czm_readNonPerspective(vec3 value, float oneOverW) {\\n\\\nreturn value * oneOverW;\\n\\\n}\\n\\\nvec4 czm_readNonPerspective(vec4 value, float oneOverW) {\\n\\\nreturn value * oneOverW;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_reverseLogDepth(float logZ)\\n\\\n{\\n\\\n#ifdef LOG_DEPTH\\n\\\nfloat near = czm_currentFrustum.x;\\n\\\nfloat far = czm_currentFrustum.y;\\n\\\nfloat log2Depth = logZ * czm_log2FarDepthFromNearPlusOne;\\n\\\nfloat depthFromNear = pow(2.0, log2Depth) - 1.0;\\n\\\nreturn far * (1.0 - near / (depthFromNear + near)) / (far - near);\\n\\\n#endif\\n\\\nreturn logZ;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"const vec4 K_RGB2HSB = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\\n\\\nvec3 czm_RGBToHSB(vec3 rgb)\\n\\\n{\\n\\\nvec4 p = mix(vec4(rgb.bg, K_RGB2HSB.wz), vec4(rgb.gb, K_RGB2HSB.xy), step(rgb.b, rgb.g));\\n\\\nvec4 q = mix(vec4(p.xyw, rgb.r), vec4(rgb.r, p.yzx), step(p.x, rgb.r));\\n\\\nfloat d = q.x - min(q.w, q.y);\\n\\\nreturn vec3(abs(q.z + (q.w - q.y) / (6.0 * d + czm_epsilon7)), d / (q.x + czm_epsilon7), q.x);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 RGBtoHCV(vec3 rgb)\\n\\\n{\\n\\\nvec4 p = (rgb.g < rgb.b) ? vec4(rgb.bg, -1.0, 2.0 / 3.0) : vec4(rgb.gb, 0.0, -1.0 / 3.0);\\n\\\nvec4 q = (rgb.r < p.x) ? vec4(p.xyw, rgb.r) : vec4(rgb.r, p.yzx);\\n\\\nfloat c = q.x - min(q.w, q.y);\\n\\\nfloat h = abs((q.w - q.y) / (6.0 * c + czm_epsilon7) + q.z);\\n\\\nreturn vec3(h, c, q.x);\\n\\\n}\\n\\\nvec3 czm_RGBToHSL(vec3 rgb)\\n\\\n{\\n\\\nvec3 hcv = RGBtoHCV(rgb);\\n\\\nfloat l = hcv.z - hcv.y * 0.5;\\n\\\nfloat s = hcv.y / (1.0 - abs(l * 2.0 - 1.0) + czm_epsilon7);\\n\\\nreturn vec3(hcv.x, s, l);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_RGBToXYZ(vec3 rgb)\\n\\\n{\\n\\\nconst mat3 RGB2XYZ = mat3(0.4124, 0.2126, 0.0193,\\n\\\n0.3576, 0.7152, 0.1192,\\n\\\n0.1805, 0.0722, 0.9505);\\n\\\nvec3 xyz = RGB2XYZ * rgb;\\n\\\nvec3 Yxy;\\n\\\nYxy.r = xyz.g;\\n\\\nfloat temp = dot(vec3(1.0), xyz);\\n\\\nYxy.gb = xyz.rg / temp;\\n\\\nreturn Yxy;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_sampleOctahedralProjectionWithFiltering(sampler2D projectedMap, vec2 textureSize, vec3 direction, float lod)\\n\\\n{\\n\\\ndirection /= dot(vec3(1.0), abs(direction));\\n\\\nvec2 rev = abs(direction.zx) - vec2(1.0);\\n\\\nvec2 neg = vec2(direction.x < 0.0 ? rev.x : -rev.x,\\n\\\ndirection.z < 0.0 ? rev.y : -rev.y);\\n\\\nvec2 uv = direction.y < 0.0 ? neg : direction.xz;\\n\\\nvec2 coord = 0.5 * uv + vec2(0.5);\\n\\\nvec2 pixel = 1.0 / textureSize;\\n\\\nif (lod > 0.0)\\n\\\n{\\n\\\nfloat scale = 1.0 / pow(2.0, lod);\\n\\\nfloat offset = ((textureSize.y + 1.0) / textureSize.x);\\n\\\ncoord.x *= offset;\\n\\\ncoord *= scale;\\n\\\ncoord.x += offset + pixel.x;\\n\\\ncoord.y += (1.0 - (1.0 / pow(2.0, lod - 1.0))) + pixel.y * (lod - 1.0) * 2.0;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\ncoord.x *= (textureSize.y / textureSize.x);\\n\\\n}\\n\\\n#ifndef OES_texture_float_linear\\n\\\nvec3 color1 = texture2D(projectedMap, coord + vec2(0.0, pixel.y)).rgb;\\n\\\nvec3 color2 = texture2D(projectedMap, coord + vec2(pixel.x, 0.0)).rgb;\\n\\\nvec3 color3 = texture2D(projectedMap, coord + pixel).rgb;\\n\\\nvec3 color4 = texture2D(projectedMap, coord).rgb;\\n\\\nvec2 texturePosition = coord * textureSize;\\n\\\nfloat fu = fract(texturePosition.x);\\n\\\nfloat fv = fract(texturePosition.y);\\n\\\nvec3 average1 = mix(color4, color2, fu);\\n\\\nvec3 average2 = mix(color1, color3, fu);\\n\\\nvec3 color = mix(average1, average2, fv);\\n\\\n#else\\n\\\nvec3 color = texture2D(projectedMap, coord).rgb;\\n\\\n#endif\\n\\\nreturn color;\\n\\\n}\\n\\\nvec3 czm_sampleOctahedralProjection(sampler2D projectedMap, vec2 textureSize, vec3 direction, float lod, float maxLod) {\\n\\\nfloat currentLod = floor(lod + 0.5);\\n\\\nfloat nextLod = min(currentLod + 1.0, maxLod);\\n\\\nvec3 colorCurrentLod = czm_sampleOctahedralProjectionWithFiltering(projectedMap, textureSize, direction, currentLod);\\n\\\nvec3 colorNextLod = czm_sampleOctahedralProjectionWithFiltering(projectedMap, textureSize, direction, nextLod);\\n\\\nreturn mix(colorNextLod, colorCurrentLod, nextLod - lod);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_saturation(vec3 rgb, float adjustment)\\n\\\n{\\n\\\nconst vec3 W = vec3(0.2125, 0.7154, 0.0721);\\n\\\nvec3 intensity = vec3(dot(rgb, W));\\n\\\nreturn mix(intensity, rgb, adjustment);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_sampleShadowMap(highp samplerCube shadowMap, vec3 d)\\n\\\n{\\n\\\nreturn czm_unpackDepth(textureCube(shadowMap, d));\\n\\\n}\\n\\\nfloat czm_sampleShadowMap(highp sampler2D shadowMap, vec2 uv)\\n\\\n{\\n\\\n#ifdef USE_SHADOW_DEPTH_TEXTURE\\n\\\nreturn texture2D(shadowMap, uv).r;\\n\\\n#else\\n\\\nreturn czm_unpackDepth(texture2D(shadowMap, uv));\\n\\\n#endif\\n\\\n}\\n\\\nfloat czm_shadowDepthCompare(samplerCube shadowMap, vec3 uv, float depth)\\n\\\n{\\n\\\nreturn step(depth, czm_sampleShadowMap(shadowMap, uv));\\n\\\n}\\n\\\nfloat czm_shadowDepthCompare(sampler2D shadowMap, vec2 uv, float depth)\\n\\\n{\\n\\\nreturn step(depth, czm_sampleShadowMap(shadowMap, uv));\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_private_shadowVisibility(float visibility, float nDotL, float normalShadingSmooth, float darkness)\\n\\\n{\\n\\\n#ifdef USE_NORMAL_SHADING\\n\\\n#ifdef USE_NORMAL_SHADING_SMOOTH\\n\\\nfloat strength = clamp(nDotL / normalShadingSmooth, 0.0, 1.0);\\n\\\n#else\\n\\\nfloat strength = step(0.0, nDotL);\\n\\\n#endif\\n\\\nvisibility *= strength;\\n\\\n#endif\\n\\\nvisibility = max(visibility, darkness);\\n\\\nreturn visibility;\\n\\\n}\\n\\\n#ifdef USE_CUBE_MAP_SHADOW\\n\\\nfloat czm_shadowVisibility(samplerCube shadowMap, czm_shadowParameters shadowParameters)\\n\\\n{\\n\\\nfloat depthBias = shadowParameters.depthBias;\\n\\\nfloat depth = shadowParameters.depth;\\n\\\nfloat nDotL = shadowParameters.nDotL;\\n\\\nfloat normalShadingSmooth = shadowParameters.normalShadingSmooth;\\n\\\nfloat darkness = shadowParameters.darkness;\\n\\\nvec3 uvw = shadowParameters.texCoords;\\n\\\ndepth -= depthBias;\\n\\\nfloat visibility = czm_shadowDepthCompare(shadowMap, uvw, depth);\\n\\\nreturn czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);\\n\\\n}\\n\\\n#else\\n\\\nfloat czm_shadowVisibility(sampler2D shadowMap, czm_shadowParameters shadowParameters)\\n\\\n{\\n\\\nfloat depthBias = shadowParameters.depthBias;\\n\\\nfloat depth = shadowParameters.depth;\\n\\\nfloat nDotL = shadowParameters.nDotL;\\n\\\nfloat normalShadingSmooth = shadowParameters.normalShadingSmooth;\\n\\\nfloat darkness = shadowParameters.darkness;\\n\\\nvec2 uv = shadowParameters.texCoords;\\n\\\ndepth -= depthBias;\\n\\\n#ifdef USE_SOFT_SHADOWS\\n\\\nvec2 texelStepSize = shadowParameters.texelStepSize;\\n\\\nfloat radius = 1.0;\\n\\\nfloat dx0 = -texelStepSize.x * radius;\\n\\\nfloat dy0 = -texelStepSize.y * radius;\\n\\\nfloat dx1 = texelStepSize.x * radius;\\n\\\nfloat dy1 = texelStepSize.y * radius;\\n\\\nfloat visibility = (\\n\\\nczm_shadowDepthCompare(shadowMap, uv, depth) +\\n\\\nczm_shadowDepthCompare(shadowMap, uv + vec2(dx0, dy0), depth) +\\n\\\nczm_shadowDepthCompare(shadowMap, uv + vec2(0.0, dy0), depth) +\\n\\\nczm_shadowDepthCompare(shadowMap, uv + vec2(dx1, dy0), depth) +\\n\\\nczm_shadowDepthCompare(shadowMap, uv + vec2(dx0, 0.0), depth) +\\n\\\nczm_shadowDepthCompare(shadowMap, uv + vec2(dx1, 0.0), depth) +\\n\\\nczm_shadowDepthCompare(shadowMap, uv + vec2(dx0, dy1), depth) +\\n\\\nczm_shadowDepthCompare(shadowMap, uv + vec2(0.0, dy1), depth) +\\n\\\nczm_shadowDepthCompare(shadowMap, uv + vec2(dx1, dy1), depth)\\n\\\n) * (1.0 / 9.0);\\n\\\n#else\\n\\\nfloat visibility = czm_shadowDepthCompare(shadowMap, uv, depth);\\n\\\n#endif\\n\\\nreturn czm_private_shadowVisibility(visibility, nDotL, normalShadingSmooth, darkness);\\n\\\n}\\n\\\n#endif\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_signNotZero(float value)\\n\\\n{\\n\\\nreturn value >= 0.0 ? 1.0 : -1.0;\\n\\\n}\\n\\\nvec2 czm_signNotZero(vec2 value)\\n\\\n{\\n\\\nreturn vec2(czm_signNotZero(value.x), czm_signNotZero(value.y));\\n\\\n}\\n\\\nvec3 czm_signNotZero(vec3 value)\\n\\\n{\\n\\\nreturn vec3(czm_signNotZero(value.x), czm_signNotZero(value.y), czm_signNotZero(value.z));\\n\\\n}\\n\\\nvec4 czm_signNotZero(vec4 value)\\n\\\n{\\n\\\nreturn vec4(czm_signNotZero(value.x), czm_signNotZero(value.y), czm_signNotZero(value.z), czm_signNotZero(value.w));\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_sphericalHarmonics(vec3 normal, vec3 coefficients[9])\\n\\\n{\\n\\\nconst float c1 = 0.429043;\\n\\\nconst float c2 = 0.511664;\\n\\\nconst float c3 = 0.743125;\\n\\\nconst float c4 = 0.886227;\\n\\\nconst float c5 = 0.247708;\\n\\\nvec3 L00 = coefficients[0];\\n\\\nvec3 L1_1 = coefficients[1];\\n\\\nvec3 L10 = coefficients[2];\\n\\\nvec3 L11 = coefficients[3];\\n\\\nvec3 L2_2 = coefficients[4];\\n\\\nvec3 L2_1 = coefficients[5];\\n\\\nvec3 L20 = coefficients[6];\\n\\\nvec3 L21 = coefficients[7];\\n\\\nvec3 L22 = coefficients[8];\\n\\\nfloat x = normal.x;\\n\\\nfloat y = normal.y;\\n\\\nfloat z = normal.z;\\n\\\nreturn c1 * L22 * (x * x - y * y) + c3 * L20 * z * z + c4 * L00 - c5 * L20 +\\n\\\n2.0 * c1 * (L2_2 * x * y + L21 * x * z + L2_1 * y * z) +\\n\\\n2.0 * c2 * (L11 * x + L1_1 * y + L10 * z);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"mat3 czm_tangentToEyeSpaceMatrix(vec3 normalEC, vec3 tangentEC, vec3 bitangentEC)\\n\\\n{\\n\\\nvec3 normal = normalize(normalEC);\\n\\\nvec3 tangent = normalize(tangentEC);\\n\\\nvec3 bitangent = normalize(bitangentEC);\\n\\\nreturn mat3(tangent.x , tangent.y , tangent.z,\\n\\\nbitangent.x, bitangent.y, bitangent.z,\\n\\\nnormal.x , normal.y , normal.z);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_transformPlane(vec4 plane, mat4 transform) {\\n\\\nvec4 transformedPlane = transform * plane;\\n\\\nfloat normalMagnitude = length(transformedPlane.xyz);\\n\\\nreturn transformedPlane / normalMagnitude;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_translateRelativeToEye(vec3 high, vec3 low)\\n\\\n{\\n\\\nvec3 highDifference = high - czm_encodedCameraPositionMCHigh;\\n\\\nvec3 lowDifference = low - czm_encodedCameraPositionMCLow;\\n\\\nreturn vec4(highDifference + lowDifference, 1.0);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_translucentPhong(vec3 toEye, czm_material material, vec3 lightDirectionEC)\\n\\\n{\\n\\\nfloat diffuse = czm_getLambertDiffuse(vec3(0.0, 0.0, 1.0), material.normal);\\n\\\nif (czm_sceneMode == czm_sceneMode3D) {\\n\\\ndiffuse += czm_getLambertDiffuse(vec3(0.0, 1.0, 0.0), material.normal);\\n\\\n}\\n\\\ndiffuse = clamp(diffuse, 0.0, 1.0);\\n\\\nfloat specular = czm_getSpecular(lightDirectionEC, toEye, material.normal, material.shininess);\\n\\\nvec3 materialDiffuse = material.diffuse * 0.5;\\n\\\nvec3 ambient = materialDiffuse;\\n\\\nvec3 color = ambient + material.emission;\\n\\\ncolor += materialDiffuse * diffuse * czm_lightColor;\\n\\\ncolor += material.specular * specular * czm_lightColor;\\n\\\nreturn vec4(color, material.alpha);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"mat2 czm_transpose(mat2 matrix)\\n\\\n{\\n\\\nreturn mat2(\\n\\\nmatrix[0][0], matrix[1][0],\\n\\\nmatrix[0][1], matrix[1][1]);\\n\\\n}\\n\\\nmat3 czm_transpose(mat3 matrix)\\n\\\n{\\n\\\nreturn mat3(\\n\\\nmatrix[0][0], matrix[1][0], matrix[2][0],\\n\\\nmatrix[0][1], matrix[1][1], matrix[2][1],\\n\\\nmatrix[0][2], matrix[1][2], matrix[2][2]);\\n\\\n}\\n\\\nmat4 czm_transpose(mat4 matrix)\\n\\\n{\\n\\\nreturn mat4(\\n\\\nmatrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],\\n\\\nmatrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],\\n\\\nmatrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],\\n\\\nmatrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_unpackDepth(vec4 packedDepth)\\n\\\n{\\n\\\nreturn dot(packedDepth, vec4(1.0, 1.0 / 255.0, 1.0 / 65025.0, 1.0 / 16581375.0));\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_unpackFloat(vec4 packedFloat)\\n\\\n{\\n\\\npackedFloat = floor(packedFloat * 255.0 + 0.5);\\n\\\nfloat sign = 1.0 - step(128.0, packedFloat[3]) * 2.0;\\n\\\nfloat exponent = 2.0 * mod(packedFloat[3], 128.0) + step(128.0, packedFloat[2]) - 127.0;\\n\\\nif (exponent == -127.0)\\n\\\n{\\n\\\nreturn 0.0;\\n\\\n}\\n\\\nfloat mantissa = mod(packedFloat[2], 128.0) * 65536.0 + packedFloat[1] * 256.0 + packedFloat[0] + float(0x800000);\\n\\\nfloat result = sign * exp2(exponent - 23.0) * mantissa;\\n\\\nreturn result;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef LOG_DEPTH\\n\\\nvarying float v_depthFromNearPlusOne;\\n\\\n#ifdef SHADOW_MAP\\n\\\nvarying vec3 v_logPositionEC;\\n\\\n#endif\\n\\\n#endif\\n\\\nvec4 czm_updatePositionDepth(vec4 coords) {\\n\\\n#if defined(LOG_DEPTH)\\n\\\n#ifdef SHADOW_MAP\\n\\\nvec3 logPositionEC = (czm_inverseProjection * coords).xyz;\\n\\\nv_logPositionEC = logPositionEC;\\n\\\n#endif\\n\\\ncoords.z = clamp(coords.z / coords.w, -1.0, 1.0) * coords.w;\\n\\\n#endif\\n\\\nreturn coords;\\n\\\n}\\n\\\nvoid czm_vertexLogDepth()\\n\\\n{\\n\\\n#ifdef LOG_DEPTH\\n\\\nv_depthFromNearPlusOne = (gl_Position.w - czm_currentFrustum.x) + 1.0;\\n\\\ngl_Position = czm_updatePositionDepth(gl_Position);\\n\\\n#endif\\n\\\n}\\n\\\nvoid czm_vertexLogDepth(vec4 clipCoords)\\n\\\n{\\n\\\n#ifdef LOG_DEPTH\\n\\\nv_depthFromNearPlusOne = (clipCoords.w - czm_currentFrustum.x) + 1.0;\\n\\\nczm_updatePositionDepth(clipCoords);\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec4 czm_windowToEyeCoordinates(vec4 fragmentCoordinate)\\n\\\n{\\n\\\nfloat x = 2.0 * (fragmentCoordinate.x - czm_viewport.x) / czm_viewport.z - 1.0;\\n\\\nfloat y = 2.0 * (fragmentCoordinate.y - czm_viewport.y) / czm_viewport.w - 1.0;\\n\\\nfloat z = (fragmentCoordinate.z - czm_viewportTransformation[3][2]) / czm_viewportTransformation[2][2];\\n\\\nvec4 q = vec4(x, y, z, 1.0);\\n\\\nq /= fragmentCoordinate.w;\\n\\\nif (!(czm_inverseProjection == mat4(0.0)))\\n\\\n{\\n\\\nq = czm_inverseProjection * q;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nfloat top = czm_frustumPlanes.x;\\n\\\nfloat bottom = czm_frustumPlanes.y;\\n\\\nfloat left = czm_frustumPlanes.z;\\n\\\nfloat right = czm_frustumPlanes.w;\\n\\\nfloat near = czm_currentFrustum.x;\\n\\\nfloat far = czm_currentFrustum.y;\\n\\\nq.x = (q.x * (right - left) + left + right) * 0.5;\\n\\\nq.y = (q.y * (top - bottom) + bottom + top) * 0.5;\\n\\\nq.z = (q.z * (near - far) - near - far) * 0.5;\\n\\\nq.w = 1.0;\\n\\\n}\\n\\\nreturn q;\\n\\\n}\\n\\\nvec4 czm_windowToEyeCoordinates(vec2 fragmentCoordinateXY, float depthOrLogDepth)\\n\\\n{\\n\\\n#ifdef LOG_DEPTH\\n\\\nfloat near = czm_currentFrustum.x;\\n\\\nfloat far = czm_currentFrustum.y;\\n\\\nfloat log2Depth = depthOrLogDepth * czm_log2FarDepthFromNearPlusOne;\\n\\\nfloat depthFromNear = pow(2.0, log2Depth) - 1.0;\\n\\\nfloat depthFromCamera = depthFromNear + near;\\n\\\nvec4 windowCoord = vec4(fragmentCoordinateXY, far * (1.0 - near / depthFromCamera) / (far - near), 1.0);\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\\n\\\neyeCoordinate.w = 1.0 / depthFromCamera;\\n\\\nreturn eyeCoordinate;\\n\\\n#else\\n\\\nvec4 windowCoord = vec4(fragmentCoordinateXY, depthOrLogDepth, 1.0);\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(windowCoord);\\n\\\n#endif\\n\\\nreturn eyeCoordinate;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#if defined(GL_EXT_frag_depth) && !defined(LOG_DEPTH)\\n\\\nvarying float v_WindowZ;\\n\\\n#endif\\n\\\nvoid czm_writeDepthClamp()\\n\\\n{\\n\\\n#if defined(GL_EXT_frag_depth) && !defined(LOG_DEPTH)\\n\\\ngl_FragDepthEXT = clamp(v_WindowZ * gl_FragCoord.w, 0.0, 1.0);\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef LOG_DEPTH\\n\\\nvarying float v_depthFromNearPlusOne;\\n\\\n#ifdef POLYGON_OFFSET\\n\\\nuniform vec2 u_polygonOffset;\\n\\\n#endif\\n\\\n#endif\\n\\\nvoid czm_writeLogDepth(float depth)\\n\\\n{\\n\\\n#if defined(GL_EXT_frag_depth) && defined(LOG_DEPTH)\\n\\\nif (depth <= 0.9999999 || depth > czm_farDepthFromNearPlusOne) {\\n\\\ndiscard;\\n\\\n}\\n\\\n#ifdef POLYGON_OFFSET\\n\\\nfloat factor = u_polygonOffset[0];\\n\\\nfloat units = u_polygonOffset[1];\\n\\\n#ifdef GL_OES_standard_derivatives\\n\\\nfloat x = dFdx(depth);\\n\\\nfloat y = dFdy(depth);\\n\\\nfloat m = sqrt(x * x + y * y);\\n\\\ndepth += m * factor;\\n\\\n#endif\\n\\\n#endif\\n\\\ngl_FragDepthEXT = log2(depth) * czm_oneOverLog2FarDepthFromNearPlusOne;\\n\\\n#ifdef POLYGON_OFFSET\\n\\\ngl_FragDepthEXT += czm_epsilon7 * units;\\n\\\n#endif\\n\\\n#endif\\n\\\n}\\n\\\nvoid czm_writeLogDepth() {\\n\\\n#ifdef LOG_DEPTH\\n\\\nczm_writeLogDepth(v_depthFromNearPlusOne);\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"float czm_writeNonPerspective(float value, float w) {\\n\\\nreturn value * w;\\n\\\n}\\n\\\nvec2 czm_writeNonPerspective(vec2 value, float w) {\\n\\\nreturn value * w;\\n\\\n}\\n\\\nvec3 czm_writeNonPerspective(vec3 value, float w) {\\n\\\nreturn value * w;\\n\\\n}\\n\\\nvec4 czm_writeNonPerspective(vec4 value, float w) {\\n\\\nreturn value * w;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"vec3 czm_XYZToRGB(vec3 Yxy)\\n\\\n{\\n\\\nconst mat3 XYZ2RGB = mat3( 3.2405, -0.9693, 0.0556,\\n\\\n-1.5371, 1.8760, -0.2040,\\n\\\n-0.4985, 0.0416, 1.0572);\\n\\\nvec3 xyz;\\n\\\nxyz.r = Yxy.r * Yxy.g / Yxy.b;\\n\\\nxyz.g = Yxy.r;\\n\\\nxyz.b = Yxy.r * (1.0 - Yxy.g - Yxy.b) / Yxy.b;\\n\\\nreturn XYZ2RGB * xyz;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nimport czm_degreesPerRadian from './Constants/degreesPerRadian.js'\nimport czm_depthRange from './Constants/depthRange.js'\nimport czm_epsilon1 from './Constants/epsilon1.js'\nimport czm_epsilon2 from './Constants/epsilon2.js'\nimport czm_epsilon3 from './Constants/epsilon3.js'\nimport czm_epsilon4 from './Constants/epsilon4.js'\nimport czm_epsilon5 from './Constants/epsilon5.js'\nimport czm_epsilon6 from './Constants/epsilon6.js'\nimport czm_epsilon7 from './Constants/epsilon7.js'\nimport czm_infinity from './Constants/infinity.js'\nimport czm_oneOverPi from './Constants/oneOverPi.js'\nimport czm_oneOverTwoPi from './Constants/oneOverTwoPi.js'\nimport czm_passCesium3DTile from './Constants/passCesium3DTile.js'\nimport czm_passCesium3DTileClassification from './Constants/passCesium3DTileClassification.js'\nimport czm_passCesium3DTileClassificationIgnoreShow from './Constants/passCesium3DTileClassificationIgnoreShow.js'\nimport czm_passClassification from './Constants/passClassification.js'\nimport czm_passCompute from './Constants/passCompute.js'\nimport czm_passEnvironment from './Constants/passEnvironment.js'\nimport czm_passGlobe from './Constants/passGlobe.js'\nimport czm_passOpaque from './Constants/passOpaque.js'\nimport czm_passOverlay from './Constants/passOverlay.js'\nimport czm_passTerrainClassification from './Constants/passTerrainClassification.js'\nimport czm_passTranslucent from './Constants/passTranslucent.js'\nimport czm_pi from './Constants/pi.js'\nimport czm_piOverFour from './Constants/piOverFour.js'\nimport czm_piOverSix from './Constants/piOverSix.js'\nimport czm_piOverThree from './Constants/piOverThree.js'\nimport czm_piOverTwo from './Constants/piOverTwo.js'\nimport czm_radiansPerDegree from './Constants/radiansPerDegree.js'\nimport czm_sceneMode2D from './Constants/sceneMode2D.js'\nimport czm_sceneMode3D from './Constants/sceneMode3D.js'\nimport czm_sceneModeColumbusView from './Constants/sceneModeColumbusView.js'\nimport czm_sceneModeMorphing from './Constants/sceneModeMorphing.js'\nimport czm_solarRadius from './Constants/solarRadius.js'\nimport czm_threePiOver2 from './Constants/threePiOver2.js'\nimport czm_twoPi from './Constants/twoPi.js'\nimport czm_webMercatorMaxLatitude from './Constants/webMercatorMaxLatitude.js'\nimport czm_depthRangeStruct from './Structs/depthRangeStruct.js'\nimport czm_material from './Structs/material.js'\nimport czm_materialInput from './Structs/materialInput.js'\nimport czm_ray from './Structs/ray.js'\nimport czm_raySegment from './Structs/raySegment.js'\nimport czm_shadowParameters from './Structs/shadowParameters.js'\nimport czm_acesTonemapping from './Functions/acesTonemapping.js'\nimport czm_alphaWeight from './Functions/alphaWeight.js'\nimport czm_antialias from './Functions/antialias.js'\nimport czm_approximateSphericalCoordinates from './Functions/approximateSphericalCoordinates.js'\nimport czm_backFacing from './Functions/backFacing.js'\nimport czm_branchFreeTernary from './Functions/branchFreeTernary.js'\nimport czm_cascadeColor from './Functions/cascadeColor.js'\nimport czm_cascadeDistance from './Functions/cascadeDistance.js'\nimport czm_cascadeMatrix from './Functions/cascadeMatrix.js'\nimport czm_cascadeWeights from './Functions/cascadeWeights.js'\nimport czm_columbusViewMorph from './Functions/columbusViewMorph.js'\nimport czm_computePosition from './Functions/computePosition.js'\nimport czm_cosineAndSine from './Functions/cosineAndSine.js'\nimport czm_decompressTextureCoordinates from './Functions/decompressTextureCoordinates.js'\nimport czm_depthClamp from './Functions/depthClamp.js'\nimport czm_eastNorthUpToEyeCoordinates from './Functions/eastNorthUpToEyeCoordinates.js'\nimport czm_ellipsoidContainsPoint from './Functions/ellipsoidContainsPoint.js'\nimport czm_ellipsoidWgs84TextureCoordinates from './Functions/ellipsoidWgs84TextureCoordinates.js'\nimport czm_equalsEpsilon from './Functions/equalsEpsilon.js'\nimport czm_eyeOffset from './Functions/eyeOffset.js'\nimport czm_eyeToWindowCoordinates from './Functions/eyeToWindowCoordinates.js'\nimport czm_fastApproximateAtan from './Functions/fastApproximateAtan.js'\nimport czm_fog from './Functions/fog.js'\nimport czm_gammaCorrect from './Functions/gammaCorrect.js'\nimport czm_geodeticSurfaceNormal from './Functions/geodeticSurfaceNormal.js'\nimport czm_getDefaultMaterial from './Functions/getDefaultMaterial.js'\nimport czm_getLambertDiffuse from './Functions/getLambertDiffuse.js'\nimport czm_getSpecular from './Functions/getSpecular.js'\nimport czm_getWaterNoise from './Functions/getWaterNoise.js'\nimport czm_HSBToRGB from './Functions/HSBToRGB.js'\nimport czm_HSLToRGB from './Functions/HSLToRGB.js'\nimport czm_hue from './Functions/hue.js'\nimport czm_inverseGamma from './Functions/inverseGamma.js'\nimport czm_isEmpty from './Functions/isEmpty.js'\nimport czm_isFull from './Functions/isFull.js'\nimport czm_latitudeToWebMercatorFraction from './Functions/latitudeToWebMercatorFraction.js'\nimport czm_lineDistance from './Functions/lineDistance.js'\nimport czm_luminance from './Functions/luminance.js'\nimport czm_metersPerPixel from './Functions/metersPerPixel.js'\nimport czm_modelToWindowCoordinates from './Functions/modelToWindowCoordinates.js'\nimport czm_multiplyWithColorBalance from './Functions/multiplyWithColorBalance.js'\nimport czm_nearFarScalar from './Functions/nearFarScalar.js'\nimport czm_octDecode from './Functions/octDecode.js'\nimport czm_packDepth from './Functions/packDepth.js'\nimport czm_phong from './Functions/phong.js'\nimport czm_planeDistance from './Functions/planeDistance.js'\nimport czm_pointAlongRay from './Functions/pointAlongRay.js'\nimport czm_rayEllipsoidIntersectionInterval from './Functions/rayEllipsoidIntersectionInterval.js'\nimport czm_readDepth from './Functions/readDepth.js'\nimport czm_readNonPerspective from './Functions/readNonPerspective.js'\nimport czm_reverseLogDepth from './Functions/reverseLogDepth.js'\nimport czm_RGBToHSB from './Functions/RGBToHSB.js'\nimport czm_RGBToHSL from './Functions/RGBToHSL.js'\nimport czm_RGBToXYZ from './Functions/RGBToXYZ.js'\nimport czm_sampleOctahedralProjection from './Functions/sampleOctahedralProjection.js'\nimport czm_saturation from './Functions/saturation.js'\nimport czm_shadowDepthCompare from './Functions/shadowDepthCompare.js'\nimport czm_shadowVisibility from './Functions/shadowVisibility.js'\nimport czm_signNotZero from './Functions/signNotZero.js'\nimport czm_sphericalHarmonics from './Functions/sphericalHarmonics.js'\nimport czm_tangentToEyeSpaceMatrix from './Functions/tangentToEyeSpaceMatrix.js'\nimport czm_transformPlane from './Functions/transformPlane.js'\nimport czm_translateRelativeToEye from './Functions/translateRelativeToEye.js'\nimport czm_translucentPhong from './Functions/translucentPhong.js'\nimport czm_transpose from './Functions/transpose.js'\nimport czm_unpackDepth from './Functions/unpackDepth.js'\nimport czm_unpackFloat from './Functions/unpackFloat.js'\nimport czm_vertexLogDepth from './Functions/vertexLogDepth.js'\nimport czm_windowToEyeCoordinates from './Functions/windowToEyeCoordinates.js'\nimport czm_writeDepthClamp from './Functions/writeDepthClamp.js'\nimport czm_writeLogDepth from './Functions/writeLogDepth.js'\nimport czm_writeNonPerspective from './Functions/writeNonPerspective.js'\nimport czm_XYZToRGB from './Functions/XYZToRGB.js'\n\nexport default {\n czm_degreesPerRadian : czm_degreesPerRadian,\n czm_depthRange : czm_depthRange,\n czm_epsilon1 : czm_epsilon1,\n czm_epsilon2 : czm_epsilon2,\n czm_epsilon3 : czm_epsilon3,\n czm_epsilon4 : czm_epsilon4,\n czm_epsilon5 : czm_epsilon5,\n czm_epsilon6 : czm_epsilon6,\n czm_epsilon7 : czm_epsilon7,\n czm_infinity : czm_infinity,\n czm_oneOverPi : czm_oneOverPi,\n czm_oneOverTwoPi : czm_oneOverTwoPi,\n czm_passCesium3DTile : czm_passCesium3DTile,\n czm_passCesium3DTileClassification : czm_passCesium3DTileClassification,\n czm_passCesium3DTileClassificationIgnoreShow : czm_passCesium3DTileClassificationIgnoreShow,\n czm_passClassification : czm_passClassification,\n czm_passCompute : czm_passCompute,\n czm_passEnvironment : czm_passEnvironment,\n czm_passGlobe : czm_passGlobe,\n czm_passOpaque : czm_passOpaque,\n czm_passOverlay : czm_passOverlay,\n czm_passTerrainClassification : czm_passTerrainClassification,\n czm_passTranslucent : czm_passTranslucent,\n czm_pi : czm_pi,\n czm_piOverFour : czm_piOverFour,\n czm_piOverSix : czm_piOverSix,\n czm_piOverThree : czm_piOverThree,\n czm_piOverTwo : czm_piOverTwo,\n czm_radiansPerDegree : czm_radiansPerDegree,\n czm_sceneMode2D : czm_sceneMode2D,\n czm_sceneMode3D : czm_sceneMode3D,\n czm_sceneModeColumbusView : czm_sceneModeColumbusView,\n czm_sceneModeMorphing : czm_sceneModeMorphing,\n czm_solarRadius : czm_solarRadius,\n czm_threePiOver2 : czm_threePiOver2,\n czm_twoPi : czm_twoPi,\n czm_webMercatorMaxLatitude : czm_webMercatorMaxLatitude,\n czm_depthRangeStruct : czm_depthRangeStruct,\n czm_material : czm_material,\n czm_materialInput : czm_materialInput,\n czm_ray : czm_ray,\n czm_raySegment : czm_raySegment,\n czm_shadowParameters : czm_shadowParameters,\n czm_acesTonemapping : czm_acesTonemapping,\n czm_alphaWeight : czm_alphaWeight,\n czm_antialias : czm_antialias,\n czm_approximateSphericalCoordinates : czm_approximateSphericalCoordinates,\n czm_backFacing : czm_backFacing,\n czm_branchFreeTernary : czm_branchFreeTernary,\n czm_cascadeColor : czm_cascadeColor,\n czm_cascadeDistance : czm_cascadeDistance,\n czm_cascadeMatrix : czm_cascadeMatrix,\n czm_cascadeWeights : czm_cascadeWeights,\n czm_columbusViewMorph : czm_columbusViewMorph,\n czm_computePosition : czm_computePosition,\n czm_cosineAndSine : czm_cosineAndSine,\n czm_decompressTextureCoordinates : czm_decompressTextureCoordinates,\n czm_depthClamp : czm_depthClamp,\n czm_eastNorthUpToEyeCoordinates : czm_eastNorthUpToEyeCoordinates,\n czm_ellipsoidContainsPoint : czm_ellipsoidContainsPoint,\n czm_ellipsoidWgs84TextureCoordinates : czm_ellipsoidWgs84TextureCoordinates,\n czm_equalsEpsilon : czm_equalsEpsilon,\n czm_eyeOffset : czm_eyeOffset,\n czm_eyeToWindowCoordinates : czm_eyeToWindowCoordinates,\n czm_fastApproximateAtan : czm_fastApproximateAtan,\n czm_fog : czm_fog,\n czm_gammaCorrect : czm_gammaCorrect,\n czm_geodeticSurfaceNormal : czm_geodeticSurfaceNormal,\n czm_getDefaultMaterial : czm_getDefaultMaterial,\n czm_getLambertDiffuse : czm_getLambertDiffuse,\n czm_getSpecular : czm_getSpecular,\n czm_getWaterNoise : czm_getWaterNoise,\n czm_HSBToRGB : czm_HSBToRGB,\n czm_HSLToRGB : czm_HSLToRGB,\n czm_hue : czm_hue,\n czm_inverseGamma : czm_inverseGamma,\n czm_isEmpty : czm_isEmpty,\n czm_isFull : czm_isFull,\n czm_latitudeToWebMercatorFraction : czm_latitudeToWebMercatorFraction,\n czm_lineDistance : czm_lineDistance,\n czm_luminance : czm_luminance,\n czm_metersPerPixel : czm_metersPerPixel,\n czm_modelToWindowCoordinates : czm_modelToWindowCoordinates,\n czm_multiplyWithColorBalance : czm_multiplyWithColorBalance,\n czm_nearFarScalar : czm_nearFarScalar,\n czm_octDecode : czm_octDecode,\n czm_packDepth : czm_packDepth,\n czm_phong : czm_phong,\n czm_planeDistance : czm_planeDistance,\n czm_pointAlongRay : czm_pointAlongRay,\n czm_rayEllipsoidIntersectionInterval : czm_rayEllipsoidIntersectionInterval,\n czm_readDepth : czm_readDepth,\n czm_readNonPerspective : czm_readNonPerspective,\n czm_reverseLogDepth : czm_reverseLogDepth,\n czm_RGBToHSB : czm_RGBToHSB,\n czm_RGBToHSL : czm_RGBToHSL,\n czm_RGBToXYZ : czm_RGBToXYZ,\n czm_sampleOctahedralProjection : czm_sampleOctahedralProjection,\n czm_saturation : czm_saturation,\n czm_shadowDepthCompare : czm_shadowDepthCompare,\n czm_shadowVisibility : czm_shadowVisibility,\n czm_signNotZero : czm_signNotZero,\n czm_sphericalHarmonics : czm_sphericalHarmonics,\n czm_tangentToEyeSpaceMatrix : czm_tangentToEyeSpaceMatrix,\n czm_transformPlane : czm_transformPlane,\n czm_translateRelativeToEye : czm_translateRelativeToEye,\n czm_translucentPhong : czm_translucentPhong,\n czm_transpose : czm_transpose,\n czm_unpackDepth : czm_unpackDepth,\n czm_unpackFloat : czm_unpackFloat,\n czm_vertexLogDepth : czm_vertexLogDepth,\n czm_windowToEyeCoordinates : czm_windowToEyeCoordinates,\n czm_writeDepthClamp : czm_writeDepthClamp,\n czm_writeLogDepth : czm_writeLogDepth,\n czm_writeNonPerspective : czm_writeNonPerspective,\n czm_XYZToRGB : czm_XYZToRGB\n};\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport modernizeShader from \"../Renderer/modernizeShader.js\";\r\nimport CzmBuiltins from \"../Shaders/Builtin/CzmBuiltins.js\";\r\nimport AutomaticUniforms from \"./AutomaticUniforms.js\";\r\n\r\nfunction removeComments(source) {\r\n // remove inline comments\r\n source = source.replace(/\\/\\/.*/g, \"\");\r\n // remove multiline comment block\r\n return source.replace(/\\/\\*\\*[\\s\\S]*?\\*\\//gm, function (match) {\r\n // preserve the number of lines in the comment block so the line numbers will be correct when debugging shaders\r\n var numberOfLines = match.match(/\\n/gm).length;\r\n var replacement = \"\";\r\n for (var lineNumber = 0; lineNumber < numberOfLines; ++lineNumber) {\r\n replacement += \"\\n\";\r\n }\r\n return replacement;\r\n });\r\n}\r\n\r\nfunction getDependencyNode(name, glslSource, nodes) {\r\n var dependencyNode;\r\n\r\n // check if already loaded\r\n for (var i = 0; i < nodes.length; ++i) {\r\n if (nodes[i].name === name) {\r\n dependencyNode = nodes[i];\r\n }\r\n }\r\n\r\n if (!defined(dependencyNode)) {\r\n // strip doc comments so we don't accidentally try to determine a dependency for something found\r\n // in a comment\r\n glslSource = removeComments(glslSource);\r\n\r\n // create new node\r\n dependencyNode = {\r\n name: name,\r\n glslSource: glslSource,\r\n dependsOn: [],\r\n requiredBy: [],\r\n evaluated: false,\r\n };\r\n nodes.push(dependencyNode);\r\n }\r\n\r\n return dependencyNode;\r\n}\r\n\r\nfunction generateDependencies(currentNode, dependencyNodes) {\r\n if (currentNode.evaluated) {\r\n return;\r\n }\r\n\r\n currentNode.evaluated = true;\r\n\r\n // identify all dependencies that are referenced from this glsl source code\r\n var czmMatches = currentNode.glslSource.match(/\\bczm_[a-zA-Z0-9_]*/g);\r\n if (defined(czmMatches) && czmMatches !== null) {\r\n // remove duplicates\r\n czmMatches = czmMatches.filter(function (elem, pos) {\r\n return czmMatches.indexOf(elem) === pos;\r\n });\r\n\r\n czmMatches.forEach(function (element) {\r\n if (\r\n element !== currentNode.name &&\r\n ShaderSource._czmBuiltinsAndUniforms.hasOwnProperty(element)\r\n ) {\r\n var referencedNode = getDependencyNode(\r\n element,\r\n ShaderSource._czmBuiltinsAndUniforms[element],\r\n dependencyNodes\r\n );\r\n currentNode.dependsOn.push(referencedNode);\r\n referencedNode.requiredBy.push(currentNode);\r\n\r\n // recursive call to find any dependencies of the new node\r\n generateDependencies(referencedNode, dependencyNodes);\r\n }\r\n });\r\n }\r\n}\r\n\r\nfunction sortDependencies(dependencyNodes) {\r\n var nodesWithoutIncomingEdges = [];\r\n var allNodes = [];\r\n\r\n while (dependencyNodes.length > 0) {\r\n var node = dependencyNodes.pop();\r\n allNodes.push(node);\r\n\r\n if (node.requiredBy.length === 0) {\r\n nodesWithoutIncomingEdges.push(node);\r\n }\r\n }\r\n\r\n while (nodesWithoutIncomingEdges.length > 0) {\r\n var currentNode = nodesWithoutIncomingEdges.shift();\r\n\r\n dependencyNodes.push(currentNode);\r\n\r\n for (var i = 0; i < currentNode.dependsOn.length; ++i) {\r\n // remove the edge from the graph\r\n var referencedNode = currentNode.dependsOn[i];\r\n var index = referencedNode.requiredBy.indexOf(currentNode);\r\n referencedNode.requiredBy.splice(index, 1);\r\n\r\n // if referenced node has no more incoming edges, add to list\r\n if (referencedNode.requiredBy.length === 0) {\r\n nodesWithoutIncomingEdges.push(referencedNode);\r\n }\r\n }\r\n }\r\n\r\n // if there are any nodes left with incoming edges, then there was a circular dependency somewhere in the graph\r\n var badNodes = [];\r\n for (var j = 0; j < allNodes.length; ++j) {\r\n if (allNodes[j].requiredBy.length !== 0) {\r\n badNodes.push(allNodes[j]);\r\n }\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (badNodes.length !== 0) {\r\n var message =\r\n \"A circular dependency was found in the following built-in functions/structs/constants: \\n\";\r\n for (var k = 0; k < badNodes.length; ++k) {\r\n message = message + badNodes[k].name + \"\\n\";\r\n }\r\n throw new DeveloperError(message);\r\n }\r\n //>>includeEnd('debug');\r\n}\r\n\r\nfunction getBuiltinsAndAutomaticUniforms(shaderSource) {\r\n // generate a dependency graph for builtin functions\r\n var dependencyNodes = [];\r\n var root = getDependencyNode(\"main\", shaderSource, dependencyNodes);\r\n generateDependencies(root, dependencyNodes);\r\n sortDependencies(dependencyNodes);\r\n\r\n // Concatenate the source code for the function dependencies.\r\n // Iterate in reverse so that dependent items are declared before they are used.\r\n var builtinsSource = \"\";\r\n for (var i = dependencyNodes.length - 1; i >= 0; --i) {\r\n builtinsSource = builtinsSource + dependencyNodes[i].glslSource + \"\\n\";\r\n }\r\n\r\n return builtinsSource.replace(root.glslSource, \"\");\r\n}\r\n\r\nfunction combineShader(shaderSource, isFragmentShader, context) {\r\n var i;\r\n var length;\r\n\r\n // Combine shader sources, generally for pseudo-polymorphism, e.g., czm_getMaterial.\r\n var combinedSources = \"\";\r\n var sources = shaderSource.sources;\r\n if (defined(sources)) {\r\n for (i = 0, length = sources.length; i < length; ++i) {\r\n // #line needs to be on its own line.\r\n combinedSources += \"\\n#line 0\\n\" + sources[i];\r\n }\r\n }\r\n\r\n combinedSources = removeComments(combinedSources);\r\n\r\n // Extract existing shader version from sources\r\n var version;\r\n combinedSources = combinedSources.replace(/#version\\s+(.*?)\\n/gm, function (\r\n match,\r\n group1\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(version) && version !== group1) {\r\n throw new DeveloperError(\r\n \"inconsistent versions found: \" + version + \" and \" + group1\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Extract #version to put at the top\r\n version = group1;\r\n\r\n // Replace original #version directive with a new line so the line numbers\r\n // are not off by one. There can be only one #version directive\r\n // and it must appear at the top of the source, only preceded by\r\n // whitespace and comments.\r\n return \"\\n\";\r\n });\r\n\r\n // Extract shader extensions from sources\r\n var extensions = [];\r\n combinedSources = combinedSources.replace(/#extension.*\\n/gm, function (\r\n match\r\n ) {\r\n // Extract extension to put at the top\r\n extensions.push(match);\r\n\r\n // Replace original #extension directive with a new line so the line numbers\r\n // are not off by one.\r\n return \"\\n\";\r\n });\r\n\r\n // Remove precision qualifier\r\n combinedSources = combinedSources.replace(\r\n /precision\\s(lowp|mediump|highp)\\s(float|int);/,\r\n \"\"\r\n );\r\n\r\n // Replace main() for picked if desired.\r\n var pickColorQualifier = shaderSource.pickColorQualifier;\r\n if (defined(pickColorQualifier)) {\r\n combinedSources = ShaderSource.createPickFragmentShaderSource(\r\n combinedSources,\r\n pickColorQualifier\r\n );\r\n }\r\n\r\n // combine into single string\r\n var result = \"\";\r\n\r\n // #version must be first\r\n // defaults to #version 100 if not specified\r\n if (defined(version)) {\r\n result = \"#version \" + version + \"\\n\";\r\n }\r\n\r\n var extensionsLength = extensions.length;\r\n for (i = 0; i < extensionsLength; i++) {\r\n result += extensions[i];\r\n }\r\n\r\n if (isFragmentShader) {\r\n // If high precision isn't support replace occurrences of highp with mediump\r\n // The highp keyword is not always available on older mobile devices\r\n // See https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/WebGL_best_practices#In_WebGL_1_highp_float_support_is_optional_in_fragment_shaders\r\n result +=\r\n \"\\\r\n#ifdef GL_FRAGMENT_PRECISION_HIGH\\n\\\r\n precision highp float;\\n\\\r\n#else\\n\\\r\n precision mediump float;\\n\\\r\n #define highp mediump\\n\\\r\n#endif\\n\\n\";\r\n }\r\n\r\n // Prepend #defines for uber-shaders\r\n var defines = shaderSource.defines;\r\n if (defined(defines)) {\r\n for (i = 0, length = defines.length; i < length; ++i) {\r\n var define = defines[i];\r\n if (define.length !== 0) {\r\n result += \"#define \" + define + \"\\n\";\r\n }\r\n }\r\n }\r\n\r\n // GLSLModernizer inserts its own layout qualifiers\r\n // at this position in the source\r\n if (context.webgl2) {\r\n result += \"#define OUTPUT_DECLARATION\\n\\n\";\r\n }\r\n\r\n // Define a constant for the OES_texture_float_linear extension since WebGL does not.\r\n if (context.textureFloatLinear) {\r\n result += \"#define OES_texture_float_linear\\n\\n\";\r\n }\r\n\r\n // Define a constant for the OES_texture_float extension since WebGL does not.\r\n if (context.floatingPointTexture) {\r\n result += \"#define OES_texture_float\\n\\n\";\r\n }\r\n\r\n // append built-ins\r\n if (shaderSource.includeBuiltIns) {\r\n result += getBuiltinsAndAutomaticUniforms(combinedSources);\r\n }\r\n\r\n // reset line number\r\n result += \"\\n#line 0\\n\";\r\n\r\n // append actual source\r\n result += combinedSources;\r\n\r\n // modernize the source\r\n if (context.webgl2) {\r\n result = modernizeShader(result, isFragmentShader, true);\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * An object containing various inputs that will be combined to form a final GLSL shader string.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {String[]} [options.sources] An array of strings to combine containing GLSL code for the shader.\r\n * @param {String[]} [options.defines] An array of strings containing GLSL identifiers to #define.\r\n * @param {String} [options.pickColorQualifier] The GLSL qualifier, uniform or varying, for the input czm_pickColor. When defined, a pick fragment shader is generated.\r\n * @param {Boolean} [options.includeBuiltIns=true] If true, referenced built-in functions will be included with the combined shader. Set to false if this shader will become a source in another shader, to avoid duplicating functions.\r\n *\r\n * @exception {DeveloperError} options.pickColorQualifier must be 'uniform' or 'varying'.\r\n *\r\n * @example\r\n * // 1. Prepend #defines to a shader\r\n * var source = new Cesium.ShaderSource({\r\n * defines : ['WHITE'],\r\n * sources : ['void main() { \\n#ifdef WHITE\\n gl_FragColor = vec4(1.0); \\n#else\\n gl_FragColor = vec4(0.0); \\n#endif\\n }']\r\n * });\r\n *\r\n * // 2. Modify a fragment shader for picking\r\n * var source = new Cesium.ShaderSource({\r\n * sources : ['void main() { gl_FragColor = vec4(1.0); }'],\r\n * pickColorQualifier : 'uniform'\r\n * });\r\n *\r\n * @private\r\n */\r\nfunction ShaderSource(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var pickColorQualifier = options.pickColorQualifier;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n defined(pickColorQualifier) &&\r\n pickColorQualifier !== \"uniform\" &&\r\n pickColorQualifier !== \"varying\"\r\n ) {\r\n throw new DeveloperError(\r\n \"options.pickColorQualifier must be 'uniform' or 'varying'.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.defines = defined(options.defines) ? options.defines.slice(0) : [];\r\n this.sources = defined(options.sources) ? options.sources.slice(0) : [];\r\n this.pickColorQualifier = pickColorQualifier;\r\n this.includeBuiltIns = defaultValue(options.includeBuiltIns, true);\r\n}\r\n\r\nShaderSource.prototype.clone = function () {\r\n return new ShaderSource({\r\n sources: this.sources,\r\n defines: this.defines,\r\n pickColorQualifier: this.pickColorQualifier,\r\n includeBuiltIns: this.includeBuiltIns,\r\n });\r\n};\r\n\r\nShaderSource.replaceMain = function (source, renamedMain) {\r\n renamedMain = \"void \" + renamedMain + \"()\";\r\n return source.replace(/void\\s+main\\s*\\(\\s*(?:void)?\\s*\\)/g, renamedMain);\r\n};\r\n\r\n/**\r\n * Create a single string containing the full, combined vertex shader with all dependencies and defines.\r\n *\r\n * @param {Context} context The current rendering context\r\n *\r\n * @returns {String} The combined shader string.\r\n */\r\nShaderSource.prototype.createCombinedVertexShader = function (context) {\r\n return combineShader(this, false, context);\r\n};\r\n\r\n/**\r\n * Create a single string containing the full, combined fragment shader with all dependencies and defines.\r\n *\r\n * @param {Context} context The current rendering context\r\n *\r\n * @returns {String} The combined shader string.\r\n */\r\nShaderSource.prototype.createCombinedFragmentShader = function (context) {\r\n return combineShader(this, true, context);\r\n};\r\n\r\n/**\r\n * For ShaderProgram testing\r\n * @private\r\n */\r\nShaderSource._czmBuiltinsAndUniforms = {};\r\n\r\n// combine automatic uniforms and Cesium built-ins\r\nfor (var builtinName in CzmBuiltins) {\r\n if (CzmBuiltins.hasOwnProperty(builtinName)) {\r\n ShaderSource._czmBuiltinsAndUniforms[builtinName] =\r\n CzmBuiltins[builtinName];\r\n }\r\n}\r\nfor (var uniformName in AutomaticUniforms) {\r\n if (AutomaticUniforms.hasOwnProperty(uniformName)) {\r\n var uniform = AutomaticUniforms[uniformName];\r\n if (typeof uniform.getDeclaration === \"function\") {\r\n ShaderSource._czmBuiltinsAndUniforms[\r\n uniformName\r\n ] = uniform.getDeclaration(uniformName);\r\n }\r\n }\r\n}\r\n\r\nShaderSource.createPickVertexShaderSource = function (vertexShaderSource) {\r\n var renamedVS = ShaderSource.replaceMain(vertexShaderSource, \"czm_old_main\");\r\n var pickMain =\r\n \"attribute vec4 pickColor; \\n\" +\r\n \"varying vec4 czm_pickColor; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" czm_old_main(); \\n\" +\r\n \" czm_pickColor = pickColor; \\n\" +\r\n \"}\";\r\n\r\n return renamedVS + \"\\n\" + pickMain;\r\n};\r\n\r\nShaderSource.createPickFragmentShaderSource = function (\r\n fragmentShaderSource,\r\n pickColorQualifier\r\n) {\r\n var renamedFS = ShaderSource.replaceMain(\r\n fragmentShaderSource,\r\n \"czm_old_main\"\r\n );\r\n var pickMain =\r\n pickColorQualifier +\r\n \" vec4 czm_pickColor; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" czm_old_main(); \\n\" +\r\n \" if (gl_FragColor.a == 0.0) { \\n\" +\r\n \" discard; \\n\" +\r\n \" } \\n\" +\r\n \" gl_FragColor = czm_pickColor; \\n\" +\r\n \"}\";\r\n\r\n return renamedFS + \"\\n\" + pickMain;\r\n};\r\n\r\nShaderSource.findVarying = function (shaderSource, names) {\r\n var sources = shaderSource.sources;\r\n\r\n var namesLength = names.length;\r\n for (var i = 0; i < namesLength; ++i) {\r\n var name = names[i];\r\n\r\n var sourcesLength = sources.length;\r\n for (var j = 0; j < sourcesLength; ++j) {\r\n if (sources[j].indexOf(name) !== -1) {\r\n return name;\r\n }\r\n }\r\n }\r\n\r\n return undefined;\r\n};\r\n\r\nvar normalVaryingNames = [\"v_normalEC\", \"v_normal\"];\r\n\r\nShaderSource.findNormalVarying = function (shaderSource) {\r\n return ShaderSource.findVarying(shaderSource, normalVaryingNames);\r\n};\r\n\r\nvar positionVaryingNames = [\"v_positionEC\"];\r\n\r\nShaderSource.findPositionVarying = function (shaderSource) {\r\n return ShaderSource.findVarying(shaderSource, positionVaryingNames);\r\n};\r\nexport default ShaderSource;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute float batchId;\\n\\\n#ifdef EXTRUDED_GEOMETRY\\n\\\nattribute vec3 extrudeDirection;\\n\\\nuniform float u_globeMinimumAltitude;\\n\\\n#endif // EXTRUDED_GEOMETRY\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nvarying vec4 v_color;\\n\\\n#endif // PER_INSTANCE_COLOR\\n\\\n#ifdef TEXTURE_COORDINATES\\n\\\n#ifdef SPHERICAL\\n\\\nvarying vec4 v_sphericalExtents;\\n\\\n#else // SPHERICAL\\n\\\nvarying vec2 v_inversePlaneExtents;\\n\\\nvarying vec4 v_westPlane;\\n\\\nvarying vec4 v_southPlane;\\n\\\n#endif // SPHERICAL\\n\\\nvarying vec3 v_uvMinAndSphericalLongitudeRotation;\\n\\\nvarying vec3 v_uMaxAndInverseDistance;\\n\\\nvarying vec3 v_vMaxAndInverseDistance;\\n\\\n#endif // TEXTURE_COORDINATES\\n\\\nvoid main()\\n\\\n{\\n\\\nvec4 position = czm_computePosition();\\n\\\n#ifdef EXTRUDED_GEOMETRY\\n\\\nfloat delta = min(u_globeMinimumAltitude, czm_geometricToleranceOverMeter * length(position.xyz));\\n\\\ndelta *= czm_sceneMode == czm_sceneMode3D ? 1.0 : 0.0;\\n\\\nposition = position + vec4(extrudeDirection * delta, 0.0);\\n\\\n#endif\\n\\\n#ifdef TEXTURE_COORDINATES\\n\\\n#ifdef SPHERICAL\\n\\\nv_sphericalExtents = czm_batchTable_sphericalExtents(batchId);\\n\\\nv_uvMinAndSphericalLongitudeRotation.z = czm_batchTable_longitudeRotation(batchId);\\n\\\n#else // SPHERICAL\\n\\\n#ifdef COLUMBUS_VIEW_2D\\n\\\nvec4 planes2D_high = czm_batchTable_planes2D_HIGH(batchId);\\n\\\nvec4 planes2D_low = czm_batchTable_planes2D_LOW(batchId);\\n\\\nvec2 idlSplitNewPlaneHiLow = vec2(EAST_MOST_X_HIGH - (WEST_MOST_X_HIGH - planes2D_high.w), EAST_MOST_X_LOW - (WEST_MOST_X_LOW - planes2D_low.w));\\n\\\nbool idlSplit = planes2D_high.x > planes2D_high.w && position3DLow.y > 0.0;\\n\\\nplanes2D_high.w = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.x, planes2D_high.w);\\n\\\nplanes2D_low.w = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.y, planes2D_low.w);\\n\\\nidlSplit = planes2D_high.x > planes2D_high.w && position3DLow.y < 0.0;\\n\\\nidlSplitNewPlaneHiLow = vec2(WEST_MOST_X_HIGH - (EAST_MOST_X_HIGH - planes2D_high.x), WEST_MOST_X_LOW - (EAST_MOST_X_LOW - planes2D_low.x));\\n\\\nplanes2D_high.x = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.x, planes2D_high.x);\\n\\\nplanes2D_low.x = czm_branchFreeTernary(idlSplit, idlSplitNewPlaneHiLow.y, planes2D_low.x);\\n\\\nvec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.xy), vec3(0.0, planes2D_low.xy))).xyz;\\n\\\nvec3 northWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.x, planes2D_high.z), vec3(0.0, planes2D_low.x, planes2D_low.z))).xyz;\\n\\\nvec3 southEastCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, planes2D_high.w, planes2D_high.y), vec3(0.0, planes2D_low.w, planes2D_low.y))).xyz;\\n\\\n#else // COLUMBUS_VIEW_2D\\n\\\nvec3 southWestCorner = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(czm_batchTable_southWest_HIGH(batchId), czm_batchTable_southWest_LOW(batchId))).xyz;\\n\\\nvec3 northWestCorner = czm_normal * czm_batchTable_northward(batchId) + southWestCorner;\\n\\\nvec3 southEastCorner = czm_normal * czm_batchTable_eastward(batchId) + southWestCorner;\\n\\\n#endif // COLUMBUS_VIEW_2D\\n\\\nvec3 eastWard = southEastCorner - southWestCorner;\\n\\\nfloat eastExtent = length(eastWard);\\n\\\neastWard /= eastExtent;\\n\\\nvec3 northWard = northWestCorner - southWestCorner;\\n\\\nfloat northExtent = length(northWard);\\n\\\nnorthWard /= northExtent;\\n\\\nv_westPlane = vec4(eastWard, -dot(eastWard, southWestCorner));\\n\\\nv_southPlane = vec4(northWard, -dot(northWard, southWestCorner));\\n\\\nv_inversePlaneExtents = vec2(1.0 / eastExtent, 1.0 / northExtent);\\n\\\n#endif // SPHERICAL\\n\\\nvec4 uvMinAndExtents = czm_batchTable_uvMinAndExtents(batchId);\\n\\\nvec4 uMaxVmax = czm_batchTable_uMaxVmax(batchId);\\n\\\nv_uMaxAndInverseDistance = vec3(uMaxVmax.xy, uvMinAndExtents.z);\\n\\\nv_vMaxAndInverseDistance = vec3(uMaxVmax.zw, uvMinAndExtents.w);\\n\\\nv_uvMinAndSphericalLongitudeRotation.xy = uvMinAndExtents.xy;\\n\\\n#endif // TEXTURE_COORDINATES\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nv_color = czm_batchTable_color(batchId);\\n\\\n#endif\\n\\\ngl_Position = czm_depthClamp(czm_modelViewProjectionRelativeToEye * position);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef GL_EXT_frag_depth\\n\\\n#extension GL_EXT_frag_depth : enable\\n\\\n#endif\\n\\\n#ifdef VECTOR_TILE\\n\\\nuniform vec4 u_highlightColor;\\n\\\n#endif\\n\\\nvoid main(void)\\n\\\n{\\n\\\n#ifdef VECTOR_TILE\\n\\\ngl_FragColor = czm_gammaCorrect(u_highlightColor);\\n\\\n#else\\n\\\ngl_FragColor = vec4(1.0);\\n\\\n#endif\\n\\\nczm_writeDepthClamp();\\n\\\n}\\n\\\n\";\n","/**\r\n * Whether a classification affects terrain, 3D Tiles or both.\r\n *\r\n * @enum {Number}\r\n */\r\nvar ClassificationType = {\r\n /**\r\n * Only terrain will be classified.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n TERRAIN: 0,\r\n /**\r\n * Only 3D Tiles will be classified.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CESIUM_3D_TILE: 1,\r\n /**\r\n * Both terrain and 3D Tiles will be classified.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n BOTH: 2,\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nClassificationType.NUMBER_OF_CLASSIFICATION_TYPES = 3;\r\n\r\nexport default Object.freeze(ClassificationType);\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * Determines the function used to compare two depths for the depth test.\r\n *\r\n * @enum {Number}\r\n */\r\nvar DepthFunction = {\r\n /**\r\n * The depth test never passes.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NEVER: WebGLConstants.NEVER,\r\n\r\n /**\r\n * The depth test passes if the incoming depth is less than the stored depth.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LESS: WebGLConstants.LESS,\r\n\r\n /**\r\n * The depth test passes if the incoming depth is equal to the stored depth.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n EQUAL: WebGLConstants.EQUAL,\r\n\r\n /**\r\n * The depth test passes if the incoming depth is less than or equal to the stored depth.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LESS_OR_EQUAL: WebGLConstants.LEQUAL,\r\n\r\n /**\r\n * The depth test passes if the incoming depth is greater than the stored depth.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n GREATER: WebGLConstants.GREATER,\r\n\r\n /**\r\n * The depth test passes if the incoming depth is not equal to the stored depth.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NOT_EQUAL: WebGLConstants.NOTEQUAL,\r\n\r\n /**\r\n * The depth test passes if the incoming depth is greater than or equal to the stored depth.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n GREATER_OR_EQUAL: WebGLConstants.GEQUAL,\r\n\r\n /**\r\n * The depth test always passes.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ALWAYS: WebGLConstants.ALWAYS,\r\n};\r\nexport default Object.freeze(DepthFunction);\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar BufferUsage = {\r\n STREAM_DRAW: WebGLConstants.STREAM_DRAW,\r\n STATIC_DRAW: WebGLConstants.STATIC_DRAW,\r\n DYNAMIC_DRAW: WebGLConstants.DYNAMIC_DRAW,\r\n\r\n validate: function (bufferUsage) {\r\n return (\r\n bufferUsage === BufferUsage.STREAM_DRAW ||\r\n bufferUsage === BufferUsage.STATIC_DRAW ||\r\n bufferUsage === BufferUsage.DYNAMIC_DRAW\r\n );\r\n },\r\n};\r\nexport default Object.freeze(BufferUsage);\r\n","import Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport BufferUsage from \"./BufferUsage.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Buffer(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n\r\n if (!defined(options.typedArray) && !defined(options.sizeInBytes)) {\r\n throw new DeveloperError(\r\n \"Either options.sizeInBytes or options.typedArray is required.\"\r\n );\r\n }\r\n\r\n if (defined(options.typedArray) && defined(options.sizeInBytes)) {\r\n throw new DeveloperError(\r\n \"Cannot pass in both options.sizeInBytes and options.typedArray.\"\r\n );\r\n }\r\n\r\n if (defined(options.typedArray)) {\r\n Check.typeOf.object(\"options.typedArray\", options.typedArray);\r\n Check.typeOf.number(\r\n \"options.typedArray.byteLength\",\r\n options.typedArray.byteLength\r\n );\r\n }\r\n\r\n if (!BufferUsage.validate(options.usage)) {\r\n throw new DeveloperError(\"usage is invalid.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var gl = options.context._gl;\r\n var bufferTarget = options.bufferTarget;\r\n var typedArray = options.typedArray;\r\n var sizeInBytes = options.sizeInBytes;\r\n var usage = options.usage;\r\n var hasArray = defined(typedArray);\r\n\r\n if (hasArray) {\r\n sizeInBytes = typedArray.byteLength;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThan(\"sizeInBytes\", sizeInBytes, 0);\r\n //>>includeEnd('debug');\r\n\r\n var buffer = gl.createBuffer();\r\n gl.bindBuffer(bufferTarget, buffer);\r\n gl.bufferData(bufferTarget, hasArray ? typedArray : sizeInBytes, usage);\r\n gl.bindBuffer(bufferTarget, null);\r\n\r\n this._gl = gl;\r\n this._webgl2 = options.context._webgl2;\r\n this._bufferTarget = bufferTarget;\r\n this._sizeInBytes = sizeInBytes;\r\n this._usage = usage;\r\n this._buffer = buffer;\r\n this.vertexArrayDestroyable = true;\r\n}\r\n\r\n/**\r\n * Creates a vertex buffer, which contains untyped vertex data in GPU-controlled memory.\r\n *

\r\n * A vertex array defines the actual makeup of a vertex, e.g., positions, normals, texture coordinates,\r\n * etc., by interpreting the raw data in one or more vertex buffers.\r\n *\r\n * @param {Object} options An object containing the following properties:\r\n * @param {Context} options.context The context in which to create the buffer\r\n * @param {ArrayBufferView} [options.typedArray] A typed array containing the data to copy to the buffer.\r\n * @param {Number} [options.sizeInBytes] A Number defining the size of the buffer in bytes. Required if options.typedArray is not given.\r\n * @param {BufferUsage} options.usage Specifies the expected usage pattern of the buffer. On some GL implementations, this can significantly affect performance. See {@link BufferUsage}.\r\n * @returns {VertexBuffer} The vertex buffer, ready to be attached to a vertex array.\r\n *\r\n * @exception {DeveloperError} Must specify either or , but not both.\r\n * @exception {DeveloperError} The buffer size must be greater than zero.\r\n * @exception {DeveloperError} Invalid usage.\r\n *\r\n *\r\n * @example\r\n * // Example 1. Create a dynamic vertex buffer 16 bytes in size.\r\n * var buffer = Buffer.createVertexBuffer({\r\n * context : context,\r\n * sizeInBytes : 16,\r\n * usage : BufferUsage.DYNAMIC_DRAW\r\n * });\r\n *\r\n * @example\r\n * // Example 2. Create a dynamic vertex buffer from three floating-point values.\r\n * // The data copied to the vertex buffer is considered raw bytes until it is\r\n * // interpreted as vertices using a vertex array.\r\n * var positionBuffer = buffer.createVertexBuffer({\r\n * context : context,\r\n * typedArray : new Float32Array([0, 0, 0]),\r\n * usage : BufferUsage.STATIC_DRAW\r\n * });\r\n *\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenBuffer.xml|glGenBuffer}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindBuffer.xml|glBindBuffer} with ARRAY_BUFFER\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml|glBufferData} with ARRAY_BUFFER\r\n */\r\nBuffer.createVertexBuffer = function (options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n //>>includeEnd('debug');\r\n\r\n return new Buffer({\r\n context: options.context,\r\n bufferTarget: WebGLConstants.ARRAY_BUFFER,\r\n typedArray: options.typedArray,\r\n sizeInBytes: options.sizeInBytes,\r\n usage: options.usage,\r\n });\r\n};\r\n\r\n/**\r\n * Creates an index buffer, which contains typed indices in GPU-controlled memory.\r\n *

\r\n * An index buffer can be attached to a vertex array to select vertices for rendering.\r\n * Context.draw can render using the entire index buffer or a subset\r\n * of the index buffer defined by an offset and count.\r\n *\r\n * @param {Object} options An object containing the following properties:\r\n * @param {Context} options.context The context in which to create the buffer\r\n * @param {ArrayBufferView} [options.typedArray] A typed array containing the data to copy to the buffer.\r\n * @param {Number} [options.sizeInBytes] A Number defining the size of the buffer in bytes. Required if options.typedArray is not given.\r\n * @param {BufferUsage} options.usage Specifies the expected usage pattern of the buffer. On some GL implementations, this can significantly affect performance. See {@link BufferUsage}.\r\n * @param {IndexDatatype} options.indexDatatype The datatype of indices in the buffer.\r\n * @returns {IndexBuffer} The index buffer, ready to be attached to a vertex array.\r\n *\r\n * @exception {DeveloperError} Must specify either or , but not both.\r\n * @exception {DeveloperError} IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system. Check context.elementIndexUint.\r\n * @exception {DeveloperError} The size in bytes must be greater than zero.\r\n * @exception {DeveloperError} Invalid usage.\r\n * @exception {DeveloperError} Invalid indexDatatype.\r\n *\r\n *\r\n * @example\r\n * // Example 1. Create a stream index buffer of unsigned shorts that is\r\n * // 16 bytes in size.\r\n * var buffer = Buffer.createIndexBuffer({\r\n * context : context,\r\n * sizeInBytes : 16,\r\n * usage : BufferUsage.STREAM_DRAW,\r\n * indexDatatype : IndexDatatype.UNSIGNED_SHORT\r\n * });\r\n *\r\n * @example\r\n * // Example 2. Create a static index buffer containing three unsigned shorts.\r\n * var buffer = Buffer.createIndexBuffer({\r\n * context : context,\r\n * typedArray : new Uint16Array([0, 1, 2]),\r\n * usage : BufferUsage.STATIC_DRAW,\r\n * indexDatatype : IndexDatatype.UNSIGNED_SHORT\r\n * });\r\n *\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGenBuffer.xml|glGenBuffer}\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBindBuffer.xml|glBindBuffer} with ELEMENT_ARRAY_BUFFER\r\n * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glBufferData.xml|glBufferData} with ELEMENT_ARRAY_BUFFER\r\n */\r\nBuffer.createIndexBuffer = function (options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n\r\n if (!IndexDatatype.validate(options.indexDatatype)) {\r\n throw new DeveloperError(\"Invalid indexDatatype.\");\r\n }\r\n\r\n if (\r\n options.indexDatatype === IndexDatatype.UNSIGNED_INT &&\r\n !options.context.elementIndexUint\r\n ) {\r\n throw new DeveloperError(\r\n \"IndexDatatype.UNSIGNED_INT requires OES_element_index_uint, which is not supported on this system. Check context.elementIndexUint.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var context = options.context;\r\n var indexDatatype = options.indexDatatype;\r\n\r\n var bytesPerIndex = IndexDatatype.getSizeInBytes(indexDatatype);\r\n var buffer = new Buffer({\r\n context: context,\r\n bufferTarget: WebGLConstants.ELEMENT_ARRAY_BUFFER,\r\n typedArray: options.typedArray,\r\n sizeInBytes: options.sizeInBytes,\r\n usage: options.usage,\r\n });\r\n\r\n var numberOfIndices = buffer.sizeInBytes / bytesPerIndex;\r\n\r\n Object.defineProperties(buffer, {\r\n indexDatatype: {\r\n get: function () {\r\n return indexDatatype;\r\n },\r\n },\r\n bytesPerIndex: {\r\n get: function () {\r\n return bytesPerIndex;\r\n },\r\n },\r\n numberOfIndices: {\r\n get: function () {\r\n return numberOfIndices;\r\n },\r\n },\r\n });\r\n\r\n return buffer;\r\n};\r\n\r\nObject.defineProperties(Buffer.prototype, {\r\n sizeInBytes: {\r\n get: function () {\r\n return this._sizeInBytes;\r\n },\r\n },\r\n\r\n usage: {\r\n get: function () {\r\n return this._usage;\r\n },\r\n },\r\n});\r\n\r\nBuffer.prototype._getBuffer = function () {\r\n return this._buffer;\r\n};\r\n\r\nBuffer.prototype.copyFromArrayView = function (arrayView, offsetInBytes) {\r\n offsetInBytes = defaultValue(offsetInBytes, 0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"arrayView\", arrayView);\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"offsetInBytes + arrayView.byteLength\",\r\n offsetInBytes + arrayView.byteLength,\r\n this._sizeInBytes\r\n );\r\n //>>includeEnd('debug');\r\n\r\n var gl = this._gl;\r\n var target = this._bufferTarget;\r\n gl.bindBuffer(target, this._buffer);\r\n gl.bufferSubData(target, offsetInBytes, arrayView);\r\n gl.bindBuffer(target, null);\r\n};\r\n\r\nBuffer.prototype.copyFromBuffer = function (\r\n readBuffer,\r\n readOffset,\r\n writeOffset,\r\n sizeInBytes\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this._webgl2) {\r\n throw new DeveloperError(\"A WebGL 2 context is required.\");\r\n }\r\n if (!defined(readBuffer)) {\r\n throw new DeveloperError(\"readBuffer must be defined.\");\r\n }\r\n if (!defined(sizeInBytes) || sizeInBytes <= 0) {\r\n throw new DeveloperError(\r\n \"sizeInBytes must be defined and be greater than zero.\"\r\n );\r\n }\r\n if (\r\n !defined(readOffset) ||\r\n readOffset < 0 ||\r\n readOffset + sizeInBytes > readBuffer._sizeInBytes\r\n ) {\r\n throw new DeveloperError(\r\n \"readOffset must be greater than or equal to zero and readOffset + sizeInBytes must be less than of equal to readBuffer.sizeInBytes.\"\r\n );\r\n }\r\n if (\r\n !defined(writeOffset) ||\r\n writeOffset < 0 ||\r\n writeOffset + sizeInBytes > this._sizeInBytes\r\n ) {\r\n throw new DeveloperError(\r\n \"writeOffset must be greater than or equal to zero and writeOffset + sizeInBytes must be less than of equal to this.sizeInBytes.\"\r\n );\r\n }\r\n if (\r\n this._buffer === readBuffer._buffer &&\r\n ((writeOffset >= readOffset && writeOffset < readOffset + sizeInBytes) ||\r\n (readOffset > writeOffset && readOffset < writeOffset + sizeInBytes))\r\n ) {\r\n throw new DeveloperError(\r\n \"When readBuffer is equal to this, the ranges [readOffset + sizeInBytes) and [writeOffset, writeOffset + sizeInBytes) must not overlap.\"\r\n );\r\n }\r\n if (\r\n (this._bufferTarget === WebGLConstants.ELEMENT_ARRAY_BUFFER &&\r\n readBuffer._bufferTarget !== WebGLConstants.ELEMENT_ARRAY_BUFFER) ||\r\n (this._bufferTarget !== WebGLConstants.ELEMENT_ARRAY_BUFFER &&\r\n readBuffer._bufferTarget === WebGLConstants.ELEMENT_ARRAY_BUFFER)\r\n ) {\r\n throw new DeveloperError(\r\n \"Can not copy an index buffer into another buffer type.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var readTarget = WebGLConstants.COPY_READ_BUFFER;\r\n var writeTarget = WebGLConstants.COPY_WRITE_BUFFER;\r\n\r\n var gl = this._gl;\r\n gl.bindBuffer(writeTarget, this._buffer);\r\n gl.bindBuffer(readTarget, readBuffer._buffer);\r\n gl.copyBufferSubData(\r\n readTarget,\r\n writeTarget,\r\n readOffset,\r\n writeOffset,\r\n sizeInBytes\r\n );\r\n gl.bindBuffer(writeTarget, null);\r\n gl.bindBuffer(readTarget, null);\r\n};\r\n\r\nBuffer.prototype.getBufferData = function (\r\n arrayView,\r\n sourceOffset,\r\n destinationOffset,\r\n length\r\n) {\r\n sourceOffset = defaultValue(sourceOffset, 0);\r\n destinationOffset = defaultValue(destinationOffset, 0);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this._webgl2) {\r\n throw new DeveloperError(\"A WebGL 2 context is required.\");\r\n }\r\n if (!defined(arrayView)) {\r\n throw new DeveloperError(\"arrayView is required.\");\r\n }\r\n\r\n var copyLength;\r\n var elementSize;\r\n var arrayLength = arrayView.byteLength;\r\n if (!defined(length)) {\r\n if (defined(arrayLength)) {\r\n copyLength = arrayLength - destinationOffset;\r\n elementSize = 1;\r\n } else {\r\n arrayLength = arrayView.length;\r\n copyLength = arrayLength - destinationOffset;\r\n elementSize = arrayView.BYTES_PER_ELEMENT;\r\n }\r\n } else {\r\n copyLength = length;\r\n if (defined(arrayLength)) {\r\n elementSize = 1;\r\n } else {\r\n arrayLength = arrayView.length;\r\n elementSize = arrayView.BYTES_PER_ELEMENT;\r\n }\r\n }\r\n\r\n if (destinationOffset < 0 || destinationOffset > arrayLength) {\r\n throw new DeveloperError(\r\n \"destinationOffset must be greater than zero and less than the arrayView length.\"\r\n );\r\n }\r\n if (destinationOffset + copyLength > arrayLength) {\r\n throw new DeveloperError(\r\n \"destinationOffset + length must be less than or equal to the arrayViewLength.\"\r\n );\r\n }\r\n if (sourceOffset < 0 || sourceOffset > this._sizeInBytes) {\r\n throw new DeveloperError(\r\n \"sourceOffset must be greater than zero and less than the buffers size.\"\r\n );\r\n }\r\n if (sourceOffset + copyLength * elementSize > this._sizeInBytes) {\r\n throw new DeveloperError(\r\n \"sourceOffset + length must be less than the buffers size.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var gl = this._gl;\r\n var target = WebGLConstants.COPY_READ_BUFFER;\r\n gl.bindBuffer(target, this._buffer);\r\n gl.getBufferSubData(\r\n target,\r\n sourceOffset,\r\n arrayView,\r\n destinationOffset,\r\n length\r\n );\r\n gl.bindBuffer(target, null);\r\n};\r\n\r\nBuffer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nBuffer.prototype.destroy = function () {\r\n this._gl.deleteBuffer(this._buffer);\r\n return destroyObject(this);\r\n};\r\nexport default Buffer;\r\n","import Check from \"../Core/Check.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Geometry from \"../Core/Geometry.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Buffer from \"./Buffer.js\";\r\nimport BufferUsage from \"./BufferUsage.js\";\r\nimport ContextLimits from \"./ContextLimits.js\";\r\n\r\nfunction addAttribute(attributes, attribute, index, context) {\r\n var hasVertexBuffer = defined(attribute.vertexBuffer);\r\n var hasValue = defined(attribute.value);\r\n var componentsPerAttribute = attribute.value\r\n ? attribute.value.length\r\n : attribute.componentsPerAttribute;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!hasVertexBuffer && !hasValue) {\r\n throw new DeveloperError(\"attribute must have a vertexBuffer or a value.\");\r\n }\r\n if (hasVertexBuffer && hasValue) {\r\n throw new DeveloperError(\r\n \"attribute cannot have both a vertexBuffer and a value. It must have either a vertexBuffer property defining per-vertex data or a value property defining data for all vertices.\"\r\n );\r\n }\r\n if (\r\n componentsPerAttribute !== 1 &&\r\n componentsPerAttribute !== 2 &&\r\n componentsPerAttribute !== 3 &&\r\n componentsPerAttribute !== 4\r\n ) {\r\n if (hasValue) {\r\n throw new DeveloperError(\r\n \"attribute.value.length must be in the range [1, 4].\"\r\n );\r\n }\r\n\r\n throw new DeveloperError(\r\n \"attribute.componentsPerAttribute must be in the range [1, 4].\"\r\n );\r\n }\r\n if (\r\n defined(attribute.componentDatatype) &&\r\n !ComponentDatatype.validate(attribute.componentDatatype)\r\n ) {\r\n throw new DeveloperError(\r\n \"attribute must have a valid componentDatatype or not specify it.\"\r\n );\r\n }\r\n if (defined(attribute.strideInBytes) && attribute.strideInBytes > 255) {\r\n // WebGL limit. Not in GL ES.\r\n throw new DeveloperError(\r\n \"attribute must have a strideInBytes less than or equal to 255 or not specify it.\"\r\n );\r\n }\r\n if (\r\n defined(attribute.instanceDivisor) &&\r\n attribute.instanceDivisor > 0 &&\r\n !context.instancedArrays\r\n ) {\r\n throw new DeveloperError(\"instanced arrays is not supported\");\r\n }\r\n if (defined(attribute.instanceDivisor) && attribute.instanceDivisor < 0) {\r\n throw new DeveloperError(\r\n \"attribute must have an instanceDivisor greater than or equal to zero\"\r\n );\r\n }\r\n if (defined(attribute.instanceDivisor) && hasValue) {\r\n throw new DeveloperError(\r\n \"attribute cannot have have an instanceDivisor if it is not backed by a buffer\"\r\n );\r\n }\r\n if (\r\n defined(attribute.instanceDivisor) &&\r\n attribute.instanceDivisor > 0 &&\r\n attribute.index === 0\r\n ) {\r\n throw new DeveloperError(\r\n \"attribute zero cannot have an instanceDivisor greater than 0\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Shallow copy the attribute; we do not want to copy the vertex buffer.\r\n var attr = {\r\n index: defaultValue(attribute.index, index),\r\n enabled: defaultValue(attribute.enabled, true),\r\n vertexBuffer: attribute.vertexBuffer,\r\n value: hasValue ? attribute.value.slice(0) : undefined,\r\n componentsPerAttribute: componentsPerAttribute,\r\n componentDatatype: defaultValue(\r\n attribute.componentDatatype,\r\n ComponentDatatype.FLOAT\r\n ),\r\n normalize: defaultValue(attribute.normalize, false),\r\n offsetInBytes: defaultValue(attribute.offsetInBytes, 0),\r\n strideInBytes: defaultValue(attribute.strideInBytes, 0),\r\n instanceDivisor: defaultValue(attribute.instanceDivisor, 0),\r\n };\r\n\r\n if (hasVertexBuffer) {\r\n // Common case: vertex buffer for per-vertex data\r\n attr.vertexAttrib = function (gl) {\r\n var index = this.index;\r\n gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer._getBuffer());\r\n gl.vertexAttribPointer(\r\n index,\r\n this.componentsPerAttribute,\r\n this.componentDatatype,\r\n this.normalize,\r\n this.strideInBytes,\r\n this.offsetInBytes\r\n );\r\n gl.enableVertexAttribArray(index);\r\n if (this.instanceDivisor > 0) {\r\n context.glVertexAttribDivisor(index, this.instanceDivisor);\r\n context._vertexAttribDivisors[index] = this.instanceDivisor;\r\n context._previousDrawInstanced = true;\r\n }\r\n };\r\n\r\n attr.disableVertexAttribArray = function (gl) {\r\n gl.disableVertexAttribArray(this.index);\r\n if (this.instanceDivisor > 0) {\r\n context.glVertexAttribDivisor(index, 0);\r\n }\r\n };\r\n } else {\r\n // Less common case: value array for the same data for each vertex\r\n switch (attr.componentsPerAttribute) {\r\n case 1:\r\n attr.vertexAttrib = function (gl) {\r\n gl.vertexAttrib1fv(this.index, this.value);\r\n };\r\n break;\r\n case 2:\r\n attr.vertexAttrib = function (gl) {\r\n gl.vertexAttrib2fv(this.index, this.value);\r\n };\r\n break;\r\n case 3:\r\n attr.vertexAttrib = function (gl) {\r\n gl.vertexAttrib3fv(this.index, this.value);\r\n };\r\n break;\r\n case 4:\r\n attr.vertexAttrib = function (gl) {\r\n gl.vertexAttrib4fv(this.index, this.value);\r\n };\r\n break;\r\n }\r\n\r\n attr.disableVertexAttribArray = function (gl) {};\r\n }\r\n\r\n attributes.push(attr);\r\n}\r\n\r\nfunction bind(gl, attributes, indexBuffer) {\r\n for (var i = 0; i < attributes.length; ++i) {\r\n var attribute = attributes[i];\r\n if (attribute.enabled) {\r\n attribute.vertexAttrib(gl);\r\n }\r\n }\r\n\r\n if (defined(indexBuffer)) {\r\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer._getBuffer());\r\n }\r\n}\r\n\r\n/**\r\n * Creates a vertex array, which defines the attributes making up a vertex, and contains an optional index buffer\r\n * to select vertices for rendering. Attributes are defined using object literals as shown in Example 1 below.\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Context} options.context The context in which the VertexArray gets created.\r\n * @param {Object[]} options.attributes An array of attributes.\r\n * @param {IndexBuffer} [options.indexBuffer] An optional index buffer.\r\n *\r\n * @returns {VertexArray} The vertex array, ready for use with drawing.\r\n *\r\n * @exception {DeveloperError} Attribute must have a vertexBuffer.\r\n * @exception {DeveloperError} Attribute must have a componentsPerAttribute.\r\n * @exception {DeveloperError} Attribute must have a valid componentDatatype or not specify it.\r\n * @exception {DeveloperError} Attribute must have a strideInBytes less than or equal to 255 or not specify it.\r\n * @exception {DeveloperError} Index n is used by more than one attribute.\r\n *\r\n *\r\n * @example\r\n * // Example 1. Create a vertex array with vertices made up of three floating point\r\n * // values, e.g., a position, from a single vertex buffer. No index buffer is used.\r\n * var positionBuffer = Buffer.createVertexBuffer({\r\n * context : context,\r\n * sizeInBytes : 12,\r\n * usage : BufferUsage.STATIC_DRAW\r\n * });\r\n * var attributes = [\r\n * {\r\n * index : 0,\r\n * enabled : true,\r\n * vertexBuffer : positionBuffer,\r\n * componentsPerAttribute : 3,\r\n * componentDatatype : ComponentDatatype.FLOAT,\r\n * normalize : false,\r\n * offsetInBytes : 0,\r\n * strideInBytes : 0 // tightly packed\r\n * instanceDivisor : 0 // not instanced\r\n * }\r\n * ];\r\n * var va = new VertexArray({\r\n * context : context,\r\n * attributes : attributes\r\n * });\r\n *\r\n * @example\r\n * // Example 2. Create a vertex array with vertices from two different vertex buffers.\r\n * // Each vertex has a three-component position and three-component normal.\r\n * var positionBuffer = Buffer.createVertexBuffer({\r\n * context : context,\r\n * sizeInBytes : 12,\r\n * usage : BufferUsage.STATIC_DRAW\r\n * });\r\n * var normalBuffer = Buffer.createVertexBuffer({\r\n * context : context,\r\n * sizeInBytes : 12,\r\n * usage : BufferUsage.STATIC_DRAW\r\n * });\r\n * var attributes = [\r\n * {\r\n * index : 0,\r\n * vertexBuffer : positionBuffer,\r\n * componentsPerAttribute : 3,\r\n * componentDatatype : ComponentDatatype.FLOAT\r\n * },\r\n * {\r\n * index : 1,\r\n * vertexBuffer : normalBuffer,\r\n * componentsPerAttribute : 3,\r\n * componentDatatype : ComponentDatatype.FLOAT\r\n * }\r\n * ];\r\n * var va = new VertexArray({\r\n * context : context,\r\n * attributes : attributes\r\n * });\r\n *\r\n * @example\r\n * // Example 3. Creates the same vertex layout as Example 2 using a single\r\n * // vertex buffer, instead of two.\r\n * var buffer = Buffer.createVertexBuffer({\r\n * context : context,\r\n * sizeInBytes : 24,\r\n * usage : BufferUsage.STATIC_DRAW\r\n * });\r\n * var attributes = [\r\n * {\r\n * vertexBuffer : buffer,\r\n * componentsPerAttribute : 3,\r\n * componentDatatype : ComponentDatatype.FLOAT,\r\n * offsetInBytes : 0,\r\n * strideInBytes : 24\r\n * },\r\n * {\r\n * vertexBuffer : buffer,\r\n * componentsPerAttribute : 3,\r\n * componentDatatype : ComponentDatatype.FLOAT,\r\n * normalize : true,\r\n * offsetInBytes : 12,\r\n * strideInBytes : 24\r\n * }\r\n * ];\r\n * var va = new VertexArray({\r\n * context : context,\r\n * attributes : attributes\r\n * });\r\n *\r\n * @see Buffer#createVertexBuffer\r\n * @see Buffer#createIndexBuffer\r\n * @see Context#draw\r\n *\r\n * @private\r\n */\r\nfunction VertexArray(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n Check.defined(\"options.attributes\", options.attributes);\r\n //>>includeEnd('debug');\r\n\r\n var context = options.context;\r\n var gl = context._gl;\r\n var attributes = options.attributes;\r\n var indexBuffer = options.indexBuffer;\r\n\r\n var i;\r\n var vaAttributes = [];\r\n var numberOfVertices = 1; // if every attribute is backed by a single value\r\n var hasInstancedAttributes = false;\r\n var hasConstantAttributes = false;\r\n\r\n var length = attributes.length;\r\n for (i = 0; i < length; ++i) {\r\n addAttribute(vaAttributes, attributes[i], i, context);\r\n }\r\n\r\n length = vaAttributes.length;\r\n for (i = 0; i < length; ++i) {\r\n var attribute = vaAttributes[i];\r\n\r\n if (defined(attribute.vertexBuffer) && attribute.instanceDivisor === 0) {\r\n // This assumes that each vertex buffer in the vertex array has the same number of vertices.\r\n var bytes =\r\n attribute.strideInBytes ||\r\n attribute.componentsPerAttribute *\r\n ComponentDatatype.getSizeInBytes(attribute.componentDatatype);\r\n numberOfVertices = attribute.vertexBuffer.sizeInBytes / bytes;\r\n break;\r\n }\r\n }\r\n\r\n for (i = 0; i < length; ++i) {\r\n if (vaAttributes[i].instanceDivisor > 0) {\r\n hasInstancedAttributes = true;\r\n }\r\n if (defined(vaAttributes[i].value)) {\r\n hasConstantAttributes = true;\r\n }\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n // Verify all attribute names are unique\r\n var uniqueIndices = {};\r\n for (i = 0; i < length; ++i) {\r\n var index = vaAttributes[i].index;\r\n if (uniqueIndices[index]) {\r\n throw new DeveloperError(\r\n \"Index \" + index + \" is used by more than one attribute.\"\r\n );\r\n }\r\n uniqueIndices[index] = true;\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var vao;\r\n\r\n // Setup VAO if supported\r\n if (context.vertexArrayObject) {\r\n vao = context.glCreateVertexArray();\r\n context.glBindVertexArray(vao);\r\n bind(gl, vaAttributes, indexBuffer);\r\n context.glBindVertexArray(null);\r\n }\r\n\r\n this._numberOfVertices = numberOfVertices;\r\n this._hasInstancedAttributes = hasInstancedAttributes;\r\n this._hasConstantAttributes = hasConstantAttributes;\r\n this._context = context;\r\n this._gl = gl;\r\n this._vao = vao;\r\n this._attributes = vaAttributes;\r\n this._indexBuffer = indexBuffer;\r\n}\r\n\r\nfunction computeNumberOfVertices(attribute) {\r\n return attribute.values.length / attribute.componentsPerAttribute;\r\n}\r\n\r\nfunction computeAttributeSizeInBytes(attribute) {\r\n return (\r\n ComponentDatatype.getSizeInBytes(attribute.componentDatatype) *\r\n attribute.componentsPerAttribute\r\n );\r\n}\r\n\r\nfunction interleaveAttributes(attributes) {\r\n var j;\r\n var name;\r\n var attribute;\r\n\r\n // Extract attribute names.\r\n var names = [];\r\n for (name in attributes) {\r\n // Attribute needs to have per-vertex values; not a constant value for all vertices.\r\n if (\r\n attributes.hasOwnProperty(name) &&\r\n defined(attributes[name]) &&\r\n defined(attributes[name].values)\r\n ) {\r\n names.push(name);\r\n\r\n if (attributes[name].componentDatatype === ComponentDatatype.DOUBLE) {\r\n attributes[name].componentDatatype = ComponentDatatype.FLOAT;\r\n attributes[name].values = ComponentDatatype.createTypedArray(\r\n ComponentDatatype.FLOAT,\r\n attributes[name].values\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Validation. Compute number of vertices.\r\n var numberOfVertices;\r\n var namesLength = names.length;\r\n\r\n if (namesLength > 0) {\r\n numberOfVertices = computeNumberOfVertices(attributes[names[0]]);\r\n\r\n for (j = 1; j < namesLength; ++j) {\r\n var currentNumberOfVertices = computeNumberOfVertices(\r\n attributes[names[j]]\r\n );\r\n\r\n if (currentNumberOfVertices !== numberOfVertices) {\r\n throw new RuntimeError(\r\n \"Each attribute list must have the same number of vertices. \" +\r\n \"Attribute \" +\r\n names[j] +\r\n \" has a different number of vertices \" +\r\n \"(\" +\r\n currentNumberOfVertices.toString() +\r\n \")\" +\r\n \" than attribute \" +\r\n names[0] +\r\n \" (\" +\r\n numberOfVertices.toString() +\r\n \").\"\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Sort attributes by the size of their components. From left to right, a vertex stores floats, shorts, and then bytes.\r\n names.sort(function (left, right) {\r\n return (\r\n ComponentDatatype.getSizeInBytes(attributes[right].componentDatatype) -\r\n ComponentDatatype.getSizeInBytes(attributes[left].componentDatatype)\r\n );\r\n });\r\n\r\n // Compute sizes and strides.\r\n var vertexSizeInBytes = 0;\r\n var offsetsInBytes = {};\r\n\r\n for (j = 0; j < namesLength; ++j) {\r\n name = names[j];\r\n attribute = attributes[name];\r\n\r\n offsetsInBytes[name] = vertexSizeInBytes;\r\n vertexSizeInBytes += computeAttributeSizeInBytes(attribute);\r\n }\r\n\r\n if (vertexSizeInBytes > 0) {\r\n // Pad each vertex to be a multiple of the largest component datatype so each\r\n // attribute can be addressed using typed arrays.\r\n var maxComponentSizeInBytes = ComponentDatatype.getSizeInBytes(\r\n attributes[names[0]].componentDatatype\r\n ); // Sorted large to small\r\n var remainder = vertexSizeInBytes % maxComponentSizeInBytes;\r\n if (remainder !== 0) {\r\n vertexSizeInBytes += maxComponentSizeInBytes - remainder;\r\n }\r\n\r\n // Total vertex buffer size in bytes, including per-vertex padding.\r\n var vertexBufferSizeInBytes = numberOfVertices * vertexSizeInBytes;\r\n\r\n // Create array for interleaved vertices. Each attribute has a different view (pointer) into the array.\r\n var buffer = new ArrayBuffer(vertexBufferSizeInBytes);\r\n var views = {};\r\n\r\n for (j = 0; j < namesLength; ++j) {\r\n name = names[j];\r\n var sizeInBytes = ComponentDatatype.getSizeInBytes(\r\n attributes[name].componentDatatype\r\n );\r\n\r\n views[name] = {\r\n pointer: ComponentDatatype.createTypedArray(\r\n attributes[name].componentDatatype,\r\n buffer\r\n ),\r\n index: offsetsInBytes[name] / sizeInBytes, // Offset in ComponentType\r\n strideInComponentType: vertexSizeInBytes / sizeInBytes,\r\n };\r\n }\r\n\r\n // Copy attributes into one interleaved array.\r\n // PERFORMANCE_IDEA: Can we optimize these loops?\r\n for (j = 0; j < numberOfVertices; ++j) {\r\n for (var n = 0; n < namesLength; ++n) {\r\n name = names[n];\r\n attribute = attributes[name];\r\n var values = attribute.values;\r\n var view = views[name];\r\n var pointer = view.pointer;\r\n\r\n var numberOfComponents = attribute.componentsPerAttribute;\r\n for (var k = 0; k < numberOfComponents; ++k) {\r\n pointer[view.index + k] = values[j * numberOfComponents + k];\r\n }\r\n\r\n view.index += view.strideInComponentType;\r\n }\r\n }\r\n\r\n return {\r\n buffer: buffer,\r\n offsetsInBytes: offsetsInBytes,\r\n vertexSizeInBytes: vertexSizeInBytes,\r\n };\r\n }\r\n\r\n // No attributes to interleave.\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Creates a vertex array from a geometry. A geometry contains vertex attributes and optional index data\r\n * in system memory, whereas a vertex array contains vertex buffers and an optional index buffer in WebGL\r\n * memory for use with rendering.\r\n *

\r\n * The geometry argument should use the standard layout like the geometry returned by {@link BoxGeometry}.\r\n *

\r\n * options can have four properties:\r\n *
    \r\n *
  • geometry: The source geometry containing data used to create the vertex array.
  • \r\n *
  • attributeLocations: An object that maps geometry attribute names to vertex shader attribute locations.
  • \r\n *
  • bufferUsage: The expected usage pattern of the vertex array's buffers. On some WebGL implementations, this can significantly affect performance. See {@link BufferUsage}. Default: BufferUsage.DYNAMIC_DRAW.
  • \r\n *
  • interleave: Determines if all attributes are interleaved in a single vertex buffer or if each attribute is stored in a separate vertex buffer. Default: false.
  • \r\n *
\r\n *
\r\n * If options is not specified or the geometry contains no data, the returned vertex array is empty.\r\n *\r\n * @param {Object} options An object defining the geometry, attribute indices, buffer usage, and vertex layout used to create the vertex array.\r\n *\r\n * @exception {RuntimeError} Each attribute list must have the same number of vertices.\r\n * @exception {DeveloperError} The geometry must have zero or one index lists.\r\n * @exception {DeveloperError} Index n is used by more than one attribute.\r\n *\r\n *\r\n * @example\r\n * // Example 1. Creates a vertex array for rendering a box. The default dynamic draw\r\n * // usage is used for the created vertex and index buffer. The attributes are not\r\n * // interleaved by default.\r\n * var geometry = new BoxGeometry();\r\n * var va = VertexArray.fromGeometry({\r\n * context : context,\r\n * geometry : geometry,\r\n * attributeLocations : GeometryPipeline.createAttributeLocations(geometry),\r\n * });\r\n *\r\n * @example\r\n * // Example 2. Creates a vertex array with interleaved attributes in a\r\n * // single vertex buffer. The vertex and index buffer have static draw usage.\r\n * var va = VertexArray.fromGeometry({\r\n * context : context,\r\n * geometry : geometry,\r\n * attributeLocations : GeometryPipeline.createAttributeLocations(geometry),\r\n * bufferUsage : BufferUsage.STATIC_DRAW,\r\n * interleave : true\r\n * });\r\n *\r\n * @example\r\n * // Example 3. When the caller destroys the vertex array, it also destroys the\r\n * // attached vertex buffer(s) and index buffer.\r\n * va = va.destroy();\r\n *\r\n * @see Buffer#createVertexBuffer\r\n * @see Buffer#createIndexBuffer\r\n * @see GeometryPipeline.createAttributeLocations\r\n * @see ShaderProgram\r\n */\r\nVertexArray.fromGeometry = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", options.context);\r\n //>>includeEnd('debug');\r\n\r\n var context = options.context;\r\n var geometry = defaultValue(options.geometry, defaultValue.EMPTY_OBJECT);\r\n\r\n var bufferUsage = defaultValue(options.bufferUsage, BufferUsage.DYNAMIC_DRAW);\r\n\r\n var attributeLocations = defaultValue(\r\n options.attributeLocations,\r\n defaultValue.EMPTY_OBJECT\r\n );\r\n var interleave = defaultValue(options.interleave, false);\r\n var createdVAAttributes = options.vertexArrayAttributes;\r\n\r\n var name;\r\n var attribute;\r\n var vertexBuffer;\r\n var vaAttributes = defined(createdVAAttributes) ? createdVAAttributes : [];\r\n var attributes = geometry.attributes;\r\n\r\n if (interleave) {\r\n // Use a single vertex buffer with interleaved vertices.\r\n var interleavedAttributes = interleaveAttributes(attributes);\r\n if (defined(interleavedAttributes)) {\r\n vertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: interleavedAttributes.buffer,\r\n usage: bufferUsage,\r\n });\r\n var offsetsInBytes = interleavedAttributes.offsetsInBytes;\r\n var strideInBytes = interleavedAttributes.vertexSizeInBytes;\r\n\r\n for (name in attributes) {\r\n if (attributes.hasOwnProperty(name) && defined(attributes[name])) {\r\n attribute = attributes[name];\r\n\r\n if (defined(attribute.values)) {\r\n // Common case: per-vertex attributes\r\n vaAttributes.push({\r\n index: attributeLocations[name],\r\n vertexBuffer: vertexBuffer,\r\n componentDatatype: attribute.componentDatatype,\r\n componentsPerAttribute: attribute.componentsPerAttribute,\r\n normalize: attribute.normalize,\r\n offsetInBytes: offsetsInBytes[name],\r\n strideInBytes: strideInBytes,\r\n });\r\n } else {\r\n // Constant attribute for all vertices\r\n vaAttributes.push({\r\n index: attributeLocations[name],\r\n value: attribute.value,\r\n componentDatatype: attribute.componentDatatype,\r\n normalize: attribute.normalize,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // One vertex buffer per attribute.\r\n for (name in attributes) {\r\n if (attributes.hasOwnProperty(name) && defined(attributes[name])) {\r\n attribute = attributes[name];\r\n\r\n var componentDatatype = attribute.componentDatatype;\r\n if (componentDatatype === ComponentDatatype.DOUBLE) {\r\n componentDatatype = ComponentDatatype.FLOAT;\r\n }\r\n\r\n vertexBuffer = undefined;\r\n if (defined(attribute.values)) {\r\n vertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: ComponentDatatype.createTypedArray(\r\n componentDatatype,\r\n attribute.values\r\n ),\r\n usage: bufferUsage,\r\n });\r\n }\r\n\r\n vaAttributes.push({\r\n index: attributeLocations[name],\r\n vertexBuffer: vertexBuffer,\r\n value: attribute.value,\r\n componentDatatype: componentDatatype,\r\n componentsPerAttribute: attribute.componentsPerAttribute,\r\n normalize: attribute.normalize,\r\n });\r\n }\r\n }\r\n }\r\n\r\n var indexBuffer;\r\n var indices = geometry.indices;\r\n if (defined(indices)) {\r\n if (\r\n Geometry.computeNumberOfVertices(geometry) >=\r\n CesiumMath.SIXTY_FOUR_KILOBYTES &&\r\n context.elementIndexUint\r\n ) {\r\n indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: new Uint32Array(indices),\r\n usage: bufferUsage,\r\n indexDatatype: IndexDatatype.UNSIGNED_INT,\r\n });\r\n } else {\r\n indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: new Uint16Array(indices),\r\n usage: bufferUsage,\r\n indexDatatype: IndexDatatype.UNSIGNED_SHORT,\r\n });\r\n }\r\n }\r\n\r\n return new VertexArray({\r\n context: context,\r\n attributes: vaAttributes,\r\n indexBuffer: indexBuffer,\r\n });\r\n};\r\n\r\nObject.defineProperties(VertexArray.prototype, {\r\n numberOfAttributes: {\r\n get: function () {\r\n return this._attributes.length;\r\n },\r\n },\r\n numberOfVertices: {\r\n get: function () {\r\n return this._numberOfVertices;\r\n },\r\n },\r\n indexBuffer: {\r\n get: function () {\r\n return this._indexBuffer;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * index is the location in the array of attributes, not the index property of an attribute.\r\n */\r\nVertexArray.prototype.getAttribute = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"index\", index);\r\n //>>includeEnd('debug');\r\n\r\n return this._attributes[index];\r\n};\r\n\r\n// Workaround for ANGLE, where the attribute divisor seems to be part of the global state instead\r\n// of the VAO state. This function is called when the vao is bound, and should be removed\r\n// once the ANGLE issue is resolved. Setting the divisor should normally happen in vertexAttrib and\r\n// disableVertexAttribArray.\r\nfunction setVertexAttribDivisor(vertexArray) {\r\n var context = vertexArray._context;\r\n var hasInstancedAttributes = vertexArray._hasInstancedAttributes;\r\n if (!hasInstancedAttributes && !context._previousDrawInstanced) {\r\n return;\r\n }\r\n context._previousDrawInstanced = hasInstancedAttributes;\r\n\r\n var divisors = context._vertexAttribDivisors;\r\n var attributes = vertexArray._attributes;\r\n var maxAttributes = ContextLimits.maximumVertexAttributes;\r\n var i;\r\n\r\n if (hasInstancedAttributes) {\r\n var length = attributes.length;\r\n for (i = 0; i < length; ++i) {\r\n var attribute = attributes[i];\r\n if (attribute.enabled) {\r\n var divisor = attribute.instanceDivisor;\r\n var index = attribute.index;\r\n if (divisor !== divisors[index]) {\r\n context.glVertexAttribDivisor(index, divisor);\r\n divisors[index] = divisor;\r\n }\r\n }\r\n }\r\n } else {\r\n for (i = 0; i < maxAttributes; ++i) {\r\n if (divisors[i] > 0) {\r\n context.glVertexAttribDivisor(i, 0);\r\n divisors[i] = 0;\r\n }\r\n }\r\n }\r\n}\r\n\r\n// Vertex attributes backed by a constant value go through vertexAttrib[1234]f[v]\r\n// which is part of context state rather than VAO state.\r\nfunction setConstantAttributes(vertexArray, gl) {\r\n var attributes = vertexArray._attributes;\r\n var length = attributes.length;\r\n for (var i = 0; i < length; ++i) {\r\n var attribute = attributes[i];\r\n if (attribute.enabled && defined(attribute.value)) {\r\n attribute.vertexAttrib(gl);\r\n }\r\n }\r\n}\r\n\r\nVertexArray.prototype._bind = function () {\r\n if (defined(this._vao)) {\r\n this._context.glBindVertexArray(this._vao);\r\n if (this._context.instancedArrays) {\r\n setVertexAttribDivisor(this);\r\n }\r\n if (this._hasConstantAttributes) {\r\n setConstantAttributes(this, this._gl);\r\n }\r\n } else {\r\n bind(this._gl, this._attributes, this._indexBuffer);\r\n }\r\n};\r\n\r\nVertexArray.prototype._unBind = function () {\r\n if (defined(this._vao)) {\r\n this._context.glBindVertexArray(null);\r\n } else {\r\n var attributes = this._attributes;\r\n var gl = this._gl;\r\n\r\n for (var i = 0; i < attributes.length; ++i) {\r\n var attribute = attributes[i];\r\n if (attribute.enabled) {\r\n attribute.disableVertexAttribArray(gl);\r\n }\r\n }\r\n if (this._indexBuffer) {\r\n gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);\r\n }\r\n }\r\n};\r\n\r\nVertexArray.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nVertexArray.prototype.destroy = function () {\r\n var attributes = this._attributes;\r\n for (var i = 0; i < attributes.length; ++i) {\r\n var vertexBuffer = attributes[i].vertexBuffer;\r\n if (\r\n defined(vertexBuffer) &&\r\n !vertexBuffer.isDestroyed() &&\r\n vertexBuffer.vertexArrayDestroyable\r\n ) {\r\n vertexBuffer.destroy();\r\n }\r\n }\r\n\r\n var indexBuffer = this._indexBuffer;\r\n if (\r\n defined(indexBuffer) &&\r\n !indexBuffer.isDestroyed() &&\r\n indexBuffer.vertexArrayDestroyable\r\n ) {\r\n indexBuffer.destroy();\r\n }\r\n\r\n if (defined(this._vao)) {\r\n this._context.glDeleteVertexArray(this._vao);\r\n }\r\n\r\n return destroyObject(this);\r\n};\r\nexport default VertexArray;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport ContextLimits from \"../Renderer/ContextLimits.js\";\r\nimport PixelDatatype from \"../Renderer/PixelDatatype.js\";\r\nimport Sampler from \"../Renderer/Sampler.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\n\r\n/**\r\n * Creates a texture to look up per instance attributes for batched primitives. For example, store each primitive's pick color in the texture.\r\n *\r\n * @alias BatchTable\r\n * @constructor\r\n * @private\r\n *\r\n * @param {Context} context The context in which the batch table is created.\r\n * @param {Object[]} attributes An array of objects describing a per instance attribute. Each object contains a datatype, components per attributes, whether it is normalized and a function name\r\n * to retrieve the value in the vertex shader.\r\n * @param {Number} numberOfInstances The number of instances in a batch table.\r\n *\r\n * @example\r\n * // create the batch table\r\n * var attributes = [{\r\n * functionName : 'getShow',\r\n * componentDatatype : ComponentDatatype.UNSIGNED_BYTE,\r\n * componentsPerAttribute : 1\r\n * }, {\r\n * functionName : 'getPickColor',\r\n * componentDatatype : ComponentDatatype.UNSIGNED_BYTE,\r\n * componentsPerAttribute : 4,\r\n * normalize : true\r\n * }];\r\n * var batchTable = new BatchTable(context, attributes, 5);\r\n *\r\n * // when creating the draw commands, update the uniform map and the vertex shader\r\n * vertexShaderSource = batchTable.getVertexShaderCallback()(vertexShaderSource);\r\n * var shaderProgram = ShaderProgram.fromCache({\r\n * // ...\r\n * vertexShaderSource : vertexShaderSource,\r\n * });\r\n *\r\n * drawCommand.shaderProgram = shaderProgram;\r\n * drawCommand.uniformMap = batchTable.getUniformMapCallback()(uniformMap);\r\n *\r\n * // use the attribute function names in the shader to retrieve the instance values\r\n * // ...\r\n * attribute float batchId;\r\n *\r\n * void main() {\r\n * // ...\r\n * float show = getShow(batchId);\r\n * vec3 pickColor = getPickColor(batchId);\r\n * // ...\r\n * }\r\n */\r\nfunction BatchTable(context, attributes, numberOfInstances) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(context)) {\r\n throw new DeveloperError(\"context is required\");\r\n }\r\n if (!defined(attributes)) {\r\n throw new DeveloperError(\"attributes is required\");\r\n }\r\n if (!defined(numberOfInstances)) {\r\n throw new DeveloperError(\"numberOfInstances is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._attributes = attributes;\r\n this._numberOfInstances = numberOfInstances;\r\n\r\n if (attributes.length === 0) {\r\n return;\r\n }\r\n\r\n // PERFORMANCE_IDEA: We may be able to arrange the attributes so they can be packing into fewer texels.\r\n // Right now, an attribute with one component uses an entire texel when 4 single component attributes can\r\n // be packed into a texel.\r\n //\r\n // Packing floats into unsigned byte textures makes the problem worse. A single component float attribute\r\n // will be packed into a single texel leaving 3 texels unused. 4 texels are reserved for each float attribute\r\n // regardless of how many components it has.\r\n var pixelDatatype = getDatatype(attributes);\r\n var textureFloatSupported = context.floatingPointTexture;\r\n var packFloats =\r\n pixelDatatype === PixelDatatype.FLOAT && !textureFloatSupported;\r\n var offsets = createOffsets(attributes, packFloats);\r\n\r\n var stride = getStride(offsets, attributes, packFloats);\r\n var maxNumberOfInstancesPerRow = Math.floor(\r\n ContextLimits.maximumTextureSize / stride\r\n );\r\n\r\n var instancesPerWidth = Math.min(\r\n numberOfInstances,\r\n maxNumberOfInstancesPerRow\r\n );\r\n var width = stride * instancesPerWidth;\r\n var height = Math.ceil(numberOfInstances / instancesPerWidth);\r\n\r\n var stepX = 1.0 / width;\r\n var centerX = stepX * 0.5;\r\n var stepY = 1.0 / height;\r\n var centerY = stepY * 0.5;\r\n\r\n this._textureDimensions = new Cartesian2(width, height);\r\n this._textureStep = new Cartesian4(stepX, centerX, stepY, centerY);\r\n this._pixelDatatype = !packFloats\r\n ? pixelDatatype\r\n : PixelDatatype.UNSIGNED_BYTE;\r\n this._packFloats = packFloats;\r\n this._offsets = offsets;\r\n this._stride = stride;\r\n this._texture = undefined;\r\n\r\n var batchLength = 4 * width * height;\r\n this._batchValues =\r\n pixelDatatype === PixelDatatype.FLOAT && !packFloats\r\n ? new Float32Array(batchLength)\r\n : new Uint8Array(batchLength);\r\n this._batchValuesDirty = false;\r\n}\r\n\r\nObject.defineProperties(BatchTable.prototype, {\r\n /**\r\n * The attribute descriptions.\r\n * @memberOf BatchTable.prototype\r\n * @type {Object[]}\r\n * @readonly\r\n */\r\n attributes: {\r\n get: function () {\r\n return this._attributes;\r\n },\r\n },\r\n /**\r\n * The number of instances.\r\n * @memberOf BatchTable.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n numberOfInstances: {\r\n get: function () {\r\n return this._numberOfInstances;\r\n },\r\n },\r\n});\r\n\r\nfunction getDatatype(attributes) {\r\n var foundFloatDatatype = false;\r\n var length = attributes.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (attributes[i].componentDatatype !== ComponentDatatype.UNSIGNED_BYTE) {\r\n foundFloatDatatype = true;\r\n break;\r\n }\r\n }\r\n return foundFloatDatatype ? PixelDatatype.FLOAT : PixelDatatype.UNSIGNED_BYTE;\r\n}\r\n\r\nfunction getAttributeType(attributes, attributeIndex) {\r\n var componentsPerAttribute =\r\n attributes[attributeIndex].componentsPerAttribute;\r\n if (componentsPerAttribute === 2) {\r\n return Cartesian2;\r\n } else if (componentsPerAttribute === 3) {\r\n return Cartesian3;\r\n } else if (componentsPerAttribute === 4) {\r\n return Cartesian4;\r\n }\r\n return Number;\r\n}\r\n\r\nfunction createOffsets(attributes, packFloats) {\r\n var offsets = new Array(attributes.length);\r\n\r\n var currentOffset = 0;\r\n var attributesLength = attributes.length;\r\n for (var i = 0; i < attributesLength; ++i) {\r\n var attribute = attributes[i];\r\n var componentDatatype = attribute.componentDatatype;\r\n\r\n offsets[i] = currentOffset;\r\n\r\n if (componentDatatype !== ComponentDatatype.UNSIGNED_BYTE && packFloats) {\r\n currentOffset += 4;\r\n } else {\r\n ++currentOffset;\r\n }\r\n }\r\n\r\n return offsets;\r\n}\r\n\r\nfunction getStride(offsets, attributes, packFloats) {\r\n var length = offsets.length;\r\n var lastOffset = offsets[length - 1];\r\n var lastAttribute = attributes[length - 1];\r\n var componentDatatype = lastAttribute.componentDatatype;\r\n\r\n if (componentDatatype !== ComponentDatatype.UNSIGNED_BYTE && packFloats) {\r\n return lastOffset + 4;\r\n }\r\n return lastOffset + 1;\r\n}\r\n\r\nvar scratchPackedFloatCartesian4 = new Cartesian4();\r\n\r\nfunction getPackedFloat(array, index, result) {\r\n var packed = Cartesian4.unpack(array, index, scratchPackedFloatCartesian4);\r\n var x = Cartesian4.unpackFloat(packed);\r\n\r\n packed = Cartesian4.unpack(array, index + 4, scratchPackedFloatCartesian4);\r\n var y = Cartesian4.unpackFloat(packed);\r\n\r\n packed = Cartesian4.unpack(array, index + 8, scratchPackedFloatCartesian4);\r\n var z = Cartesian4.unpackFloat(packed);\r\n\r\n packed = Cartesian4.unpack(array, index + 12, scratchPackedFloatCartesian4);\r\n var w = Cartesian4.unpackFloat(packed);\r\n\r\n return Cartesian4.fromElements(x, y, z, w, result);\r\n}\r\n\r\nfunction setPackedAttribute(value, array, index) {\r\n var packed = Cartesian4.packFloat(value.x, scratchPackedFloatCartesian4);\r\n Cartesian4.pack(packed, array, index);\r\n\r\n packed = Cartesian4.packFloat(value.y, packed);\r\n Cartesian4.pack(packed, array, index + 4);\r\n\r\n packed = Cartesian4.packFloat(value.z, packed);\r\n Cartesian4.pack(packed, array, index + 8);\r\n\r\n packed = Cartesian4.packFloat(value.w, packed);\r\n Cartesian4.pack(packed, array, index + 12);\r\n}\r\n\r\nvar scratchGetAttributeCartesian4 = new Cartesian4();\r\n\r\n/**\r\n * Gets the value of an attribute in the table.\r\n *\r\n * @param {Number} instanceIndex The index of the instance.\r\n * @param {Number} attributeIndex The index of the attribute.\r\n * @param {undefined|Cartesian2|Cartesian3|Cartesian4} [result] The object onto which to store the result. The type is dependent on the attribute's number of components.\r\n * @returns {Number|Cartesian2|Cartesian3|Cartesian4} The attribute value stored for the instance.\r\n *\r\n * @exception {DeveloperError} instanceIndex is out of range.\r\n * @exception {DeveloperError} attributeIndex is out of range.\r\n */\r\nBatchTable.prototype.getBatchedAttribute = function (\r\n instanceIndex,\r\n attributeIndex,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) {\r\n throw new DeveloperError(\"instanceIndex is out of range.\");\r\n }\r\n if (attributeIndex < 0 || attributeIndex >= this._attributes.length) {\r\n throw new DeveloperError(\"attributeIndex is out of range\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var attributes = this._attributes;\r\n var offset = this._offsets[attributeIndex];\r\n var stride = this._stride;\r\n\r\n var index = 4 * stride * instanceIndex + 4 * offset;\r\n var value;\r\n\r\n if (\r\n this._packFloats &&\r\n attributes[attributeIndex].componentDatatype !== PixelDatatype.UNSIGNED_BYTE\r\n ) {\r\n value = getPackedFloat(\r\n this._batchValues,\r\n index,\r\n scratchGetAttributeCartesian4\r\n );\r\n } else {\r\n value = Cartesian4.unpack(\r\n this._batchValues,\r\n index,\r\n scratchGetAttributeCartesian4\r\n );\r\n }\r\n\r\n var attributeType = getAttributeType(attributes, attributeIndex);\r\n if (defined(attributeType.fromCartesian4)) {\r\n return attributeType.fromCartesian4(value, result);\r\n } else if (defined(attributeType.clone)) {\r\n return attributeType.clone(value, result);\r\n }\r\n\r\n return value.x;\r\n};\r\n\r\nvar setAttributeScratchValues = [\r\n undefined,\r\n undefined,\r\n new Cartesian2(),\r\n new Cartesian3(),\r\n new Cartesian4(),\r\n];\r\nvar setAttributeScratchCartesian4 = new Cartesian4();\r\n\r\n/**\r\n * Sets the value of an attribute in the table.\r\n *\r\n * @param {Number} instanceIndex The index of the instance.\r\n * @param {Number} attributeIndex The index of the attribute.\r\n * @param {Number|Cartesian2|Cartesian3|Cartesian4} value The value to be stored in the table. The type of value will depend on the number of components of the attribute.\r\n *\r\n * @exception {DeveloperError} instanceIndex is out of range.\r\n * @exception {DeveloperError} attributeIndex is out of range.\r\n */\r\nBatchTable.prototype.setBatchedAttribute = function (\r\n instanceIndex,\r\n attributeIndex,\r\n value\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (instanceIndex < 0 || instanceIndex >= this._numberOfInstances) {\r\n throw new DeveloperError(\"instanceIndex is out of range.\");\r\n }\r\n if (attributeIndex < 0 || attributeIndex >= this._attributes.length) {\r\n throw new DeveloperError(\"attributeIndex is out of range\");\r\n }\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var attributes = this._attributes;\r\n var result =\r\n setAttributeScratchValues[\r\n attributes[attributeIndex].componentsPerAttribute\r\n ];\r\n var currentAttribute = this.getBatchedAttribute(\r\n instanceIndex,\r\n attributeIndex,\r\n result\r\n );\r\n var attributeType = getAttributeType(this._attributes, attributeIndex);\r\n var entriesEqual = defined(attributeType.equals)\r\n ? attributeType.equals(currentAttribute, value)\r\n : currentAttribute === value;\r\n if (entriesEqual) {\r\n return;\r\n }\r\n\r\n var attributeValue = setAttributeScratchCartesian4;\r\n attributeValue.x = defined(value.x) ? value.x : value;\r\n attributeValue.y = defined(value.y) ? value.y : 0.0;\r\n attributeValue.z = defined(value.z) ? value.z : 0.0;\r\n attributeValue.w = defined(value.w) ? value.w : 0.0;\r\n\r\n var offset = this._offsets[attributeIndex];\r\n var stride = this._stride;\r\n var index = 4 * stride * instanceIndex + 4 * offset;\r\n\r\n if (\r\n this._packFloats &&\r\n attributes[attributeIndex].componentDatatype !== PixelDatatype.UNSIGNED_BYTE\r\n ) {\r\n setPackedAttribute(attributeValue, this._batchValues, index);\r\n } else {\r\n Cartesian4.pack(attributeValue, this._batchValues, index);\r\n }\r\n\r\n this._batchValuesDirty = true;\r\n};\r\n\r\nfunction createTexture(batchTable, context) {\r\n var dimensions = batchTable._textureDimensions;\r\n batchTable._texture = new Texture({\r\n context: context,\r\n pixelFormat: PixelFormat.RGBA,\r\n pixelDatatype: batchTable._pixelDatatype,\r\n width: dimensions.x,\r\n height: dimensions.y,\r\n sampler: Sampler.NEAREST,\r\n flipY: false,\r\n });\r\n}\r\n\r\nfunction updateTexture(batchTable) {\r\n var dimensions = batchTable._textureDimensions;\r\n batchTable._texture.copyFrom({\r\n width: dimensions.x,\r\n height: dimensions.y,\r\n arrayBufferView: batchTable._batchValues,\r\n });\r\n}\r\n\r\n/**\r\n * Creates/updates the batch table texture.\r\n * @param {FrameState} frameState The frame state.\r\n *\r\n * @exception {RuntimeError} The floating point texture extension is required but not supported.\r\n */\r\nBatchTable.prototype.update = function (frameState) {\r\n if (\r\n (defined(this._texture) && !this._batchValuesDirty) ||\r\n this._attributes.length === 0\r\n ) {\r\n return;\r\n }\r\n\r\n this._batchValuesDirty = false;\r\n\r\n if (!defined(this._texture)) {\r\n createTexture(this, frameState.context);\r\n }\r\n updateTexture(this);\r\n};\r\n\r\n/**\r\n * Gets a function that will update a uniform map to contain values for looking up values in the batch table.\r\n *\r\n * @returns {BatchTable.updateUniformMapCallback} A callback for updating uniform maps.\r\n */\r\nBatchTable.prototype.getUniformMapCallback = function () {\r\n var that = this;\r\n return function (uniformMap) {\r\n if (that._attributes.length === 0) {\r\n return uniformMap;\r\n }\r\n\r\n var batchUniformMap = {\r\n batchTexture: function () {\r\n return that._texture;\r\n },\r\n batchTextureDimensions: function () {\r\n return that._textureDimensions;\r\n },\r\n batchTextureStep: function () {\r\n return that._textureStep;\r\n },\r\n };\r\n return combine(uniformMap, batchUniformMap);\r\n };\r\n};\r\n\r\nfunction getGlslComputeSt(batchTable) {\r\n var stride = batchTable._stride;\r\n\r\n // GLSL batchId is zero-based: [0, numberOfInstances - 1]\r\n if (batchTable._textureDimensions.y === 1) {\r\n return (\r\n \"uniform vec4 batchTextureStep; \\n\" +\r\n \"vec2 computeSt(float batchId) \\n\" +\r\n \"{ \\n\" +\r\n \" float stepX = batchTextureStep.x; \\n\" +\r\n \" float centerX = batchTextureStep.y; \\n\" +\r\n \" float numberOfAttributes = float(\" +\r\n stride +\r\n \"); \\n\" +\r\n \" return vec2(centerX + (batchId * numberOfAttributes * stepX), 0.5); \\n\" +\r\n \"} \\n\"\r\n );\r\n }\r\n\r\n return (\r\n \"uniform vec4 batchTextureStep; \\n\" +\r\n \"uniform vec2 batchTextureDimensions; \\n\" +\r\n \"vec2 computeSt(float batchId) \\n\" +\r\n \"{ \\n\" +\r\n \" float stepX = batchTextureStep.x; \\n\" +\r\n \" float centerX = batchTextureStep.y; \\n\" +\r\n \" float stepY = batchTextureStep.z; \\n\" +\r\n \" float centerY = batchTextureStep.w; \\n\" +\r\n \" float numberOfAttributes = float(\" +\r\n stride +\r\n \"); \\n\" +\r\n \" float xId = mod(batchId * numberOfAttributes, batchTextureDimensions.x); \\n\" +\r\n \" float yId = floor(batchId * numberOfAttributes / batchTextureDimensions.x); \\n\" +\r\n \" return vec2(centerX + (xId * stepX), centerY + (yId * stepY)); \\n\" +\r\n \"} \\n\"\r\n );\r\n}\r\n\r\nfunction getComponentType(componentsPerAttribute) {\r\n if (componentsPerAttribute === 1) {\r\n return \"float\";\r\n }\r\n return \"vec\" + componentsPerAttribute;\r\n}\r\n\r\nfunction getComponentSwizzle(componentsPerAttribute) {\r\n if (componentsPerAttribute === 1) {\r\n return \".x\";\r\n } else if (componentsPerAttribute === 2) {\r\n return \".xy\";\r\n } else if (componentsPerAttribute === 3) {\r\n return \".xyz\";\r\n }\r\n return \"\";\r\n}\r\n\r\nfunction getGlslAttributeFunction(batchTable, attributeIndex) {\r\n var attributes = batchTable._attributes;\r\n var attribute = attributes[attributeIndex];\r\n var componentsPerAttribute = attribute.componentsPerAttribute;\r\n var functionName = attribute.functionName;\r\n var functionReturnType = getComponentType(componentsPerAttribute);\r\n var functionReturnValue = getComponentSwizzle(componentsPerAttribute);\r\n\r\n var offset = batchTable._offsets[attributeIndex];\r\n\r\n var glslFunction =\r\n functionReturnType +\r\n \" \" +\r\n functionName +\r\n \"(float batchId) \\n\" +\r\n \"{ \\n\" +\r\n \" vec2 st = computeSt(batchId); \\n\" +\r\n \" st.x += batchTextureStep.x * float(\" +\r\n offset +\r\n \"); \\n\";\r\n\r\n if (\r\n batchTable._packFloats &&\r\n attribute.componentDatatype !== PixelDatatype.UNSIGNED_BYTE\r\n ) {\r\n glslFunction +=\r\n \"vec4 textureValue; \\n\" +\r\n \"textureValue.x = czm_unpackFloat(texture2D(batchTexture, st)); \\n\" +\r\n \"textureValue.y = czm_unpackFloat(texture2D(batchTexture, st + vec2(batchTextureStep.x, 0.0))); \\n\" +\r\n \"textureValue.z = czm_unpackFloat(texture2D(batchTexture, st + vec2(batchTextureStep.x * 2.0, 0.0))); \\n\" +\r\n \"textureValue.w = czm_unpackFloat(texture2D(batchTexture, st + vec2(batchTextureStep.x * 3.0, 0.0))); \\n\";\r\n } else {\r\n glslFunction += \" vec4 textureValue = texture2D(batchTexture, st); \\n\";\r\n }\r\n\r\n glslFunction +=\r\n \" \" +\r\n functionReturnType +\r\n \" value = textureValue\" +\r\n functionReturnValue +\r\n \"; \\n\";\r\n\r\n if (\r\n batchTable._pixelDatatype === PixelDatatype.UNSIGNED_BYTE &&\r\n attribute.componentDatatype === ComponentDatatype.UNSIGNED_BYTE &&\r\n !attribute.normalize\r\n ) {\r\n glslFunction += \"value *= 255.0; \\n\";\r\n } else if (\r\n batchTable._pixelDatatype === PixelDatatype.FLOAT &&\r\n attribute.componentDatatype === ComponentDatatype.UNSIGNED_BYTE &&\r\n attribute.normalize\r\n ) {\r\n glslFunction += \"value /= 255.0; \\n\";\r\n }\r\n\r\n glslFunction += \" return value; \\n\" + \"} \\n\";\r\n return glslFunction;\r\n}\r\n\r\n/**\r\n * Gets a function that will update a vertex shader to contain functions for looking up values in the batch table.\r\n *\r\n * @returns {BatchTable.updateVertexShaderSourceCallback} A callback for updating a vertex shader source.\r\n */\r\nBatchTable.prototype.getVertexShaderCallback = function () {\r\n var attributes = this._attributes;\r\n if (attributes.length === 0) {\r\n return function (source) {\r\n return source;\r\n };\r\n }\r\n\r\n var batchTableShader = \"uniform highp sampler2D batchTexture; \\n\";\r\n batchTableShader += getGlslComputeSt(this) + \"\\n\";\r\n\r\n var length = attributes.length;\r\n for (var i = 0; i < length; ++i) {\r\n batchTableShader += getGlslAttributeFunction(this, i);\r\n }\r\n\r\n return function (source) {\r\n var mainIndex = source.indexOf(\"void main\");\r\n var beforeMain = source.substring(0, mainIndex);\r\n var afterMain = source.substring(mainIndex);\r\n return beforeMain + \"\\n\" + batchTableShader + \"\\n\" + afterMain;\r\n };\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see BatchTable#destroy\r\n */\r\nBatchTable.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see BatchTable#isDestroyed\r\n */\r\nBatchTable.prototype.destroy = function () {\r\n this._texture = this._texture && this._texture.destroy();\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * A callback for updating uniform maps.\r\n * @callback BatchTable.updateUniformMapCallback\r\n *\r\n * @param {Object} uniformMap The uniform map.\r\n * @returns {Object} The new uniform map with properties for retrieving values from the batch table.\r\n */\r\n\r\n/**\r\n * A callback for updating a vertex shader source.\r\n * @callback BatchTable.updateVertexShaderSourceCallback\r\n *\r\n * @param {String} vertexShaderSource The vertex shader source.\r\n * @returns {String} The new vertex shader source with the functions for retrieving batch table values injected.\r\n */\r\nexport default BatchTable;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport GeographicProjection from \"../Core/GeographicProjection.js\";\r\nimport Geometry from \"../Core/Geometry.js\";\r\nimport GeometryAttribute from \"../Core/GeometryAttribute.js\";\r\nimport GeometryAttributes from \"../Core/GeometryAttributes.js\";\r\nimport GeometryPipeline from \"../Core/GeometryPipeline.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport WebMercatorProjection from \"../Core/WebMercatorProjection.js\";\r\n\r\nfunction transformToWorldCoordinates(\r\n instances,\r\n primitiveModelMatrix,\r\n scene3DOnly\r\n) {\r\n var toWorld = !scene3DOnly;\r\n var length = instances.length;\r\n var i;\r\n\r\n if (!toWorld && length > 1) {\r\n var modelMatrix = instances[0].modelMatrix;\r\n\r\n for (i = 1; i < length; ++i) {\r\n if (!Matrix4.equals(modelMatrix, instances[i].modelMatrix)) {\r\n toWorld = true;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (toWorld) {\r\n for (i = 0; i < length; ++i) {\r\n if (defined(instances[i].geometry)) {\r\n GeometryPipeline.transformToWorldCoordinates(instances[i]);\r\n }\r\n }\r\n } else {\r\n // Leave geometry in local coordinate system; auto update model-matrix.\r\n Matrix4.multiplyTransformation(\r\n primitiveModelMatrix,\r\n instances[0].modelMatrix,\r\n primitiveModelMatrix\r\n );\r\n }\r\n}\r\n\r\nfunction addGeometryBatchId(geometry, batchId) {\r\n var attributes = geometry.attributes;\r\n var positionAttr = attributes.position;\r\n var numberOfComponents =\r\n positionAttr.values.length / positionAttr.componentsPerAttribute;\r\n\r\n attributes.batchId = new GeometryAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 1,\r\n values: new Float32Array(numberOfComponents),\r\n });\r\n\r\n var values = attributes.batchId.values;\r\n for (var j = 0; j < numberOfComponents; ++j) {\r\n values[j] = batchId;\r\n }\r\n}\r\n\r\nfunction addBatchIds(instances) {\r\n var length = instances.length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var instance = instances[i];\r\n if (defined(instance.geometry)) {\r\n addGeometryBatchId(instance.geometry, i);\r\n } else if (\r\n defined(instance.westHemisphereGeometry) &&\r\n defined(instance.eastHemisphereGeometry)\r\n ) {\r\n addGeometryBatchId(instance.westHemisphereGeometry, i);\r\n addGeometryBatchId(instance.eastHemisphereGeometry, i);\r\n }\r\n }\r\n}\r\n\r\nfunction geometryPipeline(parameters) {\r\n var instances = parameters.instances;\r\n var projection = parameters.projection;\r\n var uintIndexSupport = parameters.elementIndexUintSupported;\r\n var scene3DOnly = parameters.scene3DOnly;\r\n var vertexCacheOptimize = parameters.vertexCacheOptimize;\r\n var compressVertices = parameters.compressVertices;\r\n var modelMatrix = parameters.modelMatrix;\r\n\r\n var i;\r\n var geometry;\r\n var primitiveType;\r\n var length = instances.length;\r\n\r\n for (i = 0; i < length; ++i) {\r\n if (defined(instances[i].geometry)) {\r\n primitiveType = instances[i].geometry.primitiveType;\r\n break;\r\n }\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n for (i = 1; i < length; ++i) {\r\n if (\r\n defined(instances[i].geometry) &&\r\n instances[i].geometry.primitiveType !== primitiveType\r\n ) {\r\n throw new DeveloperError(\r\n \"All instance geometries must have the same primitiveType.\"\r\n );\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Unify to world coordinates before combining.\r\n transformToWorldCoordinates(instances, modelMatrix, scene3DOnly);\r\n\r\n // Clip to IDL\r\n if (!scene3DOnly) {\r\n for (i = 0; i < length; ++i) {\r\n if (defined(instances[i].geometry)) {\r\n GeometryPipeline.splitLongitude(instances[i]);\r\n }\r\n }\r\n }\r\n\r\n addBatchIds(instances);\r\n\r\n // Optimize for vertex shader caches\r\n if (vertexCacheOptimize) {\r\n for (i = 0; i < length; ++i) {\r\n var instance = instances[i];\r\n if (defined(instance.geometry)) {\r\n GeometryPipeline.reorderForPostVertexCache(instance.geometry);\r\n GeometryPipeline.reorderForPreVertexCache(instance.geometry);\r\n } else if (\r\n defined(instance.westHemisphereGeometry) &&\r\n defined(instance.eastHemisphereGeometry)\r\n ) {\r\n GeometryPipeline.reorderForPostVertexCache(\r\n instance.westHemisphereGeometry\r\n );\r\n GeometryPipeline.reorderForPreVertexCache(\r\n instance.westHemisphereGeometry\r\n );\r\n\r\n GeometryPipeline.reorderForPostVertexCache(\r\n instance.eastHemisphereGeometry\r\n );\r\n GeometryPipeline.reorderForPreVertexCache(\r\n instance.eastHemisphereGeometry\r\n );\r\n }\r\n }\r\n }\r\n\r\n // Combine into single geometry for better rendering performance.\r\n var geometries = GeometryPipeline.combineInstances(instances);\r\n\r\n length = geometries.length;\r\n for (i = 0; i < length; ++i) {\r\n geometry = geometries[i];\r\n\r\n // Split positions for GPU RTE\r\n var attributes = geometry.attributes;\r\n var name;\r\n if (!scene3DOnly) {\r\n for (name in attributes) {\r\n if (\r\n attributes.hasOwnProperty(name) &&\r\n attributes[name].componentDatatype === ComponentDatatype.DOUBLE\r\n ) {\r\n var name3D = name + \"3D\";\r\n var name2D = name + \"2D\";\r\n\r\n // Compute 2D positions\r\n GeometryPipeline.projectTo2D(\r\n geometry,\r\n name,\r\n name3D,\r\n name2D,\r\n projection\r\n );\r\n if (defined(geometry.boundingSphere) && name === \"position\") {\r\n geometry.boundingSphereCV = BoundingSphere.fromVertices(\r\n geometry.attributes.position2D.values\r\n );\r\n }\r\n\r\n GeometryPipeline.encodeAttribute(\r\n geometry,\r\n name3D,\r\n name3D + \"High\",\r\n name3D + \"Low\"\r\n );\r\n GeometryPipeline.encodeAttribute(\r\n geometry,\r\n name2D,\r\n name2D + \"High\",\r\n name2D + \"Low\"\r\n );\r\n }\r\n }\r\n } else {\r\n for (name in attributes) {\r\n if (\r\n attributes.hasOwnProperty(name) &&\r\n attributes[name].componentDatatype === ComponentDatatype.DOUBLE\r\n ) {\r\n GeometryPipeline.encodeAttribute(\r\n geometry,\r\n name,\r\n name + \"3DHigh\",\r\n name + \"3DLow\"\r\n );\r\n }\r\n }\r\n }\r\n\r\n // oct encode and pack normals, compress texture coordinates\r\n if (compressVertices) {\r\n GeometryPipeline.compressVertices(geometry);\r\n }\r\n }\r\n\r\n if (!uintIndexSupport) {\r\n // Break into multiple geometries to fit within unsigned short indices if needed\r\n var splitGeometries = [];\r\n length = geometries.length;\r\n for (i = 0; i < length; ++i) {\r\n geometry = geometries[i];\r\n splitGeometries = splitGeometries.concat(\r\n GeometryPipeline.fitToUnsignedShortIndices(geometry)\r\n );\r\n }\r\n\r\n geometries = splitGeometries;\r\n }\r\n\r\n return geometries;\r\n}\r\n\r\nfunction createPickOffsets(instances, geometryName, geometries, pickOffsets) {\r\n var offset;\r\n var indexCount;\r\n var geometryIndex;\r\n\r\n var offsetIndex = pickOffsets.length - 1;\r\n if (offsetIndex >= 0) {\r\n var pickOffset = pickOffsets[offsetIndex];\r\n offset = pickOffset.offset + pickOffset.count;\r\n geometryIndex = pickOffset.index;\r\n indexCount = geometries[geometryIndex].indices.length;\r\n } else {\r\n offset = 0;\r\n geometryIndex = 0;\r\n indexCount = geometries[geometryIndex].indices.length;\r\n }\r\n\r\n var length = instances.length;\r\n for (var i = 0; i < length; ++i) {\r\n var instance = instances[i];\r\n var geometry = instance[geometryName];\r\n if (!defined(geometry)) {\r\n continue;\r\n }\r\n\r\n var count = geometry.indices.length;\r\n\r\n if (offset + count > indexCount) {\r\n offset = 0;\r\n indexCount = geometries[++geometryIndex].indices.length;\r\n }\r\n\r\n pickOffsets.push({\r\n index: geometryIndex,\r\n offset: offset,\r\n count: count,\r\n });\r\n offset += count;\r\n }\r\n}\r\n\r\nfunction createInstancePickOffsets(instances, geometries) {\r\n var pickOffsets = [];\r\n createPickOffsets(instances, \"geometry\", geometries, pickOffsets);\r\n createPickOffsets(\r\n instances,\r\n \"westHemisphereGeometry\",\r\n geometries,\r\n pickOffsets\r\n );\r\n createPickOffsets(\r\n instances,\r\n \"eastHemisphereGeometry\",\r\n geometries,\r\n pickOffsets\r\n );\r\n return pickOffsets;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nvar PrimitivePipeline = {};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitivePipeline.combineGeometry = function (parameters) {\r\n var geometries;\r\n var attributeLocations;\r\n var instances = parameters.instances;\r\n var length = instances.length;\r\n var pickOffsets;\r\n\r\n var offsetInstanceExtend;\r\n var hasOffset = false;\r\n if (length > 0) {\r\n geometries = geometryPipeline(parameters);\r\n if (geometries.length > 0) {\r\n attributeLocations = GeometryPipeline.createAttributeLocations(\r\n geometries[0]\r\n );\r\n if (parameters.createPickOffsets) {\r\n pickOffsets = createInstancePickOffsets(instances, geometries);\r\n }\r\n }\r\n if (\r\n defined(instances[0].attributes) &&\r\n defined(instances[0].attributes.offset)\r\n ) {\r\n offsetInstanceExtend = new Array(length);\r\n hasOffset = true;\r\n }\r\n }\r\n\r\n var boundingSpheres = new Array(length);\r\n var boundingSpheresCV = new Array(length);\r\n for (var i = 0; i < length; ++i) {\r\n var instance = instances[i];\r\n var geometry = instance.geometry;\r\n if (defined(geometry)) {\r\n boundingSpheres[i] = geometry.boundingSphere;\r\n boundingSpheresCV[i] = geometry.boundingSphereCV;\r\n if (hasOffset) {\r\n offsetInstanceExtend[i] = instance.geometry.offsetAttribute;\r\n }\r\n }\r\n\r\n var eastHemisphereGeometry = instance.eastHemisphereGeometry;\r\n var westHemisphereGeometry = instance.westHemisphereGeometry;\r\n if (defined(eastHemisphereGeometry) && defined(westHemisphereGeometry)) {\r\n if (\r\n defined(eastHemisphereGeometry.boundingSphere) &&\r\n defined(westHemisphereGeometry.boundingSphere)\r\n ) {\r\n boundingSpheres[i] = BoundingSphere.union(\r\n eastHemisphereGeometry.boundingSphere,\r\n westHemisphereGeometry.boundingSphere\r\n );\r\n }\r\n if (\r\n defined(eastHemisphereGeometry.boundingSphereCV) &&\r\n defined(westHemisphereGeometry.boundingSphereCV)\r\n ) {\r\n boundingSpheresCV[i] = BoundingSphere.union(\r\n eastHemisphereGeometry.boundingSphereCV,\r\n westHemisphereGeometry.boundingSphereCV\r\n );\r\n }\r\n }\r\n }\r\n\r\n return {\r\n geometries: geometries,\r\n modelMatrix: parameters.modelMatrix,\r\n attributeLocations: attributeLocations,\r\n pickOffsets: pickOffsets,\r\n offsetInstanceExtend: offsetInstanceExtend,\r\n boundingSpheres: boundingSpheres,\r\n boundingSpheresCV: boundingSpheresCV,\r\n };\r\n};\r\n\r\nfunction transferGeometry(geometry, transferableObjects) {\r\n var attributes = geometry.attributes;\r\n for (var name in attributes) {\r\n if (attributes.hasOwnProperty(name)) {\r\n var attribute = attributes[name];\r\n\r\n if (defined(attribute) && defined(attribute.values)) {\r\n transferableObjects.push(attribute.values.buffer);\r\n }\r\n }\r\n }\r\n\r\n if (defined(geometry.indices)) {\r\n transferableObjects.push(geometry.indices.buffer);\r\n }\r\n}\r\n\r\nfunction transferGeometries(geometries, transferableObjects) {\r\n var length = geometries.length;\r\n for (var i = 0; i < length; ++i) {\r\n transferGeometry(geometries[i], transferableObjects);\r\n }\r\n}\r\n\r\n// This function was created by simplifying packCreateGeometryResults into a count-only operation.\r\nfunction countCreateGeometryResults(items) {\r\n var count = 1;\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n var geometry = items[i];\r\n ++count;\r\n\r\n if (!defined(geometry)) {\r\n continue;\r\n }\r\n\r\n var attributes = geometry.attributes;\r\n\r\n count +=\r\n 7 +\r\n 2 * BoundingSphere.packedLength +\r\n (defined(geometry.indices) ? geometry.indices.length : 0);\r\n\r\n for (var property in attributes) {\r\n if (\r\n attributes.hasOwnProperty(property) &&\r\n defined(attributes[property])\r\n ) {\r\n var attribute = attributes[property];\r\n count += 5 + attribute.values.length;\r\n }\r\n }\r\n }\r\n\r\n return count;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitivePipeline.packCreateGeometryResults = function (\r\n items,\r\n transferableObjects\r\n) {\r\n var packedData = new Float64Array(countCreateGeometryResults(items));\r\n var stringTable = [];\r\n var stringHash = {};\r\n\r\n var length = items.length;\r\n var count = 0;\r\n packedData[count++] = length;\r\n for (var i = 0; i < length; i++) {\r\n var geometry = items[i];\r\n\r\n var validGeometry = defined(geometry);\r\n packedData[count++] = validGeometry ? 1.0 : 0.0;\r\n\r\n if (!validGeometry) {\r\n continue;\r\n }\r\n\r\n packedData[count++] = geometry.primitiveType;\r\n packedData[count++] = geometry.geometryType;\r\n packedData[count++] = defaultValue(geometry.offsetAttribute, -1);\r\n\r\n var validBoundingSphere = defined(geometry.boundingSphere) ? 1.0 : 0.0;\r\n packedData[count++] = validBoundingSphere;\r\n if (validBoundingSphere) {\r\n BoundingSphere.pack(geometry.boundingSphere, packedData, count);\r\n }\r\n\r\n count += BoundingSphere.packedLength;\r\n\r\n var validBoundingSphereCV = defined(geometry.boundingSphereCV) ? 1.0 : 0.0;\r\n packedData[count++] = validBoundingSphereCV;\r\n if (validBoundingSphereCV) {\r\n BoundingSphere.pack(geometry.boundingSphereCV, packedData, count);\r\n }\r\n\r\n count += BoundingSphere.packedLength;\r\n\r\n var attributes = geometry.attributes;\r\n var attributesToWrite = [];\r\n for (var property in attributes) {\r\n if (\r\n attributes.hasOwnProperty(property) &&\r\n defined(attributes[property])\r\n ) {\r\n attributesToWrite.push(property);\r\n if (!defined(stringHash[property])) {\r\n stringHash[property] = stringTable.length;\r\n stringTable.push(property);\r\n }\r\n }\r\n }\r\n\r\n packedData[count++] = attributesToWrite.length;\r\n for (var q = 0; q < attributesToWrite.length; q++) {\r\n var name = attributesToWrite[q];\r\n var attribute = attributes[name];\r\n packedData[count++] = stringHash[name];\r\n packedData[count++] = attribute.componentDatatype;\r\n packedData[count++] = attribute.componentsPerAttribute;\r\n packedData[count++] = attribute.normalize ? 1 : 0;\r\n packedData[count++] = attribute.values.length;\r\n packedData.set(attribute.values, count);\r\n count += attribute.values.length;\r\n }\r\n\r\n var indicesLength = defined(geometry.indices) ? geometry.indices.length : 0;\r\n packedData[count++] = indicesLength;\r\n\r\n if (indicesLength > 0) {\r\n packedData.set(geometry.indices, count);\r\n count += indicesLength;\r\n }\r\n }\r\n\r\n transferableObjects.push(packedData.buffer);\r\n\r\n return {\r\n stringTable: stringTable,\r\n packedData: packedData,\r\n };\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitivePipeline.unpackCreateGeometryResults = function (\r\n createGeometryResult\r\n) {\r\n var stringTable = createGeometryResult.stringTable;\r\n var packedGeometry = createGeometryResult.packedData;\r\n\r\n var i;\r\n var result = new Array(packedGeometry[0]);\r\n var resultIndex = 0;\r\n\r\n var packedGeometryIndex = 1;\r\n while (packedGeometryIndex < packedGeometry.length) {\r\n var valid = packedGeometry[packedGeometryIndex++] === 1.0;\r\n if (!valid) {\r\n result[resultIndex++] = undefined;\r\n continue;\r\n }\r\n\r\n var primitiveType = packedGeometry[packedGeometryIndex++];\r\n var geometryType = packedGeometry[packedGeometryIndex++];\r\n var offsetAttribute = packedGeometry[packedGeometryIndex++];\r\n if (offsetAttribute === -1) {\r\n offsetAttribute = undefined;\r\n }\r\n\r\n var boundingSphere;\r\n var boundingSphereCV;\r\n\r\n var validBoundingSphere = packedGeometry[packedGeometryIndex++] === 1.0;\r\n if (validBoundingSphere) {\r\n boundingSphere = BoundingSphere.unpack(\r\n packedGeometry,\r\n packedGeometryIndex\r\n );\r\n }\r\n\r\n packedGeometryIndex += BoundingSphere.packedLength;\r\n\r\n var validBoundingSphereCV = packedGeometry[packedGeometryIndex++] === 1.0;\r\n if (validBoundingSphereCV) {\r\n boundingSphereCV = BoundingSphere.unpack(\r\n packedGeometry,\r\n packedGeometryIndex\r\n );\r\n }\r\n\r\n packedGeometryIndex += BoundingSphere.packedLength;\r\n\r\n var length;\r\n var values;\r\n var componentsPerAttribute;\r\n var attributes = new GeometryAttributes();\r\n var numAttributes = packedGeometry[packedGeometryIndex++];\r\n for (i = 0; i < numAttributes; i++) {\r\n var name = stringTable[packedGeometry[packedGeometryIndex++]];\r\n var componentDatatype = packedGeometry[packedGeometryIndex++];\r\n componentsPerAttribute = packedGeometry[packedGeometryIndex++];\r\n var normalize = packedGeometry[packedGeometryIndex++] !== 0;\r\n\r\n length = packedGeometry[packedGeometryIndex++];\r\n values = ComponentDatatype.createTypedArray(componentDatatype, length);\r\n for (var valuesIndex = 0; valuesIndex < length; valuesIndex++) {\r\n values[valuesIndex] = packedGeometry[packedGeometryIndex++];\r\n }\r\n\r\n attributes[name] = new GeometryAttribute({\r\n componentDatatype: componentDatatype,\r\n componentsPerAttribute: componentsPerAttribute,\r\n normalize: normalize,\r\n values: values,\r\n });\r\n }\r\n\r\n var indices;\r\n length = packedGeometry[packedGeometryIndex++];\r\n\r\n if (length > 0) {\r\n var numberOfVertices = values.length / componentsPerAttribute;\r\n indices = IndexDatatype.createTypedArray(numberOfVertices, length);\r\n for (i = 0; i < length; i++) {\r\n indices[i] = packedGeometry[packedGeometryIndex++];\r\n }\r\n }\r\n\r\n result[resultIndex++] = new Geometry({\r\n primitiveType: primitiveType,\r\n geometryType: geometryType,\r\n boundingSphere: boundingSphere,\r\n boundingSphereCV: boundingSphereCV,\r\n indices: indices,\r\n attributes: attributes,\r\n offsetAttribute: offsetAttribute,\r\n });\r\n }\r\n\r\n return result;\r\n};\r\n\r\nfunction packInstancesForCombine(instances, transferableObjects) {\r\n var length = instances.length;\r\n var packedData = new Float64Array(1 + length * 19);\r\n var count = 0;\r\n packedData[count++] = length;\r\n for (var i = 0; i < length; i++) {\r\n var instance = instances[i];\r\n Matrix4.pack(instance.modelMatrix, packedData, count);\r\n count += Matrix4.packedLength;\r\n if (defined(instance.attributes) && defined(instance.attributes.offset)) {\r\n var values = instance.attributes.offset.value;\r\n packedData[count] = values[0];\r\n packedData[count + 1] = values[1];\r\n packedData[count + 2] = values[2];\r\n }\r\n count += 3;\r\n }\r\n transferableObjects.push(packedData.buffer);\r\n\r\n return packedData;\r\n}\r\n\r\nfunction unpackInstancesForCombine(data) {\r\n var packedInstances = data;\r\n var result = new Array(packedInstances[0]);\r\n var count = 0;\r\n\r\n var i = 1;\r\n while (i < packedInstances.length) {\r\n var modelMatrix = Matrix4.unpack(packedInstances, i);\r\n var attributes;\r\n i += Matrix4.packedLength;\r\n if (defined(packedInstances[i])) {\r\n attributes = {\r\n offset: new OffsetGeometryInstanceAttribute(\r\n packedInstances[i],\r\n packedInstances[i + 1],\r\n packedInstances[i + 2]\r\n ),\r\n };\r\n }\r\n i += 3;\r\n\r\n result[count++] = {\r\n modelMatrix: modelMatrix,\r\n attributes: attributes,\r\n };\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitivePipeline.packCombineGeometryParameters = function (\r\n parameters,\r\n transferableObjects\r\n) {\r\n var createGeometryResults = parameters.createGeometryResults;\r\n var length = createGeometryResults.length;\r\n\r\n for (var i = 0; i < length; i++) {\r\n transferableObjects.push(createGeometryResults[i].packedData.buffer);\r\n }\r\n\r\n return {\r\n createGeometryResults: parameters.createGeometryResults,\r\n packedInstances: packInstancesForCombine(\r\n parameters.instances,\r\n transferableObjects\r\n ),\r\n ellipsoid: parameters.ellipsoid,\r\n isGeographic: parameters.projection instanceof GeographicProjection,\r\n elementIndexUintSupported: parameters.elementIndexUintSupported,\r\n scene3DOnly: parameters.scene3DOnly,\r\n vertexCacheOptimize: parameters.vertexCacheOptimize,\r\n compressVertices: parameters.compressVertices,\r\n modelMatrix: parameters.modelMatrix,\r\n createPickOffsets: parameters.createPickOffsets,\r\n };\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitivePipeline.unpackCombineGeometryParameters = function (\r\n packedParameters\r\n) {\r\n var instances = unpackInstancesForCombine(packedParameters.packedInstances);\r\n var createGeometryResults = packedParameters.createGeometryResults;\r\n var length = createGeometryResults.length;\r\n var instanceIndex = 0;\r\n\r\n for (var resultIndex = 0; resultIndex < length; resultIndex++) {\r\n var geometries = PrimitivePipeline.unpackCreateGeometryResults(\r\n createGeometryResults[resultIndex]\r\n );\r\n var geometriesLength = geometries.length;\r\n for (\r\n var geometryIndex = 0;\r\n geometryIndex < geometriesLength;\r\n geometryIndex++\r\n ) {\r\n var geometry = geometries[geometryIndex];\r\n var instance = instances[instanceIndex];\r\n instance.geometry = geometry;\r\n ++instanceIndex;\r\n }\r\n }\r\n\r\n var ellipsoid = Ellipsoid.clone(packedParameters.ellipsoid);\r\n var projection = packedParameters.isGeographic\r\n ? new GeographicProjection(ellipsoid)\r\n : new WebMercatorProjection(ellipsoid);\r\n\r\n return {\r\n instances: instances,\r\n ellipsoid: ellipsoid,\r\n projection: projection,\r\n elementIndexUintSupported: packedParameters.elementIndexUintSupported,\r\n scene3DOnly: packedParameters.scene3DOnly,\r\n vertexCacheOptimize: packedParameters.vertexCacheOptimize,\r\n compressVertices: packedParameters.compressVertices,\r\n modelMatrix: Matrix4.clone(packedParameters.modelMatrix),\r\n createPickOffsets: packedParameters.createPickOffsets,\r\n };\r\n};\r\n\r\nfunction packBoundingSpheres(boundingSpheres) {\r\n var length = boundingSpheres.length;\r\n var bufferLength = 1 + (BoundingSphere.packedLength + 1) * length;\r\n var buffer = new Float32Array(bufferLength);\r\n\r\n var bufferIndex = 0;\r\n buffer[bufferIndex++] = length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var bs = boundingSpheres[i];\r\n if (!defined(bs)) {\r\n buffer[bufferIndex++] = 0.0;\r\n } else {\r\n buffer[bufferIndex++] = 1.0;\r\n BoundingSphere.pack(boundingSpheres[i], buffer, bufferIndex);\r\n }\r\n bufferIndex += BoundingSphere.packedLength;\r\n }\r\n\r\n return buffer;\r\n}\r\n\r\nfunction unpackBoundingSpheres(buffer) {\r\n var result = new Array(buffer[0]);\r\n var count = 0;\r\n\r\n var i = 1;\r\n while (i < buffer.length) {\r\n if (buffer[i++] === 1.0) {\r\n result[count] = BoundingSphere.unpack(buffer, i);\r\n }\r\n ++count;\r\n i += BoundingSphere.packedLength;\r\n }\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitivePipeline.packCombineGeometryResults = function (\r\n results,\r\n transferableObjects\r\n) {\r\n if (defined(results.geometries)) {\r\n transferGeometries(results.geometries, transferableObjects);\r\n }\r\n\r\n var packedBoundingSpheres = packBoundingSpheres(results.boundingSpheres);\r\n var packedBoundingSpheresCV = packBoundingSpheres(results.boundingSpheresCV);\r\n transferableObjects.push(\r\n packedBoundingSpheres.buffer,\r\n packedBoundingSpheresCV.buffer\r\n );\r\n\r\n return {\r\n geometries: results.geometries,\r\n attributeLocations: results.attributeLocations,\r\n modelMatrix: results.modelMatrix,\r\n pickOffsets: results.pickOffsets,\r\n offsetInstanceExtend: results.offsetInstanceExtend,\r\n boundingSpheres: packedBoundingSpheres,\r\n boundingSpheresCV: packedBoundingSpheresCV,\r\n };\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitivePipeline.unpackCombineGeometryResults = function (packedResult) {\r\n return {\r\n geometries: packedResult.geometries,\r\n attributeLocations: packedResult.attributeLocations,\r\n modelMatrix: packedResult.modelMatrix,\r\n pickOffsets: packedResult.pickOffsets,\r\n offsetInstanceExtend: packedResult.offsetInstanceExtend,\r\n boundingSpheres: unpackBoundingSpheres(packedResult.boundingSpheres),\r\n boundingSpheresCV: unpackBoundingSpheres(packedResult.boundingSpheresCV),\r\n };\r\n};\r\nexport default PrimitivePipeline;\r\n","/**\r\n * @private\r\n */\r\nvar PrimitiveState = {\r\n READY: 0,\r\n CREATING: 1,\r\n CREATED: 2,\r\n COMBINING: 3,\r\n COMBINED: 4,\r\n COMPLETE: 5,\r\n FAILED: 6,\r\n};\r\nexport default Object.freeze(PrimitiveState);\r\n","/**\r\n * Indicates if the scene is viewed in 3D, 2D, or 2.5D Columbus view.\r\n *\r\n * @enum {Number}\r\n * @see Scene#mode\r\n */\r\nvar SceneMode = {\r\n /**\r\n * Morphing between mode, e.g., 3D to 2D.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MORPHING: 0,\r\n\r\n /**\r\n * Columbus View mode. A 2.5D perspective view where the map is laid out\r\n * flat and objects with non-zero height are drawn above it.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n COLUMBUS_VIEW: 1,\r\n\r\n /**\r\n * 2D mode. The map is viewed top-down with an orthographic projection.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SCENE2D: 2,\r\n\r\n /**\r\n * 3D mode. A traditional 3D perspective view of the globe.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n SCENE3D: 3,\r\n};\r\n\r\n/**\r\n * Returns the morph time for the given scene mode.\r\n *\r\n * @param {SceneMode} value The scene mode\r\n * @returns {Number} The morph time\r\n */\r\nSceneMode.getMorphTime = function (value) {\r\n if (value === SceneMode.SCENE3D) {\r\n return 1.0;\r\n } else if (value === SceneMode.MORPHING) {\r\n return undefined;\r\n }\r\n return 0.0;\r\n};\r\nexport default Object.freeze(SceneMode);\r\n","/**\r\n * Specifies whether the object casts or receives shadows from light sources when\r\n * shadows are enabled.\r\n *\r\n * @enum {Number}\r\n */\r\nvar ShadowMode = {\r\n /**\r\n * The object does not cast or receive shadows.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n DISABLED: 0,\r\n\r\n /**\r\n * The object casts and receives shadows.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ENABLED: 1,\r\n\r\n /**\r\n * The object casts shadows only.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CAST_ONLY: 2,\r\n\r\n /**\r\n * The object receives shadows only.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RECEIVE_ONLY: 3,\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nShadowMode.NUMBER_OF_SHADOW_MODES = 4;\r\n\r\n/**\r\n * @private\r\n */\r\nShadowMode.castShadows = function (shadowMode) {\r\n return (\r\n shadowMode === ShadowMode.ENABLED || shadowMode === ShadowMode.CAST_ONLY\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nShadowMode.receiveShadows = function (shadowMode) {\r\n return (\r\n shadowMode === ShadowMode.ENABLED || shadowMode === ShadowMode.RECEIVE_ONLY\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nShadowMode.fromCastReceive = function (castShadows, receiveShadows) {\r\n if (castShadows && receiveShadows) {\r\n return ShadowMode.ENABLED;\r\n } else if (castShadows) {\r\n return ShadowMode.CAST_ONLY;\r\n } else if (receiveShadows) {\r\n return ShadowMode.RECEIVE_ONLY;\r\n }\r\n return ShadowMode.DISABLED;\r\n};\r\n\r\nexport default Object.freeze(ShadowMode);\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport clone from \"../Core/clone.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport EncodedCartesian3 from \"../Core/EncodedCartesian3.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport Geometry from \"../Core/Geometry.js\";\r\nimport GeometryAttribute from \"../Core/GeometryAttribute.js\";\r\nimport GeometryAttributes from \"../Core/GeometryAttributes.js\";\r\nimport GeometryOffsetAttribute from \"../Core/GeometryOffsetAttribute.js\";\r\nimport Intersect from \"../Core/Intersect.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Plane from \"../Core/Plane.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport subdivideArray from \"../Core/subdivideArray.js\";\r\nimport TaskProcessor from \"../Core/TaskProcessor.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport ContextLimits from \"../Renderer/ContextLimits.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport VertexArray from \"../Renderer/VertexArray.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport BatchTable from \"./BatchTable.js\";\r\nimport CullFace from \"./CullFace.js\";\r\nimport DepthFunction from \"./DepthFunction.js\";\r\nimport PrimitivePipeline from \"./PrimitivePipeline.js\";\r\nimport PrimitiveState from \"./PrimitiveState.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport ShadowMode from \"./ShadowMode.js\";\r\n\r\n/**\r\n * A primitive represents geometry in the {@link Scene}. The geometry can be from a single {@link GeometryInstance}\r\n * as shown in example 1 below, or from an array of instances, even if the geometry is from different\r\n * geometry types, e.g., an {@link RectangleGeometry} and an {@link EllipsoidGeometry} as shown in Code Example 2.\r\n *

\r\n * A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including\r\n * {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement,\r\n * and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix\r\n * and match most of them and add a new geometry or appearance independently of each other.\r\n *

\r\n *

\r\n * Combining multiple instances into one primitive is called batching, and significantly improves performance for static data.\r\n * Instances can be individually picked; {@link Scene#pick} returns their {@link GeometryInstance#id}. Using\r\n * per-instance appearances like {@link PerInstanceColorAppearance}, each instance can also have a unique color.\r\n *

\r\n *

\r\n * {@link Geometry} can either be created and batched on a web worker or the main thread. The first two examples\r\n * show geometry that will be created on a web worker by using the descriptions of the geometry. The third example\r\n * shows how to create the geometry on the main thread by explicitly calling the createGeometry method.\r\n *

\r\n *\r\n * @alias Primitive\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {GeometryInstance[]|GeometryInstance} [options.geometryInstances] The geometry instances - or a single geometry instance - to render.\r\n * @param {Appearance} [options.appearance] The appearance used to render the primitive.\r\n * @param {Appearance} [options.depthFailAppearance] The appearance used to shade this primitive when it fails the depth test.\r\n * @param {Boolean} [options.show=true] Determines if this primitive will be shown.\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms the primitive (all geometry instances) from model to world coordinates.\r\n * @param {Boolean} [options.vertexCacheOptimize=false] When true, geometry vertices are optimized for the pre and post-vertex-shader caches.\r\n * @param {Boolean} [options.interleave=false] When true, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.\r\n * @param {Boolean} [options.compressVertices=true] When true, the geometry vertices are compressed, which will save memory.\r\n * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory.\r\n * @param {Boolean} [options.allowPicking=true] When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.\r\n * @param {Boolean} [options.cull=true] When true, the renderer frustum culls and horizon culls the primitive's commands based on their bounding volume. Set this to false for a small performance gain if you are manually culling the primitive.\r\n * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.\r\n * @param {ShadowMode} [options.shadows=ShadowMode.DISABLED] Determines whether this primitive casts or receives shadows from light sources.\r\n *\r\n * @example\r\n * // 1. Draw a translucent ellipse on the surface with a checkerboard pattern\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.EllipseGeometry({\r\n * center : Cesium.Cartesian3.fromDegrees(-100.0, 20.0),\r\n * semiMinorAxis : 500000.0,\r\n * semiMajorAxis : 1000000.0,\r\n * rotation : Cesium.Math.PI_OVER_FOUR,\r\n * vertexFormat : Cesium.VertexFormat.POSITION_AND_ST\r\n * }),\r\n * id : 'object returned when this instance is picked and to get/set per-instance attributes'\r\n * });\r\n * scene.primitives.add(new Cesium.Primitive({\r\n * geometryInstances : instance,\r\n * appearance : new Cesium.EllipsoidSurfaceAppearance({\r\n * material : Cesium.Material.fromType('Checkerboard')\r\n * })\r\n * }));\r\n *\r\n * @example\r\n * // 2. Draw different instances each with a unique color\r\n * var rectangleInstance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.RectangleGeometry({\r\n * rectangle : Cesium.Rectangle.fromDegrees(-140.0, 30.0, -100.0, 40.0),\r\n * vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT\r\n * }),\r\n * id : 'rectangle',\r\n * attributes : {\r\n * color : new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5)\r\n * }\r\n * });\r\n * var ellipsoidInstance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.EllipsoidGeometry({\r\n * radii : new Cesium.Cartesian3(500000.0, 500000.0, 1000000.0),\r\n * vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL\r\n * }),\r\n * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(\r\n * Cesium.Cartesian3.fromDegrees(-95.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 500000.0), new Cesium.Matrix4()),\r\n * id : 'ellipsoid',\r\n * attributes : {\r\n * color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA)\r\n * }\r\n * });\r\n * scene.primitives.add(new Cesium.Primitive({\r\n * geometryInstances : [rectangleInstance, ellipsoidInstance],\r\n * appearance : new Cesium.PerInstanceColorAppearance()\r\n * }));\r\n *\r\n * @example\r\n * // 3. Create the geometry on the main thread.\r\n * scene.primitives.add(new Cesium.Primitive({\r\n * geometryInstances : new Cesium.GeometryInstance({\r\n * geometry : Cesium.EllipsoidGeometry.createGeometry(new Cesium.EllipsoidGeometry({\r\n * radii : new Cesium.Cartesian3(500000.0, 500000.0, 1000000.0),\r\n * vertexFormat : Cesium.VertexFormat.POSITION_AND_NORMAL\r\n * })),\r\n * modelMatrix : Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(\r\n * Cesium.Cartesian3.fromDegrees(-95.59777, 40.03883)), new Cesium.Cartesian3(0.0, 0.0, 500000.0), new Cesium.Matrix4()),\r\n * id : 'ellipsoid',\r\n * attributes : {\r\n * color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.AQUA)\r\n * }\r\n * }),\r\n * appearance : new Cesium.PerInstanceColorAppearance()\r\n * }));\r\n *\r\n * @see GeometryInstance\r\n * @see Appearance\r\n * @see ClassificationPrimitive\r\n * @see GroundPrimitive\r\n */\r\nfunction Primitive(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * The geometry instances rendered with this primitive. This may\r\n * be undefined if options.releaseGeometryInstances\r\n * is true when the primitive is constructed.\r\n *

\r\n * Changing this property after the primitive is rendered has no effect.\r\n *

\r\n *\r\n * @readonly\r\n * @type GeometryInstance[]|GeometryInstance\r\n *\r\n * @default undefined\r\n */\r\n this.geometryInstances = options.geometryInstances;\r\n\r\n /**\r\n * The {@link Appearance} used to shade this primitive. Each geometry\r\n * instance is shaded with the same appearance. Some appearances, like\r\n * {@link PerInstanceColorAppearance} allow giving each instance unique\r\n * properties.\r\n *\r\n * @type Appearance\r\n *\r\n * @default undefined\r\n */\r\n this.appearance = options.appearance;\r\n this._appearance = undefined;\r\n this._material = undefined;\r\n\r\n /**\r\n * The {@link Appearance} used to shade this primitive when it fails the depth test. Each geometry\r\n * instance is shaded with the same appearance. Some appearances, like\r\n * {@link PerInstanceColorAppearance} allow giving each instance unique\r\n * properties.\r\n *\r\n *

\r\n * When using an appearance that requires a color attribute, like PerInstanceColorAppearance,\r\n * add a depthFailColor per-instance attribute instead.\r\n *

\r\n *\r\n *

\r\n * Requires the EXT_frag_depth WebGL extension to render properly. If the extension is not supported,\r\n * there may be artifacts.\r\n *

\r\n * @type Appearance\r\n *\r\n * @default undefined\r\n */\r\n this.depthFailAppearance = options.depthFailAppearance;\r\n this._depthFailAppearance = undefined;\r\n this._depthFailMaterial = undefined;\r\n\r\n /**\r\n * The 4x4 transformation matrix that transforms the primitive (all geometry instances) from model to world coordinates.\r\n * When this is the identity matrix, the primitive is drawn in world coordinates, i.e., Earth's WGS84 coordinates.\r\n * Local reference frames can be used by providing a different transformation matrix, like that returned\r\n * by {@link Transforms.eastNorthUpToFixedFrame}.\r\n *\r\n *

\r\n * This property is only supported in 3D mode.\r\n *

\r\n *\r\n * @type Matrix4\r\n *\r\n * @default Matrix4.IDENTITY\r\n *\r\n * @example\r\n * var origin = Cesium.Cartesian3.fromDegrees(-95.0, 40.0, 200000.0);\r\n * p.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n this._modelMatrix = new Matrix4();\r\n\r\n /**\r\n * Determines if the primitive will be shown. This affects all geometry\r\n * instances in the primitive.\r\n *\r\n * @type Boolean\r\n *\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n this._vertexCacheOptimize = defaultValue(options.vertexCacheOptimize, false);\r\n this._interleave = defaultValue(options.interleave, false);\r\n this._releaseGeometryInstances = defaultValue(\r\n options.releaseGeometryInstances,\r\n true\r\n );\r\n this._allowPicking = defaultValue(options.allowPicking, true);\r\n this._asynchronous = defaultValue(options.asynchronous, true);\r\n this._compressVertices = defaultValue(options.compressVertices, true);\r\n\r\n /**\r\n * When true, the renderer frustum culls and horizon culls the primitive's commands\r\n * based on their bounding volume. Set this to false for a small performance gain\r\n * if you are manually culling the primitive.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.cull = defaultValue(options.cull, true);\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n\r\n /**\r\n * @private\r\n */\r\n this.rtcCenter = options.rtcCenter;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n defined(this.rtcCenter) &&\r\n (!defined(this.geometryInstances) ||\r\n (Array.isArray(this.geometryInstances) &&\r\n this.geometryInstances.length !== 1))\r\n ) {\r\n throw new DeveloperError(\r\n \"Relative-to-center rendering only supports one geometry instance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * Determines whether this primitive casts or receives shadows from light sources.\r\n *\r\n * @type {ShadowMode}\r\n *\r\n * @default ShadowMode.DISABLED\r\n */\r\n this.shadows = defaultValue(options.shadows, ShadowMode.DISABLED);\r\n\r\n this._translucent = undefined;\r\n\r\n this._state = PrimitiveState.READY;\r\n this._geometries = [];\r\n this._error = undefined;\r\n this._numberOfInstances = 0;\r\n\r\n this._boundingSpheres = [];\r\n this._boundingSphereWC = [];\r\n this._boundingSphereCV = [];\r\n this._boundingSphere2D = [];\r\n this._boundingSphereMorph = [];\r\n this._perInstanceAttributeCache = [];\r\n this._instanceIds = [];\r\n this._lastPerInstanceAttributeIndex = 0;\r\n\r\n this._va = [];\r\n this._attributeLocations = undefined;\r\n this._primitiveType = undefined;\r\n\r\n this._frontFaceRS = undefined;\r\n this._backFaceRS = undefined;\r\n this._sp = undefined;\r\n\r\n this._depthFailAppearance = undefined;\r\n this._spDepthFail = undefined;\r\n this._frontFaceDepthFailRS = undefined;\r\n this._backFaceDepthFailRS = undefined;\r\n\r\n this._pickIds = [];\r\n\r\n this._colorCommands = [];\r\n this._pickCommands = [];\r\n\r\n this._createBoundingVolumeFunction = options._createBoundingVolumeFunction;\r\n this._createRenderStatesFunction = options._createRenderStatesFunction;\r\n this._createShaderProgramFunction = options._createShaderProgramFunction;\r\n this._createCommandsFunction = options._createCommandsFunction;\r\n this._updateAndQueueCommandsFunction =\r\n options._updateAndQueueCommandsFunction;\r\n\r\n this._createPickOffsets = options._createPickOffsets;\r\n this._pickOffsets = undefined;\r\n\r\n this._createGeometryResults = undefined;\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._batchTable = undefined;\r\n this._batchTableAttributeIndices = undefined;\r\n this._offsetInstanceExtend = undefined;\r\n this._batchTableOffsetAttribute2DIndex = undefined;\r\n this._batchTableOffsetsUpdated = false;\r\n this._instanceBoundingSpheres = undefined;\r\n this._instanceBoundingSpheresCV = undefined;\r\n this._tempBoundingSpheres = undefined;\r\n this._recomputeBoundingSpheres = false;\r\n this._batchTableBoundingSpheresUpdated = false;\r\n this._batchTableBoundingSphereAttributeIndices = undefined;\r\n}\r\n\r\nObject.defineProperties(Primitive.prototype, {\r\n /**\r\n * When true, geometry vertices are optimized for the pre and post-vertex-shader caches.\r\n *\r\n * @memberof Primitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n vertexCacheOptimize: {\r\n get: function () {\r\n return this._vertexCacheOptimize;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.\r\n *\r\n * @memberof Primitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n interleave: {\r\n get: function () {\r\n return this._interleave;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the primitive does not keep a reference to the input geometryInstances to save memory.\r\n *\r\n * @memberof Primitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n releaseGeometryInstances: {\r\n get: function () {\r\n return this._releaseGeometryInstances;\r\n },\r\n },\r\n\r\n /**\r\n * When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved. *\r\n *\r\n * @memberof Primitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n allowPicking: {\r\n get: function () {\r\n return this._allowPicking;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the geometry instances will be created and batched on a web worker.\r\n *\r\n * @memberof Primitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n asynchronous: {\r\n get: function () {\r\n return this._asynchronous;\r\n },\r\n },\r\n\r\n /**\r\n * When true, geometry vertices are compressed, which will save memory.\r\n *\r\n * @memberof Primitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n compressVertices: {\r\n get: function () {\r\n return this._compressVertices;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the primitive is complete and ready to render. If this property is\r\n * true, the primitive will be rendered the next time that {@link Primitive#update}\r\n * is called.\r\n *\r\n * @memberof Primitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof Primitive.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n});\r\n\r\nfunction getCommonPerInstanceAttributeNames(instances) {\r\n var length = instances.length;\r\n\r\n var attributesInAllInstances = [];\r\n var attributes0 = instances[0].attributes;\r\n var name;\r\n\r\n for (name in attributes0) {\r\n if (attributes0.hasOwnProperty(name) && defined(attributes0[name])) {\r\n var attribute = attributes0[name];\r\n var inAllInstances = true;\r\n\r\n // Does this same attribute exist in all instances?\r\n for (var i = 1; i < length; ++i) {\r\n var otherAttribute = instances[i].attributes[name];\r\n\r\n if (\r\n !defined(otherAttribute) ||\r\n attribute.componentDatatype !== otherAttribute.componentDatatype ||\r\n attribute.componentsPerAttribute !==\r\n otherAttribute.componentsPerAttribute ||\r\n attribute.normalize !== otherAttribute.normalize\r\n ) {\r\n inAllInstances = false;\r\n break;\r\n }\r\n }\r\n\r\n if (inAllInstances) {\r\n attributesInAllInstances.push(name);\r\n }\r\n }\r\n }\r\n\r\n return attributesInAllInstances;\r\n}\r\n\r\nvar scratchGetAttributeCartesian2 = new Cartesian2();\r\nvar scratchGetAttributeCartesian3 = new Cartesian3();\r\nvar scratchGetAttributeCartesian4 = new Cartesian4();\r\n\r\nfunction getAttributeValue(value) {\r\n var componentsPerAttribute = value.length;\r\n if (componentsPerAttribute === 1) {\r\n return value[0];\r\n } else if (componentsPerAttribute === 2) {\r\n return Cartesian2.unpack(value, 0, scratchGetAttributeCartesian2);\r\n } else if (componentsPerAttribute === 3) {\r\n return Cartesian3.unpack(value, 0, scratchGetAttributeCartesian3);\r\n } else if (componentsPerAttribute === 4) {\r\n return Cartesian4.unpack(value, 0, scratchGetAttributeCartesian4);\r\n }\r\n}\r\n\r\nfunction createBatchTable(primitive, context) {\r\n var geometryInstances = primitive.geometryInstances;\r\n var instances = Array.isArray(geometryInstances)\r\n ? geometryInstances\r\n : [geometryInstances];\r\n var numberOfInstances = instances.length;\r\n if (numberOfInstances === 0) {\r\n return;\r\n }\r\n\r\n var names = getCommonPerInstanceAttributeNames(instances);\r\n var length = names.length;\r\n\r\n var attributes = [];\r\n var attributeIndices = {};\r\n var boundingSphereAttributeIndices = {};\r\n var offset2DIndex;\r\n\r\n var firstInstance = instances[0];\r\n var instanceAttributes = firstInstance.attributes;\r\n\r\n var i;\r\n var name;\r\n var attribute;\r\n\r\n for (i = 0; i < length; ++i) {\r\n name = names[i];\r\n attribute = instanceAttributes[name];\r\n\r\n attributeIndices[name] = i;\r\n attributes.push({\r\n functionName: \"czm_batchTable_\" + name,\r\n componentDatatype: attribute.componentDatatype,\r\n componentsPerAttribute: attribute.componentsPerAttribute,\r\n normalize: attribute.normalize,\r\n });\r\n }\r\n\r\n if (names.indexOf(\"distanceDisplayCondition\") !== -1) {\r\n attributes.push(\r\n {\r\n functionName: \"czm_batchTable_boundingSphereCenter3DHigh\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n functionName: \"czm_batchTable_boundingSphereCenter3DLow\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n functionName: \"czm_batchTable_boundingSphereCenter2DHigh\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n functionName: \"czm_batchTable_boundingSphereCenter2DLow\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n functionName: \"czm_batchTable_boundingSphereRadius\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 1,\r\n }\r\n );\r\n boundingSphereAttributeIndices.center3DHigh = attributes.length - 5;\r\n boundingSphereAttributeIndices.center3DLow = attributes.length - 4;\r\n boundingSphereAttributeIndices.center2DHigh = attributes.length - 3;\r\n boundingSphereAttributeIndices.center2DLow = attributes.length - 2;\r\n boundingSphereAttributeIndices.radius = attributes.length - 1;\r\n }\r\n\r\n if (names.indexOf(\"offset\") !== -1) {\r\n attributes.push({\r\n functionName: \"czm_batchTable_offset2D\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n });\r\n offset2DIndex = attributes.length - 1;\r\n }\r\n\r\n attributes.push({\r\n functionName: \"czm_batchTable_pickColor\",\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 4,\r\n normalize: true,\r\n });\r\n\r\n var attributesLength = attributes.length;\r\n var batchTable = new BatchTable(context, attributes, numberOfInstances);\r\n\r\n for (i = 0; i < numberOfInstances; ++i) {\r\n var instance = instances[i];\r\n instanceAttributes = instance.attributes;\r\n\r\n for (var j = 0; j < length; ++j) {\r\n name = names[j];\r\n attribute = instanceAttributes[name];\r\n var value = getAttributeValue(attribute.value);\r\n var attributeIndex = attributeIndices[name];\r\n batchTable.setBatchedAttribute(i, attributeIndex, value);\r\n }\r\n\r\n var pickObject = {\r\n primitive: defaultValue(instance.pickPrimitive, primitive),\r\n };\r\n\r\n if (defined(instance.id)) {\r\n pickObject.id = instance.id;\r\n }\r\n\r\n var pickId = context.createPickId(pickObject);\r\n primitive._pickIds.push(pickId);\r\n\r\n var pickColor = pickId.color;\r\n var color = scratchGetAttributeCartesian4;\r\n color.x = Color.floatToByte(pickColor.red);\r\n color.y = Color.floatToByte(pickColor.green);\r\n color.z = Color.floatToByte(pickColor.blue);\r\n color.w = Color.floatToByte(pickColor.alpha);\r\n\r\n batchTable.setBatchedAttribute(i, attributesLength - 1, color);\r\n }\r\n\r\n primitive._batchTable = batchTable;\r\n primitive._batchTableAttributeIndices = attributeIndices;\r\n primitive._batchTableBoundingSphereAttributeIndices = boundingSphereAttributeIndices;\r\n primitive._batchTableOffsetAttribute2DIndex = offset2DIndex;\r\n}\r\n\r\nfunction cloneAttribute(attribute) {\r\n var clonedValues;\r\n if (Array.isArray(attribute.values)) {\r\n clonedValues = attribute.values.slice(0);\r\n } else {\r\n clonedValues = new attribute.values.constructor(attribute.values);\r\n }\r\n return new GeometryAttribute({\r\n componentDatatype: attribute.componentDatatype,\r\n componentsPerAttribute: attribute.componentsPerAttribute,\r\n normalize: attribute.normalize,\r\n values: clonedValues,\r\n });\r\n}\r\n\r\nfunction cloneGeometry(geometry) {\r\n var attributes = geometry.attributes;\r\n var newAttributes = new GeometryAttributes();\r\n for (var property in attributes) {\r\n if (attributes.hasOwnProperty(property) && defined(attributes[property])) {\r\n newAttributes[property] = cloneAttribute(attributes[property]);\r\n }\r\n }\r\n\r\n var indices;\r\n if (defined(geometry.indices)) {\r\n var sourceValues = geometry.indices;\r\n if (Array.isArray(sourceValues)) {\r\n indices = sourceValues.slice(0);\r\n } else {\r\n indices = new sourceValues.constructor(sourceValues);\r\n }\r\n }\r\n\r\n return new Geometry({\r\n attributes: newAttributes,\r\n indices: indices,\r\n primitiveType: geometry.primitiveType,\r\n boundingSphere: BoundingSphere.clone(geometry.boundingSphere),\r\n });\r\n}\r\n\r\nfunction cloneInstance(instance, geometry) {\r\n return {\r\n geometry: geometry,\r\n attributes: instance.attributes,\r\n modelMatrix: Matrix4.clone(instance.modelMatrix),\r\n pickPrimitive: instance.pickPrimitive,\r\n id: instance.id,\r\n };\r\n}\r\n\r\nvar positionRegex = /attribute\\s+vec(?:3|4)\\s+(.*)3DHigh;/g;\r\n\r\nPrimitive._modifyShaderPosition = function (\r\n primitive,\r\n vertexShaderSource,\r\n scene3DOnly\r\n) {\r\n var match;\r\n\r\n var forwardDecl = \"\";\r\n var attributes = \"\";\r\n var computeFunctions = \"\";\r\n\r\n while ((match = positionRegex.exec(vertexShaderSource)) !== null) {\r\n var name = match[1];\r\n\r\n var functionName =\r\n \"vec4 czm_compute\" + name[0].toUpperCase() + name.substr(1) + \"()\";\r\n\r\n // Don't forward-declare czm_computePosition because computePosition.glsl already does.\r\n if (functionName !== \"vec4 czm_computePosition()\") {\r\n forwardDecl += functionName + \";\\n\";\r\n }\r\n\r\n if (!defined(primitive.rtcCenter)) {\r\n // Use GPU RTE\r\n if (!scene3DOnly) {\r\n attributes +=\r\n \"attribute vec3 \" +\r\n name +\r\n \"2DHigh;\\n\" +\r\n \"attribute vec3 \" +\r\n name +\r\n \"2DLow;\\n\";\r\n\r\n computeFunctions +=\r\n functionName +\r\n \"\\n\" +\r\n \"{\\n\" +\r\n \" vec4 p;\\n\" +\r\n \" if (czm_morphTime == 1.0)\\n\" +\r\n \" {\\n\" +\r\n \" p = czm_translateRelativeToEye(\" +\r\n name +\r\n \"3DHigh, \" +\r\n name +\r\n \"3DLow);\\n\" +\r\n \" }\\n\" +\r\n \" else if (czm_morphTime == 0.0)\\n\" +\r\n \" {\\n\" +\r\n \" p = czm_translateRelativeToEye(\" +\r\n name +\r\n \"2DHigh.zxy, \" +\r\n name +\r\n \"2DLow.zxy);\\n\" +\r\n \" }\\n\" +\r\n \" else\\n\" +\r\n \" {\\n\" +\r\n \" p = czm_columbusViewMorph(\\n\" +\r\n \" czm_translateRelativeToEye(\" +\r\n name +\r\n \"2DHigh.zxy, \" +\r\n name +\r\n \"2DLow.zxy),\\n\" +\r\n \" czm_translateRelativeToEye(\" +\r\n name +\r\n \"3DHigh, \" +\r\n name +\r\n \"3DLow),\\n\" +\r\n \" czm_morphTime);\\n\" +\r\n \" }\\n\" +\r\n \" return p;\\n\" +\r\n \"}\\n\\n\";\r\n } else {\r\n computeFunctions +=\r\n functionName +\r\n \"\\n\" +\r\n \"{\\n\" +\r\n \" return czm_translateRelativeToEye(\" +\r\n name +\r\n \"3DHigh, \" +\r\n name +\r\n \"3DLow);\\n\" +\r\n \"}\\n\\n\";\r\n }\r\n } else {\r\n // Use RTC\r\n vertexShaderSource = vertexShaderSource.replace(\r\n /attribute\\s+vec(?:3|4)\\s+position3DHigh;/g,\r\n \"\"\r\n );\r\n vertexShaderSource = vertexShaderSource.replace(\r\n /attribute\\s+vec(?:3|4)\\s+position3DLow;/g,\r\n \"\"\r\n );\r\n\r\n forwardDecl += \"uniform mat4 u_modifiedModelView;\\n\";\r\n attributes += \"attribute vec4 position;\\n\";\r\n\r\n computeFunctions +=\r\n functionName +\r\n \"\\n\" +\r\n \"{\\n\" +\r\n \" return u_modifiedModelView * position;\\n\" +\r\n \"}\\n\\n\";\r\n\r\n vertexShaderSource = vertexShaderSource.replace(\r\n /czm_modelViewRelativeToEye\\s+\\*\\s+/g,\r\n \"\"\r\n );\r\n vertexShaderSource = vertexShaderSource.replace(\r\n /czm_modelViewProjectionRelativeToEye/g,\r\n \"czm_projection\"\r\n );\r\n }\r\n }\r\n\r\n return [forwardDecl, attributes, vertexShaderSource, computeFunctions].join(\r\n \"\\n\"\r\n );\r\n};\r\n\r\nPrimitive._appendShowToShader = function (primitive, vertexShaderSource) {\r\n if (!defined(primitive._batchTableAttributeIndices.show)) {\r\n return vertexShaderSource;\r\n }\r\n\r\n var renamedVS = ShaderSource.replaceMain(\r\n vertexShaderSource,\r\n \"czm_non_show_main\"\r\n );\r\n var showMain =\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" czm_non_show_main(); \\n\" +\r\n \" gl_Position *= czm_batchTable_show(batchId); \\n\" +\r\n \"}\";\r\n\r\n return renamedVS + \"\\n\" + showMain;\r\n};\r\n\r\nPrimitive._updateColorAttribute = function (\r\n primitive,\r\n vertexShaderSource,\r\n isDepthFail\r\n) {\r\n // some appearances have a color attribute for per vertex color.\r\n // only remove if color is a per instance attribute.\r\n if (\r\n !defined(primitive._batchTableAttributeIndices.color) &&\r\n !defined(primitive._batchTableAttributeIndices.depthFailColor)\r\n ) {\r\n return vertexShaderSource;\r\n }\r\n\r\n if (vertexShaderSource.search(/attribute\\s+vec4\\s+color;/g) === -1) {\r\n return vertexShaderSource;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n isDepthFail &&\r\n !defined(primitive._batchTableAttributeIndices.depthFailColor)\r\n ) {\r\n throw new DeveloperError(\r\n \"A depthFailColor per-instance attribute is required when using a depth fail appearance that uses a color attribute.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var modifiedVS = vertexShaderSource;\r\n modifiedVS = modifiedVS.replace(/attribute\\s+vec4\\s+color;/g, \"\");\r\n if (!isDepthFail) {\r\n modifiedVS = modifiedVS.replace(\r\n /(\\b)color(\\b)/g,\r\n \"$1czm_batchTable_color(batchId)$2\"\r\n );\r\n } else {\r\n modifiedVS = modifiedVS.replace(\r\n /(\\b)color(\\b)/g,\r\n \"$1czm_batchTable_depthFailColor(batchId)$2\"\r\n );\r\n }\r\n return modifiedVS;\r\n};\r\n\r\nfunction appendPickToVertexShader(source) {\r\n var renamedVS = ShaderSource.replaceMain(source, \"czm_non_pick_main\");\r\n var pickMain =\r\n \"varying vec4 v_pickColor; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" czm_non_pick_main(); \\n\" +\r\n \" v_pickColor = czm_batchTable_pickColor(batchId); \\n\" +\r\n \"}\";\r\n\r\n return renamedVS + \"\\n\" + pickMain;\r\n}\r\n\r\nfunction appendPickToFragmentShader(source) {\r\n return \"varying vec4 v_pickColor;\\n\" + source;\r\n}\r\n\r\nPrimitive._updatePickColorAttribute = function (source) {\r\n var vsPick = source.replace(/attribute\\s+vec4\\s+pickColor;/g, \"\");\r\n vsPick = vsPick.replace(\r\n /(\\b)pickColor(\\b)/g,\r\n \"$1czm_batchTable_pickColor(batchId)$2\"\r\n );\r\n return vsPick;\r\n};\r\n\r\nPrimitive._appendOffsetToShader = function (primitive, vertexShaderSource) {\r\n if (!defined(primitive._batchTableAttributeIndices.offset)) {\r\n return vertexShaderSource;\r\n }\r\n\r\n var attr = \"attribute float batchId;\\n\";\r\n attr += \"attribute float applyOffset;\";\r\n var modifiedShader = vertexShaderSource.replace(\r\n /attribute\\s+float\\s+batchId;/g,\r\n attr\r\n );\r\n\r\n var str = \"vec4 $1 = czm_computePosition();\\n\";\r\n str += \" if (czm_sceneMode == czm_sceneMode3D)\\n\";\r\n str += \" {\\n\";\r\n str +=\r\n \" $1 = $1 + vec4(czm_batchTable_offset(batchId) * applyOffset, 0.0);\";\r\n str += \" }\\n\";\r\n str += \" else\\n\";\r\n str += \" {\\n\";\r\n str +=\r\n \" $1 = $1 + vec4(czm_batchTable_offset2D(batchId) * applyOffset, 0.0);\";\r\n str += \" }\\n\";\r\n modifiedShader = modifiedShader.replace(\r\n /vec4\\s+([A-Za-z0-9_]+)\\s+=\\s+czm_computePosition\\(\\);/g,\r\n str\r\n );\r\n return modifiedShader;\r\n};\r\n\r\nPrimitive._appendDistanceDisplayConditionToShader = function (\r\n primitive,\r\n vertexShaderSource,\r\n scene3DOnly\r\n) {\r\n if (\r\n !defined(primitive._batchTableAttributeIndices.distanceDisplayCondition)\r\n ) {\r\n return vertexShaderSource;\r\n }\r\n\r\n var renamedVS = ShaderSource.replaceMain(\r\n vertexShaderSource,\r\n \"czm_non_distanceDisplayCondition_main\"\r\n );\r\n var distanceDisplayConditionMain =\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" czm_non_distanceDisplayCondition_main(); \\n\" +\r\n \" vec2 distanceDisplayCondition = czm_batchTable_distanceDisplayCondition(batchId);\\n\" +\r\n \" vec3 boundingSphereCenter3DHigh = czm_batchTable_boundingSphereCenter3DHigh(batchId);\\n\" +\r\n \" vec3 boundingSphereCenter3DLow = czm_batchTable_boundingSphereCenter3DLow(batchId);\\n\" +\r\n \" float boundingSphereRadius = czm_batchTable_boundingSphereRadius(batchId);\\n\";\r\n\r\n if (!scene3DOnly) {\r\n distanceDisplayConditionMain +=\r\n \" vec3 boundingSphereCenter2DHigh = czm_batchTable_boundingSphereCenter2DHigh(batchId);\\n\" +\r\n \" vec3 boundingSphereCenter2DLow = czm_batchTable_boundingSphereCenter2DLow(batchId);\\n\" +\r\n \" vec4 centerRTE;\\n\" +\r\n \" if (czm_morphTime == 1.0)\\n\" +\r\n \" {\\n\" +\r\n \" centerRTE = czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow);\\n\" +\r\n \" }\\n\" +\r\n \" else if (czm_morphTime == 0.0)\\n\" +\r\n \" {\\n\" +\r\n \" centerRTE = czm_translateRelativeToEye(boundingSphereCenter2DHigh.zxy, boundingSphereCenter2DLow.zxy);\\n\" +\r\n \" }\\n\" +\r\n \" else\\n\" +\r\n \" {\\n\" +\r\n \" centerRTE = czm_columbusViewMorph(\\n\" +\r\n \" czm_translateRelativeToEye(boundingSphereCenter2DHigh.zxy, boundingSphereCenter2DLow.zxy),\\n\" +\r\n \" czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow),\\n\" +\r\n \" czm_morphTime);\\n\" +\r\n \" }\\n\";\r\n } else {\r\n distanceDisplayConditionMain +=\r\n \" vec4 centerRTE = czm_translateRelativeToEye(boundingSphereCenter3DHigh, boundingSphereCenter3DLow);\\n\";\r\n }\r\n\r\n distanceDisplayConditionMain +=\r\n \" float radiusSq = boundingSphereRadius * boundingSphereRadius; \\n\" +\r\n \" float distanceSq; \\n\" +\r\n \" if (czm_sceneMode == czm_sceneMode2D) \\n\" +\r\n \" { \\n\" +\r\n \" distanceSq = czm_eyeHeight2D.y - radiusSq; \\n\" +\r\n \" } \\n\" +\r\n \" else \\n\" +\r\n \" { \\n\" +\r\n \" distanceSq = dot(centerRTE.xyz, centerRTE.xyz) - radiusSq; \\n\" +\r\n \" } \\n\" +\r\n \" distanceSq = max(distanceSq, 0.0); \\n\" +\r\n \" float nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x; \\n\" +\r\n \" float farSq = distanceDisplayCondition.y * distanceDisplayCondition.y; \\n\" +\r\n \" float show = (distanceSq >= nearSq && distanceSq <= farSq) ? 1.0 : 0.0; \\n\" +\r\n \" gl_Position *= show; \\n\" +\r\n \"}\";\r\n return renamedVS + \"\\n\" + distanceDisplayConditionMain;\r\n};\r\n\r\nfunction modifyForEncodedNormals(primitive, vertexShaderSource) {\r\n if (!primitive.compressVertices) {\r\n return vertexShaderSource;\r\n }\r\n\r\n var containsNormal =\r\n vertexShaderSource.search(/attribute\\s+vec3\\s+normal;/g) !== -1;\r\n var containsSt = vertexShaderSource.search(/attribute\\s+vec2\\s+st;/g) !== -1;\r\n if (!containsNormal && !containsSt) {\r\n return vertexShaderSource;\r\n }\r\n\r\n var containsTangent =\r\n vertexShaderSource.search(/attribute\\s+vec3\\s+tangent;/g) !== -1;\r\n var containsBitangent =\r\n vertexShaderSource.search(/attribute\\s+vec3\\s+bitangent;/g) !== -1;\r\n\r\n var numComponents = containsSt && containsNormal ? 2.0 : 1.0;\r\n numComponents += containsTangent || containsBitangent ? 1 : 0;\r\n\r\n var type = numComponents > 1 ? \"vec\" + numComponents : \"float\";\r\n\r\n var attributeName = \"compressedAttributes\";\r\n var attributeDecl = \"attribute \" + type + \" \" + attributeName + \";\";\r\n\r\n var globalDecl = \"\";\r\n var decode = \"\";\r\n\r\n if (containsSt) {\r\n globalDecl += \"vec2 st;\\n\";\r\n var stComponent = numComponents > 1 ? attributeName + \".x\" : attributeName;\r\n decode +=\r\n \" st = czm_decompressTextureCoordinates(\" + stComponent + \");\\n\";\r\n }\r\n\r\n if (containsNormal && containsTangent && containsBitangent) {\r\n globalDecl += \"vec3 normal;\\n\" + \"vec3 tangent;\\n\" + \"vec3 bitangent;\\n\";\r\n decode +=\r\n \" czm_octDecode(\" +\r\n attributeName +\r\n \".\" +\r\n (containsSt ? \"yz\" : \"xy\") +\r\n \", normal, tangent, bitangent);\\n\";\r\n } else {\r\n if (containsNormal) {\r\n globalDecl += \"vec3 normal;\\n\";\r\n decode +=\r\n \" normal = czm_octDecode(\" +\r\n attributeName +\r\n (numComponents > 1 ? \".\" + (containsSt ? \"y\" : \"x\") : \"\") +\r\n \");\\n\";\r\n }\r\n\r\n if (containsTangent) {\r\n globalDecl += \"vec3 tangent;\\n\";\r\n decode +=\r\n \" tangent = czm_octDecode(\" +\r\n attributeName +\r\n \".\" +\r\n (containsSt && containsNormal ? \"z\" : \"y\") +\r\n \");\\n\";\r\n }\r\n\r\n if (containsBitangent) {\r\n globalDecl += \"vec3 bitangent;\\n\";\r\n decode +=\r\n \" bitangent = czm_octDecode(\" +\r\n attributeName +\r\n \".\" +\r\n (containsSt && containsNormal ? \"z\" : \"y\") +\r\n \");\\n\";\r\n }\r\n }\r\n\r\n var modifiedVS = vertexShaderSource;\r\n modifiedVS = modifiedVS.replace(/attribute\\s+vec3\\s+normal;/g, \"\");\r\n modifiedVS = modifiedVS.replace(/attribute\\s+vec2\\s+st;/g, \"\");\r\n modifiedVS = modifiedVS.replace(/attribute\\s+vec3\\s+tangent;/g, \"\");\r\n modifiedVS = modifiedVS.replace(/attribute\\s+vec3\\s+bitangent;/g, \"\");\r\n modifiedVS = ShaderSource.replaceMain(modifiedVS, \"czm_non_compressed_main\");\r\n var compressedMain =\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n decode +\r\n \" czm_non_compressed_main(); \\n\" +\r\n \"}\";\r\n\r\n return [attributeDecl, globalDecl, modifiedVS, compressedMain].join(\"\\n\");\r\n}\r\n\r\nfunction depthClampVS(vertexShaderSource) {\r\n var modifiedVS = ShaderSource.replaceMain(\r\n vertexShaderSource,\r\n \"czm_non_depth_clamp_main\"\r\n );\r\n modifiedVS +=\r\n \"void main() {\\n\" +\r\n \" czm_non_depth_clamp_main();\\n\" +\r\n \" gl_Position = czm_depthClamp(gl_Position);\" +\r\n \"}\\n\";\r\n return modifiedVS;\r\n}\r\n\r\nfunction depthClampFS(fragmentShaderSource) {\r\n var modifiedFS = ShaderSource.replaceMain(\r\n fragmentShaderSource,\r\n \"czm_non_depth_clamp_main\"\r\n );\r\n modifiedFS +=\r\n \"void main() {\\n\" +\r\n \" czm_non_depth_clamp_main();\\n\" +\r\n \"#if defined(GL_EXT_frag_depth)\\n\" +\r\n \" #if defined(LOG_DEPTH)\\n\" +\r\n \" czm_writeLogDepth();\\n\" +\r\n \" #else\\n\" +\r\n \" czm_writeDepthClamp();\\n\" +\r\n \" #endif\\n\" +\r\n \"#endif\\n\" +\r\n \"}\\n\";\r\n modifiedFS =\r\n \"#ifdef GL_EXT_frag_depth\\n\" +\r\n \"#extension GL_EXT_frag_depth : enable\\n\" +\r\n \"#endif\\n\" +\r\n modifiedFS;\r\n return modifiedFS;\r\n}\r\n\r\nfunction validateShaderMatching(shaderProgram, attributeLocations) {\r\n // For a VAO and shader program to be compatible, the VAO must have\r\n // all active attribute in the shader program. The VAO may have\r\n // extra attributes with the only concern being a potential\r\n // performance hit due to extra memory bandwidth and cache pollution.\r\n // The shader source could have extra attributes that are not used,\r\n // but there is no guarantee they will be optimized out.\r\n //\r\n // Here, we validate that the VAO has all attributes required\r\n // to match the shader program.\r\n var shaderAttributes = shaderProgram.vertexAttributes;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n for (var name in shaderAttributes) {\r\n if (shaderAttributes.hasOwnProperty(name)) {\r\n if (!defined(attributeLocations[name])) {\r\n throw new DeveloperError(\r\n \"Appearance/Geometry mismatch. The appearance requires vertex shader attribute input '\" +\r\n name +\r\n \"', which was not computed as part of the Geometry. Use the appearance's vertexFormat property when constructing the geometry.\"\r\n );\r\n }\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n}\r\n\r\nfunction getUniformFunction(uniforms, name) {\r\n return function () {\r\n return uniforms[name];\r\n };\r\n}\r\n\r\nvar numberOfCreationWorkers = Math.max(\r\n FeatureDetection.hardwareConcurrency - 1,\r\n 1\r\n);\r\nvar createGeometryTaskProcessors;\r\nvar combineGeometryTaskProcessor = new TaskProcessor(\"combineGeometry\");\r\n\r\nfunction loadAsynchronous(primitive, frameState) {\r\n var instances;\r\n var geometry;\r\n var i;\r\n var j;\r\n\r\n var instanceIds = primitive._instanceIds;\r\n\r\n if (primitive._state === PrimitiveState.READY) {\r\n instances = Array.isArray(primitive.geometryInstances)\r\n ? primitive.geometryInstances\r\n : [primitive.geometryInstances];\r\n var length = (primitive._numberOfInstances = instances.length);\r\n\r\n var promises = [];\r\n var subTasks = [];\r\n for (i = 0; i < length; ++i) {\r\n geometry = instances[i].geometry;\r\n instanceIds.push(instances[i].id);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(geometry._workerName)) {\r\n throw new DeveloperError(\r\n \"_workerName must be defined for asynchronous geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n subTasks.push({\r\n moduleName: geometry._workerName,\r\n geometry: geometry,\r\n });\r\n }\r\n\r\n if (!defined(createGeometryTaskProcessors)) {\r\n createGeometryTaskProcessors = new Array(numberOfCreationWorkers);\r\n for (i = 0; i < numberOfCreationWorkers; i++) {\r\n createGeometryTaskProcessors[i] = new TaskProcessor(\"createGeometry\");\r\n }\r\n }\r\n\r\n var subTask;\r\n subTasks = subdivideArray(subTasks, numberOfCreationWorkers);\r\n\r\n for (i = 0; i < subTasks.length; i++) {\r\n var packedLength = 0;\r\n var workerSubTasks = subTasks[i];\r\n var workerSubTasksLength = workerSubTasks.length;\r\n for (j = 0; j < workerSubTasksLength; ++j) {\r\n subTask = workerSubTasks[j];\r\n geometry = subTask.geometry;\r\n if (defined(geometry.constructor.pack)) {\r\n subTask.offset = packedLength;\r\n packedLength += defaultValue(\r\n geometry.constructor.packedLength,\r\n geometry.packedLength\r\n );\r\n }\r\n }\r\n\r\n var subTaskTransferableObjects;\r\n\r\n if (packedLength > 0) {\r\n var array = new Float64Array(packedLength);\r\n subTaskTransferableObjects = [array.buffer];\r\n\r\n for (j = 0; j < workerSubTasksLength; ++j) {\r\n subTask = workerSubTasks[j];\r\n geometry = subTask.geometry;\r\n if (defined(geometry.constructor.pack)) {\r\n geometry.constructor.pack(geometry, array, subTask.offset);\r\n subTask.geometry = array;\r\n }\r\n }\r\n }\r\n\r\n promises.push(\r\n createGeometryTaskProcessors[i].scheduleTask(\r\n {\r\n subTasks: subTasks[i],\r\n },\r\n subTaskTransferableObjects\r\n )\r\n );\r\n }\r\n\r\n primitive._state = PrimitiveState.CREATING;\r\n\r\n when\r\n .all(promises, function (results) {\r\n primitive._createGeometryResults = results;\r\n primitive._state = PrimitiveState.CREATED;\r\n })\r\n .otherwise(function (error) {\r\n setReady(primitive, frameState, PrimitiveState.FAILED, error);\r\n });\r\n } else if (primitive._state === PrimitiveState.CREATED) {\r\n var transferableObjects = [];\r\n instances = Array.isArray(primitive.geometryInstances)\r\n ? primitive.geometryInstances\r\n : [primitive.geometryInstances];\r\n\r\n var scene3DOnly = frameState.scene3DOnly;\r\n var projection = frameState.mapProjection;\r\n\r\n var promise = combineGeometryTaskProcessor.scheduleTask(\r\n PrimitivePipeline.packCombineGeometryParameters(\r\n {\r\n createGeometryResults: primitive._createGeometryResults,\r\n instances: instances,\r\n ellipsoid: projection.ellipsoid,\r\n projection: projection,\r\n elementIndexUintSupported: frameState.context.elementIndexUint,\r\n scene3DOnly: scene3DOnly,\r\n vertexCacheOptimize: primitive.vertexCacheOptimize,\r\n compressVertices: primitive.compressVertices,\r\n modelMatrix: primitive.modelMatrix,\r\n createPickOffsets: primitive._createPickOffsets,\r\n },\r\n transferableObjects\r\n ),\r\n transferableObjects\r\n );\r\n\r\n primitive._createGeometryResults = undefined;\r\n primitive._state = PrimitiveState.COMBINING;\r\n\r\n when(promise, function (packedResult) {\r\n var result = PrimitivePipeline.unpackCombineGeometryResults(packedResult);\r\n primitive._geometries = result.geometries;\r\n primitive._attributeLocations = result.attributeLocations;\r\n primitive.modelMatrix = Matrix4.clone(\r\n result.modelMatrix,\r\n primitive.modelMatrix\r\n );\r\n primitive._pickOffsets = result.pickOffsets;\r\n primitive._offsetInstanceExtend = result.offsetInstanceExtend;\r\n primitive._instanceBoundingSpheres = result.boundingSpheres;\r\n primitive._instanceBoundingSpheresCV = result.boundingSpheresCV;\r\n\r\n if (defined(primitive._geometries) && primitive._geometries.length > 0) {\r\n primitive._recomputeBoundingSpheres = true;\r\n primitive._state = PrimitiveState.COMBINED;\r\n } else {\r\n setReady(primitive, frameState, PrimitiveState.FAILED, undefined);\r\n }\r\n }).otherwise(function (error) {\r\n setReady(primitive, frameState, PrimitiveState.FAILED, error);\r\n });\r\n }\r\n}\r\n\r\nfunction loadSynchronous(primitive, frameState) {\r\n var instances = Array.isArray(primitive.geometryInstances)\r\n ? primitive.geometryInstances\r\n : [primitive.geometryInstances];\r\n var length = (primitive._numberOfInstances = instances.length);\r\n var clonedInstances = new Array(length);\r\n var instanceIds = primitive._instanceIds;\r\n\r\n var instance;\r\n var i;\r\n\r\n var geometryIndex = 0;\r\n for (i = 0; i < length; i++) {\r\n instance = instances[i];\r\n var geometry = instance.geometry;\r\n\r\n var createdGeometry;\r\n if (defined(geometry.attributes) && defined(geometry.primitiveType)) {\r\n createdGeometry = cloneGeometry(geometry);\r\n } else {\r\n createdGeometry = geometry.constructor.createGeometry(geometry);\r\n }\r\n\r\n clonedInstances[geometryIndex++] = cloneInstance(instance, createdGeometry);\r\n instanceIds.push(instance.id);\r\n }\r\n\r\n clonedInstances.length = geometryIndex;\r\n\r\n var scene3DOnly = frameState.scene3DOnly;\r\n var projection = frameState.mapProjection;\r\n\r\n var result = PrimitivePipeline.combineGeometry({\r\n instances: clonedInstances,\r\n ellipsoid: projection.ellipsoid,\r\n projection: projection,\r\n elementIndexUintSupported: frameState.context.elementIndexUint,\r\n scene3DOnly: scene3DOnly,\r\n vertexCacheOptimize: primitive.vertexCacheOptimize,\r\n compressVertices: primitive.compressVertices,\r\n modelMatrix: primitive.modelMatrix,\r\n createPickOffsets: primitive._createPickOffsets,\r\n });\r\n\r\n primitive._geometries = result.geometries;\r\n primitive._attributeLocations = result.attributeLocations;\r\n primitive.modelMatrix = Matrix4.clone(\r\n result.modelMatrix,\r\n primitive.modelMatrix\r\n );\r\n primitive._pickOffsets = result.pickOffsets;\r\n primitive._offsetInstanceExtend = result.offsetInstanceExtend;\r\n primitive._instanceBoundingSpheres = result.boundingSpheres;\r\n primitive._instanceBoundingSpheresCV = result.boundingSpheresCV;\r\n\r\n if (defined(primitive._geometries) && primitive._geometries.length > 0) {\r\n primitive._recomputeBoundingSpheres = true;\r\n primitive._state = PrimitiveState.COMBINED;\r\n } else {\r\n setReady(primitive, frameState, PrimitiveState.FAILED, undefined);\r\n }\r\n}\r\n\r\nfunction recomputeBoundingSpheres(primitive, frameState) {\r\n var offsetIndex = primitive._batchTableAttributeIndices.offset;\r\n if (!primitive._recomputeBoundingSpheres || !defined(offsetIndex)) {\r\n primitive._recomputeBoundingSpheres = false;\r\n return;\r\n }\r\n\r\n var i;\r\n var offsetInstanceExtend = primitive._offsetInstanceExtend;\r\n var boundingSpheres = primitive._instanceBoundingSpheres;\r\n var length = boundingSpheres.length;\r\n var newBoundingSpheres = primitive._tempBoundingSpheres;\r\n if (!defined(newBoundingSpheres)) {\r\n newBoundingSpheres = new Array(length);\r\n for (i = 0; i < length; i++) {\r\n newBoundingSpheres[i] = new BoundingSphere();\r\n }\r\n primitive._tempBoundingSpheres = newBoundingSpheres;\r\n }\r\n for (i = 0; i < length; ++i) {\r\n var newBS = newBoundingSpheres[i];\r\n var offset = primitive._batchTable.getBatchedAttribute(\r\n i,\r\n offsetIndex,\r\n new Cartesian3()\r\n );\r\n newBS = boundingSpheres[i].clone(newBS);\r\n transformBoundingSphere(newBS, offset, offsetInstanceExtend[i]);\r\n }\r\n var combinedBS = [];\r\n var combinedWestBS = [];\r\n var combinedEastBS = [];\r\n\r\n for (i = 0; i < length; ++i) {\r\n var bs = newBoundingSpheres[i];\r\n\r\n var minX = bs.center.x - bs.radius;\r\n if (\r\n minX > 0 ||\r\n BoundingSphere.intersectPlane(bs, Plane.ORIGIN_ZX_PLANE) !==\r\n Intersect.INTERSECTING\r\n ) {\r\n combinedBS.push(bs);\r\n } else {\r\n combinedWestBS.push(bs);\r\n combinedEastBS.push(bs);\r\n }\r\n }\r\n\r\n var resultBS1 = combinedBS[0];\r\n var resultBS2 = combinedEastBS[0];\r\n var resultBS3 = combinedWestBS[0];\r\n\r\n for (i = 1; i < combinedBS.length; i++) {\r\n resultBS1 = BoundingSphere.union(resultBS1, combinedBS[i]);\r\n }\r\n for (i = 1; i < combinedEastBS.length; i++) {\r\n resultBS2 = BoundingSphere.union(resultBS2, combinedEastBS[i]);\r\n }\r\n for (i = 1; i < combinedWestBS.length; i++) {\r\n resultBS3 = BoundingSphere.union(resultBS3, combinedWestBS[i]);\r\n }\r\n var result = [];\r\n if (defined(resultBS1)) {\r\n result.push(resultBS1);\r\n }\r\n if (defined(resultBS2)) {\r\n result.push(resultBS2);\r\n }\r\n if (defined(resultBS3)) {\r\n result.push(resultBS3);\r\n }\r\n\r\n for (i = 0; i < result.length; i++) {\r\n var boundingSphere = result[i].clone(primitive._boundingSpheres[i]);\r\n primitive._boundingSpheres[i] = boundingSphere;\r\n primitive._boundingSphereCV[i] = BoundingSphere.projectTo2D(\r\n boundingSphere,\r\n frameState.mapProjection,\r\n primitive._boundingSphereCV[i]\r\n );\r\n }\r\n\r\n Primitive._updateBoundingVolumes(\r\n primitive,\r\n frameState,\r\n primitive.modelMatrix,\r\n true\r\n );\r\n primitive._recomputeBoundingSpheres = false;\r\n}\r\n\r\nvar scratchBoundingSphereCenterEncoded = new EncodedCartesian3();\r\nvar scratchBoundingSphereCartographic = new Cartographic();\r\nvar scratchBoundingSphereCenter2D = new Cartesian3();\r\nvar scratchBoundingSphere = new BoundingSphere();\r\n\r\nfunction updateBatchTableBoundingSpheres(primitive, frameState) {\r\n var hasDistanceDisplayCondition = defined(\r\n primitive._batchTableAttributeIndices.distanceDisplayCondition\r\n );\r\n if (\r\n !hasDistanceDisplayCondition ||\r\n primitive._batchTableBoundingSpheresUpdated\r\n ) {\r\n return;\r\n }\r\n\r\n var indices = primitive._batchTableBoundingSphereAttributeIndices;\r\n var center3DHighIndex = indices.center3DHigh;\r\n var center3DLowIndex = indices.center3DLow;\r\n var center2DHighIndex = indices.center2DHigh;\r\n var center2DLowIndex = indices.center2DLow;\r\n var radiusIndex = indices.radius;\r\n\r\n var projection = frameState.mapProjection;\r\n var ellipsoid = projection.ellipsoid;\r\n\r\n var batchTable = primitive._batchTable;\r\n var boundingSpheres = primitive._instanceBoundingSpheres;\r\n var length = boundingSpheres.length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var boundingSphere = boundingSpheres[i];\r\n if (!defined(boundingSphere)) {\r\n continue;\r\n }\r\n\r\n var modelMatrix = primitive.modelMatrix;\r\n if (defined(modelMatrix)) {\r\n boundingSphere = BoundingSphere.transform(\r\n boundingSphere,\r\n modelMatrix,\r\n scratchBoundingSphere\r\n );\r\n }\r\n\r\n var center = boundingSphere.center;\r\n var radius = boundingSphere.radius;\r\n\r\n var encodedCenter = EncodedCartesian3.fromCartesian(\r\n center,\r\n scratchBoundingSphereCenterEncoded\r\n );\r\n batchTable.setBatchedAttribute(i, center3DHighIndex, encodedCenter.high);\r\n batchTable.setBatchedAttribute(i, center3DLowIndex, encodedCenter.low);\r\n\r\n if (!frameState.scene3DOnly) {\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n center,\r\n scratchBoundingSphereCartographic\r\n );\r\n var center2D = projection.project(\r\n cartographic,\r\n scratchBoundingSphereCenter2D\r\n );\r\n encodedCenter = EncodedCartesian3.fromCartesian(\r\n center2D,\r\n scratchBoundingSphereCenterEncoded\r\n );\r\n batchTable.setBatchedAttribute(i, center2DHighIndex, encodedCenter.high);\r\n batchTable.setBatchedAttribute(i, center2DLowIndex, encodedCenter.low);\r\n }\r\n\r\n batchTable.setBatchedAttribute(i, radiusIndex, radius);\r\n }\r\n\r\n primitive._batchTableBoundingSpheresUpdated = true;\r\n}\r\n\r\nvar offsetScratchCartesian = new Cartesian3();\r\nvar offsetCenterScratch = new Cartesian3();\r\nfunction updateBatchTableOffsets(primitive, frameState) {\r\n var hasOffset = defined(primitive._batchTableAttributeIndices.offset);\r\n if (\r\n !hasOffset ||\r\n primitive._batchTableOffsetsUpdated ||\r\n frameState.scene3DOnly\r\n ) {\r\n return;\r\n }\r\n\r\n var index2D = primitive._batchTableOffsetAttribute2DIndex;\r\n\r\n var projection = frameState.mapProjection;\r\n var ellipsoid = projection.ellipsoid;\r\n\r\n var batchTable = primitive._batchTable;\r\n var boundingSpheres = primitive._instanceBoundingSpheres;\r\n var length = boundingSpheres.length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var boundingSphere = boundingSpheres[i];\r\n if (!defined(boundingSphere)) {\r\n continue;\r\n }\r\n var offset = batchTable.getBatchedAttribute(\r\n i,\r\n primitive._batchTableAttributeIndices.offset\r\n );\r\n if (Cartesian3.equals(offset, Cartesian3.ZERO)) {\r\n batchTable.setBatchedAttribute(i, index2D, Cartesian3.ZERO);\r\n continue;\r\n }\r\n\r\n var modelMatrix = primitive.modelMatrix;\r\n if (defined(modelMatrix)) {\r\n boundingSphere = BoundingSphere.transform(\r\n boundingSphere,\r\n modelMatrix,\r\n scratchBoundingSphere\r\n );\r\n }\r\n\r\n var center = boundingSphere.center;\r\n center = ellipsoid.scaleToGeodeticSurface(center, offsetCenterScratch);\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n center,\r\n scratchBoundingSphereCartographic\r\n );\r\n var center2D = projection.project(\r\n cartographic,\r\n scratchBoundingSphereCenter2D\r\n );\r\n\r\n var newPoint = Cartesian3.add(offset, center, offsetScratchCartesian);\r\n cartographic = ellipsoid.cartesianToCartographic(newPoint, cartographic);\r\n\r\n var newPointProjected = projection.project(\r\n cartographic,\r\n offsetScratchCartesian\r\n );\r\n\r\n var newVector = Cartesian3.subtract(\r\n newPointProjected,\r\n center2D,\r\n offsetScratchCartesian\r\n );\r\n\r\n var x = newVector.x;\r\n newVector.x = newVector.z;\r\n newVector.z = newVector.y;\r\n newVector.y = x;\r\n\r\n batchTable.setBatchedAttribute(i, index2D, newVector);\r\n }\r\n\r\n primitive._batchTableOffsetsUpdated = true;\r\n}\r\n\r\nfunction createVertexArray(primitive, frameState) {\r\n var attributeLocations = primitive._attributeLocations;\r\n var geometries = primitive._geometries;\r\n var scene3DOnly = frameState.scene3DOnly;\r\n var context = frameState.context;\r\n\r\n var va = [];\r\n var length = geometries.length;\r\n for (var i = 0; i < length; ++i) {\r\n var geometry = geometries[i];\r\n\r\n va.push(\r\n VertexArray.fromGeometry({\r\n context: context,\r\n geometry: geometry,\r\n attributeLocations: attributeLocations,\r\n bufferUsage: BufferUsage.STATIC_DRAW,\r\n interleave: primitive._interleave,\r\n })\r\n );\r\n\r\n if (defined(primitive._createBoundingVolumeFunction)) {\r\n primitive._createBoundingVolumeFunction(frameState, geometry);\r\n } else {\r\n primitive._boundingSpheres.push(\r\n BoundingSphere.clone(geometry.boundingSphere)\r\n );\r\n primitive._boundingSphereWC.push(new BoundingSphere());\r\n\r\n if (!scene3DOnly) {\r\n var center = geometry.boundingSphereCV.center;\r\n var x = center.x;\r\n var y = center.y;\r\n var z = center.z;\r\n center.x = z;\r\n center.y = x;\r\n center.z = y;\r\n\r\n primitive._boundingSphereCV.push(\r\n BoundingSphere.clone(geometry.boundingSphereCV)\r\n );\r\n primitive._boundingSphere2D.push(new BoundingSphere());\r\n primitive._boundingSphereMorph.push(new BoundingSphere());\r\n }\r\n }\r\n }\r\n\r\n primitive._va = va;\r\n primitive._primitiveType = geometries[0].primitiveType;\r\n\r\n if (primitive.releaseGeometryInstances) {\r\n primitive.geometryInstances = undefined;\r\n }\r\n\r\n primitive._geometries = undefined;\r\n setReady(primitive, frameState, PrimitiveState.COMPLETE, undefined);\r\n}\r\n\r\nfunction createRenderStates(primitive, context, appearance, twoPasses) {\r\n var renderState = appearance.getRenderState();\r\n var rs;\r\n\r\n if (twoPasses) {\r\n rs = clone(renderState, false);\r\n rs.cull = {\r\n enabled: true,\r\n face: CullFace.BACK,\r\n };\r\n primitive._frontFaceRS = RenderState.fromCache(rs);\r\n\r\n rs.cull.face = CullFace.FRONT;\r\n primitive._backFaceRS = RenderState.fromCache(rs);\r\n } else {\r\n primitive._frontFaceRS = RenderState.fromCache(renderState);\r\n primitive._backFaceRS = primitive._frontFaceRS;\r\n }\r\n\r\n rs = clone(renderState, false);\r\n if (defined(primitive._depthFailAppearance)) {\r\n rs.depthTest.enabled = false;\r\n }\r\n\r\n if (defined(primitive._depthFailAppearance)) {\r\n renderState = primitive._depthFailAppearance.getRenderState();\r\n rs = clone(renderState, false);\r\n rs.depthTest.func = DepthFunction.GREATER;\r\n if (twoPasses) {\r\n rs.cull = {\r\n enabled: true,\r\n face: CullFace.BACK,\r\n };\r\n primitive._frontFaceDepthFailRS = RenderState.fromCache(rs);\r\n\r\n rs.cull.face = CullFace.FRONT;\r\n primitive._backFaceDepthFailRS = RenderState.fromCache(rs);\r\n } else {\r\n primitive._frontFaceDepthFailRS = RenderState.fromCache(rs);\r\n primitive._backFaceDepthFailRS = primitive._frontFaceRS;\r\n }\r\n }\r\n}\r\n\r\nfunction createShaderProgram(primitive, frameState, appearance) {\r\n var context = frameState.context;\r\n\r\n var attributeLocations = primitive._attributeLocations;\r\n\r\n var vs = primitive._batchTable.getVertexShaderCallback()(\r\n appearance.vertexShaderSource\r\n );\r\n vs = Primitive._appendOffsetToShader(primitive, vs);\r\n vs = Primitive._appendShowToShader(primitive, vs);\r\n vs = Primitive._appendDistanceDisplayConditionToShader(\r\n primitive,\r\n vs,\r\n frameState.scene3DOnly\r\n );\r\n vs = appendPickToVertexShader(vs);\r\n vs = Primitive._updateColorAttribute(primitive, vs, false);\r\n vs = modifyForEncodedNormals(primitive, vs);\r\n vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly);\r\n var fs = appearance.getFragmentShaderSource();\r\n fs = appendPickToFragmentShader(fs);\r\n\r\n primitive._sp = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: primitive._sp,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n validateShaderMatching(primitive._sp, attributeLocations);\r\n\r\n if (defined(primitive._depthFailAppearance)) {\r\n vs = primitive._batchTable.getVertexShaderCallback()(\r\n primitive._depthFailAppearance.vertexShaderSource\r\n );\r\n vs = Primitive._appendShowToShader(primitive, vs);\r\n vs = Primitive._appendDistanceDisplayConditionToShader(\r\n primitive,\r\n vs,\r\n frameState.scene3DOnly\r\n );\r\n vs = appendPickToVertexShader(vs);\r\n vs = Primitive._updateColorAttribute(primitive, vs, true);\r\n vs = modifyForEncodedNormals(primitive, vs);\r\n vs = Primitive._modifyShaderPosition(primitive, vs, frameState.scene3DOnly);\r\n vs = depthClampVS(vs);\r\n\r\n fs = primitive._depthFailAppearance.getFragmentShaderSource();\r\n fs = appendPickToFragmentShader(fs);\r\n fs = depthClampFS(fs);\r\n\r\n primitive._spDepthFail = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: primitive._spDepthFail,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n validateShaderMatching(primitive._spDepthFail, attributeLocations);\r\n }\r\n}\r\n\r\nvar modifiedModelViewScratch = new Matrix4();\r\nvar rtcScratch = new Cartesian3();\r\n\r\nfunction getUniforms(primitive, appearance, material, frameState) {\r\n // Create uniform map by combining uniforms from the appearance and material if either have uniforms.\r\n var materialUniformMap = defined(material) ? material._uniforms : undefined;\r\n var appearanceUniformMap = {};\r\n var appearanceUniforms = appearance.uniforms;\r\n if (defined(appearanceUniforms)) {\r\n // Convert to uniform map of functions for the renderer\r\n for (var name in appearanceUniforms) {\r\n if (appearanceUniforms.hasOwnProperty(name)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(materialUniformMap) && defined(materialUniformMap[name])) {\r\n // Later, we could rename uniforms behind-the-scenes if needed.\r\n throw new DeveloperError(\r\n \"Appearance and material have a uniform with the same name: \" + name\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n appearanceUniformMap[name] = getUniformFunction(\r\n appearanceUniforms,\r\n name\r\n );\r\n }\r\n }\r\n }\r\n var uniforms = combine(appearanceUniformMap, materialUniformMap);\r\n uniforms = primitive._batchTable.getUniformMapCallback()(uniforms);\r\n\r\n if (defined(primitive.rtcCenter)) {\r\n uniforms.u_modifiedModelView = function () {\r\n var viewMatrix = frameState.context.uniformState.view;\r\n Matrix4.multiply(\r\n viewMatrix,\r\n primitive._modelMatrix,\r\n modifiedModelViewScratch\r\n );\r\n Matrix4.multiplyByPoint(\r\n modifiedModelViewScratch,\r\n primitive.rtcCenter,\r\n rtcScratch\r\n );\r\n Matrix4.setTranslation(\r\n modifiedModelViewScratch,\r\n rtcScratch,\r\n modifiedModelViewScratch\r\n );\r\n return modifiedModelViewScratch;\r\n };\r\n }\r\n\r\n return uniforms;\r\n}\r\n\r\nfunction createCommands(\r\n primitive,\r\n appearance,\r\n material,\r\n translucent,\r\n twoPasses,\r\n colorCommands,\r\n pickCommands,\r\n frameState\r\n) {\r\n var uniforms = getUniforms(primitive, appearance, material, frameState);\r\n\r\n var depthFailUniforms;\r\n if (defined(primitive._depthFailAppearance)) {\r\n depthFailUniforms = getUniforms(\r\n primitive,\r\n primitive._depthFailAppearance,\r\n primitive._depthFailAppearance.material,\r\n frameState\r\n );\r\n }\r\n\r\n var pass = translucent ? Pass.TRANSLUCENT : Pass.OPAQUE;\r\n\r\n var multiplier = twoPasses ? 2 : 1;\r\n multiplier *= defined(primitive._depthFailAppearance) ? 2 : 1;\r\n colorCommands.length = primitive._va.length * multiplier;\r\n\r\n var length = colorCommands.length;\r\n var vaIndex = 0;\r\n for (var i = 0; i < length; ++i) {\r\n var colorCommand;\r\n\r\n if (twoPasses) {\r\n colorCommand = colorCommands[i];\r\n if (!defined(colorCommand)) {\r\n colorCommand = colorCommands[i] = new DrawCommand({\r\n owner: primitive,\r\n primitiveType: primitive._primitiveType,\r\n });\r\n }\r\n colorCommand.vertexArray = primitive._va[vaIndex];\r\n colorCommand.renderState = primitive._backFaceRS;\r\n colorCommand.shaderProgram = primitive._sp;\r\n colorCommand.uniformMap = uniforms;\r\n colorCommand.pass = pass;\r\n\r\n ++i;\r\n }\r\n\r\n colorCommand = colorCommands[i];\r\n if (!defined(colorCommand)) {\r\n colorCommand = colorCommands[i] = new DrawCommand({\r\n owner: primitive,\r\n primitiveType: primitive._primitiveType,\r\n });\r\n }\r\n colorCommand.vertexArray = primitive._va[vaIndex];\r\n colorCommand.renderState = primitive._frontFaceRS;\r\n colorCommand.shaderProgram = primitive._sp;\r\n colorCommand.uniformMap = uniforms;\r\n colorCommand.pass = pass;\r\n\r\n if (defined(primitive._depthFailAppearance)) {\r\n if (twoPasses) {\r\n ++i;\r\n\r\n colorCommand = colorCommands[i];\r\n if (!defined(colorCommand)) {\r\n colorCommand = colorCommands[i] = new DrawCommand({\r\n owner: primitive,\r\n primitiveType: primitive._primitiveType,\r\n });\r\n }\r\n colorCommand.vertexArray = primitive._va[vaIndex];\r\n colorCommand.renderState = primitive._backFaceDepthFailRS;\r\n colorCommand.shaderProgram = primitive._spDepthFail;\r\n colorCommand.uniformMap = depthFailUniforms;\r\n colorCommand.pass = pass;\r\n }\r\n\r\n ++i;\r\n\r\n colorCommand = colorCommands[i];\r\n if (!defined(colorCommand)) {\r\n colorCommand = colorCommands[i] = new DrawCommand({\r\n owner: primitive,\r\n primitiveType: primitive._primitiveType,\r\n });\r\n }\r\n colorCommand.vertexArray = primitive._va[vaIndex];\r\n colorCommand.renderState = primitive._frontFaceDepthFailRS;\r\n colorCommand.shaderProgram = primitive._spDepthFail;\r\n colorCommand.uniformMap = depthFailUniforms;\r\n colorCommand.pass = pass;\r\n }\r\n\r\n ++vaIndex;\r\n }\r\n}\r\n\r\nPrimitive._updateBoundingVolumes = function (\r\n primitive,\r\n frameState,\r\n modelMatrix,\r\n forceUpdate\r\n) {\r\n var i;\r\n var length;\r\n var boundingSphere;\r\n\r\n if (forceUpdate || !Matrix4.equals(modelMatrix, primitive._modelMatrix)) {\r\n Matrix4.clone(modelMatrix, primitive._modelMatrix);\r\n length = primitive._boundingSpheres.length;\r\n for (i = 0; i < length; ++i) {\r\n boundingSphere = primitive._boundingSpheres[i];\r\n if (defined(boundingSphere)) {\r\n primitive._boundingSphereWC[i] = BoundingSphere.transform(\r\n boundingSphere,\r\n modelMatrix,\r\n primitive._boundingSphereWC[i]\r\n );\r\n if (!frameState.scene3DOnly) {\r\n primitive._boundingSphere2D[i] = BoundingSphere.clone(\r\n primitive._boundingSphereCV[i],\r\n primitive._boundingSphere2D[i]\r\n );\r\n primitive._boundingSphere2D[i].center.x = 0.0;\r\n primitive._boundingSphereMorph[i] = BoundingSphere.union(\r\n primitive._boundingSphereWC[i],\r\n primitive._boundingSphereCV[i]\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Update bounding volumes for primitives that are sized in pixels.\r\n // The pixel size in meters varies based on the distance from the camera.\r\n var pixelSize = primitive.appearance.pixelSize;\r\n if (defined(pixelSize)) {\r\n length = primitive._boundingSpheres.length;\r\n for (i = 0; i < length; ++i) {\r\n boundingSphere = primitive._boundingSpheres[i];\r\n var boundingSphereWC = primitive._boundingSphereWC[i];\r\n var pixelSizeInMeters = frameState.camera.getPixelSize(\r\n boundingSphere,\r\n frameState.context.drawingBufferWidth,\r\n frameState.context.drawingBufferHeight\r\n );\r\n var sizeInMeters = pixelSizeInMeters * pixelSize;\r\n boundingSphereWC.radius = boundingSphere.radius + sizeInMeters;\r\n }\r\n }\r\n};\r\n\r\nfunction updateAndQueueCommands(\r\n primitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n frameState.mode !== SceneMode.SCENE3D &&\r\n !Matrix4.equals(modelMatrix, Matrix4.IDENTITY)\r\n ) {\r\n throw new DeveloperError(\r\n \"Primitive.modelMatrix is only supported in 3D mode.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n Primitive._updateBoundingVolumes(primitive, frameState, modelMatrix);\r\n\r\n var boundingSpheres;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n boundingSpheres = primitive._boundingSphereWC;\r\n } else if (frameState.mode === SceneMode.COLUMBUS_VIEW) {\r\n boundingSpheres = primitive._boundingSphereCV;\r\n } else if (\r\n frameState.mode === SceneMode.SCENE2D &&\r\n defined(primitive._boundingSphere2D)\r\n ) {\r\n boundingSpheres = primitive._boundingSphere2D;\r\n } else if (defined(primitive._boundingSphereMorph)) {\r\n boundingSpheres = primitive._boundingSphereMorph;\r\n }\r\n\r\n var commandList = frameState.commandList;\r\n var passes = frameState.passes;\r\n if (passes.render || passes.pick) {\r\n var allowPicking = primitive.allowPicking;\r\n var castShadows = ShadowMode.castShadows(primitive.shadows);\r\n var receiveShadows = ShadowMode.receiveShadows(primitive.shadows);\r\n var colorLength = colorCommands.length;\r\n\r\n var factor = twoPasses ? 2 : 1;\r\n factor *= defined(primitive._depthFailAppearance) ? 2 : 1;\r\n\r\n for (var j = 0; j < colorLength; ++j) {\r\n var sphereIndex = Math.floor(j / factor);\r\n var colorCommand = colorCommands[j];\r\n colorCommand.modelMatrix = modelMatrix;\r\n colorCommand.boundingVolume = boundingSpheres[sphereIndex];\r\n colorCommand.cull = cull;\r\n colorCommand.debugShowBoundingVolume = debugShowBoundingVolume;\r\n colorCommand.castShadows = castShadows;\r\n colorCommand.receiveShadows = receiveShadows;\r\n\r\n if (allowPicking) {\r\n colorCommand.pickId = \"v_pickColor\";\r\n } else {\r\n colorCommand.pickId = undefined;\r\n }\r\n\r\n commandList.push(colorCommand);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Called when {@link Viewer} or {@link CesiumWidget} render the scene to\r\n * get the draw commands needed to render this primitive.\r\n *

\r\n * Do not call this function directly. This is documented just to\r\n * list the exceptions that may be propagated when the scene is rendered:\r\n *

\r\n *\r\n * @exception {DeveloperError} All instance geometries must have the same primitiveType.\r\n * @exception {DeveloperError} Appearance and material have a uniform with the same name.\r\n * @exception {DeveloperError} Primitive.modelMatrix is only supported in 3D mode.\r\n * @exception {RuntimeError} Vertex texture fetch support is required to render primitives with per-instance attributes. The maximum number of vertex texture image units must be greater than zero.\r\n */\r\nPrimitive.prototype.update = function (frameState) {\r\n if (\r\n (!defined(this.geometryInstances) && this._va.length === 0) ||\r\n (defined(this.geometryInstances) &&\r\n Array.isArray(this.geometryInstances) &&\r\n this.geometryInstances.length === 0) ||\r\n !defined(this.appearance) ||\r\n (frameState.mode !== SceneMode.SCENE3D && frameState.scene3DOnly) ||\r\n (!frameState.passes.render && !frameState.passes.pick)\r\n ) {\r\n return;\r\n }\r\n\r\n if (defined(this._error)) {\r\n throw this._error;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(this.rtcCenter) && !frameState.scene3DOnly) {\r\n throw new DeveloperError(\r\n \"RTC rendering is only available for 3D only scenes.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._state === PrimitiveState.FAILED) {\r\n return;\r\n }\r\n\r\n var context = frameState.context;\r\n if (!defined(this._batchTable)) {\r\n createBatchTable(this, context);\r\n }\r\n if (this._batchTable.attributes.length > 0) {\r\n if (ContextLimits.maximumVertexTextureImageUnits === 0) {\r\n throw new RuntimeError(\r\n \"Vertex texture fetch support is required to render primitives with per-instance attributes. The maximum number of vertex texture image units must be greater than zero.\"\r\n );\r\n }\r\n this._batchTable.update(frameState);\r\n }\r\n\r\n if (\r\n this._state !== PrimitiveState.COMPLETE &&\r\n this._state !== PrimitiveState.COMBINED\r\n ) {\r\n if (this.asynchronous) {\r\n loadAsynchronous(this, frameState);\r\n } else {\r\n loadSynchronous(this, frameState);\r\n }\r\n }\r\n\r\n if (this._state === PrimitiveState.COMBINED) {\r\n updateBatchTableBoundingSpheres(this, frameState);\r\n updateBatchTableOffsets(this, frameState);\r\n createVertexArray(this, frameState);\r\n }\r\n\r\n if (!this.show || this._state !== PrimitiveState.COMPLETE) {\r\n return;\r\n }\r\n\r\n if (!this._batchTableOffsetsUpdated) {\r\n updateBatchTableOffsets(this, frameState);\r\n }\r\n if (this._recomputeBoundingSpheres) {\r\n recomputeBoundingSpheres(this, frameState);\r\n }\r\n\r\n // Create or recreate render state and shader program if appearance/material changed\r\n var appearance = this.appearance;\r\n var material = appearance.material;\r\n var createRS = false;\r\n var createSP = false;\r\n\r\n if (this._appearance !== appearance) {\r\n this._appearance = appearance;\r\n this._material = material;\r\n createRS = true;\r\n createSP = true;\r\n } else if (this._material !== material) {\r\n this._material = material;\r\n createSP = true;\r\n }\r\n\r\n var depthFailAppearance = this.depthFailAppearance;\r\n var depthFailMaterial = defined(depthFailAppearance)\r\n ? depthFailAppearance.material\r\n : undefined;\r\n\r\n if (this._depthFailAppearance !== depthFailAppearance) {\r\n this._depthFailAppearance = depthFailAppearance;\r\n this._depthFailMaterial = depthFailMaterial;\r\n createRS = true;\r\n createSP = true;\r\n } else if (this._depthFailMaterial !== depthFailMaterial) {\r\n this._depthFailMaterial = depthFailMaterial;\r\n createSP = true;\r\n }\r\n\r\n var translucent = this._appearance.isTranslucent();\r\n if (this._translucent !== translucent) {\r\n this._translucent = translucent;\r\n createRS = true;\r\n }\r\n\r\n if (defined(this._material)) {\r\n this._material.update(context);\r\n }\r\n\r\n var twoPasses = appearance.closed && translucent;\r\n\r\n if (createRS) {\r\n var rsFunc = defaultValue(\r\n this._createRenderStatesFunction,\r\n createRenderStates\r\n );\r\n rsFunc(this, context, appearance, twoPasses);\r\n }\r\n\r\n if (createSP) {\r\n var spFunc = defaultValue(\r\n this._createShaderProgramFunction,\r\n createShaderProgram\r\n );\r\n spFunc(this, frameState, appearance);\r\n }\r\n\r\n if (createRS || createSP) {\r\n var commandFunc = defaultValue(\r\n this._createCommandsFunction,\r\n createCommands\r\n );\r\n commandFunc(\r\n this,\r\n appearance,\r\n material,\r\n translucent,\r\n twoPasses,\r\n this._colorCommands,\r\n this._pickCommands,\r\n frameState\r\n );\r\n }\r\n\r\n var updateAndQueueCommandsFunc = defaultValue(\r\n this._updateAndQueueCommandsFunction,\r\n updateAndQueueCommands\r\n );\r\n updateAndQueueCommandsFunc(\r\n this,\r\n frameState,\r\n this._colorCommands,\r\n this._pickCommands,\r\n this.modelMatrix,\r\n this.cull,\r\n this.debugShowBoundingVolume,\r\n twoPasses\r\n );\r\n};\r\n\r\nvar offsetBoundingSphereScratch1 = new BoundingSphere();\r\nvar offsetBoundingSphereScratch2 = new BoundingSphere();\r\nfunction transformBoundingSphere(boundingSphere, offset, offsetAttribute) {\r\n if (offsetAttribute === GeometryOffsetAttribute.TOP) {\r\n var origBS = BoundingSphere.clone(\r\n boundingSphere,\r\n offsetBoundingSphereScratch1\r\n );\r\n var offsetBS = BoundingSphere.clone(\r\n boundingSphere,\r\n offsetBoundingSphereScratch2\r\n );\r\n offsetBS.center = Cartesian3.add(offsetBS.center, offset, offsetBS.center);\r\n boundingSphere = BoundingSphere.union(origBS, offsetBS, boundingSphere);\r\n } else if (offsetAttribute === GeometryOffsetAttribute.ALL) {\r\n boundingSphere.center = Cartesian3.add(\r\n boundingSphere.center,\r\n offset,\r\n boundingSphere.center\r\n );\r\n }\r\n\r\n return boundingSphere;\r\n}\r\n\r\nfunction createGetFunction(batchTable, instanceIndex, attributeIndex) {\r\n return function () {\r\n var attributeValue = batchTable.getBatchedAttribute(\r\n instanceIndex,\r\n attributeIndex\r\n );\r\n var attribute = batchTable.attributes[attributeIndex];\r\n var componentsPerAttribute = attribute.componentsPerAttribute;\r\n var value = ComponentDatatype.createTypedArray(\r\n attribute.componentDatatype,\r\n componentsPerAttribute\r\n );\r\n if (defined(attributeValue.constructor.pack)) {\r\n attributeValue.constructor.pack(attributeValue, value, 0);\r\n } else {\r\n value[0] = attributeValue;\r\n }\r\n return value;\r\n };\r\n}\r\n\r\nfunction createSetFunction(\r\n batchTable,\r\n instanceIndex,\r\n attributeIndex,\r\n primitive,\r\n name\r\n) {\r\n return function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(value) ||\r\n !defined(value.length) ||\r\n value.length < 1 ||\r\n value.length > 4\r\n ) {\r\n throw new DeveloperError(\r\n \"value must be and array with length between 1 and 4.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n var attributeValue = getAttributeValue(value);\r\n batchTable.setBatchedAttribute(\r\n instanceIndex,\r\n attributeIndex,\r\n attributeValue\r\n );\r\n if (name === \"offset\") {\r\n primitive._recomputeBoundingSpheres = true;\r\n primitive._batchTableOffsetsUpdated = false;\r\n }\r\n };\r\n}\r\n\r\nvar offsetScratch = new Cartesian3();\r\n\r\nfunction createBoundingSphereProperties(primitive, properties, index) {\r\n properties.boundingSphere = {\r\n get: function () {\r\n var boundingSphere = primitive._instanceBoundingSpheres[index];\r\n if (defined(boundingSphere)) {\r\n boundingSphere = boundingSphere.clone();\r\n var modelMatrix = primitive.modelMatrix;\r\n var offset = properties.offset;\r\n if (defined(offset)) {\r\n transformBoundingSphere(\r\n boundingSphere,\r\n Cartesian3.fromArray(offset.get(), 0, offsetScratch),\r\n primitive._offsetInstanceExtend[index]\r\n );\r\n }\r\n if (defined(modelMatrix)) {\r\n boundingSphere = BoundingSphere.transform(\r\n boundingSphere,\r\n modelMatrix\r\n );\r\n }\r\n }\r\n\r\n return boundingSphere;\r\n },\r\n };\r\n properties.boundingSphereCV = {\r\n get: function () {\r\n return primitive._instanceBoundingSpheresCV[index];\r\n },\r\n };\r\n}\r\n\r\nfunction createPickIdProperty(primitive, properties, index) {\r\n properties.pickId = {\r\n get: function () {\r\n return primitive._pickIds[index];\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Returns the modifiable per-instance attributes for a {@link GeometryInstance}.\r\n *\r\n * @param {*} id The id of the {@link GeometryInstance}.\r\n * @returns {Object} The typed array in the attribute's format or undefined if the is no instance with id.\r\n *\r\n * @exception {DeveloperError} must call update before calling getGeometryInstanceAttributes.\r\n *\r\n * @example\r\n * var attributes = primitive.getGeometryInstanceAttributes('an id');\r\n * attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA);\r\n * attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true);\r\n * attributes.distanceDisplayCondition = Cesium.DistanceDisplayConditionGeometryInstanceAttribute.toValue(100.0, 10000.0);\r\n * attributes.offset = Cesium.OffsetGeometryInstanceAttribute.toValue(Cartesian3.IDENTITY);\r\n */\r\nPrimitive.prototype.getGeometryInstanceAttributes = function (id) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(id)) {\r\n throw new DeveloperError(\"id is required\");\r\n }\r\n if (!defined(this._batchTable)) {\r\n throw new DeveloperError(\r\n \"must call update before calling getGeometryInstanceAttributes\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var index = -1;\r\n var lastIndex = this._lastPerInstanceAttributeIndex;\r\n var ids = this._instanceIds;\r\n var length = ids.length;\r\n for (var i = 0; i < length; ++i) {\r\n var curIndex = (lastIndex + i) % length;\r\n if (id === ids[curIndex]) {\r\n index = curIndex;\r\n break;\r\n }\r\n }\r\n\r\n if (index === -1) {\r\n return undefined;\r\n }\r\n\r\n var attributes = this._perInstanceAttributeCache[index];\r\n if (defined(attributes)) {\r\n return attributes;\r\n }\r\n\r\n var batchTable = this._batchTable;\r\n var perInstanceAttributeIndices = this._batchTableAttributeIndices;\r\n attributes = {};\r\n var properties = {};\r\n\r\n for (var name in perInstanceAttributeIndices) {\r\n if (perInstanceAttributeIndices.hasOwnProperty(name)) {\r\n var attributeIndex = perInstanceAttributeIndices[name];\r\n properties[name] = {\r\n get: createGetFunction(batchTable, index, attributeIndex),\r\n set: createSetFunction(batchTable, index, attributeIndex, this, name),\r\n };\r\n }\r\n }\r\n\r\n createBoundingSphereProperties(this, properties, index);\r\n createPickIdProperty(this, properties, index);\r\n Object.defineProperties(attributes, properties);\r\n\r\n this._lastPerInstanceAttributeIndex = index;\r\n this._perInstanceAttributeCache[index] = attributes;\r\n return attributes;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see Primitive#destroy\r\n */\r\nPrimitive.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * e = e && e.destroy();\r\n *\r\n * @see Primitive#isDestroyed\r\n */\r\nPrimitive.prototype.destroy = function () {\r\n var length;\r\n var i;\r\n\r\n this._sp = this._sp && this._sp.destroy();\r\n this._spDepthFail = this._spDepthFail && this._spDepthFail.destroy();\r\n\r\n var va = this._va;\r\n length = va.length;\r\n for (i = 0; i < length; ++i) {\r\n va[i].destroy();\r\n }\r\n this._va = undefined;\r\n\r\n var pickIds = this._pickIds;\r\n length = pickIds.length;\r\n for (i = 0; i < length; ++i) {\r\n pickIds[i].destroy();\r\n }\r\n this._pickIds = undefined;\r\n\r\n this._batchTable = this._batchTable && this._batchTable.destroy();\r\n\r\n //These objects may be fairly large and reference other large objects (like Entities)\r\n //We explicitly set them to undefined here so that the memory can be freed\r\n //even if a reference to the destroyed Primitive has been kept around.\r\n this._instanceIds = undefined;\r\n this._perInstanceAttributeCache = undefined;\r\n this._attributeLocations = undefined;\r\n\r\n return destroyObject(this);\r\n};\r\n\r\nfunction setReady(primitive, frameState, state, error) {\r\n primitive._error = error;\r\n primitive._state = state;\r\n frameState.afterRender.push(function () {\r\n primitive._ready =\r\n primitive._state === PrimitiveState.COMPLETE ||\r\n primitive._state === PrimitiveState.FAILED;\r\n if (!defined(error)) {\r\n primitive._readyPromise.resolve(primitive);\r\n } else {\r\n primitive._readyPromise.reject(error);\r\n }\r\n });\r\n}\r\nexport default Primitive;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef GL_EXT_frag_depth\\n\\\n#extension GL_EXT_frag_depth : enable\\n\\\n#endif\\n\\\n#ifdef TEXTURE_COORDINATES\\n\\\n#ifdef SPHERICAL\\n\\\nvarying vec4 v_sphericalExtents;\\n\\\n#else // SPHERICAL\\n\\\nvarying vec2 v_inversePlaneExtents;\\n\\\nvarying vec4 v_westPlane;\\n\\\nvarying vec4 v_southPlane;\\n\\\n#endif // SPHERICAL\\n\\\nvarying vec3 v_uvMinAndSphericalLongitudeRotation;\\n\\\nvarying vec3 v_uMaxAndInverseDistance;\\n\\\nvarying vec3 v_vMaxAndInverseDistance;\\n\\\n#endif // TEXTURE_COORDINATES\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nvarying vec4 v_color;\\n\\\n#endif\\n\\\n#ifdef NORMAL_EC\\n\\\nvec3 getEyeCoordinate3FromWindowCoordinate(vec2 fragCoord, float logDepthOrDepth) {\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(fragCoord, logDepthOrDepth);\\n\\\nreturn eyeCoordinate.xyz / eyeCoordinate.w;\\n\\\n}\\n\\\nvec3 vectorFromOffset(vec4 eyeCoordinate, vec2 positiveOffset) {\\n\\\nvec2 glFragCoordXY = gl_FragCoord.xy;\\n\\\nfloat upOrRightLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY + positiveOffset) / czm_viewport.zw));\\n\\\nfloat downOrLeftLogDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, (glFragCoordXY - positiveOffset) / czm_viewport.zw));\\n\\\nbvec2 upOrRightInBounds = lessThan(glFragCoordXY + positiveOffset, czm_viewport.zw);\\n\\\nfloat useUpOrRight = float(upOrRightLogDepth > 0.0 && upOrRightInBounds.x && upOrRightInBounds.y);\\n\\\nfloat useDownOrLeft = float(useUpOrRight == 0.0);\\n\\\nvec3 upOrRightEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY + positiveOffset, upOrRightLogDepth);\\n\\\nvec3 downOrLeftEC = getEyeCoordinate3FromWindowCoordinate(glFragCoordXY - positiveOffset, downOrLeftLogDepth);\\n\\\nreturn (upOrRightEC - (eyeCoordinate.xyz / eyeCoordinate.w)) * useUpOrRight + ((eyeCoordinate.xyz / eyeCoordinate.w) - downOrLeftEC) * useDownOrLeft;\\n\\\n}\\n\\\n#endif // NORMAL_EC\\n\\\nvoid main(void)\\n\\\n{\\n\\\n#ifdef REQUIRES_EC\\n\\\nfloat logDepthOrDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw));\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);\\n\\\n#endif\\n\\\n#ifdef REQUIRES_WC\\n\\\nvec4 worldCoordinate4 = czm_inverseView * eyeCoordinate;\\n\\\nvec3 worldCoordinate = worldCoordinate4.xyz / worldCoordinate4.w;\\n\\\n#endif\\n\\\n#ifdef TEXTURE_COORDINATES\\n\\\nvec2 uv;\\n\\\n#ifdef SPHERICAL\\n\\\nvec2 sphericalLatLong = czm_approximateSphericalCoordinates(worldCoordinate);\\n\\\nsphericalLatLong.y += v_uvMinAndSphericalLongitudeRotation.z;\\n\\\nsphericalLatLong.y = czm_branchFreeTernary(sphericalLatLong.y < czm_pi, sphericalLatLong.y, sphericalLatLong.y - czm_twoPi);\\n\\\nuv.x = (sphericalLatLong.y - v_sphericalExtents.y) * v_sphericalExtents.w;\\n\\\nuv.y = (sphericalLatLong.x - v_sphericalExtents.x) * v_sphericalExtents.z;\\n\\\n#else // SPHERICAL\\n\\\nuv.x = czm_planeDistance(v_westPlane, eyeCoordinate.xyz / eyeCoordinate.w) * v_inversePlaneExtents.x;\\n\\\nuv.y = czm_planeDistance(v_southPlane, eyeCoordinate.xyz / eyeCoordinate.w) * v_inversePlaneExtents.y;\\n\\\n#endif // SPHERICAL\\n\\\n#endif // TEXTURE_COORDINATES\\n\\\n#ifdef PICK\\n\\\n#ifdef CULL_FRAGMENTS\\n\\\nif (0.0 <= uv.x && uv.x <= 1.0 && 0.0 <= uv.y && uv.y <= 1.0 || logDepthOrDepth != 0.0) {\\n\\\ngl_FragColor.a = 1.0;\\n\\\nczm_writeDepthClamp();\\n\\\n}\\n\\\n#else // CULL_FRAGMENTS\\n\\\ngl_FragColor.a = 1.0;\\n\\\n#endif // CULL_FRAGMENTS\\n\\\n#else // PICK\\n\\\n#ifdef CULL_FRAGMENTS\\n\\\nif (uv.x <= 0.0 || 1.0 <= uv.x || uv.y <= 0.0 || 1.0 <= uv.y || logDepthOrDepth == 0.0) {\\n\\\ndiscard;\\n\\\n}\\n\\\n#endif\\n\\\n#ifdef NORMAL_EC\\n\\\nvec3 downUp = vectorFromOffset(eyeCoordinate, vec2(0.0, 1.0));\\n\\\nvec3 leftRight = vectorFromOffset(eyeCoordinate, vec2(1.0, 0.0));\\n\\\nvec3 normalEC = normalize(cross(leftRight, downUp));\\n\\\n#endif\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nvec4 color = czm_gammaCorrect(v_color);\\n\\\n#ifdef FLAT\\n\\\ngl_FragColor = color;\\n\\\n#else // FLAT\\n\\\nczm_materialInput materialInput;\\n\\\nmaterialInput.normalEC = normalEC;\\n\\\nmaterialInput.positionToEyeEC = -eyeCoordinate.xyz;\\n\\\nczm_material material = czm_getDefaultMaterial(materialInput);\\n\\\nmaterial.diffuse = color.rgb;\\n\\\nmaterial.alpha = color.a;\\n\\\ngl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material, czm_lightDirectionEC);\\n\\\n#endif // FLAT\\n\\\ngl_FragColor.rgb *= gl_FragColor.a;\\n\\\n#else // PER_INSTANCE_COLOR\\n\\\nczm_materialInput materialInput;\\n\\\n#ifdef USES_NORMAL_EC\\n\\\nmaterialInput.normalEC = normalEC;\\n\\\n#endif\\n\\\n#ifdef USES_POSITION_TO_EYE_EC\\n\\\nmaterialInput.positionToEyeEC = -eyeCoordinate.xyz;\\n\\\n#endif\\n\\\n#ifdef USES_TANGENT_TO_EYE\\n\\\nmaterialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(worldCoordinate, normalEC);\\n\\\n#endif\\n\\\n#ifdef USES_ST\\n\\\nmaterialInput.st.x = czm_lineDistance(v_uvMinAndSphericalLongitudeRotation.xy, v_uMaxAndInverseDistance.xy, uv) * v_uMaxAndInverseDistance.z;\\n\\\nmaterialInput.st.y = czm_lineDistance(v_uvMinAndSphericalLongitudeRotation.xy, v_vMaxAndInverseDistance.xy, uv) * v_vMaxAndInverseDistance.z;\\n\\\n#endif\\n\\\nczm_material material = czm_getMaterial(materialInput);\\n\\\n#ifdef FLAT\\n\\\ngl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\\n\\\n#else // FLAT\\n\\\ngl_FragColor = czm_phong(normalize(-eyeCoordinate.xyz), material, czm_lightDirectionEC);\\n\\\n#endif // FLAT\\n\\\ngl_FragColor.rgb *= gl_FragColor.a;\\n\\\n#endif // PER_INSTANCE_COLOR\\n\\\nczm_writeDepthClamp();\\n\\\n#endif // PICK\\n\\\n}\\n\\\n\";\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport EncodedCartesian3 from \"../Core/EncodedCartesian3.js\";\r\nimport GeometryInstanceAttribute from \"../Core/GeometryInstanceAttribute.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ShadowVolumeAppearanceFS from \"../Shaders/ShadowVolumeAppearanceFS.js\";\r\n\r\n/**\r\n * Creates shaders for a ClassificationPrimitive to use a given Appearance, as well as for picking.\r\n *\r\n * @param {Boolean} extentsCulling Discard fragments outside the instance's texture coordinate extents.\r\n * @param {Boolean} planarExtents If true, texture coordinates will be computed using planes instead of spherical coordinates.\r\n * @param {Appearance} appearance An Appearance to be used with a ClassificationPrimitive via GroundPrimitive.\r\n * @private\r\n */\r\nfunction ShadowVolumeAppearance(extentsCulling, planarExtents, appearance) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.bool(\"extentsCulling\", extentsCulling);\r\n Check.typeOf.bool(\"planarExtents\", planarExtents);\r\n Check.typeOf.object(\"appearance\", appearance);\r\n //>>includeEnd('debug');\r\n\r\n this._projectionExtentDefines = {\r\n eastMostYhighDefine: \"\",\r\n eastMostYlowDefine: \"\",\r\n westMostYhighDefine: \"\",\r\n westMostYlowDefine: \"\",\r\n };\r\n\r\n // Compute shader dependencies\r\n var colorShaderDependencies = new ShaderDependencies();\r\n colorShaderDependencies.requiresTextureCoordinates = extentsCulling;\r\n colorShaderDependencies.requiresEC = !appearance.flat;\r\n\r\n var pickShaderDependencies = new ShaderDependencies();\r\n pickShaderDependencies.requiresTextureCoordinates = extentsCulling;\r\n\r\n if (appearance instanceof PerInstanceColorAppearance) {\r\n // PerInstanceColorAppearance doesn't have material.shaderSource, instead it has its own vertex and fragment shaders\r\n colorShaderDependencies.requiresNormalEC = !appearance.flat;\r\n } else {\r\n // Scan material source for what hookups are needed. Assume czm_materialInput materialInput.\r\n var materialShaderSource =\r\n appearance.material.shaderSource + \"\\n\" + appearance.fragmentShaderSource;\r\n\r\n colorShaderDependencies.normalEC =\r\n materialShaderSource.indexOf(\"materialInput.normalEC\") !== -1 ||\r\n materialShaderSource.indexOf(\"czm_getDefaultMaterial\") !== -1;\r\n colorShaderDependencies.positionToEyeEC =\r\n materialShaderSource.indexOf(\"materialInput.positionToEyeEC\") !== -1;\r\n colorShaderDependencies.tangentToEyeMatrix =\r\n materialShaderSource.indexOf(\"materialInput.tangentToEyeMatrix\") !== -1;\r\n colorShaderDependencies.st =\r\n materialShaderSource.indexOf(\"materialInput.st\") !== -1;\r\n }\r\n\r\n this._colorShaderDependencies = colorShaderDependencies;\r\n this._pickShaderDependencies = pickShaderDependencies;\r\n this._appearance = appearance;\r\n this._extentsCulling = extentsCulling;\r\n this._planarExtents = planarExtents;\r\n}\r\n\r\n/**\r\n * Create the fragment shader for a ClassificationPrimitive's color pass when rendering for color.\r\n *\r\n * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.\r\n * @returns {ShaderSource} Shader source for the fragment shader.\r\n */\r\nShadowVolumeAppearance.prototype.createFragmentShader = function (\r\n columbusView2D\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.bool(\"columbusView2D\", columbusView2D);\r\n //>>includeEnd('debug');\r\n\r\n var appearance = this._appearance;\r\n var dependencies = this._colorShaderDependencies;\r\n\r\n var defines = [];\r\n if (!columbusView2D && !this._planarExtents) {\r\n defines.push(\"SPHERICAL\");\r\n }\r\n if (dependencies.requiresEC) {\r\n defines.push(\"REQUIRES_EC\");\r\n }\r\n if (dependencies.requiresWC) {\r\n defines.push(\"REQUIRES_WC\");\r\n }\r\n if (dependencies.requiresTextureCoordinates) {\r\n defines.push(\"TEXTURE_COORDINATES\");\r\n }\r\n if (this._extentsCulling) {\r\n defines.push(\"CULL_FRAGMENTS\");\r\n }\r\n if (dependencies.requiresNormalEC) {\r\n defines.push(\"NORMAL_EC\");\r\n }\r\n if (appearance instanceof PerInstanceColorAppearance) {\r\n defines.push(\"PER_INSTANCE_COLOR\");\r\n }\r\n\r\n // Material inputs. Use of parameters in the material is different\r\n // from requirement of the parameters in the overall shader, for example,\r\n // texture coordinates may be used for fragment culling but not for the material itself.\r\n if (dependencies.normalEC) {\r\n defines.push(\"USES_NORMAL_EC\");\r\n }\r\n if (dependencies.positionToEyeEC) {\r\n defines.push(\"USES_POSITION_TO_EYE_EC\");\r\n }\r\n if (dependencies.tangentToEyeMatrix) {\r\n defines.push(\"USES_TANGENT_TO_EYE\");\r\n }\r\n if (dependencies.st) {\r\n defines.push(\"USES_ST\");\r\n }\r\n\r\n if (appearance.flat) {\r\n defines.push(\"FLAT\");\r\n }\r\n\r\n var materialSource = \"\";\r\n if (!(appearance instanceof PerInstanceColorAppearance)) {\r\n materialSource = appearance.material.shaderSource;\r\n }\r\n\r\n return new ShaderSource({\r\n defines: defines,\r\n sources: [materialSource, ShadowVolumeAppearanceFS],\r\n });\r\n};\r\n\r\nShadowVolumeAppearance.prototype.createPickFragmentShader = function (\r\n columbusView2D\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.bool(\"columbusView2D\", columbusView2D);\r\n //>>includeEnd('debug');\r\n\r\n var dependencies = this._pickShaderDependencies;\r\n\r\n var defines = [\"PICK\"];\r\n if (!columbusView2D && !this._planarExtents) {\r\n defines.push(\"SPHERICAL\");\r\n }\r\n if (dependencies.requiresEC) {\r\n defines.push(\"REQUIRES_EC\");\r\n }\r\n if (dependencies.requiresWC) {\r\n defines.push(\"REQUIRES_WC\");\r\n }\r\n if (dependencies.requiresTextureCoordinates) {\r\n defines.push(\"TEXTURE_COORDINATES\");\r\n }\r\n if (this._extentsCulling) {\r\n defines.push(\"CULL_FRAGMENTS\");\r\n }\r\n return new ShaderSource({\r\n defines: defines,\r\n sources: [ShadowVolumeAppearanceFS],\r\n pickColorQualifier: \"varying\",\r\n });\r\n};\r\n\r\n/**\r\n * Create the vertex shader for a ClassificationPrimitive's color pass on the final of 3 shadow volume passes\r\n *\r\n * @param {String[]} defines External defines to pass to the vertex shader.\r\n * @param {String} vertexShaderSource ShadowVolumeAppearanceVS with any required modifications for computing position.\r\n * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.\r\n * @param {MapProjection} mapProjection Current scene's map projection.\r\n * @returns {String} Shader source for the vertex shader.\r\n */\r\nShadowVolumeAppearance.prototype.createVertexShader = function (\r\n defines,\r\n vertexShaderSource,\r\n columbusView2D,\r\n mapProjection\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"defines\", defines);\r\n Check.typeOf.string(\"vertexShaderSource\", vertexShaderSource);\r\n Check.typeOf.bool(\"columbusView2D\", columbusView2D);\r\n Check.defined(\"mapProjection\", mapProjection);\r\n //>>includeEnd('debug');\r\n return createShadowVolumeAppearanceVS(\r\n this._colorShaderDependencies,\r\n this._planarExtents,\r\n columbusView2D,\r\n defines,\r\n vertexShaderSource,\r\n this._appearance,\r\n mapProjection,\r\n this._projectionExtentDefines\r\n );\r\n};\r\n\r\n/**\r\n * Create the vertex shader for a ClassificationPrimitive's pick pass on the final of 3 shadow volume passes\r\n *\r\n * @param {String[]} defines External defines to pass to the vertex shader.\r\n * @param {String} vertexShaderSource ShadowVolumeAppearanceVS with any required modifications for computing position and picking.\r\n * @param {Boolean} columbusView2D Whether the shader will be used for Columbus View or 2D.\r\n * @param {MapProjection} mapProjection Current scene's map projection.\r\n * @returns {String} Shader source for the vertex shader.\r\n */\r\nShadowVolumeAppearance.prototype.createPickVertexShader = function (\r\n defines,\r\n vertexShaderSource,\r\n columbusView2D,\r\n mapProjection\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"defines\", defines);\r\n Check.typeOf.string(\"vertexShaderSource\", vertexShaderSource);\r\n Check.typeOf.bool(\"columbusView2D\", columbusView2D);\r\n Check.defined(\"mapProjection\", mapProjection);\r\n //>>includeEnd('debug');\r\n return createShadowVolumeAppearanceVS(\r\n this._pickShaderDependencies,\r\n this._planarExtents,\r\n columbusView2D,\r\n defines,\r\n vertexShaderSource,\r\n undefined,\r\n mapProjection,\r\n this._projectionExtentDefines\r\n );\r\n};\r\n\r\nvar longitudeExtentsCartesianScratch = new Cartesian3();\r\nvar longitudeExtentsCartographicScratch = new Cartographic();\r\nvar longitudeExtentsEncodeScratch = {\r\n high: 0.0,\r\n low: 0.0,\r\n};\r\nfunction createShadowVolumeAppearanceVS(\r\n shaderDependencies,\r\n planarExtents,\r\n columbusView2D,\r\n defines,\r\n vertexShaderSource,\r\n appearance,\r\n mapProjection,\r\n projectionExtentDefines\r\n) {\r\n var allDefines = defines.slice();\r\n\r\n if (projectionExtentDefines.eastMostYhighDefine === \"\") {\r\n var eastMostCartographic = longitudeExtentsCartographicScratch;\r\n eastMostCartographic.longitude = CesiumMath.PI;\r\n eastMostCartographic.latitude = 0.0;\r\n eastMostCartographic.height = 0.0;\r\n var eastMostCartesian = mapProjection.project(\r\n eastMostCartographic,\r\n longitudeExtentsCartesianScratch\r\n );\r\n var encoded = EncodedCartesian3.encode(\r\n eastMostCartesian.x,\r\n longitudeExtentsEncodeScratch\r\n );\r\n projectionExtentDefines.eastMostYhighDefine =\r\n \"EAST_MOST_X_HIGH \" +\r\n encoded.high.toFixed((encoded.high + \"\").length + 1);\r\n projectionExtentDefines.eastMostYlowDefine =\r\n \"EAST_MOST_X_LOW \" + encoded.low.toFixed((encoded.low + \"\").length + 1);\r\n\r\n var westMostCartographic = longitudeExtentsCartographicScratch;\r\n westMostCartographic.longitude = -CesiumMath.PI;\r\n westMostCartographic.latitude = 0.0;\r\n westMostCartographic.height = 0.0;\r\n var westMostCartesian = mapProjection.project(\r\n westMostCartographic,\r\n longitudeExtentsCartesianScratch\r\n );\r\n encoded = EncodedCartesian3.encode(\r\n westMostCartesian.x,\r\n longitudeExtentsEncodeScratch\r\n );\r\n projectionExtentDefines.westMostYhighDefine =\r\n \"WEST_MOST_X_HIGH \" +\r\n encoded.high.toFixed((encoded.high + \"\").length + 1);\r\n projectionExtentDefines.westMostYlowDefine =\r\n \"WEST_MOST_X_LOW \" + encoded.low.toFixed((encoded.low + \"\").length + 1);\r\n }\r\n\r\n if (columbusView2D) {\r\n allDefines.push(projectionExtentDefines.eastMostYhighDefine);\r\n allDefines.push(projectionExtentDefines.eastMostYlowDefine);\r\n allDefines.push(projectionExtentDefines.westMostYhighDefine);\r\n allDefines.push(projectionExtentDefines.westMostYlowDefine);\r\n }\r\n\r\n if (defined(appearance) && appearance instanceof PerInstanceColorAppearance) {\r\n allDefines.push(\"PER_INSTANCE_COLOR\");\r\n }\r\n if (shaderDependencies.requiresTextureCoordinates) {\r\n allDefines.push(\"TEXTURE_COORDINATES\");\r\n if (!(planarExtents || columbusView2D)) {\r\n allDefines.push(\"SPHERICAL\");\r\n }\r\n if (columbusView2D) {\r\n allDefines.push(\"COLUMBUS_VIEW_2D\");\r\n }\r\n }\r\n\r\n return new ShaderSource({\r\n defines: allDefines,\r\n sources: [vertexShaderSource],\r\n });\r\n}\r\n\r\n/**\r\n * Tracks shader dependencies.\r\n * @private\r\n */\r\nfunction ShaderDependencies() {\r\n this._requiresEC = false;\r\n this._requiresWC = false; // depends on eye coordinates, needed for material and for phong\r\n this._requiresNormalEC = false; // depends on eye coordinates, needed for material\r\n this._requiresTextureCoordinates = false; // depends on world coordinates, needed for material and for culling\r\n\r\n this._usesNormalEC = false;\r\n this._usesPositionToEyeEC = false;\r\n this._usesTangentToEyeMat = false;\r\n this._usesSt = false;\r\n}\r\n\r\nObject.defineProperties(ShaderDependencies.prototype, {\r\n // Set when assessing final shading (flat vs. phong) and culling using computed texture coordinates\r\n requiresEC: {\r\n get: function () {\r\n return this._requiresEC;\r\n },\r\n set: function (value) {\r\n this._requiresEC = value || this._requiresEC;\r\n },\r\n },\r\n requiresWC: {\r\n get: function () {\r\n return this._requiresWC;\r\n },\r\n set: function (value) {\r\n this._requiresWC = value || this._requiresWC;\r\n this.requiresEC = this._requiresWC;\r\n },\r\n },\r\n requiresNormalEC: {\r\n get: function () {\r\n return this._requiresNormalEC;\r\n },\r\n set: function (value) {\r\n this._requiresNormalEC = value || this._requiresNormalEC;\r\n this.requiresEC = this._requiresNormalEC;\r\n },\r\n },\r\n requiresTextureCoordinates: {\r\n get: function () {\r\n return this._requiresTextureCoordinates;\r\n },\r\n set: function (value) {\r\n this._requiresTextureCoordinates =\r\n value || this._requiresTextureCoordinates;\r\n this.requiresWC = this._requiresTextureCoordinates;\r\n },\r\n },\r\n // Get/Set when assessing material hookups\r\n normalEC: {\r\n set: function (value) {\r\n this.requiresNormalEC = value;\r\n this._usesNormalEC = value;\r\n },\r\n get: function () {\r\n return this._usesNormalEC;\r\n },\r\n },\r\n tangentToEyeMatrix: {\r\n set: function (value) {\r\n this.requiresWC = value;\r\n this.requiresNormalEC = value;\r\n this._usesTangentToEyeMat = value;\r\n },\r\n get: function () {\r\n return this._usesTangentToEyeMat;\r\n },\r\n },\r\n positionToEyeEC: {\r\n set: function (value) {\r\n this.requiresEC = value;\r\n this._usesPositionToEyeEC = value;\r\n },\r\n get: function () {\r\n return this._usesPositionToEyeEC;\r\n },\r\n },\r\n st: {\r\n set: function (value) {\r\n this.requiresTextureCoordinates = value;\r\n this._usesSt = value;\r\n },\r\n get: function () {\r\n return this._usesSt;\r\n },\r\n },\r\n});\r\n\r\nfunction pointLineDistance(point1, point2, point) {\r\n return (\r\n Math.abs(\r\n (point2.y - point1.y) * point.x -\r\n (point2.x - point1.x) * point.y +\r\n point2.x * point1.y -\r\n point2.y * point1.x\r\n ) / Cartesian2.distance(point2, point1)\r\n );\r\n}\r\n\r\nvar points2DScratch = [\r\n new Cartesian2(),\r\n new Cartesian2(),\r\n new Cartesian2(),\r\n new Cartesian2(),\r\n];\r\n\r\n// textureCoordinateRotationPoints form 2 lines in the computed UV space that remap to desired texture coordinates.\r\n// This allows simulation of baked texture coordinates for EllipseGeometry, RectangleGeometry, and PolygonGeometry.\r\nfunction addTextureCoordinateRotationAttributes(\r\n attributes,\r\n textureCoordinateRotationPoints\r\n) {\r\n var points2D = points2DScratch;\r\n\r\n var minXYCorner = Cartesian2.unpack(\r\n textureCoordinateRotationPoints,\r\n 0,\r\n points2D[0]\r\n );\r\n var maxYCorner = Cartesian2.unpack(\r\n textureCoordinateRotationPoints,\r\n 2,\r\n points2D[1]\r\n );\r\n var maxXCorner = Cartesian2.unpack(\r\n textureCoordinateRotationPoints,\r\n 4,\r\n points2D[2]\r\n );\r\n\r\n attributes.uMaxVmax = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n normalize: false,\r\n value: [maxYCorner.x, maxYCorner.y, maxXCorner.x, maxXCorner.y],\r\n });\r\n\r\n var inverseExtentX =\r\n 1.0 / pointLineDistance(minXYCorner, maxYCorner, maxXCorner);\r\n var inverseExtentY =\r\n 1.0 / pointLineDistance(minXYCorner, maxXCorner, maxYCorner);\r\n\r\n attributes.uvMinAndExtents = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n normalize: false,\r\n value: [minXYCorner.x, minXYCorner.y, inverseExtentX, inverseExtentY],\r\n });\r\n}\r\n\r\nvar cartographicScratch = new Cartographic();\r\nvar cornerScratch = new Cartesian3();\r\nvar northWestScratch = new Cartesian3();\r\nvar southEastScratch = new Cartesian3();\r\nvar highLowScratch = { high: 0.0, low: 0.0 };\r\nfunction add2DTextureCoordinateAttributes(rectangle, projection, attributes) {\r\n // Compute corner positions in double precision\r\n var carto = cartographicScratch;\r\n carto.height = 0.0;\r\n\r\n carto.longitude = rectangle.west;\r\n carto.latitude = rectangle.south;\r\n\r\n var southWestCorner = projection.project(carto, cornerScratch);\r\n\r\n carto.latitude = rectangle.north;\r\n var northWest = projection.project(carto, northWestScratch);\r\n\r\n carto.longitude = rectangle.east;\r\n carto.latitude = rectangle.south;\r\n var southEast = projection.project(carto, southEastScratch);\r\n\r\n // Since these positions are all in the 2D plane, there's a lot of zeros\r\n // and a lot of repetition. So we only need to encode 4 values.\r\n // Encode:\r\n // x: x value for southWestCorner\r\n // y: y value for southWestCorner\r\n // z: y value for northWest\r\n // w: x value for southEast\r\n\r\n var valuesHigh = [0, 0, 0, 0];\r\n var valuesLow = [0, 0, 0, 0];\r\n var encoded = EncodedCartesian3.encode(southWestCorner.x, highLowScratch);\r\n valuesHigh[0] = encoded.high;\r\n valuesLow[0] = encoded.low;\r\n\r\n encoded = EncodedCartesian3.encode(southWestCorner.y, highLowScratch);\r\n valuesHigh[1] = encoded.high;\r\n valuesLow[1] = encoded.low;\r\n\r\n encoded = EncodedCartesian3.encode(northWest.y, highLowScratch);\r\n valuesHigh[2] = encoded.high;\r\n valuesLow[2] = encoded.low;\r\n\r\n encoded = EncodedCartesian3.encode(southEast.x, highLowScratch);\r\n valuesHigh[3] = encoded.high;\r\n valuesLow[3] = encoded.low;\r\n\r\n attributes.planes2D_HIGH = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n normalize: false,\r\n value: valuesHigh,\r\n });\r\n\r\n attributes.planes2D_LOW = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n normalize: false,\r\n value: valuesLow,\r\n });\r\n}\r\n\r\nvar enuMatrixScratch = new Matrix4();\r\nvar inverseEnuScratch = new Matrix4();\r\nvar rectanglePointCartesianScratch = new Cartesian3();\r\nvar rectangleCenterScratch = new Cartographic();\r\nvar pointsCartographicScratch = [\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n new Cartographic(),\r\n];\r\n/**\r\n * When computing planes to bound the rectangle,\r\n * need to factor in \"bulge\" and other distortion.\r\n * Flatten the ellipsoid-centered corners and edge-centers of the rectangle\r\n * into the plane of the local ENU system, compute bounds in 2D, and\r\n * project back to ellipsoid-centered.\r\n *\r\n * @private\r\n */\r\nfunction computeRectangleBounds(\r\n rectangle,\r\n ellipsoid,\r\n height,\r\n southWestCornerResult,\r\n eastVectorResult,\r\n northVectorResult\r\n) {\r\n // Compute center of rectangle\r\n var centerCartographic = Rectangle.center(rectangle, rectangleCenterScratch);\r\n centerCartographic.height = height;\r\n var centerCartesian = Cartographic.toCartesian(\r\n centerCartographic,\r\n ellipsoid,\r\n rectanglePointCartesianScratch\r\n );\r\n var enuMatrix = Transforms.eastNorthUpToFixedFrame(\r\n centerCartesian,\r\n ellipsoid,\r\n enuMatrixScratch\r\n );\r\n var inverseEnu = Matrix4.inverse(enuMatrix, inverseEnuScratch);\r\n\r\n var west = rectangle.west;\r\n var east = rectangle.east;\r\n var north = rectangle.north;\r\n var south = rectangle.south;\r\n\r\n var cartographics = pointsCartographicScratch;\r\n cartographics[0].latitude = south;\r\n cartographics[0].longitude = west;\r\n cartographics[1].latitude = north;\r\n cartographics[1].longitude = west;\r\n cartographics[2].latitude = north;\r\n cartographics[2].longitude = east;\r\n cartographics[3].latitude = south;\r\n cartographics[3].longitude = east;\r\n\r\n var longitudeCenter = (west + east) * 0.5;\r\n var latitudeCenter = (north + south) * 0.5;\r\n\r\n cartographics[4].latitude = south;\r\n cartographics[4].longitude = longitudeCenter;\r\n cartographics[5].latitude = north;\r\n cartographics[5].longitude = longitudeCenter;\r\n cartographics[6].latitude = latitudeCenter;\r\n cartographics[6].longitude = west;\r\n cartographics[7].latitude = latitudeCenter;\r\n cartographics[7].longitude = east;\r\n\r\n var minX = Number.POSITIVE_INFINITY;\r\n var maxX = Number.NEGATIVE_INFINITY;\r\n var minY = Number.POSITIVE_INFINITY;\r\n var maxY = Number.NEGATIVE_INFINITY;\r\n for (var i = 0; i < 8; i++) {\r\n cartographics[i].height = height;\r\n var pointCartesian = Cartographic.toCartesian(\r\n cartographics[i],\r\n ellipsoid,\r\n rectanglePointCartesianScratch\r\n );\r\n Matrix4.multiplyByPoint(inverseEnu, pointCartesian, pointCartesian);\r\n pointCartesian.z = 0.0; // flatten into XY plane of ENU coordinate system\r\n minX = Math.min(minX, pointCartesian.x);\r\n maxX = Math.max(maxX, pointCartesian.x);\r\n minY = Math.min(minY, pointCartesian.y);\r\n maxY = Math.max(maxY, pointCartesian.y);\r\n }\r\n\r\n var southWestCorner = southWestCornerResult;\r\n southWestCorner.x = minX;\r\n southWestCorner.y = minY;\r\n southWestCorner.z = 0.0;\r\n Matrix4.multiplyByPoint(enuMatrix, southWestCorner, southWestCorner);\r\n\r\n var southEastCorner = eastVectorResult;\r\n southEastCorner.x = maxX;\r\n southEastCorner.y = minY;\r\n southEastCorner.z = 0.0;\r\n Matrix4.multiplyByPoint(enuMatrix, southEastCorner, southEastCorner);\r\n // make eastward vector\r\n Cartesian3.subtract(southEastCorner, southWestCorner, eastVectorResult);\r\n\r\n var northWestCorner = northVectorResult;\r\n northWestCorner.x = minX;\r\n northWestCorner.y = maxY;\r\n northWestCorner.z = 0.0;\r\n Matrix4.multiplyByPoint(enuMatrix, northWestCorner, northWestCorner);\r\n // make eastward vector\r\n Cartesian3.subtract(northWestCorner, southWestCorner, northVectorResult);\r\n}\r\n\r\nvar eastwardScratch = new Cartesian3();\r\nvar northwardScratch = new Cartesian3();\r\nvar encodeScratch = new EncodedCartesian3();\r\n/**\r\n * Gets an attributes object containing:\r\n * - 3 high-precision points as 6 GeometryInstanceAttributes. These points are used to compute eye-space planes.\r\n * - 1 texture coordinate rotation GeometryInstanceAttributes\r\n * - 2 GeometryInstanceAttributes used to compute high-precision points in 2D and Columbus View.\r\n * These points are used to compute eye-space planes like above.\r\n *\r\n * Used to compute texture coordinates for small-area ClassificationPrimitives with materials or multiple non-overlapping instances.\r\n *\r\n * @see ShadowVolumeAppearance\r\n * @private\r\n *\r\n * @param {Rectangle} boundingRectangle Rectangle object that the points will approximately bound\r\n * @param {Number[]} textureCoordinateRotationPoints Points in the computed texture coordinate system for remapping texture coordinates\r\n * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates\r\n * @param {MapProjection} projection The MapProjection used for 2D and Columbus View.\r\n * @param {Number} [height=0] The maximum height for the shadow volume.\r\n * @returns {Object} An attributes dictionary containing planar texture coordinate attributes.\r\n */\r\nShadowVolumeAppearance.getPlanarTextureCoordinateAttributes = function (\r\n boundingRectangle,\r\n textureCoordinateRotationPoints,\r\n ellipsoid,\r\n projection,\r\n height\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"boundingRectangle\", boundingRectangle);\r\n Check.defined(\r\n \"textureCoordinateRotationPoints\",\r\n textureCoordinateRotationPoints\r\n );\r\n Check.typeOf.object(\"ellipsoid\", ellipsoid);\r\n Check.typeOf.object(\"projection\", projection);\r\n //>>includeEnd('debug');\r\n\r\n var corner = cornerScratch;\r\n var eastward = eastwardScratch;\r\n var northward = northwardScratch;\r\n computeRectangleBounds(\r\n boundingRectangle,\r\n ellipsoid,\r\n defaultValue(height, 0.0),\r\n corner,\r\n eastward,\r\n northward\r\n );\r\n\r\n var attributes = {};\r\n addTextureCoordinateRotationAttributes(\r\n attributes,\r\n textureCoordinateRotationPoints\r\n );\r\n\r\n var encoded = EncodedCartesian3.fromCartesian(corner, encodeScratch);\r\n\r\n attributes.southWest_HIGH = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n normalize: false,\r\n value: Cartesian3.pack(encoded.high, [0, 0, 0]),\r\n });\r\n attributes.southWest_LOW = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n normalize: false,\r\n value: Cartesian3.pack(encoded.low, [0, 0, 0]),\r\n });\r\n attributes.eastward = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n normalize: false,\r\n value: Cartesian3.pack(eastward, [0, 0, 0]),\r\n });\r\n attributes.northward = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n normalize: false,\r\n value: Cartesian3.pack(northward, [0, 0, 0]),\r\n });\r\n\r\n add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes);\r\n return attributes;\r\n};\r\n\r\nvar spherePointScratch = new Cartesian3();\r\nfunction latLongToSpherical(latitude, longitude, ellipsoid, result) {\r\n var cartographic = cartographicScratch;\r\n cartographic.latitude = latitude;\r\n cartographic.longitude = longitude;\r\n cartographic.height = 0.0;\r\n\r\n var spherePoint = Cartographic.toCartesian(\r\n cartographic,\r\n ellipsoid,\r\n spherePointScratch\r\n );\r\n\r\n // Project into plane with vertical for latitude\r\n var magXY = Math.sqrt(\r\n spherePoint.x * spherePoint.x + spherePoint.y * spherePoint.y\r\n );\r\n\r\n // Use fastApproximateAtan2 for alignment with shader\r\n var sphereLatitude = CesiumMath.fastApproximateAtan2(magXY, spherePoint.z);\r\n var sphereLongitude = CesiumMath.fastApproximateAtan2(\r\n spherePoint.x,\r\n spherePoint.y\r\n );\r\n\r\n result.x = sphereLatitude;\r\n result.y = sphereLongitude;\r\n\r\n return result;\r\n}\r\n\r\nvar sphericalScratch = new Cartesian2();\r\n/**\r\n * Gets an attributes object containing:\r\n * - the southwest corner of a rectangular area in spherical coordinates, as well as the inverse of the latitude/longitude range.\r\n * These are computed using the same atan2 approximation used in the shader.\r\n * - 1 texture coordinate rotation GeometryInstanceAttributes\r\n * - 2 GeometryInstanceAttributes used to compute high-precision points in 2D and Columbus View.\r\n * These points are used to compute eye-space planes like above.\r\n *\r\n * Used when computing texture coordinates for large-area ClassificationPrimitives with materials or\r\n * multiple non-overlapping instances.\r\n * @see ShadowVolumeAppearance\r\n * @private\r\n *\r\n * @param {Rectangle} boundingRectangle Rectangle object that the spherical extents will approximately bound\r\n * @param {Number[]} textureCoordinateRotationPoints Points in the computed texture coordinate system for remapping texture coordinates\r\n * @param {Ellipsoid} ellipsoid Ellipsoid for converting Rectangle points to world coordinates\r\n * @param {MapProjection} projection The MapProjection used for 2D and Columbus View.\r\n * @returns {Object} An attributes dictionary containing spherical texture coordinate attributes.\r\n */\r\nShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes = function (\r\n boundingRectangle,\r\n textureCoordinateRotationPoints,\r\n ellipsoid,\r\n projection\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"boundingRectangle\", boundingRectangle);\r\n Check.defined(\r\n \"textureCoordinateRotationPoints\",\r\n textureCoordinateRotationPoints\r\n );\r\n Check.typeOf.object(\"ellipsoid\", ellipsoid);\r\n Check.typeOf.object(\"projection\", projection);\r\n //>>includeEnd('debug');\r\n\r\n // rectangle cartographic coords !== spherical because it's on an ellipsoid\r\n var southWestExtents = latLongToSpherical(\r\n boundingRectangle.south,\r\n boundingRectangle.west,\r\n ellipsoid,\r\n sphericalScratch\r\n );\r\n\r\n var south = southWestExtents.x;\r\n var west = southWestExtents.y;\r\n\r\n var northEastExtents = latLongToSpherical(\r\n boundingRectangle.north,\r\n boundingRectangle.east,\r\n ellipsoid,\r\n sphericalScratch\r\n );\r\n var north = northEastExtents.x;\r\n var east = northEastExtents.y;\r\n\r\n // If the bounding rectangle crosses the IDL, rotate the spherical extents so the cross no longer happens.\r\n // This rotation must happen in the shader too.\r\n var rotationRadians = 0.0;\r\n if (west > east) {\r\n rotationRadians = CesiumMath.PI - west;\r\n west = -CesiumMath.PI;\r\n east += rotationRadians;\r\n }\r\n\r\n // Slightly pad extents to avoid floating point error when fragment culling at edges.\r\n south -= CesiumMath.EPSILON5;\r\n west -= CesiumMath.EPSILON5;\r\n north += CesiumMath.EPSILON5;\r\n east += CesiumMath.EPSILON5;\r\n\r\n var longitudeRangeInverse = 1.0 / (east - west);\r\n var latitudeRangeInverse = 1.0 / (north - south);\r\n\r\n var attributes = {\r\n sphericalExtents: new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n normalize: false,\r\n value: [south, west, latitudeRangeInverse, longitudeRangeInverse],\r\n }),\r\n longitudeRotation: new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 1,\r\n normalize: false,\r\n value: [rotationRadians],\r\n }),\r\n };\r\n\r\n addTextureCoordinateRotationAttributes(\r\n attributes,\r\n textureCoordinateRotationPoints\r\n );\r\n add2DTextureCoordinateAttributes(boundingRectangle, projection, attributes);\r\n return attributes;\r\n};\r\n\r\nShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes = function (\r\n attributes\r\n) {\r\n return (\r\n defined(attributes.southWest_HIGH) &&\r\n defined(attributes.southWest_LOW) &&\r\n defined(attributes.northward) &&\r\n defined(attributes.eastward) &&\r\n defined(attributes.planes2D_HIGH) &&\r\n defined(attributes.planes2D_LOW) &&\r\n defined(attributes.uMaxVmax) &&\r\n defined(attributes.uvMinAndExtents)\r\n );\r\n};\r\n\r\nShadowVolumeAppearance.hasAttributesForSphericalExtents = function (\r\n attributes\r\n) {\r\n return (\r\n defined(attributes.sphericalExtents) &&\r\n defined(attributes.longitudeRotation) &&\r\n defined(attributes.planes2D_HIGH) &&\r\n defined(attributes.planes2D_LOW) &&\r\n defined(attributes.uMaxVmax) &&\r\n defined(attributes.uvMinAndExtents)\r\n );\r\n};\r\n\r\nfunction shouldUseSpherical(rectangle) {\r\n return (\r\n Math.max(rectangle.width, rectangle.height) >\r\n ShadowVolumeAppearance.MAX_WIDTH_FOR_PLANAR_EXTENTS\r\n );\r\n}\r\n\r\n/**\r\n * Computes whether the given rectangle is wide enough that texture coordinates\r\n * over its area should be computed using spherical extents instead of distance to planes.\r\n *\r\n * @param {Rectangle} rectangle A rectangle\r\n * @private\r\n */\r\nShadowVolumeAppearance.shouldUseSphericalCoordinates = function (rectangle) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"rectangle\", rectangle);\r\n //>>includeEnd('debug');\r\n\r\n return shouldUseSpherical(rectangle);\r\n};\r\n\r\n/**\r\n * Texture coordinates for ground primitives are computed either using spherical coordinates for large areas or\r\n * using distance from planes for small areas.\r\n *\r\n * @type {Number}\r\n * @constant\r\n * @private\r\n */\r\nShadowVolumeAppearance.MAX_WIDTH_FOR_PLANAR_EXTENTS = CesiumMath.toRadians(1.0);\r\nexport default ShadowVolumeAppearance;\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * Determines the function used to compare stencil values for the stencil test.\r\n *\r\n * @enum {Number}\r\n */\r\nvar StencilFunction = {\r\n /**\r\n * The stencil test never passes.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NEVER: WebGLConstants.NEVER,\r\n\r\n /**\r\n * The stencil test passes when the masked reference value is less than the masked stencil value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LESS: WebGLConstants.LESS,\r\n\r\n /**\r\n * The stencil test passes when the masked reference value is equal to the masked stencil value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n EQUAL: WebGLConstants.EQUAL,\r\n\r\n /**\r\n * The stencil test passes when the masked reference value is less than or equal to the masked stencil value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n LESS_OR_EQUAL: WebGLConstants.LEQUAL,\r\n\r\n /**\r\n * The stencil test passes when the masked reference value is greater than the masked stencil value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n GREATER: WebGLConstants.GREATER,\r\n\r\n /**\r\n * The stencil test passes when the masked reference value is not equal to the masked stencil value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NOT_EQUAL: WebGLConstants.NOTEQUAL,\r\n\r\n /**\r\n * The stencil test passes when the masked reference value is greater than or equal to the masked stencil value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n GREATER_OR_EQUAL: WebGLConstants.GEQUAL,\r\n\r\n /**\r\n * The stencil test always passes.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ALWAYS: WebGLConstants.ALWAYS,\r\n};\r\nexport default Object.freeze(StencilFunction);\r\n","import WebGLConstants from \"../Core/WebGLConstants.js\";\r\n\r\n/**\r\n * Determines the action taken based on the result of the stencil test.\r\n *\r\n * @enum {Number}\r\n */\r\nvar StencilOperation = {\r\n /**\r\n * Sets the stencil buffer value to zero.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ZERO: WebGLConstants.ZERO,\r\n\r\n /**\r\n * Does not change the stencil buffer.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n KEEP: WebGLConstants.KEEP,\r\n\r\n /**\r\n * Replaces the stencil buffer value with the reference value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n REPLACE: WebGLConstants.REPLACE,\r\n\r\n /**\r\n * Increments the stencil buffer value, clamping to unsigned byte.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n INCREMENT: WebGLConstants.INCR,\r\n\r\n /**\r\n * Decrements the stencil buffer value, clamping to zero.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n DECREMENT: WebGLConstants.DECR,\r\n\r\n /**\r\n * Bitwise inverts the existing stencil buffer value.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n INVERT: WebGLConstants.INVERT,\r\n\r\n /**\r\n * Increments the stencil buffer value, wrapping to zero when exceeding the unsigned byte range.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n INCREMENT_WRAP: WebGLConstants.INCR_WRAP,\r\n\r\n /**\r\n * Decrements the stencil buffer value, wrapping to the maximum unsigned byte instead of going below zero.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n DECREMENT_WRAP: WebGLConstants.DECR_WRAP,\r\n};\r\nexport default Object.freeze(StencilOperation);\r\n","import StencilFunction from \"./StencilFunction.js\";\r\nimport StencilOperation from \"./StencilOperation.js\";\r\n\r\n/**\r\n * The most significant bit is used to identify whether the pixel is 3D Tiles.\r\n * The next three bits store selection depth for the skip LODs optimization.\r\n * The last four bits are for increment/decrement shadow volume operations for classification.\r\n *\r\n * @private\r\n */\r\nvar StencilConstants = {\r\n CESIUM_3D_TILE_MASK: 0x80,\r\n SKIP_LOD_MASK: 0x70,\r\n SKIP_LOD_BIT_SHIFT: 4,\r\n CLASSIFICATION_MASK: 0x0f,\r\n};\r\n\r\nStencilConstants.setCesium3DTileBit = function () {\r\n return {\r\n enabled: true,\r\n frontFunction: StencilFunction.ALWAYS,\r\n frontOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.KEEP,\r\n zPass: StencilOperation.REPLACE,\r\n },\r\n backFunction: StencilFunction.ALWAYS,\r\n backOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.KEEP,\r\n zPass: StencilOperation.REPLACE,\r\n },\r\n reference: StencilConstants.CESIUM_3D_TILE_MASK,\r\n mask: StencilConstants.CESIUM_3D_TILE_MASK,\r\n };\r\n};\r\nexport default Object.freeze(StencilConstants);\r\n","import ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport ShadowVolumeAppearanceVS from \"../Shaders/ShadowVolumeAppearanceVS.js\";\r\nimport ShadowVolumeFS from \"../Shaders/ShadowVolumeFS.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport ClassificationType from \"./ClassificationType.js\";\r\nimport DepthFunction from \"./DepthFunction.js\";\r\nimport PerInstanceColorAppearance from \"./PerInstanceColorAppearance.js\";\r\nimport Primitive from \"./Primitive.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport ShadowVolumeAppearance from \"./ShadowVolumeAppearance.js\";\r\nimport StencilConstants from \"./StencilConstants.js\";\r\nimport StencilFunction from \"./StencilFunction.js\";\r\nimport StencilOperation from \"./StencilOperation.js\";\r\n\r\n/**\r\n * A classification primitive represents a volume enclosing geometry in the {@link Scene} to be highlighted.\r\n *

\r\n * A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including\r\n * {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement,\r\n * and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix\r\n * and match most of them and add a new geometry or appearance independently of each other.\r\n * Only {@link PerInstanceColorAppearance} with the same color across all instances is supported at this time when using\r\n * ClassificationPrimitive directly.\r\n * For full {@link Appearance} support when classifying terrain or 3D Tiles use {@link GroundPrimitive} instead.\r\n *

\r\n *

\r\n * For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there\r\n * will be rendering artifacts for some viewing angles.\r\n *

\r\n *

\r\n * Valid geometries are {@link BoxGeometry}, {@link CylinderGeometry}, {@link EllipsoidGeometry}, {@link PolylineVolumeGeometry}, and {@link SphereGeometry}.\r\n *

\r\n *

\r\n * Geometries that follow the surface of the ellipsoid, such as {@link CircleGeometry}, {@link CorridorGeometry}, {@link EllipseGeometry}, {@link PolygonGeometry}, and {@link RectangleGeometry},\r\n * are also valid if they are extruded volumes; otherwise, they will not be rendered.\r\n *

\r\n *\r\n * @alias ClassificationPrimitive\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Array|GeometryInstance} [options.geometryInstances] The geometry instances to render. This can either be a single instance or an array of length one.\r\n * @param {Appearance} [options.appearance] The appearance used to render the primitive. Defaults to PerInstanceColorAppearance when GeometryInstances have a color attribute.\r\n * @param {Boolean} [options.show=true] Determines if this primitive will be shown.\r\n * @param {Boolean} [options.vertexCacheOptimize=false] When true, geometry vertices are optimized for the pre and post-vertex-shader caches.\r\n * @param {Boolean} [options.interleave=false] When true, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.\r\n * @param {Boolean} [options.compressVertices=true] When true, the geometry vertices are compressed, which will save memory.\r\n * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory.\r\n * @param {Boolean} [options.allowPicking=true] When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.\r\n * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. If false initializeTerrainHeights() must be called first.\r\n * @param {ClassificationType} [options.classificationType=ClassificationType.BOTH] Determines whether terrain, 3D Tiles or both will be classified.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.\r\n * @param {Boolean} [options.debugShowShadowVolume=false] For debugging only. Determines if the shadow volume for each geometry in the primitive is drawn. Must be true on\r\n * creation for the volumes to be created before the geometry is released or options.releaseGeometryInstance must be false.\r\n *\r\n * @see Primitive\r\n * @see GroundPrimitive\r\n * @see GeometryInstance\r\n * @see Appearance\r\n */\r\nfunction ClassificationPrimitive(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var geometryInstances = options.geometryInstances;\r\n\r\n /**\r\n * The geometry instance rendered with this primitive. This may\r\n * be undefined if options.releaseGeometryInstances\r\n * is true when the primitive is constructed.\r\n *

\r\n * Changing this property after the primitive is rendered has no effect.\r\n *

\r\n *

\r\n * Because of the rendering technique used, all geometry instances must be the same color.\r\n * If there is an instance with a differing color, a DeveloperError will be thrown\r\n * on the first attempt to render.\r\n *

\r\n *\r\n * @readonly\r\n * @type {Array|GeometryInstance}\r\n *\r\n * @default undefined\r\n */\r\n this.geometryInstances = geometryInstances;\r\n /**\r\n * Determines if the primitive will be shown. This affects all geometry\r\n * instances in the primitive.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n /**\r\n * Determines whether terrain, 3D Tiles or both will be classified.\r\n *\r\n * @type {ClassificationType}\r\n *\r\n * @default ClassificationType.BOTH\r\n */\r\n this.classificationType = defaultValue(\r\n options.classificationType,\r\n ClassificationType.BOTH\r\n );\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the shadow volume for each geometry in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowShadowVolume = defaultValue(\r\n options.debugShowShadowVolume,\r\n false\r\n );\r\n this._debugShowShadowVolume = false;\r\n\r\n // These are used by GroundPrimitive to augment the shader and uniform map.\r\n this._extruded = defaultValue(options._extruded, false);\r\n this._uniformMap = options._uniformMap;\r\n\r\n this._sp = undefined;\r\n this._spStencil = undefined;\r\n this._spPick = undefined;\r\n this._spColor = undefined;\r\n\r\n this._spPick2D = undefined; // only derived if necessary\r\n this._spColor2D = undefined; // only derived if necessary\r\n\r\n this._rsStencilDepthPass = undefined;\r\n this._rsStencilDepthPass3DTiles = undefined;\r\n this._rsColorPass = undefined;\r\n this._rsPickPass = undefined;\r\n\r\n this._commandsIgnoreShow = [];\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._primitive = undefined;\r\n this._pickPrimitive = options._pickPrimitive;\r\n\r\n // Set in update\r\n this._hasSphericalExtentsAttribute = false;\r\n this._hasPlanarExtentsAttributes = false;\r\n this._hasPerColorAttribute = false;\r\n\r\n this.appearance = options.appearance;\r\n\r\n this._createBoundingVolumeFunction = options._createBoundingVolumeFunction;\r\n this._updateAndQueueCommandsFunction =\r\n options._updateAndQueueCommandsFunction;\r\n\r\n this._usePickOffsets = false;\r\n\r\n this._primitiveOptions = {\r\n geometryInstances: undefined,\r\n appearance: undefined,\r\n vertexCacheOptimize: defaultValue(options.vertexCacheOptimize, false),\r\n interleave: defaultValue(options.interleave, false),\r\n releaseGeometryInstances: defaultValue(\r\n options.releaseGeometryInstances,\r\n true\r\n ),\r\n allowPicking: defaultValue(options.allowPicking, true),\r\n asynchronous: defaultValue(options.asynchronous, true),\r\n compressVertices: defaultValue(options.compressVertices, true),\r\n _createBoundingVolumeFunction: undefined,\r\n _createRenderStatesFunction: undefined,\r\n _createShaderProgramFunction: undefined,\r\n _createCommandsFunction: undefined,\r\n _updateAndQueueCommandsFunction: undefined,\r\n _createPickOffsets: true,\r\n };\r\n}\r\n\r\nObject.defineProperties(ClassificationPrimitive.prototype, {\r\n /**\r\n * When true, geometry vertices are optimized for the pre and post-vertex-shader caches.\r\n *\r\n * @memberof ClassificationPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n vertexCacheOptimize: {\r\n get: function () {\r\n return this._primitiveOptions.vertexCacheOptimize;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.\r\n *\r\n * @memberof ClassificationPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n interleave: {\r\n get: function () {\r\n return this._primitiveOptions.interleave;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the primitive does not keep a reference to the input geometryInstances to save memory.\r\n *\r\n * @memberof ClassificationPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n releaseGeometryInstances: {\r\n get: function () {\r\n return this._primitiveOptions.releaseGeometryInstances;\r\n },\r\n },\r\n\r\n /**\r\n * When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.\r\n *\r\n * @memberof ClassificationPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n allowPicking: {\r\n get: function () {\r\n return this._primitiveOptions.allowPicking;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the geometry instances will be created and batched on a web worker.\r\n *\r\n * @memberof ClassificationPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n asynchronous: {\r\n get: function () {\r\n return this._primitiveOptions.asynchronous;\r\n },\r\n },\r\n\r\n /**\r\n * When true, geometry vertices are compressed, which will save memory.\r\n *\r\n * @memberof ClassificationPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n compressVertices: {\r\n get: function () {\r\n return this._primitiveOptions.compressVertices;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the primitive is complete and ready to render. If this property is\r\n * true, the primitive will be rendered the next time that {@link ClassificationPrimitive#update}\r\n * is called.\r\n *\r\n * @memberof ClassificationPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof ClassificationPrimitive.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n /**\r\n * Returns true if the ClassificationPrimitive needs a separate shader and commands for 2D.\r\n * This is because texture coordinates on ClassificationPrimitives are computed differently,\r\n * and are used for culling when multiple GeometryInstances are batched in one ClassificationPrimitive.\r\n * @memberof ClassificationPrimitive.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n * @private\r\n */\r\n _needs2DShader: {\r\n get: function () {\r\n return (\r\n this._hasPlanarExtentsAttributes || this._hasSphericalExtentsAttribute\r\n );\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Determines if ClassificationPrimitive rendering is supported.\r\n *\r\n * @param {Scene} scene The scene.\r\n * @returns {Boolean} true if ClassificationPrimitives are supported; otherwise, returns false\r\n */\r\nClassificationPrimitive.isSupported = function (scene) {\r\n return scene.context.stencilBuffer;\r\n};\r\n\r\nfunction getStencilDepthRenderState(enableStencil, mask3DTiles) {\r\n var stencilFunction = mask3DTiles\r\n ? StencilFunction.EQUAL\r\n : StencilFunction.ALWAYS;\r\n return {\r\n colorMask: {\r\n red: false,\r\n green: false,\r\n blue: false,\r\n alpha: false,\r\n },\r\n stencilTest: {\r\n enabled: enableStencil,\r\n frontFunction: stencilFunction,\r\n frontOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.DECREMENT_WRAP,\r\n zPass: StencilOperation.KEEP,\r\n },\r\n backFunction: stencilFunction,\r\n backOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.INCREMENT_WRAP,\r\n zPass: StencilOperation.KEEP,\r\n },\r\n reference: StencilConstants.CESIUM_3D_TILE_MASK,\r\n mask: StencilConstants.CESIUM_3D_TILE_MASK,\r\n },\r\n stencilMask: StencilConstants.CLASSIFICATION_MASK,\r\n depthTest: {\r\n enabled: true,\r\n func: DepthFunction.LESS_OR_EQUAL,\r\n },\r\n depthMask: false,\r\n };\r\n}\r\n\r\nfunction getColorRenderState(enableStencil) {\r\n return {\r\n stencilTest: {\r\n enabled: enableStencil,\r\n frontFunction: StencilFunction.NOT_EQUAL,\r\n frontOperation: {\r\n fail: StencilOperation.ZERO,\r\n zFail: StencilOperation.ZERO,\r\n zPass: StencilOperation.ZERO,\r\n },\r\n backFunction: StencilFunction.NOT_EQUAL,\r\n backOperation: {\r\n fail: StencilOperation.ZERO,\r\n zFail: StencilOperation.ZERO,\r\n zPass: StencilOperation.ZERO,\r\n },\r\n reference: 0,\r\n mask: StencilConstants.CLASSIFICATION_MASK,\r\n },\r\n stencilMask: StencilConstants.CLASSIFICATION_MASK,\r\n depthTest: {\r\n enabled: false,\r\n },\r\n depthMask: false,\r\n blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,\r\n };\r\n}\r\n\r\nvar pickRenderState = {\r\n stencilTest: {\r\n enabled: true,\r\n frontFunction: StencilFunction.NOT_EQUAL,\r\n frontOperation: {\r\n fail: StencilOperation.ZERO,\r\n zFail: StencilOperation.ZERO,\r\n zPass: StencilOperation.ZERO,\r\n },\r\n backFunction: StencilFunction.NOT_EQUAL,\r\n backOperation: {\r\n fail: StencilOperation.ZERO,\r\n zFail: StencilOperation.ZERO,\r\n zPass: StencilOperation.ZERO,\r\n },\r\n reference: 0,\r\n mask: StencilConstants.CLASSIFICATION_MASK,\r\n },\r\n stencilMask: StencilConstants.CLASSIFICATION_MASK,\r\n depthTest: {\r\n enabled: false,\r\n },\r\n depthMask: false,\r\n};\r\n\r\nfunction createRenderStates(\r\n classificationPrimitive,\r\n context,\r\n appearance,\r\n twoPasses\r\n) {\r\n if (defined(classificationPrimitive._rsStencilDepthPass)) {\r\n return;\r\n }\r\n var stencilEnabled = !classificationPrimitive.debugShowShadowVolume;\r\n\r\n classificationPrimitive._rsStencilDepthPass = RenderState.fromCache(\r\n getStencilDepthRenderState(stencilEnabled, false)\r\n );\r\n classificationPrimitive._rsStencilDepthPass3DTiles = RenderState.fromCache(\r\n getStencilDepthRenderState(stencilEnabled, true)\r\n );\r\n classificationPrimitive._rsColorPass = RenderState.fromCache(\r\n getColorRenderState(stencilEnabled, false)\r\n );\r\n classificationPrimitive._rsPickPass = RenderState.fromCache(pickRenderState);\r\n}\r\n\r\nfunction modifyForEncodedNormals(primitive, vertexShaderSource) {\r\n if (!primitive.compressVertices) {\r\n return vertexShaderSource;\r\n }\r\n\r\n if (\r\n vertexShaderSource.search(/attribute\\s+vec3\\s+extrudeDirection;/g) !== -1\r\n ) {\r\n var attributeName = \"compressedAttributes\";\r\n\r\n //only shadow volumes use extrudeDirection, and shadow volumes use vertexFormat: POSITION_ONLY so we don't need to check other attributes\r\n var attributeDecl = \"attribute vec2 \" + attributeName + \";\";\r\n\r\n var globalDecl = \"vec3 extrudeDirection;\\n\";\r\n var decode =\r\n \" extrudeDirection = czm_octDecode(\" + attributeName + \", 65535.0);\\n\";\r\n\r\n var modifiedVS = vertexShaderSource;\r\n modifiedVS = modifiedVS.replace(\r\n /attribute\\s+vec3\\s+extrudeDirection;/g,\r\n \"\"\r\n );\r\n modifiedVS = ShaderSource.replaceMain(\r\n modifiedVS,\r\n \"czm_non_compressed_main\"\r\n );\r\n var compressedMain =\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n decode +\r\n \" czm_non_compressed_main(); \\n\" +\r\n \"}\";\r\n\r\n return [attributeDecl, globalDecl, modifiedVS, compressedMain].join(\"\\n\");\r\n }\r\n}\r\n\r\nfunction createShaderProgram(classificationPrimitive, frameState) {\r\n var context = frameState.context;\r\n var primitive = classificationPrimitive._primitive;\r\n var vs = ShadowVolumeAppearanceVS;\r\n vs = classificationPrimitive._primitive._batchTable.getVertexShaderCallback()(\r\n vs\r\n );\r\n vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs);\r\n vs = Primitive._modifyShaderPosition(\r\n classificationPrimitive,\r\n vs,\r\n frameState.scene3DOnly\r\n );\r\n vs = Primitive._updateColorAttribute(primitive, vs);\r\n\r\n var planarExtents = classificationPrimitive._hasPlanarExtentsAttributes;\r\n var cullFragmentsUsingExtents =\r\n planarExtents || classificationPrimitive._hasSphericalExtentsAttribute;\r\n\r\n if (classificationPrimitive._extruded) {\r\n vs = modifyForEncodedNormals(primitive, vs);\r\n }\r\n\r\n var extrudedDefine = classificationPrimitive._extruded\r\n ? \"EXTRUDED_GEOMETRY\"\r\n : \"\";\r\n\r\n var vsSource = new ShaderSource({\r\n defines: [extrudedDefine],\r\n sources: [vs],\r\n });\r\n var fsSource = new ShaderSource({\r\n sources: [ShadowVolumeFS],\r\n });\r\n var attributeLocations =\r\n classificationPrimitive._primitive._attributeLocations;\r\n\r\n var shadowVolumeAppearance = new ShadowVolumeAppearance(\r\n cullFragmentsUsingExtents,\r\n planarExtents,\r\n classificationPrimitive.appearance\r\n );\r\n\r\n classificationPrimitive._spStencil = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: classificationPrimitive._spStencil,\r\n vertexShaderSource: vsSource,\r\n fragmentShaderSource: fsSource,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n if (classificationPrimitive._primitive.allowPicking) {\r\n var vsPick = ShaderSource.createPickVertexShaderSource(vs);\r\n vsPick = Primitive._appendShowToShader(primitive, vsPick);\r\n vsPick = Primitive._updatePickColorAttribute(vsPick);\r\n\r\n var pickFS3D = shadowVolumeAppearance.createPickFragmentShader(false);\r\n var pickVS3D = shadowVolumeAppearance.createPickVertexShader(\r\n [extrudedDefine],\r\n vsPick,\r\n false,\r\n frameState.mapProjection\r\n );\r\n\r\n classificationPrimitive._spPick = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: classificationPrimitive._spPick,\r\n vertexShaderSource: pickVS3D,\r\n fragmentShaderSource: pickFS3D,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n // Derive a 2D pick shader if the primitive uses texture coordinate-based fragment culling,\r\n // since texture coordinates are computed differently in 2D.\r\n if (cullFragmentsUsingExtents) {\r\n var pickProgram2D = context.shaderCache.getDerivedShaderProgram(\r\n classificationPrimitive._spPick,\r\n \"2dPick\"\r\n );\r\n if (!defined(pickProgram2D)) {\r\n var pickFS2D = shadowVolumeAppearance.createPickFragmentShader(true);\r\n var pickVS2D = shadowVolumeAppearance.createPickVertexShader(\r\n [extrudedDefine],\r\n vsPick,\r\n true,\r\n frameState.mapProjection\r\n );\r\n\r\n pickProgram2D = context.shaderCache.createDerivedShaderProgram(\r\n classificationPrimitive._spPick,\r\n \"2dPick\",\r\n {\r\n vertexShaderSource: pickVS2D,\r\n fragmentShaderSource: pickFS2D,\r\n attributeLocations: attributeLocations,\r\n }\r\n );\r\n }\r\n classificationPrimitive._spPick2D = pickProgram2D;\r\n }\r\n } else {\r\n classificationPrimitive._spPick = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vsSource,\r\n fragmentShaderSource: fsSource,\r\n attributeLocations: attributeLocations,\r\n });\r\n }\r\n\r\n vs = Primitive._appendShowToShader(primitive, vs);\r\n vsSource = new ShaderSource({\r\n defines: [extrudedDefine],\r\n sources: [vs],\r\n });\r\n\r\n classificationPrimitive._sp = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: classificationPrimitive._sp,\r\n vertexShaderSource: vsSource,\r\n fragmentShaderSource: fsSource,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n // Create a fragment shader that computes only required material hookups using screen space techniques\r\n var fsColorSource = shadowVolumeAppearance.createFragmentShader(false);\r\n var vsColorSource = shadowVolumeAppearance.createVertexShader(\r\n [extrudedDefine],\r\n vs,\r\n false,\r\n frameState.mapProjection\r\n );\r\n\r\n classificationPrimitive._spColor = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: classificationPrimitive._spColor,\r\n vertexShaderSource: vsColorSource,\r\n fragmentShaderSource: fsColorSource,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n // Derive a 2D shader if the primitive uses texture coordinate-based fragment culling,\r\n // since texture coordinates are computed differently in 2D.\r\n // Any material that uses texture coordinates will also equip texture coordinate-based fragment culling.\r\n if (cullFragmentsUsingExtents) {\r\n var colorProgram2D = context.shaderCache.getDerivedShaderProgram(\r\n classificationPrimitive._spColor,\r\n \"2dColor\"\r\n );\r\n if (!defined(colorProgram2D)) {\r\n var fsColorSource2D = shadowVolumeAppearance.createFragmentShader(true);\r\n var vsColorSource2D = shadowVolumeAppearance.createVertexShader(\r\n [extrudedDefine],\r\n vs,\r\n true,\r\n frameState.mapProjection\r\n );\r\n\r\n colorProgram2D = context.shaderCache.createDerivedShaderProgram(\r\n classificationPrimitive._spColor,\r\n \"2dColor\",\r\n {\r\n vertexShaderSource: vsColorSource2D,\r\n fragmentShaderSource: fsColorSource2D,\r\n attributeLocations: attributeLocations,\r\n }\r\n );\r\n }\r\n classificationPrimitive._spColor2D = colorProgram2D;\r\n }\r\n}\r\n\r\nfunction createColorCommands(classificationPrimitive, colorCommands) {\r\n var primitive = classificationPrimitive._primitive;\r\n var length = primitive._va.length * 2; // each geometry (pack of vertex attributes) needs 2 commands: front/back stencils and fill\r\n colorCommands.length = length;\r\n\r\n var i;\r\n var command;\r\n var derivedCommand;\r\n var vaIndex = 0;\r\n var uniformMap = primitive._batchTable.getUniformMapCallback()(\r\n classificationPrimitive._uniformMap\r\n );\r\n\r\n var needs2DShader = classificationPrimitive._needs2DShader;\r\n\r\n for (i = 0; i < length; i += 2) {\r\n var vertexArray = primitive._va[vaIndex++];\r\n\r\n // Stencil depth command\r\n command = colorCommands[i];\r\n if (!defined(command)) {\r\n command = colorCommands[i] = new DrawCommand({\r\n owner: classificationPrimitive,\r\n primitiveType: primitive._primitiveType,\r\n });\r\n }\r\n\r\n command.vertexArray = vertexArray;\r\n command.renderState = classificationPrimitive._rsStencilDepthPass;\r\n command.shaderProgram = classificationPrimitive._sp;\r\n command.uniformMap = uniformMap;\r\n command.pass = Pass.TERRAIN_CLASSIFICATION;\r\n\r\n derivedCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.tileset\r\n );\r\n derivedCommand.renderState =\r\n classificationPrimitive._rsStencilDepthPass3DTiles;\r\n derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n command.derivedCommands.tileset = derivedCommand;\r\n\r\n // Color command\r\n command = colorCommands[i + 1];\r\n if (!defined(command)) {\r\n command = colorCommands[i + 1] = new DrawCommand({\r\n owner: classificationPrimitive,\r\n primitiveType: primitive._primitiveType,\r\n });\r\n }\r\n\r\n command.vertexArray = vertexArray;\r\n command.renderState = classificationPrimitive._rsColorPass;\r\n command.shaderProgram = classificationPrimitive._spColor;\r\n command.pass = Pass.TERRAIN_CLASSIFICATION;\r\n\r\n var appearance = classificationPrimitive.appearance;\r\n var material = appearance.material;\r\n if (defined(material)) {\r\n uniformMap = combine(uniformMap, material._uniforms);\r\n }\r\n\r\n command.uniformMap = uniformMap;\r\n\r\n derivedCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.tileset\r\n );\r\n derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n command.derivedCommands.tileset = derivedCommand;\r\n\r\n // Derive for 2D if texture coordinates are ever computed\r\n if (needs2DShader) {\r\n // First derive from the terrain command\r\n var derived2DCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.appearance2D\r\n );\r\n derived2DCommand.shaderProgram = classificationPrimitive._spColor2D;\r\n command.derivedCommands.appearance2D = derived2DCommand;\r\n\r\n // Then derive from the 3D Tiles command\r\n derived2DCommand = DrawCommand.shallowClone(\r\n derivedCommand,\r\n derivedCommand.derivedCommands.appearance2D\r\n );\r\n derived2DCommand.shaderProgram = classificationPrimitive._spColor2D;\r\n derivedCommand.derivedCommands.appearance2D = derived2DCommand;\r\n }\r\n }\r\n\r\n var commandsIgnoreShow = classificationPrimitive._commandsIgnoreShow;\r\n var spStencil = classificationPrimitive._spStencil;\r\n\r\n var commandIndex = 0;\r\n length = commandsIgnoreShow.length = length / 2;\r\n\r\n for (var j = 0; j < length; ++j) {\r\n var commandIgnoreShow = (commandsIgnoreShow[j] = DrawCommand.shallowClone(\r\n colorCommands[commandIndex],\r\n commandsIgnoreShow[j]\r\n ));\r\n commandIgnoreShow.shaderProgram = spStencil;\r\n commandIgnoreShow.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW;\r\n\r\n commandIndex += 2;\r\n }\r\n}\r\n\r\nfunction createPickCommands(classificationPrimitive, pickCommands) {\r\n var usePickOffsets = classificationPrimitive._usePickOffsets;\r\n\r\n var primitive = classificationPrimitive._primitive;\r\n var length = primitive._va.length * 2; // each geometry (pack of vertex attributes) needs 2 commands: front/back stencils and fill\r\n\r\n // Fallback for batching same-color geometry instances\r\n var pickOffsets;\r\n var pickIndex = 0;\r\n var pickOffset;\r\n if (usePickOffsets) {\r\n pickOffsets = primitive._pickOffsets;\r\n length = pickOffsets.length * 2;\r\n }\r\n\r\n pickCommands.length = length;\r\n\r\n var j;\r\n var command;\r\n var derivedCommand;\r\n var vaIndex = 0;\r\n var uniformMap = primitive._batchTable.getUniformMapCallback()(\r\n classificationPrimitive._uniformMap\r\n );\r\n\r\n var needs2DShader = classificationPrimitive._needs2DShader;\r\n\r\n for (j = 0; j < length; j += 2) {\r\n var vertexArray = primitive._va[vaIndex++];\r\n if (usePickOffsets) {\r\n pickOffset = pickOffsets[pickIndex++];\r\n vertexArray = primitive._va[pickOffset.index];\r\n }\r\n\r\n // Stencil depth command\r\n command = pickCommands[j];\r\n if (!defined(command)) {\r\n command = pickCommands[j] = new DrawCommand({\r\n owner: classificationPrimitive,\r\n primitiveType: primitive._primitiveType,\r\n pickOnly: true,\r\n });\r\n }\r\n\r\n command.vertexArray = vertexArray;\r\n command.renderState = classificationPrimitive._rsStencilDepthPass;\r\n command.shaderProgram = classificationPrimitive._sp;\r\n command.uniformMap = uniformMap;\r\n command.pass = Pass.TERRAIN_CLASSIFICATION;\r\n if (usePickOffsets) {\r\n command.offset = pickOffset.offset;\r\n command.count = pickOffset.count;\r\n }\r\n\r\n // Derive for 3D Tiles classification\r\n derivedCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.tileset\r\n );\r\n derivedCommand.renderState =\r\n classificationPrimitive._rsStencilDepthPass3DTiles;\r\n derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n command.derivedCommands.tileset = derivedCommand;\r\n\r\n // Pick color command\r\n command = pickCommands[j + 1];\r\n if (!defined(command)) {\r\n command = pickCommands[j + 1] = new DrawCommand({\r\n owner: classificationPrimitive,\r\n primitiveType: primitive._primitiveType,\r\n pickOnly: true,\r\n });\r\n }\r\n\r\n command.vertexArray = vertexArray;\r\n command.renderState = classificationPrimitive._rsPickPass;\r\n command.shaderProgram = classificationPrimitive._spPick;\r\n command.uniformMap = uniformMap;\r\n command.pass = Pass.TERRAIN_CLASSIFICATION;\r\n if (usePickOffsets) {\r\n command.offset = pickOffset.offset;\r\n command.count = pickOffset.count;\r\n }\r\n\r\n derivedCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.tileset\r\n );\r\n derivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n command.derivedCommands.tileset = derivedCommand;\r\n\r\n // Derive for 2D if texture coordinates are ever computed\r\n if (needs2DShader) {\r\n // First derive from the terrain command\r\n var derived2DCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.pick2D\r\n );\r\n derived2DCommand.shaderProgram = classificationPrimitive._spPick2D;\r\n command.derivedCommands.pick2D = derived2DCommand;\r\n\r\n // Then derive from the 3D Tiles command\r\n derived2DCommand = DrawCommand.shallowClone(\r\n derivedCommand,\r\n derivedCommand.derivedCommands.pick2D\r\n );\r\n derived2DCommand.shaderProgram = classificationPrimitive._spPick2D;\r\n derivedCommand.derivedCommands.pick2D = derived2DCommand;\r\n }\r\n }\r\n}\r\n\r\nfunction createCommands(\r\n classificationPrimitive,\r\n appearance,\r\n material,\r\n translucent,\r\n twoPasses,\r\n colorCommands,\r\n pickCommands\r\n) {\r\n createColorCommands(classificationPrimitive, colorCommands);\r\n createPickCommands(classificationPrimitive, pickCommands);\r\n}\r\n\r\nfunction boundingVolumeIndex(commandIndex, length) {\r\n return Math.floor((commandIndex % length) / 2);\r\n}\r\n\r\nfunction updateAndQueueRenderCommand(\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n) {\r\n command.modelMatrix = modelMatrix;\r\n command.boundingVolume = boundingVolume;\r\n command.cull = cull;\r\n command.debugShowBoundingVolume = debugShowBoundingVolume;\r\n\r\n frameState.commandList.push(command);\r\n}\r\n\r\nfunction updateAndQueuePickCommand(\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume\r\n) {\r\n command.modelMatrix = modelMatrix;\r\n command.boundingVolume = boundingVolume;\r\n command.cull = cull;\r\n\r\n frameState.commandList.push(command);\r\n}\r\n\r\nfunction updateAndQueueCommands(\r\n classificationPrimitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n) {\r\n var primitive = classificationPrimitive._primitive;\r\n Primitive._updateBoundingVolumes(primitive, frameState, modelMatrix);\r\n\r\n var boundingVolumes;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n boundingVolumes = primitive._boundingSphereWC;\r\n } else if (frameState.mode === SceneMode.COLUMBUS_VIEW) {\r\n boundingVolumes = primitive._boundingSphereCV;\r\n } else if (\r\n frameState.mode === SceneMode.SCENE2D &&\r\n defined(primitive._boundingSphere2D)\r\n ) {\r\n boundingVolumes = primitive._boundingSphere2D;\r\n } else if (defined(primitive._boundingSphereMorph)) {\r\n boundingVolumes = primitive._boundingSphereMorph;\r\n }\r\n\r\n var classificationType = classificationPrimitive.classificationType;\r\n var queueTerrainCommands =\r\n classificationType !== ClassificationType.CESIUM_3D_TILE;\r\n var queue3DTilesCommands = classificationType !== ClassificationType.TERRAIN;\r\n\r\n var passes = frameState.passes;\r\n\r\n var i;\r\n var boundingVolume;\r\n var command;\r\n\r\n if (passes.render) {\r\n var colorLength = colorCommands.length;\r\n for (i = 0; i < colorLength; ++i) {\r\n boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)];\r\n if (queueTerrainCommands) {\r\n command = colorCommands[i];\r\n updateAndQueueRenderCommand(\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n );\r\n }\r\n if (queue3DTilesCommands) {\r\n command = colorCommands[i].derivedCommands.tileset;\r\n updateAndQueueRenderCommand(\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n );\r\n }\r\n }\r\n\r\n if (frameState.invertClassification) {\r\n var ignoreShowCommands = classificationPrimitive._commandsIgnoreShow;\r\n var ignoreShowCommandsLength = ignoreShowCommands.length;\r\n for (i = 0; i < ignoreShowCommandsLength; ++i) {\r\n boundingVolume = boundingVolumes[i];\r\n command = ignoreShowCommands[i];\r\n updateAndQueueRenderCommand(\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (passes.pick) {\r\n var pickLength = pickCommands.length;\r\n var pickOffsets = primitive._pickOffsets;\r\n for (i = 0; i < pickLength; ++i) {\r\n var pickOffset = pickOffsets[boundingVolumeIndex(i, pickLength)];\r\n boundingVolume = boundingVolumes[pickOffset.index];\r\n if (queueTerrainCommands) {\r\n command = pickCommands[i];\r\n updateAndQueuePickCommand(\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume\r\n );\r\n }\r\n if (queue3DTilesCommands) {\r\n command = pickCommands[i].derivedCommands.tileset;\r\n updateAndQueuePickCommand(\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume\r\n );\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Called when {@link Viewer} or {@link CesiumWidget} render the scene to\r\n * get the draw commands needed to render this primitive.\r\n *

\r\n * Do not call this function directly. This is documented just to\r\n * list the exceptions that may be propagated when the scene is rendered:\r\n *

\r\n *\r\n * @exception {DeveloperError} All instance geometries must have the same primitiveType.\r\n * @exception {DeveloperError} Appearance and material have a uniform with the same name.\r\n * @exception {DeveloperError} Not all of the geometry instances have the same color attribute.\r\n */\r\nClassificationPrimitive.prototype.update = function (frameState) {\r\n if (!defined(this._primitive) && !defined(this.geometryInstances)) {\r\n return;\r\n }\r\n\r\n var appearance = this.appearance;\r\n if (defined(appearance) && defined(appearance.material)) {\r\n appearance.material.update(frameState.context);\r\n }\r\n\r\n var that = this;\r\n var primitiveOptions = this._primitiveOptions;\r\n\r\n if (!defined(this._primitive)) {\r\n var instances = Array.isArray(this.geometryInstances)\r\n ? this.geometryInstances\r\n : [this.geometryInstances];\r\n var length = instances.length;\r\n\r\n var i;\r\n var instance;\r\n var attributes;\r\n\r\n var hasPerColorAttribute = false;\r\n var allColorsSame = true;\r\n var firstColor;\r\n var hasSphericalExtentsAttribute = false;\r\n var hasPlanarExtentsAttributes = false;\r\n\r\n if (length > 0) {\r\n attributes = instances[0].attributes;\r\n // Not expecting these to be set by users, should only be set via GroundPrimitive.\r\n // So don't check for mismatch.\r\n hasSphericalExtentsAttribute = ShadowVolumeAppearance.hasAttributesForSphericalExtents(\r\n attributes\r\n );\r\n hasPlanarExtentsAttributes = ShadowVolumeAppearance.hasAttributesForTextureCoordinatePlanes(\r\n attributes\r\n );\r\n firstColor = attributes.color;\r\n }\r\n\r\n for (i = 0; i < length; i++) {\r\n instance = instances[i];\r\n var color = instance.attributes.color;\r\n if (defined(color)) {\r\n hasPerColorAttribute = true;\r\n }\r\n //>>includeStart('debug', pragmas.debug);\r\n else if (hasPerColorAttribute) {\r\n throw new DeveloperError(\r\n \"All GeometryInstances must have color attributes to use per-instance color.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n allColorsSame =\r\n allColorsSame &&\r\n defined(color) &&\r\n ColorGeometryInstanceAttribute.equals(firstColor, color);\r\n }\r\n\r\n // If no attributes exist for computing spherical extents or fragment culling,\r\n // throw if the colors aren't all the same.\r\n if (\r\n !allColorsSame &&\r\n !hasSphericalExtentsAttribute &&\r\n !hasPlanarExtentsAttributes\r\n ) {\r\n throw new DeveloperError(\r\n \"All GeometryInstances must have the same color attribute except via GroundPrimitives\"\r\n );\r\n }\r\n\r\n // default to a color appearance\r\n if (hasPerColorAttribute && !defined(appearance)) {\r\n appearance = new PerInstanceColorAppearance({\r\n flat: true,\r\n });\r\n this.appearance = appearance;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !hasPerColorAttribute &&\r\n appearance instanceof PerInstanceColorAppearance\r\n ) {\r\n throw new DeveloperError(\r\n \"PerInstanceColorAppearance requires color GeometryInstanceAttributes on all GeometryInstances\"\r\n );\r\n }\r\n if (\r\n defined(appearance.material) &&\r\n !hasSphericalExtentsAttribute &&\r\n !hasPlanarExtentsAttributes\r\n ) {\r\n throw new DeveloperError(\r\n \"Materials on ClassificationPrimitives are not supported except via GroundPrimitives\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._usePickOffsets =\r\n !hasSphericalExtentsAttribute && !hasPlanarExtentsAttributes;\r\n this._hasSphericalExtentsAttribute = hasSphericalExtentsAttribute;\r\n this._hasPlanarExtentsAttributes = hasPlanarExtentsAttributes;\r\n this._hasPerColorAttribute = hasPerColorAttribute;\r\n\r\n var geometryInstances = new Array(length);\r\n for (i = 0; i < length; ++i) {\r\n instance = instances[i];\r\n geometryInstances[i] = new GeometryInstance({\r\n geometry: instance.geometry,\r\n attributes: instance.attributes,\r\n modelMatrix: instance.modelMatrix,\r\n id: instance.id,\r\n pickPrimitive: defaultValue(this._pickPrimitive, that),\r\n });\r\n }\r\n\r\n primitiveOptions.appearance = appearance;\r\n primitiveOptions.geometryInstances = geometryInstances;\r\n\r\n if (defined(this._createBoundingVolumeFunction)) {\r\n primitiveOptions._createBoundingVolumeFunction = function (\r\n frameState,\r\n geometry\r\n ) {\r\n that._createBoundingVolumeFunction(frameState, geometry);\r\n };\r\n }\r\n\r\n primitiveOptions._createRenderStatesFunction = function (\r\n primitive,\r\n context,\r\n appearance,\r\n twoPasses\r\n ) {\r\n createRenderStates(that, context);\r\n };\r\n primitiveOptions._createShaderProgramFunction = function (\r\n primitive,\r\n frameState,\r\n appearance\r\n ) {\r\n createShaderProgram(that, frameState);\r\n };\r\n primitiveOptions._createCommandsFunction = function (\r\n primitive,\r\n appearance,\r\n material,\r\n translucent,\r\n twoPasses,\r\n colorCommands,\r\n pickCommands\r\n ) {\r\n createCommands(\r\n that,\r\n undefined,\r\n undefined,\r\n true,\r\n false,\r\n colorCommands,\r\n pickCommands\r\n );\r\n };\r\n\r\n if (defined(this._updateAndQueueCommandsFunction)) {\r\n primitiveOptions._updateAndQueueCommandsFunction = function (\r\n primitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n ) {\r\n that._updateAndQueueCommandsFunction(\r\n primitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n );\r\n };\r\n } else {\r\n primitiveOptions._updateAndQueueCommandsFunction = function (\r\n primitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n ) {\r\n updateAndQueueCommands(\r\n that,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n );\r\n };\r\n }\r\n\r\n this._primitive = new Primitive(primitiveOptions);\r\n this._primitive.readyPromise.then(function (primitive) {\r\n that._ready = true;\r\n\r\n if (that.releaseGeometryInstances) {\r\n that.geometryInstances = undefined;\r\n }\r\n\r\n var error = primitive._error;\r\n if (!defined(error)) {\r\n that._readyPromise.resolve(that);\r\n } else {\r\n that._readyPromise.reject(error);\r\n }\r\n });\r\n }\r\n\r\n if (\r\n this.debugShowShadowVolume &&\r\n !this._debugShowShadowVolume &&\r\n this._ready\r\n ) {\r\n this._debugShowShadowVolume = true;\r\n this._rsStencilDepthPass = RenderState.fromCache(\r\n getStencilDepthRenderState(false, false)\r\n );\r\n this._rsStencilDepthPass3DTiles = RenderState.fromCache(\r\n getStencilDepthRenderState(false, true)\r\n );\r\n this._rsColorPass = RenderState.fromCache(getColorRenderState(false));\r\n } else if (!this.debugShowShadowVolume && this._debugShowShadowVolume) {\r\n this._debugShowShadowVolume = false;\r\n this._rsStencilDepthPass = RenderState.fromCache(\r\n getStencilDepthRenderState(true, false)\r\n );\r\n this._rsStencilDepthPass3DTiles = RenderState.fromCache(\r\n getStencilDepthRenderState(true, true)\r\n );\r\n this._rsColorPass = RenderState.fromCache(getColorRenderState(true));\r\n }\r\n // Update primitive appearance\r\n if (this._primitive.appearance !== appearance) {\r\n //>>includeStart('debug', pragmas.debug);\r\n // Check if the appearance is supported by the geometry attributes\r\n if (\r\n !this._hasSphericalExtentsAttribute &&\r\n !this._hasPlanarExtentsAttributes &&\r\n defined(appearance.material)\r\n ) {\r\n throw new DeveloperError(\r\n \"Materials on ClassificationPrimitives are not supported except via GroundPrimitive\"\r\n );\r\n }\r\n if (\r\n !this._hasPerColorAttribute &&\r\n appearance instanceof PerInstanceColorAppearance\r\n ) {\r\n throw new DeveloperError(\r\n \"PerInstanceColorAppearance requires color GeometryInstanceAttribute\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n this._primitive.appearance = appearance;\r\n }\r\n\r\n this._primitive.show = this.show;\r\n this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;\r\n this._primitive.update(frameState);\r\n};\r\n\r\n/**\r\n * Returns the modifiable per-instance attributes for a {@link GeometryInstance}.\r\n *\r\n * @param {*} id The id of the {@link GeometryInstance}.\r\n * @returns {Object} The typed array in the attribute's format or undefined if the is no instance with id.\r\n *\r\n * @exception {DeveloperError} must call update before calling getGeometryInstanceAttributes.\r\n *\r\n * @example\r\n * var attributes = primitive.getGeometryInstanceAttributes('an id');\r\n * attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA);\r\n * attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true);\r\n */\r\nClassificationPrimitive.prototype.getGeometryInstanceAttributes = function (\r\n id\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(this._primitive)) {\r\n throw new DeveloperError(\r\n \"must call update before calling getGeometryInstanceAttributes\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return this._primitive.getGeometryInstanceAttributes(id);\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see ClassificationPrimitive#destroy\r\n */\r\nClassificationPrimitive.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * e = e && e.destroy();\r\n *\r\n * @see ClassificationPrimitive#isDestroyed\r\n */\r\nClassificationPrimitive.prototype.destroy = function () {\r\n this._primitive = this._primitive && this._primitive.destroy();\r\n this._sp = this._sp && this._sp.destroy();\r\n this._spPick = this._spPick && this._spPick.destroy();\r\n this._spColor = this._spColor && this._spColor.destroy();\r\n\r\n // Derived programs, destroyed above if they existed.\r\n this._spPick2D = undefined;\r\n this._spColor2D = undefined;\r\n return destroyObject(this);\r\n};\r\nexport default ClassificationPrimitive;\r\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport OrientedBoundingBox from \"../Core/OrientedBoundingBox.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport ClassificationPrimitive from \"./ClassificationPrimitive.js\";\r\nimport ClassificationType from \"./ClassificationType.js\";\r\nimport PerInstanceColorAppearance from \"./PerInstanceColorAppearance.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport ShadowVolumeAppearance from \"./ShadowVolumeAppearance.js\";\r\n\r\nvar GroundPrimitiveUniformMap = {\r\n u_globeMinimumAltitude: function () {\r\n return 55000.0;\r\n },\r\n};\r\n\r\n/**\r\n * A ground primitive represents geometry draped over terrain or 3D Tiles in the {@link Scene}.\r\n *

\r\n * A primitive combines geometry instances with an {@link Appearance} that describes the full shading, including\r\n * {@link Material} and {@link RenderState}. Roughly, the geometry instance defines the structure and placement,\r\n * and the appearance defines the visual characteristics. Decoupling geometry and appearance allows us to mix\r\n * and match most of them and add a new geometry or appearance independently of each other.\r\n *

\r\n *

\r\n * Support for the WEBGL_depth_texture extension is required to use GeometryInstances with different PerInstanceColors\r\n * or materials besides PerInstanceColorAppearance.\r\n *

\r\n *

\r\n * Textured GroundPrimitives were designed for notional patterns and are not meant for precisely mapping\r\n * textures to terrain - for that use case, use {@link SingleTileImageryProvider}.\r\n *

\r\n *

\r\n * For correct rendering, this feature requires the EXT_frag_depth WebGL extension. For hardware that do not support this extension, there\r\n * will be rendering artifacts for some viewing angles.\r\n *

\r\n *

\r\n * Valid geometries are {@link CircleGeometry}, {@link CorridorGeometry}, {@link EllipseGeometry}, {@link PolygonGeometry}, and {@link RectangleGeometry}.\r\n *

\r\n *\r\n * @alias GroundPrimitive\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Array|GeometryInstance} [options.geometryInstances] The geometry instances to render.\r\n * @param {Appearance} [options.appearance] The appearance used to render the primitive. Defaults to a flat PerInstanceColorAppearance when GeometryInstances have a color attribute.\r\n * @param {Boolean} [options.show=true] Determines if this primitive will be shown.\r\n * @param {Boolean} [options.vertexCacheOptimize=false] When true, geometry vertices are optimized for the pre and post-vertex-shader caches.\r\n * @param {Boolean} [options.interleave=false] When true, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.\r\n * @param {Boolean} [options.compressVertices=true] When true, the geometry vertices are compressed, which will save memory.\r\n * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory.\r\n * @param {Boolean} [options.allowPicking=true] When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.\r\n * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. If false initializeTerrainHeights() must be called first.\r\n * @param {ClassificationType} [options.classificationType=ClassificationType.BOTH] Determines whether terrain, 3D Tiles or both will be classified.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.\r\n * @param {Boolean} [options.debugShowShadowVolume=false] For debugging only. Determines if the shadow volume for each geometry in the primitive is drawn. Must be true on\r\n * creation for the volumes to be created before the geometry is released or options.releaseGeometryInstance must be false.\r\n *\r\n * @example\r\n * // Example 1: Create primitive with a single instance\r\n * var rectangleInstance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.RectangleGeometry({\r\n * rectangle : Cesium.Rectangle.fromDegrees(-140.0, 30.0, -100.0, 40.0)\r\n * }),\r\n * id : 'rectangle',\r\n * attributes : {\r\n * color : new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5)\r\n * }\r\n * });\r\n * scene.primitives.add(new Cesium.GroundPrimitive({\r\n * geometryInstances : rectangleInstance\r\n * }));\r\n *\r\n * // Example 2: Batch instances\r\n * var color = new Cesium.ColorGeometryInstanceAttribute(0.0, 1.0, 1.0, 0.5); // Both instances must have the same color.\r\n * var rectangleInstance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.RectangleGeometry({\r\n * rectangle : Cesium.Rectangle.fromDegrees(-140.0, 30.0, -100.0, 40.0)\r\n * }),\r\n * id : 'rectangle',\r\n * attributes : {\r\n * color : color\r\n * }\r\n * });\r\n * var ellipseInstance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.EllipseGeometry({\r\n * center : Cesium.Cartesian3.fromDegrees(-105.0, 40.0),\r\n * semiMinorAxis : 300000.0,\r\n * semiMajorAxis : 400000.0\r\n * }),\r\n * id : 'ellipse',\r\n * attributes : {\r\n * color : color\r\n * }\r\n * });\r\n * scene.primitives.add(new Cesium.GroundPrimitive({\r\n * geometryInstances : [rectangleInstance, ellipseInstance]\r\n * }));\r\n *\r\n * @see Primitive\r\n * @see ClassificationPrimitive\r\n * @see GeometryInstance\r\n * @see Appearance\r\n */\r\nfunction GroundPrimitive(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var appearance = options.appearance;\r\n var geometryInstances = options.geometryInstances;\r\n if (!defined(appearance) && defined(geometryInstances)) {\r\n var geometryInstancesArray = Array.isArray(geometryInstances)\r\n ? geometryInstances\r\n : [geometryInstances];\r\n var geometryInstanceCount = geometryInstancesArray.length;\r\n for (var i = 0; i < geometryInstanceCount; i++) {\r\n var attributes = geometryInstancesArray[i].attributes;\r\n if (defined(attributes) && defined(attributes.color)) {\r\n appearance = new PerInstanceColorAppearance({\r\n flat: true,\r\n });\r\n break;\r\n }\r\n }\r\n }\r\n /**\r\n * The {@link Appearance} used to shade this primitive. Each geometry\r\n * instance is shaded with the same appearance. Some appearances, like\r\n * {@link PerInstanceColorAppearance} allow giving each instance unique\r\n * properties.\r\n *\r\n * @type Appearance\r\n *\r\n * @default undefined\r\n */\r\n this.appearance = appearance;\r\n\r\n /**\r\n * The geometry instances rendered with this primitive. This may\r\n * be undefined if options.releaseGeometryInstances\r\n * is true when the primitive is constructed.\r\n *

\r\n * Changing this property after the primitive is rendered has no effect.\r\n *

\r\n *\r\n * @readonly\r\n * @type {Array|GeometryInstance}\r\n *\r\n * @default undefined\r\n */\r\n this.geometryInstances = options.geometryInstances;\r\n /**\r\n * Determines if the primitive will be shown. This affects all geometry\r\n * instances in the primitive.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n /**\r\n * Determines whether terrain, 3D Tiles or both will be classified.\r\n *\r\n * @type {ClassificationType}\r\n *\r\n * @default ClassificationType.BOTH\r\n */\r\n this.classificationType = defaultValue(\r\n options.classificationType,\r\n ClassificationType.BOTH\r\n );\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the shadow volume for each geometry in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowShadowVolume = defaultValue(\r\n options.debugShowShadowVolume,\r\n false\r\n );\r\n\r\n this._boundingVolumes = [];\r\n this._boundingVolumes2D = [];\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._primitive = undefined;\r\n\r\n this._maxHeight = undefined;\r\n this._minHeight = undefined;\r\n\r\n this._maxTerrainHeight = ApproximateTerrainHeights._defaultMaxTerrainHeight;\r\n this._minTerrainHeight = ApproximateTerrainHeights._defaultMinTerrainHeight;\r\n\r\n this._boundingSpheresKeys = [];\r\n this._boundingSpheres = [];\r\n\r\n this._useFragmentCulling = false;\r\n // Used when inserting in an OrderedPrimitiveCollection\r\n this._zIndex = undefined;\r\n\r\n var that = this;\r\n this._classificationPrimitiveOptions = {\r\n geometryInstances: undefined,\r\n appearance: undefined,\r\n vertexCacheOptimize: defaultValue(options.vertexCacheOptimize, false),\r\n interleave: defaultValue(options.interleave, false),\r\n releaseGeometryInstances: defaultValue(\r\n options.releaseGeometryInstances,\r\n true\r\n ),\r\n allowPicking: defaultValue(options.allowPicking, true),\r\n asynchronous: defaultValue(options.asynchronous, true),\r\n compressVertices: defaultValue(options.compressVertices, true),\r\n _createBoundingVolumeFunction: undefined,\r\n _updateAndQueueCommandsFunction: undefined,\r\n _pickPrimitive: that,\r\n _extruded: true,\r\n _uniformMap: GroundPrimitiveUniformMap,\r\n };\r\n}\r\n\r\nObject.defineProperties(GroundPrimitive.prototype, {\r\n /**\r\n * When true, geometry vertices are optimized for the pre and post-vertex-shader caches.\r\n *\r\n * @memberof GroundPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n vertexCacheOptimize: {\r\n get: function () {\r\n return this._classificationPrimitiveOptions.vertexCacheOptimize;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.\r\n *\r\n * @memberof GroundPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n interleave: {\r\n get: function () {\r\n return this._classificationPrimitiveOptions.interleave;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the primitive does not keep a reference to the input geometryInstances to save memory.\r\n *\r\n * @memberof GroundPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n releaseGeometryInstances: {\r\n get: function () {\r\n return this._classificationPrimitiveOptions.releaseGeometryInstances;\r\n },\r\n },\r\n\r\n /**\r\n * When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.\r\n *\r\n * @memberof GroundPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n allowPicking: {\r\n get: function () {\r\n return this._classificationPrimitiveOptions.allowPicking;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the geometry instances will be created and batched on a web worker.\r\n *\r\n * @memberof GroundPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n asynchronous: {\r\n get: function () {\r\n return this._classificationPrimitiveOptions.asynchronous;\r\n },\r\n },\r\n\r\n /**\r\n * When true, geometry vertices are compressed, which will save memory.\r\n *\r\n * @memberof GroundPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n compressVertices: {\r\n get: function () {\r\n return this._classificationPrimitiveOptions.compressVertices;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the primitive is complete and ready to render. If this property is\r\n * true, the primitive will be rendered the next time that {@link GroundPrimitive#update}\r\n * is called.\r\n *\r\n * @memberof GroundPrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof GroundPrimitive.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Determines if GroundPrimitive rendering is supported.\r\n *\r\n * @function\r\n * @param {Scene} scene The scene.\r\n * @returns {Boolean} true if GroundPrimitives are supported; otherwise, returns false\r\n */\r\nGroundPrimitive.isSupported = ClassificationPrimitive.isSupported;\r\n\r\nfunction getComputeMaximumHeightFunction(primitive) {\r\n return function (granularity, ellipsoid) {\r\n var r = ellipsoid.maximumRadius;\r\n var delta = r / Math.cos(granularity * 0.5) - r;\r\n return primitive._maxHeight + delta;\r\n };\r\n}\r\n\r\nfunction getComputeMinimumHeightFunction(primitive) {\r\n return function (granularity, ellipsoid) {\r\n return primitive._minHeight;\r\n };\r\n}\r\n\r\nvar scratchBVCartesianHigh = new Cartesian3();\r\nvar scratchBVCartesianLow = new Cartesian3();\r\nvar scratchBVCartesian = new Cartesian3();\r\nvar scratchBVCartographic = new Cartographic();\r\nvar scratchBVRectangle = new Rectangle();\r\n\r\nfunction getRectangle(frameState, geometry) {\r\n var ellipsoid = frameState.mapProjection.ellipsoid;\r\n\r\n if (\r\n !defined(geometry.attributes) ||\r\n !defined(geometry.attributes.position3DHigh)\r\n ) {\r\n if (defined(geometry.rectangle)) {\r\n return geometry.rectangle;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n var highPositions = geometry.attributes.position3DHigh.values;\r\n var lowPositions = geometry.attributes.position3DLow.values;\r\n var length = highPositions.length;\r\n\r\n var minLat = Number.POSITIVE_INFINITY;\r\n var minLon = Number.POSITIVE_INFINITY;\r\n var maxLat = Number.NEGATIVE_INFINITY;\r\n var maxLon = Number.NEGATIVE_INFINITY;\r\n\r\n for (var i = 0; i < length; i += 3) {\r\n var highPosition = Cartesian3.unpack(\r\n highPositions,\r\n i,\r\n scratchBVCartesianHigh\r\n );\r\n var lowPosition = Cartesian3.unpack(lowPositions, i, scratchBVCartesianLow);\r\n\r\n var position = Cartesian3.add(\r\n highPosition,\r\n lowPosition,\r\n scratchBVCartesian\r\n );\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n position,\r\n scratchBVCartographic\r\n );\r\n\r\n var latitude = cartographic.latitude;\r\n var longitude = cartographic.longitude;\r\n\r\n minLat = Math.min(minLat, latitude);\r\n minLon = Math.min(minLon, longitude);\r\n maxLat = Math.max(maxLat, latitude);\r\n maxLon = Math.max(maxLon, longitude);\r\n }\r\n\r\n var rectangle = scratchBVRectangle;\r\n rectangle.north = maxLat;\r\n rectangle.south = minLat;\r\n rectangle.east = maxLon;\r\n rectangle.west = minLon;\r\n\r\n return rectangle;\r\n}\r\n\r\nfunction setMinMaxTerrainHeights(primitive, rectangle, ellipsoid) {\r\n var result = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n rectangle,\r\n ellipsoid\r\n );\r\n\r\n primitive._minTerrainHeight = result.minimumTerrainHeight;\r\n primitive._maxTerrainHeight = result.maximumTerrainHeight;\r\n}\r\n\r\nfunction createBoundingVolume(groundPrimitive, frameState, geometry) {\r\n var ellipsoid = frameState.mapProjection.ellipsoid;\r\n var rectangle = getRectangle(frameState, geometry);\r\n\r\n var obb = OrientedBoundingBox.fromRectangle(\r\n rectangle,\r\n groundPrimitive._minHeight,\r\n groundPrimitive._maxHeight,\r\n ellipsoid\r\n );\r\n groundPrimitive._boundingVolumes.push(obb);\r\n\r\n if (!frameState.scene3DOnly) {\r\n var projection = frameState.mapProjection;\r\n var boundingVolume = BoundingSphere.fromRectangleWithHeights2D(\r\n rectangle,\r\n projection,\r\n groundPrimitive._maxHeight,\r\n groundPrimitive._minHeight\r\n );\r\n Cartesian3.fromElements(\r\n boundingVolume.center.z,\r\n boundingVolume.center.x,\r\n boundingVolume.center.y,\r\n boundingVolume.center\r\n );\r\n\r\n groundPrimitive._boundingVolumes2D.push(boundingVolume);\r\n }\r\n}\r\n\r\nfunction boundingVolumeIndex(commandIndex, length) {\r\n return Math.floor((commandIndex % length) / 2);\r\n}\r\n\r\nfunction updateAndQueueRenderCommand(\r\n groundPrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n) {\r\n // Use derived appearance command for 2D if needed\r\n var classificationPrimitive = groundPrimitive._primitive;\r\n if (\r\n frameState.mode !== SceneMode.SCENE3D &&\r\n command.shaderProgram === classificationPrimitive._spColor &&\r\n classificationPrimitive._needs2DShader\r\n ) {\r\n command = command.derivedCommands.appearance2D;\r\n }\r\n\r\n command.owner = groundPrimitive;\r\n command.modelMatrix = modelMatrix;\r\n command.boundingVolume = boundingVolume;\r\n command.cull = cull;\r\n command.debugShowBoundingVolume = debugShowBoundingVolume;\r\n\r\n frameState.commandList.push(command);\r\n}\r\n\r\nfunction updateAndQueuePickCommand(\r\n groundPrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume\r\n) {\r\n // Use derived pick command for 2D if needed\r\n var classificationPrimitive = groundPrimitive._primitive;\r\n if (\r\n frameState.mode !== SceneMode.SCENE3D &&\r\n command.shaderProgram === classificationPrimitive._spPick &&\r\n classificationPrimitive._needs2DShader\r\n ) {\r\n command = command.derivedCommands.pick2D;\r\n }\r\n\r\n command.owner = groundPrimitive;\r\n command.modelMatrix = modelMatrix;\r\n command.boundingVolume = boundingVolume;\r\n command.cull = cull;\r\n\r\n frameState.commandList.push(command);\r\n}\r\n\r\nfunction updateAndQueueCommands(\r\n groundPrimitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n) {\r\n var boundingVolumes;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n boundingVolumes = groundPrimitive._boundingVolumes;\r\n } else {\r\n boundingVolumes = groundPrimitive._boundingVolumes2D;\r\n }\r\n\r\n var classificationType = groundPrimitive.classificationType;\r\n var queueTerrainCommands =\r\n classificationType !== ClassificationType.CESIUM_3D_TILE;\r\n var queue3DTilesCommands = classificationType !== ClassificationType.TERRAIN;\r\n\r\n var passes = frameState.passes;\r\n var classificationPrimitive = groundPrimitive._primitive;\r\n\r\n var i;\r\n var boundingVolume;\r\n var command;\r\n\r\n if (passes.render) {\r\n var colorLength = colorCommands.length;\r\n\r\n for (i = 0; i < colorLength; ++i) {\r\n boundingVolume = boundingVolumes[boundingVolumeIndex(i, colorLength)];\r\n if (queueTerrainCommands) {\r\n command = colorCommands[i];\r\n updateAndQueueRenderCommand(\r\n groundPrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n );\r\n }\r\n if (queue3DTilesCommands) {\r\n command = colorCommands[i].derivedCommands.tileset;\r\n updateAndQueueRenderCommand(\r\n groundPrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n );\r\n }\r\n }\r\n\r\n if (frameState.invertClassification) {\r\n var ignoreShowCommands = classificationPrimitive._commandsIgnoreShow;\r\n var ignoreShowCommandsLength = ignoreShowCommands.length;\r\n for (i = 0; i < ignoreShowCommandsLength; ++i) {\r\n boundingVolume = boundingVolumes[i];\r\n command = ignoreShowCommands[i];\r\n updateAndQueueRenderCommand(\r\n groundPrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (passes.pick) {\r\n var pickLength = pickCommands.length;\r\n\r\n var pickOffsets;\r\n if (!groundPrimitive._useFragmentCulling) {\r\n // Must be using pick offsets\r\n pickOffsets = classificationPrimitive._primitive._pickOffsets;\r\n }\r\n for (i = 0; i < pickLength; ++i) {\r\n boundingVolume = boundingVolumes[boundingVolumeIndex(i, pickLength)];\r\n if (!groundPrimitive._useFragmentCulling) {\r\n var pickOffset = pickOffsets[boundingVolumeIndex(i, pickLength)];\r\n boundingVolume = boundingVolumes[pickOffset.index];\r\n }\r\n if (queueTerrainCommands) {\r\n command = pickCommands[i];\r\n updateAndQueuePickCommand(\r\n groundPrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume\r\n );\r\n }\r\n if (queue3DTilesCommands) {\r\n command = pickCommands[i].derivedCommands.tileset;\r\n updateAndQueuePickCommand(\r\n groundPrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume\r\n );\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Initializes the minimum and maximum terrain heights. This only needs to be called if you are creating the\r\n * GroundPrimitive synchronously.\r\n *\r\n * @returns {Promise} A promise that will resolve once the terrain heights have been loaded.\r\n *\r\n */\r\nGroundPrimitive.initializeTerrainHeights = function () {\r\n return ApproximateTerrainHeights.initialize();\r\n};\r\n\r\n/**\r\n * Called when {@link Viewer} or {@link CesiumWidget} render the scene to\r\n * get the draw commands needed to render this primitive.\r\n *

\r\n * Do not call this function directly. This is documented just to\r\n * list the exceptions that may be propagated when the scene is rendered:\r\n *

\r\n *\r\n * @exception {DeveloperError} For synchronous GroundPrimitive, you must call GroundPrimitive.initializeTerrainHeights() and wait for the returned promise to resolve.\r\n * @exception {DeveloperError} All instance geometries must have the same primitiveType.\r\n * @exception {DeveloperError} Appearance and material have a uniform with the same name.\r\n */\r\nGroundPrimitive.prototype.update = function (frameState) {\r\n if (!defined(this._primitive) && !defined(this.geometryInstances)) {\r\n return;\r\n }\r\n\r\n if (!ApproximateTerrainHeights.initialized) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.asynchronous) {\r\n throw new DeveloperError(\r\n \"For synchronous GroundPrimitives, you must call GroundPrimitive.initializeTerrainHeights() and wait for the returned promise to resolve.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n GroundPrimitive.initializeTerrainHeights();\r\n return;\r\n }\r\n\r\n var that = this;\r\n var primitiveOptions = this._classificationPrimitiveOptions;\r\n\r\n if (!defined(this._primitive)) {\r\n var ellipsoid = frameState.mapProjection.ellipsoid;\r\n\r\n var instance;\r\n var geometry;\r\n var instanceType;\r\n\r\n var instances = Array.isArray(this.geometryInstances)\r\n ? this.geometryInstances\r\n : [this.geometryInstances];\r\n var length = instances.length;\r\n var groundInstances = new Array(length);\r\n\r\n var i;\r\n var rectangle;\r\n for (i = 0; i < length; ++i) {\r\n instance = instances[i];\r\n geometry = instance.geometry;\r\n var instanceRectangle = getRectangle(frameState, geometry);\r\n if (!defined(rectangle)) {\r\n rectangle = Rectangle.clone(instanceRectangle);\r\n } else if (defined(instanceRectangle)) {\r\n Rectangle.union(rectangle, instanceRectangle, rectangle);\r\n }\r\n\r\n var id = instance.id;\r\n if (defined(id) && defined(instanceRectangle)) {\r\n var boundingSphere = ApproximateTerrainHeights.getBoundingSphere(\r\n instanceRectangle,\r\n ellipsoid\r\n );\r\n this._boundingSpheresKeys.push(id);\r\n this._boundingSpheres.push(boundingSphere);\r\n }\r\n\r\n instanceType = geometry.constructor;\r\n if (!defined(instanceType) || !defined(instanceType.createShadowVolume)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\r\n \"Not all of the geometry instances have GroundPrimitive support.\"\r\n );\r\n //>>includeEnd('debug');\r\n }\r\n }\r\n\r\n // Now compute the min/max heights for the primitive\r\n setMinMaxTerrainHeights(this, rectangle, ellipsoid);\r\n var exaggeration = frameState.terrainExaggeration;\r\n this._minHeight = this._minTerrainHeight * exaggeration;\r\n this._maxHeight = this._maxTerrainHeight * exaggeration;\r\n\r\n var useFragmentCulling = GroundPrimitive._supportsMaterials(\r\n frameState.context\r\n );\r\n this._useFragmentCulling = useFragmentCulling;\r\n\r\n if (useFragmentCulling) {\r\n // Determine whether to add spherical or planar extent attributes for computing texture coordinates.\r\n // This depends on the size of the GeometryInstances.\r\n var attributes;\r\n var usePlanarExtents = true;\r\n for (i = 0; i < length; ++i) {\r\n instance = instances[i];\r\n geometry = instance.geometry;\r\n rectangle = getRectangle(frameState, geometry);\r\n if (ShadowVolumeAppearance.shouldUseSphericalCoordinates(rectangle)) {\r\n usePlanarExtents = false;\r\n break;\r\n }\r\n }\r\n\r\n for (i = 0; i < length; ++i) {\r\n instance = instances[i];\r\n geometry = instance.geometry;\r\n instanceType = geometry.constructor;\r\n\r\n var boundingRectangle = getRectangle(frameState, geometry);\r\n var textureCoordinateRotationPoints =\r\n geometry.textureCoordinateRotationPoints;\r\n\r\n if (usePlanarExtents) {\r\n attributes = ShadowVolumeAppearance.getPlanarTextureCoordinateAttributes(\r\n boundingRectangle,\r\n textureCoordinateRotationPoints,\r\n ellipsoid,\r\n frameState.mapProjection,\r\n this._maxHeight\r\n );\r\n } else {\r\n attributes = ShadowVolumeAppearance.getSphericalExtentGeometryInstanceAttributes(\r\n boundingRectangle,\r\n textureCoordinateRotationPoints,\r\n ellipsoid,\r\n frameState.mapProjection\r\n );\r\n }\r\n\r\n var instanceAttributes = instance.attributes;\r\n for (var attributeKey in instanceAttributes) {\r\n if (instanceAttributes.hasOwnProperty(attributeKey)) {\r\n attributes[attributeKey] = instanceAttributes[attributeKey];\r\n }\r\n }\r\n\r\n groundInstances[i] = new GeometryInstance({\r\n geometry: instanceType.createShadowVolume(\r\n geometry,\r\n getComputeMinimumHeightFunction(this),\r\n getComputeMaximumHeightFunction(this)\r\n ),\r\n attributes: attributes,\r\n id: instance.id,\r\n });\r\n }\r\n } else {\r\n // ClassificationPrimitive will check if the colors are all the same if it detects lack of fragment culling attributes\r\n for (i = 0; i < length; ++i) {\r\n instance = instances[i];\r\n geometry = instance.geometry;\r\n instanceType = geometry.constructor;\r\n groundInstances[i] = new GeometryInstance({\r\n geometry: instanceType.createShadowVolume(\r\n geometry,\r\n getComputeMinimumHeightFunction(this),\r\n getComputeMaximumHeightFunction(this)\r\n ),\r\n attributes: instance.attributes,\r\n id: instance.id,\r\n });\r\n }\r\n }\r\n\r\n primitiveOptions.geometryInstances = groundInstances;\r\n primitiveOptions.appearance = this.appearance;\r\n\r\n primitiveOptions._createBoundingVolumeFunction = function (\r\n frameState,\r\n geometry\r\n ) {\r\n createBoundingVolume(that, frameState, geometry);\r\n };\r\n primitiveOptions._updateAndQueueCommandsFunction = function (\r\n primitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n ) {\r\n updateAndQueueCommands(\r\n that,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n );\r\n };\r\n\r\n this._primitive = new ClassificationPrimitive(primitiveOptions);\r\n this._primitive.readyPromise.then(function (primitive) {\r\n that._ready = true;\r\n\r\n if (that.releaseGeometryInstances) {\r\n that.geometryInstances = undefined;\r\n }\r\n\r\n var error = primitive._error;\r\n if (!defined(error)) {\r\n that._readyPromise.resolve(that);\r\n } else {\r\n that._readyPromise.reject(error);\r\n }\r\n });\r\n }\r\n\r\n this._primitive.appearance = this.appearance;\r\n this._primitive.show = this.show;\r\n this._primitive.debugShowShadowVolume = this.debugShowShadowVolume;\r\n this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;\r\n this._primitive.update(frameState);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nGroundPrimitive.prototype.getBoundingSphere = function (id) {\r\n var index = this._boundingSpheresKeys.indexOf(id);\r\n if (index !== -1) {\r\n return this._boundingSpheres[index];\r\n }\r\n\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Returns the modifiable per-instance attributes for a {@link GeometryInstance}.\r\n *\r\n * @param {*} id The id of the {@link GeometryInstance}.\r\n * @returns {Object} The typed array in the attribute's format or undefined if the is no instance with id.\r\n *\r\n * @exception {DeveloperError} must call update before calling getGeometryInstanceAttributes.\r\n *\r\n * @example\r\n * var attributes = primitive.getGeometryInstanceAttributes('an id');\r\n * attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA);\r\n * attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true);\r\n */\r\nGroundPrimitive.prototype.getGeometryInstanceAttributes = function (id) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(this._primitive)) {\r\n throw new DeveloperError(\r\n \"must call update before calling getGeometryInstanceAttributes\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return this._primitive.getGeometryInstanceAttributes(id);\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see GroundPrimitive#destroy\r\n */\r\nGroundPrimitive.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * e = e && e.destroy();\r\n *\r\n * @see GroundPrimitive#isDestroyed\r\n */\r\nGroundPrimitive.prototype.destroy = function () {\r\n this._primitive = this._primitive && this._primitive.destroy();\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * Exposed for testing.\r\n *\r\n * @param {Context} context Rendering context\r\n * @returns {Boolean} Whether or not the current context supports materials on GroundPrimitives.\r\n * @private\r\n */\r\nGroundPrimitive._supportsMaterials = function (context) {\r\n return context.depthTexture;\r\n};\r\n\r\n/**\r\n * Checks if the given Scene supports materials on GroundPrimitives.\r\n * Materials on GroundPrimitives require support for the WEBGL_depth_texture extension.\r\n *\r\n * @param {Scene} scene The current scene.\r\n * @returns {Boolean} Whether or not the current scene supports materials on GroundPrimitives.\r\n */\r\nGroundPrimitive.supportsMaterials = function (scene) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"scene\", scene);\r\n //>>includeEnd('debug');\r\n\r\n return GroundPrimitive._supportsMaterials(scene.frameState.context);\r\n};\r\nexport default GroundPrimitive;\r\n","import Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Material from \"../Scene/Material.js\";\r\n\r\n/**\r\n * The interface for all {@link Property} objects that represent {@link Material} uniforms.\r\n * This type defines an interface and cannot be instantiated directly.\r\n *\r\n * @alias MaterialProperty\r\n * @constructor\r\n * @abstract\r\n *\r\n * @see ColorMaterialProperty\r\n * @see CompositeMaterialProperty\r\n * @see GridMaterialProperty\r\n * @see ImageMaterialProperty\r\n * @see PolylineGlowMaterialProperty\r\n * @see PolylineOutlineMaterialProperty\r\n * @see StripeMaterialProperty\r\n */\r\nfunction MaterialProperty() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\nObject.defineProperties(MaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof MaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof MaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n * @function\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nMaterialProperty.prototype.getType = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n * @function\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nMaterialProperty.prototype.getValue = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n * @function\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nMaterialProperty.prototype.equals = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * @private\r\n */\r\nMaterialProperty.getValue = function (time, materialProperty, material) {\r\n var type;\r\n\r\n if (defined(materialProperty)) {\r\n type = materialProperty.getType(time);\r\n if (defined(type)) {\r\n if (!defined(material) || material.type !== type) {\r\n material = Material.fromType(type);\r\n }\r\n materialProperty.getValue(time, material.uniforms);\r\n return material;\r\n }\r\n }\r\n\r\n if (!defined(material) || material.type !== Material.ColorType) {\r\n material = Material.fromType(Material.ColorType);\r\n }\r\n Color.clone(Color.WHITE, material.uniforms.color);\r\n\r\n return material;\r\n};\r\nexport default MaterialProperty;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport GroundPrimitive from \"../Scene/GroundPrimitive.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport Primitive from \"../Scene/Primitive.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport MaterialProperty from \"./MaterialProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * Defines the interface for a dynamic geometry updater. A DynamicGeometryUpdater\r\n * is responsible for handling visualization of a specific type of geometry\r\n * that needs to be recomputed based on simulation time.\r\n * This object is never used directly by client code, but is instead created by\r\n * {@link GeometryUpdater} implementations which contain dynamic geometry.\r\n *\r\n * This type defines an interface and cannot be instantiated directly.\r\n *\r\n * @alias DynamicGeometryUpdater\r\n * @constructor\r\n * @private\r\n * @abstract\r\n */\r\nfunction DynamicGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n orderedGroundPrimitives\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"geometryUpdater\", geometryUpdater);\r\n Check.defined(\"primitives\", primitives);\r\n Check.defined(\"orderedGroundPrimitives\", orderedGroundPrimitives);\r\n //>>includeEnd('debug');\r\n\r\n this._primitives = primitives;\r\n this._orderedGroundPrimitives = orderedGroundPrimitives;\r\n this._primitive = undefined;\r\n this._outlinePrimitive = undefined;\r\n this._geometryUpdater = geometryUpdater;\r\n this._options = geometryUpdater._options;\r\n this._entity = geometryUpdater._entity;\r\n this._material = undefined;\r\n}\r\n\r\nDynamicGeometryUpdater.prototype._isHidden = function (entity, geometry, time) {\r\n return (\r\n !entity.isShowing ||\r\n !entity.isAvailable(time) ||\r\n !Property.getValueOrDefault(geometry.show, time, true)\r\n );\r\n};\r\n\r\nDynamicGeometryUpdater.prototype._setOptions =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Updates the geometry to the specified time.\r\n * @memberof DynamicGeometryUpdater\r\n * @function\r\n *\r\n * @param {JulianDate} time The current time.\r\n */\r\nDynamicGeometryUpdater.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var geometryUpdater = this._geometryUpdater;\r\n var onTerrain = geometryUpdater._onTerrain;\r\n\r\n var primitives = this._primitives;\r\n var orderedGroundPrimitives = this._orderedGroundPrimitives;\r\n if (onTerrain) {\r\n orderedGroundPrimitives.remove(this._primitive);\r\n } else {\r\n primitives.removeAndDestroy(this._primitive);\r\n primitives.removeAndDestroy(this._outlinePrimitive);\r\n this._outlinePrimitive = undefined;\r\n }\r\n this._primitive = undefined;\r\n\r\n var entity = this._entity;\r\n var geometry = entity[this._geometryUpdater._geometryPropertyName];\r\n this._setOptions(entity, geometry, time);\r\n if (this._isHidden(entity, geometry, time)) {\r\n return;\r\n }\r\n\r\n var shadows = this._geometryUpdater.shadowsProperty.getValue(time);\r\n var options = this._options;\r\n if (!defined(geometry.fill) || geometry.fill.getValue(time)) {\r\n var fillMaterialProperty = geometryUpdater.fillMaterialProperty;\r\n var isColorAppearance =\r\n fillMaterialProperty instanceof ColorMaterialProperty;\r\n var appearance;\r\n var closed = geometryUpdater._getIsClosed(options);\r\n if (isColorAppearance) {\r\n appearance = new PerInstanceColorAppearance({\r\n closed: closed,\r\n flat:\r\n onTerrain && !geometryUpdater._supportsMaterialsforEntitiesOnTerrain,\r\n });\r\n } else {\r\n var material = MaterialProperty.getValue(\r\n time,\r\n fillMaterialProperty,\r\n this._material\r\n );\r\n this._material = material;\r\n appearance = new MaterialAppearance({\r\n material: material,\r\n translucent: material.isTranslucent(),\r\n closed: closed,\r\n });\r\n }\r\n\r\n if (onTerrain) {\r\n options.vertexFormat = PerInstanceColorAppearance.VERTEX_FORMAT;\r\n this._primitive = orderedGroundPrimitives.add(\r\n new GroundPrimitive({\r\n geometryInstances: this._geometryUpdater.createFillGeometryInstance(\r\n time\r\n ),\r\n appearance: appearance,\r\n asynchronous: false,\r\n shadows: shadows,\r\n classificationType: this._geometryUpdater.classificationTypeProperty.getValue(\r\n time\r\n ),\r\n }),\r\n Property.getValueOrUndefined(this._geometryUpdater.zIndex, time)\r\n );\r\n } else {\r\n options.vertexFormat = appearance.vertexFormat;\r\n\r\n var fillInstance = this._geometryUpdater.createFillGeometryInstance(time);\r\n\r\n if (isColorAppearance) {\r\n appearance.translucent = fillInstance.attributes.color.value[3] !== 255;\r\n }\r\n\r\n this._primitive = primitives.add(\r\n new Primitive({\r\n geometryInstances: fillInstance,\r\n appearance: appearance,\r\n asynchronous: false,\r\n shadows: shadows,\r\n })\r\n );\r\n }\r\n }\r\n\r\n if (\r\n !onTerrain &&\r\n defined(geometry.outline) &&\r\n geometry.outline.getValue(time)\r\n ) {\r\n var outlineInstance = this._geometryUpdater.createOutlineGeometryInstance(\r\n time\r\n );\r\n var outlineWidth = Property.getValueOrDefault(\r\n geometry.outlineWidth,\r\n time,\r\n 1.0\r\n );\r\n\r\n this._outlinePrimitive = primitives.add(\r\n new Primitive({\r\n geometryInstances: outlineInstance,\r\n appearance: new PerInstanceColorAppearance({\r\n flat: true,\r\n translucent: outlineInstance.attributes.color.value[3] !== 255,\r\n renderState: {\r\n lineWidth: geometryUpdater._scene.clampLineWidth(outlineWidth),\r\n },\r\n }),\r\n asynchronous: false,\r\n shadows: shadows,\r\n })\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n * @function\r\n *\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nDynamicGeometryUpdater.prototype.getBoundingSphere = function (result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n var entity = this._entity;\r\n var primitive = this._primitive;\r\n var outlinePrimitive = this._outlinePrimitive;\r\n\r\n var attributes;\r\n\r\n //Outline and Fill geometries have the same bounding sphere, so just use whichever one is defined and ready\r\n if (defined(primitive) && primitive.show && primitive.ready) {\r\n attributes = primitive.getGeometryInstanceAttributes(entity);\r\n if (defined(attributes) && defined(attributes.boundingSphere)) {\r\n BoundingSphere.clone(attributes.boundingSphere, result);\r\n return BoundingSphereState.DONE;\r\n }\r\n }\r\n\r\n if (\r\n defined(outlinePrimitive) &&\r\n outlinePrimitive.show &&\r\n outlinePrimitive.ready\r\n ) {\r\n attributes = outlinePrimitive.getGeometryInstanceAttributes(entity);\r\n if (defined(attributes) && defined(attributes.boundingSphere)) {\r\n BoundingSphere.clone(attributes.boundingSphere, result);\r\n return BoundingSphereState.DONE;\r\n }\r\n }\r\n\r\n if (\r\n (defined(primitive) && !primitive.ready) ||\r\n (defined(outlinePrimitive) && !outlinePrimitive.ready)\r\n ) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n\r\n return BoundingSphereState.FAILED;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n * @memberof DynamicGeometryUpdater\r\n * @function\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nDynamicGeometryUpdater.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys and resources used by the object. Once an object is destroyed, it should not be used.\r\n * @memberof DynamicGeometryUpdater\r\n * @function\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nDynamicGeometryUpdater.prototype.destroy = function () {\r\n var primitives = this._primitives;\r\n var orderedGroundPrimitives = this._orderedGroundPrimitives;\r\n if (this._geometryUpdater._onTerrain) {\r\n orderedGroundPrimitives.remove(this._primitive);\r\n } else {\r\n primitives.removeAndDestroy(this._primitive);\r\n }\r\n primitives.removeAndDestroy(this._outlinePrimitive);\r\n destroyObject(this);\r\n};\r\nexport default DynamicGeometryUpdater;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef GL_EXT_frag_depth\\n\\\n#extension GL_EXT_frag_depth : enable\\n\\\n#endif\\n\\\nvarying vec4 v_startPlaneNormalEcAndHalfWidth;\\n\\\nvarying vec4 v_endPlaneNormalEcAndBatchId;\\n\\\nvarying vec4 v_rightPlaneEC;\\n\\\nvarying vec4 v_endEcAndStartEcX;\\n\\\nvarying vec4 v_texcoordNormalizationAndStartEcYZ;\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nvarying vec4 v_color;\\n\\\n#endif\\n\\\nvoid main(void)\\n\\\n{\\n\\\nfloat logDepthOrDepth = czm_branchFreeTernary(czm_sceneMode == czm_sceneMode2D, gl_FragCoord.z, czm_unpackDepth(texture2D(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw)));\\n\\\nvec3 ecStart = vec3(v_endEcAndStartEcX.w, v_texcoordNormalizationAndStartEcYZ.zw);\\n\\\nif (logDepthOrDepth == 0.0) {\\n\\\n#ifdef DEBUG_SHOW_VOLUME\\n\\\ngl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);\\n\\\nreturn;\\n\\\n#else // DEBUG_SHOW_VOLUME\\n\\\ndiscard;\\n\\\n#endif // DEBUG_SHOW_VOLUME\\n\\\n}\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);\\n\\\neyeCoordinate /= eyeCoordinate.w;\\n\\\nfloat halfMaxWidth = v_startPlaneNormalEcAndHalfWidth.w * czm_metersPerPixel(eyeCoordinate);\\n\\\nfloat widthwiseDistance = czm_planeDistance(v_rightPlaneEC, eyeCoordinate.xyz);\\n\\\nfloat distanceFromStart = czm_planeDistance(v_startPlaneNormalEcAndHalfWidth.xyz, -dot(ecStart, v_startPlaneNormalEcAndHalfWidth.xyz), eyeCoordinate.xyz);\\n\\\nfloat distanceFromEnd = czm_planeDistance(v_endPlaneNormalEcAndBatchId.xyz, -dot(v_endEcAndStartEcX.xyz, v_endPlaneNormalEcAndBatchId.xyz), eyeCoordinate.xyz);\\n\\\nif (abs(widthwiseDistance) > halfMaxWidth || distanceFromStart < 0.0 || distanceFromEnd < 0.0) {\\n\\\n#ifdef DEBUG_SHOW_VOLUME\\n\\\ngl_FragColor = vec4(1.0, 0.0, 0.0, 0.5);\\n\\\nreturn;\\n\\\n#else // DEBUG_SHOW_VOLUME\\n\\\ndiscard;\\n\\\n#endif // DEBUG_SHOW_VOLUME\\n\\\n}\\n\\\nvec3 alignedPlaneNormal;\\n\\\nalignedPlaneNormal = cross(v_rightPlaneEC.xyz, v_startPlaneNormalEcAndHalfWidth.xyz);\\n\\\nalignedPlaneNormal = normalize(cross(alignedPlaneNormal, v_rightPlaneEC.xyz));\\n\\\ndistanceFromStart = czm_planeDistance(alignedPlaneNormal, -dot(alignedPlaneNormal, ecStart), eyeCoordinate.xyz);\\n\\\nalignedPlaneNormal = cross(v_rightPlaneEC.xyz, v_endPlaneNormalEcAndBatchId.xyz);\\n\\\nalignedPlaneNormal = normalize(cross(alignedPlaneNormal, v_rightPlaneEC.xyz));\\n\\\ndistanceFromEnd = czm_planeDistance(alignedPlaneNormal, -dot(alignedPlaneNormal, v_endEcAndStartEcX.xyz), eyeCoordinate.xyz);\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\ngl_FragColor = czm_gammaCorrect(v_color);\\n\\\n#else // PER_INSTANCE_COLOR\\n\\\nfloat s = clamp(distanceFromStart / (distanceFromStart + distanceFromEnd), 0.0, 1.0);\\n\\\ns = (s * v_texcoordNormalizationAndStartEcYZ.x) + v_texcoordNormalizationAndStartEcYZ.y;\\n\\\nfloat t = (widthwiseDistance + halfMaxWidth) / (2.0 * halfMaxWidth);\\n\\\nczm_materialInput materialInput;\\n\\\nmaterialInput.s = s;\\n\\\nmaterialInput.st = vec2(s, t);\\n\\\nmaterialInput.str = vec3(s, t, 0.0);\\n\\\nczm_material material = czm_getMaterial(materialInput);\\n\\\ngl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\\n\\\n#endif // PER_INSTANCE_COLOR\\n\\\ngl_FragColor.rgb *= gl_FragColor.a;\\n\\\nczm_writeDepthClamp();\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec3 v_forwardDirectionEC;\\n\\\nvarying vec3 v_texcoordNormalizationAndHalfWidth;\\n\\\nvarying float v_batchId;\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nvarying vec4 v_color;\\n\\\n#else\\n\\\nvarying vec2 v_alignedPlaneDistances;\\n\\\nvarying float v_texcoordT;\\n\\\n#endif\\n\\\nfloat rayPlaneDistanceUnsafe(vec3 origin, vec3 direction, vec3 planeNormal, float planeDistance) {\\n\\\nreturn (-planeDistance - dot(planeNormal, origin)) / dot(planeNormal, direction);\\n\\\n}\\n\\\nvoid main(void)\\n\\\n{\\n\\\nvec4 eyeCoordinate = gl_FragCoord;\\n\\\neyeCoordinate /= eyeCoordinate.w;\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\ngl_FragColor = czm_gammaCorrect(v_color);\\n\\\n#else // PER_INSTANCE_COLOR\\n\\\nfloat distanceFromStart = rayPlaneDistanceUnsafe(eyeCoordinate.xyz, -v_forwardDirectionEC, v_forwardDirectionEC.xyz, v_alignedPlaneDistances.x);\\n\\\nfloat distanceFromEnd = rayPlaneDistanceUnsafe(eyeCoordinate.xyz, v_forwardDirectionEC, -v_forwardDirectionEC.xyz, v_alignedPlaneDistances.y);\\n\\\ndistanceFromStart = max(0.0, distanceFromStart);\\n\\\ndistanceFromEnd = max(0.0, distanceFromEnd);\\n\\\nfloat s = distanceFromStart / (distanceFromStart + distanceFromEnd);\\n\\\ns = (s * v_texcoordNormalizationAndHalfWidth.x) + v_texcoordNormalizationAndHalfWidth.y;\\n\\\nczm_materialInput materialInput;\\n\\\nmaterialInput.s = s;\\n\\\nmaterialInput.st = vec2(s, v_texcoordT);\\n\\\nmaterialInput.str = vec3(s, v_texcoordT, 0.0);\\n\\\nczm_material material = czm_getMaterial(materialInput);\\n\\\ngl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\\n\\\n#endif // PER_INSTANCE_COLOR\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec4 startHiAndForwardOffsetX;\\n\\\nattribute vec4 startLoAndForwardOffsetY;\\n\\\nattribute vec4 startNormalAndForwardOffsetZ;\\n\\\nattribute vec4 endNormalAndTextureCoordinateNormalizationX;\\n\\\nattribute vec4 rightNormalAndTextureCoordinateNormalizationY;\\n\\\nattribute vec4 startHiLo2D;\\n\\\nattribute vec4 offsetAndRight2D;\\n\\\nattribute vec4 startEndNormals2D;\\n\\\nattribute vec2 texcoordNormalization2D;\\n\\\nattribute float batchId;\\n\\\nvarying vec3 v_forwardDirectionEC;\\n\\\nvarying vec3 v_texcoordNormalizationAndHalfWidth;\\n\\\nvarying float v_batchId;\\n\\\n#ifdef WIDTH_VARYING\\n\\\nvarying float v_width;\\n\\\n#endif\\n\\\n#ifdef ANGLE_VARYING\\n\\\nvarying float v_polylineAngle;\\n\\\n#endif\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nvarying vec4 v_color;\\n\\\n#else\\n\\\nvarying vec2 v_alignedPlaneDistances;\\n\\\nvarying float v_texcoordT;\\n\\\n#endif\\n\\\nvoid main()\\n\\\n{\\n\\\nv_batchId = batchId;\\n\\\nvec4 posRelativeToEye2D = czm_translateRelativeToEye(vec3(0.0, startHiLo2D.xy), vec3(0.0, startHiLo2D.zw));\\n\\\nvec4 posRelativeToEye3D = czm_translateRelativeToEye(startHiAndForwardOffsetX.xyz, startLoAndForwardOffsetY.xyz);\\n\\\nvec4 posRelativeToEye = czm_columbusViewMorph(posRelativeToEye2D, posRelativeToEye3D, czm_morphTime);\\n\\\nvec3 posEc2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz;\\n\\\nvec3 posEc3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz;\\n\\\nvec3 startEC = (czm_modelViewRelativeToEye * posRelativeToEye).xyz;\\n\\\nvec4 startPlane2D;\\n\\\nvec4 startPlane3D;\\n\\\nstartPlane2D.xyz = czm_normal * vec3(0.0, startEndNormals2D.xy);\\n\\\nstartPlane3D.xyz = czm_normal * startNormalAndForwardOffsetZ.xyz;\\n\\\nstartPlane2D.w = -dot(startPlane2D.xyz, posEc2D);\\n\\\nstartPlane3D.w = -dot(startPlane3D.xyz, posEc3D);\\n\\\nvec4 rightPlane2D;\\n\\\nvec4 rightPlane3D;\\n\\\nrightPlane2D.xyz = czm_normal * vec3(0.0, offsetAndRight2D.zw);\\n\\\nrightPlane3D.xyz = czm_normal * rightNormalAndTextureCoordinateNormalizationY.xyz;\\n\\\nrightPlane2D.w = -dot(rightPlane2D.xyz, posEc2D);\\n\\\nrightPlane3D.w = -dot(rightPlane3D.xyz, posEc3D);\\n\\\nposRelativeToEye2D = posRelativeToEye2D + vec4(0.0, offsetAndRight2D.xy, 0.0);\\n\\\nposRelativeToEye3D = posRelativeToEye3D + vec4(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w, 0.0);\\n\\\nposRelativeToEye = czm_columbusViewMorph(posRelativeToEye2D, posRelativeToEye3D, czm_morphTime);\\n\\\nposEc2D = (czm_modelViewRelativeToEye * posRelativeToEye2D).xyz;\\n\\\nposEc3D = (czm_modelViewRelativeToEye * posRelativeToEye3D).xyz;\\n\\\nvec3 endEC = (czm_modelViewRelativeToEye * posRelativeToEye).xyz;\\n\\\nvec3 forwardEc3D = czm_normal * normalize(vec3(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w));\\n\\\nvec3 forwardEc2D = czm_normal * normalize(vec3(0.0, offsetAndRight2D.xy));\\n\\\nvec4 endPlane2D;\\n\\\nvec4 endPlane3D;\\n\\\nendPlane2D.xyz = czm_normal * vec3(0.0, startEndNormals2D.zw);\\n\\\nendPlane3D.xyz = czm_normal * endNormalAndTextureCoordinateNormalizationX.xyz;\\n\\\nendPlane2D.w = -dot(endPlane2D.xyz, posEc2D);\\n\\\nendPlane3D.w = -dot(endPlane3D.xyz, posEc3D);\\n\\\nv_forwardDirectionEC = normalize(endEC - startEC);\\n\\\nvec2 cleanTexcoordNormalization2D;\\n\\\ncleanTexcoordNormalization2D.x = abs(texcoordNormalization2D.x);\\n\\\ncleanTexcoordNormalization2D.y = czm_branchFreeTernary(texcoordNormalization2D.y > 1.0, 0.0, abs(texcoordNormalization2D.y));\\n\\\nvec2 cleanTexcoordNormalization3D;\\n\\\ncleanTexcoordNormalization3D.x = abs(endNormalAndTextureCoordinateNormalizationX.w);\\n\\\ncleanTexcoordNormalization3D.y = rightNormalAndTextureCoordinateNormalizationY.w;\\n\\\ncleanTexcoordNormalization3D.y = czm_branchFreeTernary(cleanTexcoordNormalization3D.y > 1.0, 0.0, abs(cleanTexcoordNormalization3D.y));\\n\\\nv_texcoordNormalizationAndHalfWidth.xy = mix(cleanTexcoordNormalization2D, cleanTexcoordNormalization3D, czm_morphTime);\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nv_color = czm_batchTable_color(batchId);\\n\\\n#else // PER_INSTANCE_COLOR\\n\\\nv_alignedPlaneDistances.x = -dot(v_forwardDirectionEC, startEC);\\n\\\nv_alignedPlaneDistances.y = -dot(-v_forwardDirectionEC, endEC);\\n\\\n#endif // PER_INSTANCE_COLOR\\n\\\n#ifdef WIDTH_VARYING\\n\\\nfloat width = czm_batchTable_width(batchId);\\n\\\nfloat halfWidth = width * 0.5;\\n\\\nv_width = width;\\n\\\nv_texcoordNormalizationAndHalfWidth.z = halfWidth;\\n\\\n#else\\n\\\nfloat halfWidth = 0.5 * czm_batchTable_width(batchId);\\n\\\nv_texcoordNormalizationAndHalfWidth.z = halfWidth;\\n\\\n#endif\\n\\\nvec4 positionEc3D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position3DHigh, position3DLow);\\n\\\nfloat absStartPlaneDistance = abs(czm_planeDistance(startPlane3D, positionEc3D.xyz));\\n\\\nfloat absEndPlaneDistance = abs(czm_planeDistance(endPlane3D, positionEc3D.xyz));\\n\\\nvec3 planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlane3D.xyz, endPlane3D.xyz);\\n\\\nvec3 upOrDown = normalize(cross(rightPlane3D.xyz, planeDirection));\\n\\\nvec3 normalEC = normalize(cross(planeDirection, upOrDown));\\n\\\nvec3 geodeticSurfaceNormal = normalize(cross(normalEC, forwardEc3D));\\n\\\ngeodeticSurfaceNormal *= float(0.0 <= rightNormalAndTextureCoordinateNormalizationY.w && rightNormalAndTextureCoordinateNormalizationY.w <= 1.0);\\n\\\ngeodeticSurfaceNormal *= MAX_TERRAIN_HEIGHT;\\n\\\npositionEc3D.xyz += geodeticSurfaceNormal;\\n\\\nnormalEC *= sign(endNormalAndTextureCoordinateNormalizationX.w);\\n\\\npositionEc3D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEc3D)) * normalEC;\\n\\\nvec4 positionEc2D = czm_modelViewRelativeToEye * czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy);\\n\\\nabsStartPlaneDistance = abs(czm_planeDistance(startPlane2D, positionEc2D.xyz));\\n\\\nabsEndPlaneDistance = abs(czm_planeDistance(endPlane2D, positionEc2D.xyz));\\n\\\nplaneDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlane2D.xyz, endPlane2D.xyz);\\n\\\nupOrDown = normalize(cross(rightPlane2D.xyz, planeDirection));\\n\\\nnormalEC = normalize(cross(planeDirection, upOrDown));\\n\\\ngeodeticSurfaceNormal = normalize(cross(normalEC, forwardEc2D));\\n\\\ngeodeticSurfaceNormal *= float(0.0 <= texcoordNormalization2D.y && texcoordNormalization2D.y <= 1.0);\\n\\\ngeodeticSurfaceNormal *= MAX_TERRAIN_HEIGHT;\\n\\\npositionEc2D.xyz += geodeticSurfaceNormal;\\n\\\nnormalEC *= sign(texcoordNormalization2D.x);\\n\\\n#ifndef PER_INSTANCE_COLOR\\n\\\nv_texcoordT = clamp(sign(texcoordNormalization2D.x), 0.0, 1.0);\\n\\\n#endif\\n\\\npositionEc2D.xyz += halfWidth * max(0.0, czm_metersPerPixel(positionEc2D)) * normalEC;\\n\\\ngl_Position = czm_projection * mix(positionEc2D, positionEc3D, czm_morphTime);\\n\\\n#ifdef ANGLE_VARYING\\n\\\nvec2 approxLineDirection = normalize(vec2(v_forwardDirectionEC.x, -v_forwardDirectionEC.y));\\n\\\napproxLineDirection.y = czm_branchFreeTernary(approxLineDirection.x == 0.0 && approxLineDirection.y == 0.0, -1.0, approxLineDirection.y);\\n\\\nv_polylineAngle = czm_fastApproximateAtan(approxLineDirection.x, approxLineDirection.y);\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\n#ifndef COLUMBUS_VIEW_2D\\n\\\nattribute vec4 startHiAndForwardOffsetX;\\n\\\nattribute vec4 startLoAndForwardOffsetY;\\n\\\nattribute vec4 startNormalAndForwardOffsetZ;\\n\\\nattribute vec4 endNormalAndTextureCoordinateNormalizationX;\\n\\\nattribute vec4 rightNormalAndTextureCoordinateNormalizationY;\\n\\\n#else\\n\\\nattribute vec4 startHiLo2D;\\n\\\nattribute vec4 offsetAndRight2D;\\n\\\nattribute vec4 startEndNormals2D;\\n\\\nattribute vec2 texcoordNormalization2D;\\n\\\n#endif\\n\\\nattribute float batchId;\\n\\\nvarying vec4 v_startPlaneNormalEcAndHalfWidth;\\n\\\nvarying vec4 v_endPlaneNormalEcAndBatchId;\\n\\\nvarying vec4 v_rightPlaneEC;\\n\\\nvarying vec4 v_endEcAndStartEcX;\\n\\\nvarying vec4 v_texcoordNormalizationAndStartEcYZ;\\n\\\n#ifdef WIDTH_VARYING\\n\\\nvarying float v_width;\\n\\\n#endif\\n\\\n#ifdef ANGLE_VARYING\\n\\\nvarying float v_polylineAngle;\\n\\\n#endif\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nvarying vec4 v_color;\\n\\\n#endif\\n\\\nvoid main()\\n\\\n{\\n\\\n#ifdef COLUMBUS_VIEW_2D\\n\\\nvec3 ecStart = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(vec3(0.0, startHiLo2D.xy), vec3(0.0, startHiLo2D.zw))).xyz;\\n\\\nvec3 forwardDirectionEC = czm_normal * vec3(0.0, offsetAndRight2D.xy);\\n\\\nvec3 ecEnd = forwardDirectionEC + ecStart;\\n\\\nforwardDirectionEC = normalize(forwardDirectionEC);\\n\\\nv_rightPlaneEC.xyz = czm_normal * vec3(0.0, offsetAndRight2D.zw);\\n\\\nv_rightPlaneEC.w = -dot(v_rightPlaneEC.xyz, ecStart);\\n\\\nvec4 startPlaneEC;\\n\\\nstartPlaneEC.xyz = czm_normal * vec3(0.0, startEndNormals2D.xy);\\n\\\nstartPlaneEC.w = -dot(startPlaneEC.xyz, ecStart);\\n\\\nvec4 endPlaneEC;\\n\\\nendPlaneEC.xyz = czm_normal * vec3(0.0, startEndNormals2D.zw);\\n\\\nendPlaneEC.w = -dot(endPlaneEC.xyz, ecEnd);\\n\\\nv_texcoordNormalizationAndStartEcYZ.x = abs(texcoordNormalization2D.x);\\n\\\nv_texcoordNormalizationAndStartEcYZ.y = texcoordNormalization2D.y;\\n\\\n#else // COLUMBUS_VIEW_2D\\n\\\nvec3 ecStart = (czm_modelViewRelativeToEye * czm_translateRelativeToEye(startHiAndForwardOffsetX.xyz, startLoAndForwardOffsetY.xyz)).xyz;\\n\\\nvec3 offset = czm_normal * vec3(startHiAndForwardOffsetX.w, startLoAndForwardOffsetY.w, startNormalAndForwardOffsetZ.w);\\n\\\nvec3 ecEnd = ecStart + offset;\\n\\\nvec3 forwardDirectionEC = normalize(offset);\\n\\\nvec4 startPlaneEC;\\n\\\nstartPlaneEC.xyz = czm_normal * startNormalAndForwardOffsetZ.xyz;\\n\\\nstartPlaneEC.w = -dot(startPlaneEC.xyz, ecStart);\\n\\\nvec4 endPlaneEC;\\n\\\nendPlaneEC.xyz = czm_normal * endNormalAndTextureCoordinateNormalizationX.xyz;\\n\\\nendPlaneEC.w = -dot(endPlaneEC.xyz, ecEnd);\\n\\\nv_rightPlaneEC.xyz = czm_normal * rightNormalAndTextureCoordinateNormalizationY.xyz;\\n\\\nv_rightPlaneEC.w = -dot(v_rightPlaneEC.xyz, ecStart);\\n\\\nv_texcoordNormalizationAndStartEcYZ.x = abs(endNormalAndTextureCoordinateNormalizationX.w);\\n\\\nv_texcoordNormalizationAndStartEcYZ.y = rightNormalAndTextureCoordinateNormalizationY.w;\\n\\\n#endif // COLUMBUS_VIEW_2D\\n\\\nv_endEcAndStartEcX.xyz = ecEnd;\\n\\\nv_endEcAndStartEcX.w = ecStart.x;\\n\\\nv_texcoordNormalizationAndStartEcYZ.zw = ecStart.yz;\\n\\\n#ifdef PER_INSTANCE_COLOR\\n\\\nv_color = czm_batchTable_color(batchId);\\n\\\n#endif // PER_INSTANCE_COLOR\\n\\\nvec4 positionRelativeToEye = czm_computePosition();\\n\\\nvec4 positionEC = czm_modelViewRelativeToEye * positionRelativeToEye;\\n\\\nfloat absStartPlaneDistance = abs(czm_planeDistance(startPlaneEC, positionEC.xyz));\\n\\\nfloat absEndPlaneDistance = abs(czm_planeDistance(endPlaneEC, positionEC.xyz));\\n\\\nvec3 planeDirection = czm_branchFreeTernary(absStartPlaneDistance < absEndPlaneDistance, startPlaneEC.xyz, endPlaneEC.xyz);\\n\\\nvec3 upOrDown = normalize(cross(v_rightPlaneEC.xyz, planeDirection));\\n\\\nvec3 normalEC = normalize(cross(planeDirection, upOrDown));\\n\\\nupOrDown = cross(forwardDirectionEC, normalEC);\\n\\\nupOrDown = float(czm_sceneMode == czm_sceneMode3D) * upOrDown;\\n\\\nupOrDown = float(v_texcoordNormalizationAndStartEcYZ.y > 1.0 || v_texcoordNormalizationAndStartEcYZ.y < 0.0) * upOrDown;\\n\\\nupOrDown = min(GLOBE_MINIMUM_ALTITUDE, czm_geometricToleranceOverMeter * length(positionRelativeToEye.xyz)) * upOrDown;\\n\\\npositionEC.xyz += upOrDown;\\n\\\nv_texcoordNormalizationAndStartEcYZ.y = czm_branchFreeTernary(v_texcoordNormalizationAndStartEcYZ.y > 1.0, 0.0, abs(v_texcoordNormalizationAndStartEcYZ.y));\\n\\\nfloat width = czm_batchTable_width(batchId);\\n\\\n#ifdef WIDTH_VARYING\\n\\\nv_width = width;\\n\\\n#endif\\n\\\nv_startPlaneNormalEcAndHalfWidth.xyz = startPlaneEC.xyz;\\n\\\nv_startPlaneNormalEcAndHalfWidth.w = width * 0.5;\\n\\\nv_endPlaneNormalEcAndBatchId.xyz = endPlaneEC.xyz;\\n\\\nv_endPlaneNormalEcAndBatchId.w = batchId;\\n\\\nwidth = width * max(0.0, czm_metersPerPixel(positionEC));\\n\\\nwidth = width / dot(normalEC, v_rightPlaneEC.xyz);\\n\\\n#ifdef COLUMBUS_VIEW_2D\\n\\\nnormalEC *= sign(texcoordNormalization2D.x);\\n\\\n#else\\n\\\nnormalEC *= sign(endNormalAndTextureCoordinateNormalizationX.w);\\n\\\n#endif\\n\\\npositionEC.xyz += width * normalEC;\\n\\\ngl_Position = czm_depthClamp(czm_projection * positionEC);\\n\\\n#ifdef ANGLE_VARYING\\n\\\nvec2 approxLineDirection = normalize(vec2(forwardDirectionEC.x, -forwardDirectionEC.y));\\n\\\napproxLineDirection.y = czm_branchFreeTernary(approxLineDirection.x == 0.0 && approxLineDirection.y == 0.0, -1.0, approxLineDirection.y);\\n\\\nv_polylineAngle = czm_fastApproximateAtan(approxLineDirection.x, approxLineDirection.y);\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec3 prevPosition3DHigh;\\n\\\nattribute vec3 prevPosition3DLow;\\n\\\nattribute vec3 nextPosition3DHigh;\\n\\\nattribute vec3 nextPosition3DLow;\\n\\\nattribute vec2 expandAndWidth;\\n\\\nattribute vec4 color;\\n\\\nattribute float batchId;\\n\\\nvarying vec4 v_color;\\n\\\nvoid main()\\n\\\n{\\n\\\nfloat expandDir = expandAndWidth.x;\\n\\\nfloat width = abs(expandAndWidth.y) + 0.5;\\n\\\nbool usePrev = expandAndWidth.y < 0.0;\\n\\\nvec4 p = czm_computePosition();\\n\\\nvec4 prev = czm_computePrevPosition();\\n\\\nvec4 next = czm_computeNextPosition();\\n\\\nfloat angle;\\n\\\nvec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev, angle);\\n\\\ngl_Position = czm_viewportOrthographic * positionWC;\\n\\\nv_color = color;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"void clipLineSegmentToNearPlane(\\n\\\nvec3 p0,\\n\\\nvec3 p1,\\n\\\nout vec4 positionWC,\\n\\\nout bool clipped,\\n\\\nout bool culledByNearPlane,\\n\\\nout vec4 clippedPositionEC)\\n\\\n{\\n\\\nculledByNearPlane = false;\\n\\\nclipped = false;\\n\\\nvec3 p0ToP1 = p1 - p0;\\n\\\nfloat magnitude = length(p0ToP1);\\n\\\nvec3 direction = normalize(p0ToP1);\\n\\\nfloat endPoint0Distance = czm_currentFrustum.x + p0.z;\\n\\\nfloat denominator = -direction.z;\\n\\\nif (endPoint0Distance > 0.0 && abs(denominator) < czm_epsilon7)\\n\\\n{\\n\\\nculledByNearPlane = true;\\n\\\n}\\n\\\nelse if (endPoint0Distance > 0.0)\\n\\\n{\\n\\\nfloat t = endPoint0Distance / denominator;\\n\\\nif (t < 0.0 || t > magnitude)\\n\\\n{\\n\\\nculledByNearPlane = true;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\np0 = p0 + t * direction;\\n\\\np0.z = min(p0.z, -czm_currentFrustum.x);\\n\\\nclipped = true;\\n\\\n}\\n\\\n}\\n\\\nclippedPositionEC = vec4(p0, 1.0);\\n\\\npositionWC = czm_eyeToWindowCoordinates(clippedPositionEC);\\n\\\n}\\n\\\nvec4 getPolylineWindowCoordinatesEC(vec4 positionEC, vec4 prevEC, vec4 nextEC, float expandDirection, float width, bool usePrevious, out float angle)\\n\\\n{\\n\\\n#ifdef POLYLINE_DASH\\n\\\nvec4 positionWindow = czm_eyeToWindowCoordinates(positionEC);\\n\\\nvec4 previousWindow = czm_eyeToWindowCoordinates(prevEC);\\n\\\nvec4 nextWindow = czm_eyeToWindowCoordinates(nextEC);\\n\\\nvec2 lineDir;\\n\\\nif (usePrevious) {\\n\\\nlineDir = normalize(positionWindow.xy - previousWindow.xy);\\n\\\n}\\n\\\nelse {\\n\\\nlineDir = normalize(nextWindow.xy - positionWindow.xy);\\n\\\n}\\n\\\nangle = atan(lineDir.x, lineDir.y) - 1.570796327;\\n\\\nangle = floor(angle / czm_piOverFour + 0.5) * czm_piOverFour;\\n\\\n#endif\\n\\\nvec4 clippedPrevWC, clippedPrevEC;\\n\\\nbool prevSegmentClipped, prevSegmentCulled;\\n\\\nclipLineSegmentToNearPlane(prevEC.xyz, positionEC.xyz, clippedPrevWC, prevSegmentClipped, prevSegmentCulled, clippedPrevEC);\\n\\\nvec4 clippedNextWC, clippedNextEC;\\n\\\nbool nextSegmentClipped, nextSegmentCulled;\\n\\\nclipLineSegmentToNearPlane(nextEC.xyz, positionEC.xyz, clippedNextWC, nextSegmentClipped, nextSegmentCulled, clippedNextEC);\\n\\\nbool segmentClipped, segmentCulled;\\n\\\nvec4 clippedPositionWC, clippedPositionEC;\\n\\\nclipLineSegmentToNearPlane(positionEC.xyz, usePrevious ? prevEC.xyz : nextEC.xyz, clippedPositionWC, segmentClipped, segmentCulled, clippedPositionEC);\\n\\\nif (segmentCulled)\\n\\\n{\\n\\\nreturn vec4(0.0, 0.0, 0.0, 1.0);\\n\\\n}\\n\\\nvec2 directionToPrevWC = normalize(clippedPrevWC.xy - clippedPositionWC.xy);\\n\\\nvec2 directionToNextWC = normalize(clippedNextWC.xy - clippedPositionWC.xy);\\n\\\nif (prevSegmentCulled)\\n\\\n{\\n\\\ndirectionToPrevWC = -directionToNextWC;\\n\\\n}\\n\\\nelse if (nextSegmentCulled)\\n\\\n{\\n\\\ndirectionToNextWC = -directionToPrevWC;\\n\\\n}\\n\\\nvec2 thisSegmentForwardWC, otherSegmentForwardWC;\\n\\\nif (usePrevious)\\n\\\n{\\n\\\nthisSegmentForwardWC = -directionToPrevWC;\\n\\\notherSegmentForwardWC = directionToNextWC;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nthisSegmentForwardWC = directionToNextWC;\\n\\\notherSegmentForwardWC = -directionToPrevWC;\\n\\\n}\\n\\\nvec2 thisSegmentLeftWC = vec2(-thisSegmentForwardWC.y, thisSegmentForwardWC.x);\\n\\\nvec2 leftWC = thisSegmentLeftWC;\\n\\\nfloat expandWidth = width * 0.5;\\n\\\nif (!czm_equalsEpsilon(prevEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1) && !czm_equalsEpsilon(nextEC.xyz - positionEC.xyz, vec3(0.0), czm_epsilon1))\\n\\\n{\\n\\\nvec2 otherSegmentLeftWC = vec2(-otherSegmentForwardWC.y, otherSegmentForwardWC.x);\\n\\\nvec2 leftSumWC = thisSegmentLeftWC + otherSegmentLeftWC;\\n\\\nfloat leftSumLength = length(leftSumWC);\\n\\\nleftWC = leftSumLength < czm_epsilon6 ? thisSegmentLeftWC : (leftSumWC / leftSumLength);\\n\\\nvec2 u = -thisSegmentForwardWC;\\n\\\nvec2 v = leftWC;\\n\\\nfloat sinAngle = abs(u.x * v.y - u.y * v.x);\\n\\\nexpandWidth = clamp(expandWidth / sinAngle, 0.0, width * 2.0);\\n\\\n}\\n\\\nvec2 offset = leftWC * expandDirection * expandWidth * czm_pixelRatio;\\n\\\nreturn vec4(clippedPositionWC.xy + offset, -clippedPositionWC.z, 1.0) * (czm_projection * clippedPositionEC).w;\\n\\\n}\\n\\\nvec4 getPolylineWindowCoordinates(vec4 position, vec4 previous, vec4 next, float expandDirection, float width, bool usePrevious, out float angle)\\n\\\n{\\n\\\nvec4 positionEC = czm_modelViewRelativeToEye * position;\\n\\\nvec4 prevEC = czm_modelViewRelativeToEye * previous;\\n\\\nvec4 nextEC = czm_modelViewRelativeToEye * next;\\n\\\nreturn getPolylineWindowCoordinatesEC(positionEC, prevEC, nextEC, expandDirection, width, usePrevious, angle);\\n\\\n}\\n\\\n\";\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport VertexFormat from \"../Core/VertexFormat.js\";\r\nimport PerInstanceFlatColorAppearanceFS from \"../Shaders/Appearances/PerInstanceFlatColorAppearanceFS.js\";\r\nimport PolylineColorAppearanceVS from \"../Shaders/Appearances/PolylineColorAppearanceVS.js\";\r\nimport PolylineCommon from \"../Shaders/PolylineCommon.js\";\r\nimport Appearance from \"./Appearance.js\";\r\n\r\nvar defaultVertexShaderSource =\r\n PolylineCommon + \"\\n\" + PolylineColorAppearanceVS;\r\nvar defaultFragmentShaderSource = PerInstanceFlatColorAppearanceFS;\r\n\r\nif (!FeatureDetection.isInternetExplorer()) {\r\n defaultVertexShaderSource =\r\n \"#define CLIP_POLYLINE \\n\" + defaultVertexShaderSource;\r\n}\r\n\r\n/**\r\n * An appearance for {@link GeometryInstance} instances with color attributes and\r\n * {@link PolylineGeometry} or {@link GroundPolylineGeometry}.\r\n * This allows several geometry instances, each with a different color, to\r\n * be drawn with the same {@link Primitive}.\r\n *\r\n * @alias PolylineColorAppearance\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.translucent=true] When true, the geometry is expected to appear translucent so {@link PolylineColorAppearance#renderState} has alpha blending enabled.\r\n * @param {String} [options.vertexShaderSource] Optional GLSL vertex shader source to override the default vertex shader.\r\n * @param {String} [options.fragmentShaderSource] Optional GLSL fragment shader source to override the default fragment shader.\r\n * @param {Object} [options.renderState] Optional render state to override the default render state.\r\n *\r\n * @example\r\n * // A solid white line segment\r\n * var primitive = new Cesium.Primitive({\r\n * geometryInstances : new Cesium.GeometryInstance({\r\n * geometry : new Cesium.PolylineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * 0.0, 0.0,\r\n * 5.0, 0.0\r\n * ]),\r\n * width : 10.0,\r\n * vertexFormat : Cesium.PolylineColorAppearance.VERTEX_FORMAT\r\n * }),\r\n * attributes : {\r\n * color : Cesium.ColorGeometryInstanceAttribute.fromColor(new Cesium.Color(1.0, 1.0, 1.0, 1.0))\r\n * }\r\n * }),\r\n * appearance : new Cesium.PolylineColorAppearance({\r\n * translucent : false\r\n * })\r\n * });\r\n */\r\nfunction PolylineColorAppearance(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var translucent = defaultValue(options.translucent, true);\r\n var closed = false;\r\n var vertexFormat = PolylineColorAppearance.VERTEX_FORMAT;\r\n\r\n /**\r\n * This property is part of the {@link Appearance} interface, but is not\r\n * used by {@link PolylineColorAppearance} since a fully custom fragment shader is used.\r\n *\r\n * @type Material\r\n *\r\n * @default undefined\r\n */\r\n this.material = undefined;\r\n\r\n /**\r\n * When true, the geometry is expected to appear translucent so\r\n * {@link PolylineColorAppearance#renderState} has alpha blending enabled.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.translucent = translucent;\r\n\r\n this._vertexShaderSource = defaultValue(\r\n options.vertexShaderSource,\r\n defaultVertexShaderSource\r\n );\r\n this._fragmentShaderSource = defaultValue(\r\n options.fragmentShaderSource,\r\n defaultFragmentShaderSource\r\n );\r\n this._renderState = Appearance.getDefaultRenderState(\r\n translucent,\r\n closed,\r\n options.renderState\r\n );\r\n this._closed = closed;\r\n\r\n // Non-derived members\r\n\r\n this._vertexFormat = vertexFormat;\r\n}\r\n\r\nObject.defineProperties(PolylineColorAppearance.prototype, {\r\n /**\r\n * The GLSL source code for the vertex shader.\r\n *\r\n * @memberof PolylineColorAppearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n vertexShaderSource: {\r\n get: function () {\r\n return this._vertexShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The GLSL source code for the fragment shader.\r\n *\r\n * @memberof PolylineColorAppearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n fragmentShaderSource: {\r\n get: function () {\r\n return this._fragmentShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The WebGL fixed-function state to use when rendering the geometry.\r\n *

\r\n * The render state can be explicitly defined when constructing a {@link PolylineColorAppearance}\r\n * instance, or it is set implicitly via {@link PolylineColorAppearance#translucent}.\r\n *

\r\n *\r\n * @memberof PolylineColorAppearance.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n renderState: {\r\n get: function () {\r\n return this._renderState;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the geometry is expected to be closed so\r\n * {@link PolylineColorAppearance#renderState} has backface culling enabled.\r\n * This is always false for PolylineColorAppearance.\r\n *\r\n * @memberof PolylineColorAppearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n closed: {\r\n get: function () {\r\n return this._closed;\r\n },\r\n },\r\n\r\n /**\r\n * The {@link VertexFormat} that this appearance instance is compatible with.\r\n * A geometry can have more vertex attributes and still be compatible - at a\r\n * potential performance cost - but it can't have less.\r\n *\r\n * @memberof PolylineColorAppearance.prototype\r\n *\r\n * @type VertexFormat\r\n * @readonly\r\n *\r\n * @default {@link PolylineColorAppearance.VERTEX_FORMAT}\r\n */\r\n vertexFormat: {\r\n get: function () {\r\n return this._vertexFormat;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * The {@link VertexFormat} that all {@link PolylineColorAppearance} instances\r\n * are compatible with. This requires only a position attribute.\r\n *\r\n * @type VertexFormat\r\n *\r\n * @constant\r\n */\r\nPolylineColorAppearance.VERTEX_FORMAT = VertexFormat.POSITION_ONLY;\r\n\r\n/**\r\n * Procedurally creates the full GLSL fragment shader source.\r\n *\r\n * @function\r\n *\r\n * @returns {String} The full GLSL fragment shader source.\r\n */\r\nPolylineColorAppearance.prototype.getFragmentShaderSource =\r\n Appearance.prototype.getFragmentShaderSource;\r\n\r\n/**\r\n * Determines if the geometry is translucent based on {@link PolylineColorAppearance#translucent}.\r\n *\r\n * @function\r\n *\r\n * @returns {Boolean} true if the appearance is translucent.\r\n */\r\nPolylineColorAppearance.prototype.isTranslucent =\r\n Appearance.prototype.isTranslucent;\r\n\r\n/**\r\n * Creates a render state. This is not the final render state instance; instead,\r\n * it can contain a subset of render state properties identical to the render state\r\n * created in the context.\r\n *\r\n * @function\r\n *\r\n * @returns {Object} The render state.\r\n */\r\nPolylineColorAppearance.prototype.getRenderState =\r\n Appearance.prototype.getRenderState;\r\nexport default PolylineColorAppearance;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec3 prevPosition3DHigh;\\n\\\nattribute vec3 prevPosition3DLow;\\n\\\nattribute vec3 nextPosition3DHigh;\\n\\\nattribute vec3 nextPosition3DLow;\\n\\\nattribute vec2 expandAndWidth;\\n\\\nattribute vec2 st;\\n\\\nattribute float batchId;\\n\\\nvarying float v_width;\\n\\\nvarying vec2 v_st;\\n\\\nvarying float v_polylineAngle;\\n\\\nvoid main()\\n\\\n{\\n\\\nfloat expandDir = expandAndWidth.x;\\n\\\nfloat width = abs(expandAndWidth.y) + 0.5;\\n\\\nbool usePrev = expandAndWidth.y < 0.0;\\n\\\nvec4 p = czm_computePosition();\\n\\\nvec4 prev = czm_computePrevPosition();\\n\\\nvec4 next = czm_computeNextPosition();\\n\\\nfloat angle;\\n\\\nvec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev, angle);\\n\\\ngl_Position = czm_viewportOrthographic * positionWC;\\n\\\nv_width = width;\\n\\\nv_st.s = st.s;\\n\\\nv_st.t = czm_writeNonPerspective(st.t, gl_Position.w);\\n\\\nv_polylineAngle = angle;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef VECTOR_TILE\\n\\\nuniform vec4 u_highlightColor;\\n\\\n#endif\\n\\\nvarying vec2 v_st;\\n\\\nvoid main()\\n\\\n{\\n\\\nczm_materialInput materialInput;\\n\\\nvec2 st = v_st;\\n\\\nst.t = czm_readNonPerspective(st.t, gl_FragCoord.w);\\n\\\nmaterialInput.s = st.s;\\n\\\nmaterialInput.st = st;\\n\\\nmaterialInput.str = vec3(st, 0.0);\\n\\\nczm_material material = czm_getMaterial(materialInput);\\n\\\ngl_FragColor = vec4(material.diffuse + material.emission, material.alpha);\\n\\\n#ifdef VECTOR_TILE\\n\\\ngl_FragColor *= u_highlightColor;\\n\\\n#endif\\n\\\nczm_writeLogDepth();\\n\\\n}\\n\\\n\";\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport VertexFormat from \"../Core/VertexFormat.js\";\r\nimport PolylineMaterialAppearanceVS from \"../Shaders/Appearances/PolylineMaterialAppearanceVS.js\";\r\nimport PolylineCommon from \"../Shaders/PolylineCommon.js\";\r\nimport PolylineFS from \"../Shaders/PolylineFS.js\";\r\nimport Appearance from \"./Appearance.js\";\r\nimport Material from \"./Material.js\";\r\n\r\nvar defaultVertexShaderSource =\r\n PolylineCommon + \"\\n\" + PolylineMaterialAppearanceVS;\r\nvar defaultFragmentShaderSource = PolylineFS;\r\n\r\nif (!FeatureDetection.isInternetExplorer()) {\r\n defaultVertexShaderSource =\r\n \"#define CLIP_POLYLINE \\n\" + defaultVertexShaderSource;\r\n}\r\n\r\n/**\r\n * An appearance for {@link PolylineGeometry} that supports shading with materials.\r\n *\r\n * @alias PolylineMaterialAppearance\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.translucent=true] When true, the geometry is expected to appear translucent so {@link PolylineMaterialAppearance#renderState} has alpha blending enabled.\r\n * @param {Material} [options.material=Material.ColorType] The material used to determine the fragment color.\r\n * @param {String} [options.vertexShaderSource] Optional GLSL vertex shader source to override the default vertex shader.\r\n * @param {String} [options.fragmentShaderSource] Optional GLSL fragment shader source to override the default fragment shader.\r\n * @param {Object} [options.renderState] Optional render state to override the default render state.\r\n *\r\n * @see {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}\r\n *\r\n * @example\r\n * var primitive = new Cesium.Primitive({\r\n * geometryInstances : new Cesium.GeometryInstance({\r\n * geometry : new Cesium.PolylineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * 0.0, 0.0,\r\n * 5.0, 0.0\r\n * ]),\r\n * width : 10.0,\r\n * vertexFormat : Cesium.PolylineMaterialAppearance.VERTEX_FORMAT\r\n * })\r\n * }),\r\n * appearance : new Cesium.PolylineMaterialAppearance({\r\n * material : Cesium.Material.fromType('Color')\r\n * })\r\n * });\r\n */\r\nfunction PolylineMaterialAppearance(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var translucent = defaultValue(options.translucent, true);\r\n var closed = false;\r\n var vertexFormat = PolylineMaterialAppearance.VERTEX_FORMAT;\r\n\r\n /**\r\n * The material used to determine the fragment color. Unlike other {@link PolylineMaterialAppearance}\r\n * properties, this is not read-only, so an appearance's material can change on the fly.\r\n *\r\n * @type Material\r\n *\r\n * @default {@link Material.ColorType}\r\n *\r\n * @see {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}\r\n */\r\n this.material = defined(options.material)\r\n ? options.material\r\n : Material.fromType(Material.ColorType);\r\n\r\n /**\r\n * When true, the geometry is expected to appear translucent so\r\n * {@link PolylineMaterialAppearance#renderState} has alpha blending enabled.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.translucent = translucent;\r\n\r\n this._vertexShaderSource = defaultValue(\r\n options.vertexShaderSource,\r\n defaultVertexShaderSource\r\n );\r\n this._fragmentShaderSource = defaultValue(\r\n options.fragmentShaderSource,\r\n defaultFragmentShaderSource\r\n );\r\n this._renderState = Appearance.getDefaultRenderState(\r\n translucent,\r\n closed,\r\n options.renderState\r\n );\r\n this._closed = closed;\r\n\r\n // Non-derived members\r\n\r\n this._vertexFormat = vertexFormat;\r\n}\r\n\r\nObject.defineProperties(PolylineMaterialAppearance.prototype, {\r\n /**\r\n * The GLSL source code for the vertex shader.\r\n *\r\n * @memberof PolylineMaterialAppearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n vertexShaderSource: {\r\n get: function () {\r\n var vs = this._vertexShaderSource;\r\n if (\r\n this.material.shaderSource.search(\r\n /varying\\s+float\\s+v_polylineAngle;/g\r\n ) !== -1\r\n ) {\r\n vs = \"#define POLYLINE_DASH\\n\" + vs;\r\n }\r\n return vs;\r\n },\r\n },\r\n\r\n /**\r\n * The GLSL source code for the fragment shader.\r\n *\r\n * @memberof PolylineMaterialAppearance.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n fragmentShaderSource: {\r\n get: function () {\r\n return this._fragmentShaderSource;\r\n },\r\n },\r\n\r\n /**\r\n * The WebGL fixed-function state to use when rendering the geometry.\r\n *

\r\n * The render state can be explicitly defined when constructing a {@link PolylineMaterialAppearance}\r\n * instance, or it is set implicitly via {@link PolylineMaterialAppearance#translucent}\r\n * and {@link PolylineMaterialAppearance#closed}.\r\n *

\r\n *\r\n * @memberof PolylineMaterialAppearance.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n renderState: {\r\n get: function () {\r\n return this._renderState;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the geometry is expected to be closed so\r\n * {@link PolylineMaterialAppearance#renderState} has backface culling enabled.\r\n * This is always false for PolylineMaterialAppearance.\r\n *\r\n * @memberof PolylineMaterialAppearance.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n closed: {\r\n get: function () {\r\n return this._closed;\r\n },\r\n },\r\n\r\n /**\r\n * The {@link VertexFormat} that this appearance instance is compatible with.\r\n * A geometry can have more vertex attributes and still be compatible - at a\r\n * potential performance cost - but it can't have less.\r\n *\r\n * @memberof PolylineMaterialAppearance.prototype\r\n *\r\n * @type VertexFormat\r\n * @readonly\r\n *\r\n * @default {@link PolylineMaterialAppearance.VERTEX_FORMAT}\r\n */\r\n vertexFormat: {\r\n get: function () {\r\n return this._vertexFormat;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * The {@link VertexFormat} that all {@link PolylineMaterialAppearance} instances\r\n * are compatible with. This requires position and st attributes.\r\n *\r\n * @type VertexFormat\r\n *\r\n * @constant\r\n */\r\nPolylineMaterialAppearance.VERTEX_FORMAT = VertexFormat.POSITION_AND_ST;\r\n\r\n/**\r\n * Procedurally creates the full GLSL fragment shader source. For {@link PolylineMaterialAppearance},\r\n * this is derived from {@link PolylineMaterialAppearance#fragmentShaderSource} and {@link PolylineMaterialAppearance#material}.\r\n *\r\n * @function\r\n *\r\n * @returns {String} The full GLSL fragment shader source.\r\n */\r\nPolylineMaterialAppearance.prototype.getFragmentShaderSource =\r\n Appearance.prototype.getFragmentShaderSource;\r\n\r\n/**\r\n * Determines if the geometry is translucent based on {@link PolylineMaterialAppearance#translucent} and {@link Material#isTranslucent}.\r\n *\r\n * @function\r\n *\r\n * @returns {Boolean} true if the appearance is translucent.\r\n */\r\nPolylineMaterialAppearance.prototype.isTranslucent =\r\n Appearance.prototype.isTranslucent;\r\n\r\n/**\r\n * Creates a render state. This is not the final render state instance; instead,\r\n * it can contain a subset of render state properties identical to the render state\r\n * created in the context.\r\n *\r\n * @function\r\n *\r\n * @returns {Object} The render state.\r\n */\r\nPolylineMaterialAppearance.prototype.getRenderState =\r\n Appearance.prototype.getRenderState;\r\nexport default PolylineMaterialAppearance;\r\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport GeometryInstanceAttribute from \"../Core/GeometryInstanceAttribute.js\";\r\nimport GroundPolylineGeometry from \"../Core/GroundPolylineGeometry.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport PolylineShadowVolumeFS from \"../Shaders/PolylineShadowVolumeFS.js\";\r\nimport PolylineShadowVolumeMorphFS from \"../Shaders/PolylineShadowVolumeMorphFS.js\";\r\nimport PolylineShadowVolumeMorphVS from \"../Shaders/PolylineShadowVolumeMorphVS.js\";\r\nimport PolylineShadowVolumeVS from \"../Shaders/PolylineShadowVolumeVS.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport ClassificationType from \"./ClassificationType.js\";\r\nimport CullFace from \"./CullFace.js\";\r\nimport PolylineColorAppearance from \"./PolylineColorAppearance.js\";\r\nimport PolylineMaterialAppearance from \"./PolylineMaterialAppearance.js\";\r\nimport Primitive from \"./Primitive.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport StencilConstants from \"./StencilConstants.js\";\r\nimport StencilFunction from \"./StencilFunction.js\";\r\nimport StencilOperation from \"./StencilOperation.js\";\r\n\r\n/**\r\n * A GroundPolylinePrimitive represents a polyline draped over the terrain or 3D Tiles in the {@link Scene}.\r\n *

\r\n * Only to be used with GeometryInstances containing {@link GroundPolylineGeometry}.\r\n *

\r\n *\r\n * @alias GroundPolylinePrimitive\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Array|GeometryInstance} [options.geometryInstances] GeometryInstances containing GroundPolylineGeometry\r\n * @param {Appearance} [options.appearance] The Appearance used to render the polyline. Defaults to a white color {@link Material} on a {@link PolylineMaterialAppearance}.\r\n * @param {Boolean} [options.show=true] Determines if this primitive will be shown.\r\n * @param {Boolean} [options.interleave=false] When true, geometry vertex attributes are interleaved, which can slightly improve rendering performance but increases load time.\r\n * @param {Boolean} [options.releaseGeometryInstances=true] When true, the primitive does not keep a reference to the input geometryInstances to save memory.\r\n * @param {Boolean} [options.allowPicking=true] When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.\r\n * @param {Boolean} [options.asynchronous=true] Determines if the primitive will be created asynchronously or block until ready. If false initializeTerrainHeights() must be called first.\r\n * @param {ClassificationType} [options.classificationType=ClassificationType.BOTH] Determines whether terrain, 3D Tiles or both will be classified.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.\r\n * @param {Boolean} [options.debugShowShadowVolume=false] For debugging only. Determines if the shadow volume for each geometry in the primitive is drawn. Must be true on creation to have effect.\r\n *\r\n * @example\r\n * // 1. Draw a polyline on terrain with a basic color material\r\n *\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.GroundPolylineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * -112.1340164450331, 36.05494287836128,\r\n * -112.08821010582645, 36.097804071380715\r\n * ]),\r\n * width : 4.0\r\n * }),\r\n * id : 'object returned when this instance is picked and to get/set per-instance attributes'\r\n * });\r\n *\r\n * scene.groundPrimitives.add(new Cesium.GroundPolylinePrimitive({\r\n * geometryInstances : instance,\r\n * appearance : new Cesium.PolylineMaterialAppearance()\r\n * }));\r\n *\r\n * // 2. Draw a looped polyline on terrain with per-instance color and a distance display condition.\r\n * // Distance display conditions for polylines on terrain are based on an approximate terrain height\r\n * // instead of true terrain height.\r\n *\r\n * var instance = new Cesium.GeometryInstance({\r\n * geometry : new Cesium.GroundPolylineGeometry({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * -112.1340164450331, 36.05494287836128,\r\n * -112.08821010582645, 36.097804071380715,\r\n * -112.13296079730024, 36.168769146801104\r\n * ]),\r\n * loop : true,\r\n * width : 4.0\r\n * }),\r\n * attributes : {\r\n * color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromCssColorString('green').withAlpha(0.7)),\r\n * distanceDisplayCondition : new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(1000, 30000)\r\n * },\r\n * id : 'object returned when this instance is picked and to get/set per-instance attributes'\r\n * });\r\n *\r\n * scene.groundPrimitives.add(new Cesium.GroundPolylinePrimitive({\r\n * geometryInstances : instance,\r\n * appearance : new Cesium.PolylineColorAppearance()\r\n * }));\r\n */\r\nfunction GroundPolylinePrimitive(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * The geometry instances rendered with this primitive. This may\r\n * be undefined if options.releaseGeometryInstances\r\n * is true when the primitive is constructed.\r\n *

\r\n * Changing this property after the primitive is rendered has no effect.\r\n *

\r\n *\r\n * @readonly\r\n * @type {Array|GeometryInstance}\r\n *\r\n * @default undefined\r\n */\r\n this.geometryInstances = options.geometryInstances;\r\n this._hasPerInstanceColors = true;\r\n\r\n var appearance = options.appearance;\r\n if (!defined(appearance)) {\r\n appearance = new PolylineMaterialAppearance();\r\n }\r\n /**\r\n * The {@link Appearance} used to shade this primitive. Each geometry\r\n * instance is shaded with the same appearance. Some appearances, like\r\n * {@link PolylineColorAppearance} allow giving each instance unique\r\n * properties.\r\n *\r\n * @type Appearance\r\n *\r\n * @default undefined\r\n */\r\n this.appearance = appearance;\r\n\r\n /**\r\n * Determines if the primitive will be shown. This affects all geometry\r\n * instances in the primitive.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * Determines whether terrain, 3D Tiles or both will be classified.\r\n *\r\n * @type {ClassificationType}\r\n *\r\n * @default ClassificationType.BOTH\r\n */\r\n this.classificationType = defaultValue(\r\n options.classificationType,\r\n ClassificationType.BOTH\r\n );\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n\r\n // Shadow volume is shown by removing a discard in the shader, so this isn't toggleable.\r\n this._debugShowShadowVolume = defaultValue(\r\n options.debugShowShadowVolume,\r\n false\r\n );\r\n\r\n this._primitiveOptions = {\r\n geometryInstances: undefined,\r\n appearance: undefined,\r\n vertexCacheOptimize: false,\r\n interleave: defaultValue(options.interleave, false),\r\n releaseGeometryInstances: defaultValue(\r\n options.releaseGeometryInstances,\r\n true\r\n ),\r\n allowPicking: defaultValue(options.allowPicking, true),\r\n asynchronous: defaultValue(options.asynchronous, true),\r\n compressVertices: false,\r\n _createShaderProgramFunction: undefined,\r\n _createCommandsFunction: undefined,\r\n _updateAndQueueCommandsFunction: undefined,\r\n };\r\n\r\n // Used when inserting in an OrderedPrimitiveCollection\r\n this._zIndex = undefined;\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._primitive = undefined;\r\n\r\n this._sp = undefined;\r\n this._sp2D = undefined;\r\n this._spMorph = undefined;\r\n\r\n this._renderState = getRenderState(false);\r\n this._renderState3DTiles = getRenderState(true);\r\n\r\n this._renderStateMorph = RenderState.fromCache({\r\n cull: {\r\n enabled: true,\r\n face: CullFace.FRONT, // Geometry is \"inverted,\" so cull front when materials on volume instead of on terrain (morph)\r\n },\r\n depthTest: {\r\n enabled: true,\r\n },\r\n blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,\r\n depthMask: false,\r\n });\r\n}\r\n\r\nObject.defineProperties(GroundPolylinePrimitive.prototype, {\r\n /**\r\n * Determines if geometry vertex attributes are interleaved, which can slightly improve rendering performance.\r\n *\r\n * @memberof GroundPolylinePrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n interleave: {\r\n get: function () {\r\n return this._primitiveOptions.interleave;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the primitive does not keep a reference to the input geometryInstances to save memory.\r\n *\r\n * @memberof GroundPolylinePrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n releaseGeometryInstances: {\r\n get: function () {\r\n return this._primitiveOptions.releaseGeometryInstances;\r\n },\r\n },\r\n\r\n /**\r\n * When true, each geometry instance will only be pickable with {@link Scene#pick}. When false, GPU memory is saved.\r\n *\r\n * @memberof GroundPolylinePrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n allowPicking: {\r\n get: function () {\r\n return this._primitiveOptions.allowPicking;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the geometry instances will be created and batched on a web worker.\r\n *\r\n * @memberof GroundPolylinePrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n asynchronous: {\r\n get: function () {\r\n return this._primitiveOptions.asynchronous;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the primitive is complete and ready to render. If this property is\r\n * true, the primitive will be rendered the next time that {@link GroundPolylinePrimitive#update}\r\n * is called.\r\n *\r\n * @memberof GroundPolylinePrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof GroundPolylinePrimitive.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * If true, draws the shadow volume for each geometry in the primitive.\r\n *

\r\n *\r\n * @memberof GroundPolylinePrimitive.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n debugShowShadowVolume: {\r\n get: function () {\r\n return this._debugShowShadowVolume;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Initializes the minimum and maximum terrain heights. This only needs to be called if you are creating the\r\n * GroundPolylinePrimitive synchronously.\r\n *\r\n * @returns {Promise} A promise that will resolve once the terrain heights have been loaded.\r\n */\r\nGroundPolylinePrimitive.initializeTerrainHeights = function () {\r\n return ApproximateTerrainHeights.initialize();\r\n};\r\n\r\nfunction createShaderProgram(groundPolylinePrimitive, frameState, appearance) {\r\n var context = frameState.context;\r\n var primitive = groundPolylinePrimitive._primitive;\r\n var attributeLocations = primitive._attributeLocations;\r\n\r\n var vs = primitive._batchTable.getVertexShaderCallback()(\r\n PolylineShadowVolumeVS\r\n );\r\n vs = Primitive._appendShowToShader(primitive, vs);\r\n vs = Primitive._appendDistanceDisplayConditionToShader(primitive, vs);\r\n vs = Primitive._modifyShaderPosition(\r\n groundPolylinePrimitive,\r\n vs,\r\n frameState.scene3DOnly\r\n );\r\n\r\n var vsMorph = primitive._batchTable.getVertexShaderCallback()(\r\n PolylineShadowVolumeMorphVS\r\n );\r\n vsMorph = Primitive._appendShowToShader(primitive, vsMorph);\r\n vsMorph = Primitive._appendDistanceDisplayConditionToShader(\r\n primitive,\r\n vsMorph\r\n );\r\n vsMorph = Primitive._modifyShaderPosition(\r\n groundPolylinePrimitive,\r\n vsMorph,\r\n frameState.scene3DOnly\r\n );\r\n\r\n // Access pick color from fragment shader.\r\n // Helps with varying budget.\r\n var fs = primitive._batchTable.getVertexShaderCallback()(\r\n PolylineShadowVolumeFS\r\n );\r\n\r\n var vsDefines = [\r\n \"GLOBE_MINIMUM_ALTITUDE \" +\r\n frameState.mapProjection.ellipsoid.minimumRadius.toFixed(1),\r\n ];\r\n var colorDefine = \"\";\r\n var materialShaderSource = \"\";\r\n if (defined(appearance.material)) {\r\n materialShaderSource = defined(appearance.material)\r\n ? appearance.material.shaderSource\r\n : \"\";\r\n\r\n // Check for use of v_width and v_polylineAngle in material shader\r\n // to determine whether these varyings should be active in the vertex shader.\r\n if (\r\n materialShaderSource.search(/varying\\s+float\\s+v_polylineAngle;/g) !== -1\r\n ) {\r\n vsDefines.push(\"ANGLE_VARYING\");\r\n }\r\n if (materialShaderSource.search(/varying\\s+float\\s+v_width;/g) !== -1) {\r\n vsDefines.push(\"WIDTH_VARYING\");\r\n }\r\n } else {\r\n colorDefine = \"PER_INSTANCE_COLOR\";\r\n }\r\n\r\n vsDefines.push(colorDefine);\r\n var fsDefines = groundPolylinePrimitive.debugShowShadowVolume\r\n ? [\"DEBUG_SHOW_VOLUME\", colorDefine]\r\n : [colorDefine];\r\n\r\n var vsColor3D = new ShaderSource({\r\n defines: vsDefines,\r\n sources: [vs],\r\n });\r\n var fsColor3D = new ShaderSource({\r\n defines: fsDefines,\r\n sources: [materialShaderSource, fs],\r\n });\r\n groundPolylinePrimitive._sp = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: primitive._sp,\r\n vertexShaderSource: vsColor3D,\r\n fragmentShaderSource: fsColor3D,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n // Derive 2D/CV\r\n var colorProgram2D = context.shaderCache.getDerivedShaderProgram(\r\n groundPolylinePrimitive._sp,\r\n \"2dColor\"\r\n );\r\n if (!defined(colorProgram2D)) {\r\n var vsColor2D = new ShaderSource({\r\n defines: vsDefines.concat([\"COLUMBUS_VIEW_2D\"]),\r\n sources: [vs],\r\n });\r\n colorProgram2D = context.shaderCache.createDerivedShaderProgram(\r\n groundPolylinePrimitive._sp,\r\n \"2dColor\",\r\n {\r\n context: context,\r\n shaderProgram: groundPolylinePrimitive._sp2D,\r\n vertexShaderSource: vsColor2D,\r\n fragmentShaderSource: fsColor3D,\r\n attributeLocations: attributeLocations,\r\n }\r\n );\r\n }\r\n groundPolylinePrimitive._sp2D = colorProgram2D;\r\n\r\n // Derive Morph\r\n var colorProgramMorph = context.shaderCache.getDerivedShaderProgram(\r\n groundPolylinePrimitive._sp,\r\n \"MorphColor\"\r\n );\r\n if (!defined(colorProgramMorph)) {\r\n var vsColorMorph = new ShaderSource({\r\n defines: vsDefines.concat([\r\n \"MAX_TERRAIN_HEIGHT \" +\r\n ApproximateTerrainHeights._defaultMaxTerrainHeight.toFixed(1),\r\n ]),\r\n sources: [vsMorph],\r\n });\r\n\r\n fs = primitive._batchTable.getVertexShaderCallback()(\r\n PolylineShadowVolumeMorphFS\r\n );\r\n var fsColorMorph = new ShaderSource({\r\n defines: fsDefines,\r\n sources: [materialShaderSource, fs],\r\n });\r\n colorProgramMorph = context.shaderCache.createDerivedShaderProgram(\r\n groundPolylinePrimitive._sp,\r\n \"MorphColor\",\r\n {\r\n context: context,\r\n shaderProgram: groundPolylinePrimitive._spMorph,\r\n vertexShaderSource: vsColorMorph,\r\n fragmentShaderSource: fsColorMorph,\r\n attributeLocations: attributeLocations,\r\n }\r\n );\r\n }\r\n groundPolylinePrimitive._spMorph = colorProgramMorph;\r\n}\r\n\r\nfunction getRenderState(mask3DTiles) {\r\n return RenderState.fromCache({\r\n cull: {\r\n enabled: true, // prevent double-draw. Geometry is \"inverted\" (reversed winding order) so we're drawing backfaces.\r\n },\r\n blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,\r\n depthMask: false,\r\n stencilTest: {\r\n enabled: mask3DTiles,\r\n frontFunction: StencilFunction.EQUAL,\r\n frontOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.KEEP,\r\n zPass: StencilOperation.KEEP,\r\n },\r\n backFunction: StencilFunction.EQUAL,\r\n backOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.KEEP,\r\n zPass: StencilOperation.KEEP,\r\n },\r\n reference: StencilConstants.CESIUM_3D_TILE_MASK,\r\n mask: StencilConstants.CESIUM_3D_TILE_MASK,\r\n },\r\n });\r\n}\r\n\r\nfunction createCommands(\r\n groundPolylinePrimitive,\r\n appearance,\r\n material,\r\n translucent,\r\n colorCommands,\r\n pickCommands\r\n) {\r\n var primitive = groundPolylinePrimitive._primitive;\r\n var length = primitive._va.length;\r\n colorCommands.length = length;\r\n pickCommands.length = length;\r\n\r\n var isPolylineColorAppearance = appearance instanceof PolylineColorAppearance;\r\n\r\n var materialUniforms = isPolylineColorAppearance ? {} : material._uniforms;\r\n var uniformMap = primitive._batchTable.getUniformMapCallback()(\r\n materialUniforms\r\n );\r\n\r\n for (var i = 0; i < length; i++) {\r\n var vertexArray = primitive._va[i];\r\n\r\n var command = colorCommands[i];\r\n if (!defined(command)) {\r\n command = colorCommands[i] = new DrawCommand({\r\n owner: groundPolylinePrimitive,\r\n primitiveType: primitive._primitiveType,\r\n });\r\n }\r\n\r\n command.vertexArray = vertexArray;\r\n command.renderState = groundPolylinePrimitive._renderState;\r\n command.shaderProgram = groundPolylinePrimitive._sp;\r\n command.uniformMap = uniformMap;\r\n command.pass = Pass.TERRAIN_CLASSIFICATION;\r\n command.pickId = \"czm_batchTable_pickColor(v_endPlaneNormalEcAndBatchId.w)\";\r\n\r\n var derivedTilesetCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.tileset\r\n );\r\n derivedTilesetCommand.renderState =\r\n groundPolylinePrimitive._renderState3DTiles;\r\n derivedTilesetCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n command.derivedCommands.tileset = derivedTilesetCommand;\r\n\r\n // derive for 2D\r\n var derived2DCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.color2D\r\n );\r\n derived2DCommand.shaderProgram = groundPolylinePrimitive._sp2D;\r\n command.derivedCommands.color2D = derived2DCommand;\r\n\r\n var derived2DTilesetCommand = DrawCommand.shallowClone(\r\n derivedTilesetCommand,\r\n derivedTilesetCommand.derivedCommands.color2D\r\n );\r\n derived2DTilesetCommand.shaderProgram = groundPolylinePrimitive._sp2D;\r\n derivedTilesetCommand.derivedCommands.color2D = derived2DTilesetCommand;\r\n\r\n // derive for Morph\r\n var derivedMorphCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.colorMorph\r\n );\r\n derivedMorphCommand.renderState = groundPolylinePrimitive._renderStateMorph;\r\n derivedMorphCommand.shaderProgram = groundPolylinePrimitive._spMorph;\r\n derivedMorphCommand.pickId = \"czm_batchTable_pickColor(v_batchId)\";\r\n command.derivedCommands.colorMorph = derivedMorphCommand;\r\n }\r\n}\r\n\r\nfunction updateAndQueueCommand(\r\n groundPolylinePrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n) {\r\n // Use derived appearance command for morph and 2D\r\n if (frameState.mode === SceneMode.MORPHING) {\r\n command = command.derivedCommands.colorMorph;\r\n } else if (frameState.mode !== SceneMode.SCENE3D) {\r\n command = command.derivedCommands.color2D;\r\n }\r\n command.modelMatrix = modelMatrix;\r\n command.boundingVolume = boundingVolume;\r\n command.cull = cull;\r\n command.debugShowBoundingVolume = debugShowBoundingVolume;\r\n\r\n frameState.commandList.push(command);\r\n}\r\n\r\nfunction updateAndQueueCommands(\r\n groundPolylinePrimitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume\r\n) {\r\n var primitive = groundPolylinePrimitive._primitive;\r\n\r\n Primitive._updateBoundingVolumes(primitive, frameState, modelMatrix); // Expected to be identity - GroundPrimitives don't support other model matrices\r\n\r\n var boundingSpheres;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n boundingSpheres = primitive._boundingSphereWC;\r\n } else if (frameState.mode === SceneMode.COLUMBUS_VIEW) {\r\n boundingSpheres = primitive._boundingSphereCV;\r\n } else if (\r\n frameState.mode === SceneMode.SCENE2D &&\r\n defined(primitive._boundingSphere2D)\r\n ) {\r\n boundingSpheres = primitive._boundingSphere2D;\r\n } else if (defined(primitive._boundingSphereMorph)) {\r\n boundingSpheres = primitive._boundingSphereMorph;\r\n }\r\n\r\n var morphing = frameState.mode === SceneMode.MORPHING;\r\n var classificationType = groundPolylinePrimitive.classificationType;\r\n var queueTerrainCommands =\r\n classificationType !== ClassificationType.CESIUM_3D_TILE;\r\n var queue3DTilesCommands =\r\n classificationType !== ClassificationType.TERRAIN && !morphing;\r\n\r\n var command;\r\n var passes = frameState.passes;\r\n if (passes.render || (passes.pick && primitive.allowPicking)) {\r\n var colorLength = colorCommands.length;\r\n for (var j = 0; j < colorLength; ++j) {\r\n var boundingVolume = boundingSpheres[j];\r\n if (queueTerrainCommands) {\r\n command = colorCommands[j];\r\n updateAndQueueCommand(\r\n groundPolylinePrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n );\r\n }\r\n if (queue3DTilesCommands) {\r\n command = colorCommands[j].derivedCommands.tileset;\r\n updateAndQueueCommand(\r\n groundPolylinePrimitive,\r\n command,\r\n frameState,\r\n modelMatrix,\r\n cull,\r\n boundingVolume,\r\n debugShowBoundingVolume\r\n );\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Called when {@link Viewer} or {@link CesiumWidget} render the scene to\r\n * get the draw commands needed to render this primitive.\r\n *

\r\n * Do not call this function directly. This is documented just to\r\n * list the exceptions that may be propagated when the scene is rendered:\r\n *

\r\n *\r\n * @exception {DeveloperError} For synchronous GroundPolylinePrimitives, you must call GroundPolylinePrimitives.initializeTerrainHeights() and wait for the returned promise to resolve.\r\n * @exception {DeveloperError} All GeometryInstances must have color attributes to use PolylineColorAppearance with GroundPolylinePrimitive.\r\n */\r\nGroundPolylinePrimitive.prototype.update = function (frameState) {\r\n if (!defined(this._primitive) && !defined(this.geometryInstances)) {\r\n return;\r\n }\r\n\r\n if (!ApproximateTerrainHeights.initialized) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.asynchronous) {\r\n throw new DeveloperError(\r\n \"For synchronous GroundPolylinePrimitives, you must call GroundPolylinePrimitives.initializeTerrainHeights() and wait for the returned promise to resolve.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n GroundPolylinePrimitive.initializeTerrainHeights();\r\n return;\r\n }\r\n\r\n var i;\r\n\r\n var that = this;\r\n var primitiveOptions = this._primitiveOptions;\r\n if (!defined(this._primitive)) {\r\n var geometryInstances = Array.isArray(this.geometryInstances)\r\n ? this.geometryInstances\r\n : [this.geometryInstances];\r\n var geometryInstancesLength = geometryInstances.length;\r\n var groundInstances = new Array(geometryInstancesLength);\r\n\r\n var attributes;\r\n\r\n // Check if each instance has a color attribute.\r\n for (i = 0; i < geometryInstancesLength; ++i) {\r\n attributes = geometryInstances[i].attributes;\r\n if (!defined(attributes) || !defined(attributes.color)) {\r\n this._hasPerInstanceColors = false;\r\n break;\r\n }\r\n }\r\n\r\n for (i = 0; i < geometryInstancesLength; ++i) {\r\n var geometryInstance = geometryInstances[i];\r\n attributes = {};\r\n var instanceAttributes = geometryInstance.attributes;\r\n for (var attributeKey in instanceAttributes) {\r\n if (instanceAttributes.hasOwnProperty(attributeKey)) {\r\n attributes[attributeKey] = instanceAttributes[attributeKey];\r\n }\r\n }\r\n\r\n // Automatically create line width attribute if not already given\r\n if (!defined(attributes.width)) {\r\n attributes.width = new GeometryInstanceAttribute({\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 1.0,\r\n value: [geometryInstance.geometry.width],\r\n });\r\n }\r\n\r\n // Update each geometry for framestate.scene3DOnly = true and projection\r\n geometryInstance.geometry._scene3DOnly = frameState.scene3DOnly;\r\n GroundPolylineGeometry.setProjectionAndEllipsoid(\r\n geometryInstance.geometry,\r\n frameState.mapProjection\r\n );\r\n\r\n groundInstances[i] = new GeometryInstance({\r\n geometry: geometryInstance.geometry,\r\n attributes: attributes,\r\n id: geometryInstance.id,\r\n pickPrimitive: that,\r\n });\r\n }\r\n\r\n primitiveOptions.geometryInstances = groundInstances;\r\n primitiveOptions.appearance = this.appearance;\r\n\r\n primitiveOptions._createShaderProgramFunction = function (\r\n primitive,\r\n frameState,\r\n appearance\r\n ) {\r\n createShaderProgram(that, frameState, appearance);\r\n };\r\n primitiveOptions._createCommandsFunction = function (\r\n primitive,\r\n appearance,\r\n material,\r\n translucent,\r\n twoPasses,\r\n colorCommands,\r\n pickCommands\r\n ) {\r\n createCommands(\r\n that,\r\n appearance,\r\n material,\r\n translucent,\r\n colorCommands,\r\n pickCommands\r\n );\r\n };\r\n primitiveOptions._updateAndQueueCommandsFunction = function (\r\n primitive,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume,\r\n twoPasses\r\n ) {\r\n updateAndQueueCommands(\r\n that,\r\n frameState,\r\n colorCommands,\r\n pickCommands,\r\n modelMatrix,\r\n cull,\r\n debugShowBoundingVolume\r\n );\r\n };\r\n\r\n this._primitive = new Primitive(primitiveOptions);\r\n this._primitive.readyPromise.then(function (primitive) {\r\n that._ready = true;\r\n\r\n if (that.releaseGeometryInstances) {\r\n that.geometryInstances = undefined;\r\n }\r\n\r\n var error = primitive._error;\r\n if (!defined(error)) {\r\n that._readyPromise.resolve(that);\r\n } else {\r\n that._readyPromise.reject(error);\r\n }\r\n });\r\n }\r\n\r\n if (\r\n this.appearance instanceof PolylineColorAppearance &&\r\n !this._hasPerInstanceColors\r\n ) {\r\n throw new DeveloperError(\r\n \"All GeometryInstances must have color attributes to use PolylineColorAppearance with GroundPolylinePrimitive.\"\r\n );\r\n }\r\n\r\n this._primitive.appearance = this.appearance;\r\n this._primitive.show = this.show;\r\n this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;\r\n this._primitive.update(frameState);\r\n};\r\n\r\n/**\r\n * Returns the modifiable per-instance attributes for a {@link GeometryInstance}.\r\n *\r\n * @param {*} id The id of the {@link GeometryInstance}.\r\n * @returns {Object} The typed array in the attribute's format or undefined if the is no instance with id.\r\n *\r\n * @exception {DeveloperError} must call update before calling getGeometryInstanceAttributes.\r\n *\r\n * @example\r\n * var attributes = primitive.getGeometryInstanceAttributes('an id');\r\n * attributes.color = Cesium.ColorGeometryInstanceAttribute.toValue(Cesium.Color.AQUA);\r\n * attributes.show = Cesium.ShowGeometryInstanceAttribute.toValue(true);\r\n */\r\nGroundPolylinePrimitive.prototype.getGeometryInstanceAttributes = function (\r\n id\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(this._primitive)) {\r\n throw new DeveloperError(\r\n \"must call update before calling getGeometryInstanceAttributes\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return this._primitive.getGeometryInstanceAttributes(id);\r\n};\r\n\r\n/**\r\n * Checks if the given Scene supports GroundPolylinePrimitives.\r\n * GroundPolylinePrimitives require support for the WEBGL_depth_texture extension.\r\n *\r\n * @param {Scene} scene The current scene.\r\n * @returns {Boolean} Whether or not the current scene supports GroundPolylinePrimitives.\r\n */\r\nGroundPolylinePrimitive.isSupported = function (scene) {\r\n return scene.frameState.context.depthTexture;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see GroundPolylinePrimitive#destroy\r\n */\r\nGroundPolylinePrimitive.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * e = e && e.destroy();\r\n *\r\n * @see GroundPolylinePrimitive#isDestroyed\r\n */\r\nGroundPolylinePrimitive.prototype.destroy = function () {\r\n this._primitive = this._primitive && this._primitive.destroy();\r\n this._sp = this._sp && this._sp.destroy();\r\n\r\n // Derived programs, destroyed above if they existed.\r\n this._sp2D = undefined;\r\n this._spMorph = undefined;\r\n\r\n return destroyObject(this);\r\n};\r\nexport default GroundPolylinePrimitive;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultRepeat = new Cartesian2(1, 1);\r\nvar defaultTransparent = false;\r\nvar defaultColor = Color.WHITE;\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to image {@link Material} uniforms.\r\n * @alias ImageMaterialProperty\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Property|String|HTMLImageElement|HTMLCanvasElement|HTMLVideoElement} [options.image] A Property specifying the Image, URL, Canvas, or Video.\r\n * @param {Property|Cartesian2} [options.repeat=new Cartesian2(1.0, 1.0)] A {@link Cartesian2} Property specifying the number of times the image repeats in each direction.\r\n * @param {Property|Color} [options.color=Color.WHITE] The color applied to the image\r\n * @param {Property|Boolean} [options.transparent=false] Set to true when the image has transparency (for example, when a png has transparent sections)\r\n */\r\nfunction ImageMaterialProperty(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._definitionChanged = new Event();\r\n this._image = undefined;\r\n this._imageSubscription = undefined;\r\n this._repeat = undefined;\r\n this._repeatSubscription = undefined;\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n this._transparent = undefined;\r\n this._transparentSubscription = undefined;\r\n\r\n this.image = options.image;\r\n this.repeat = options.repeat;\r\n this.color = options.color;\r\n this.transparent = options.transparent;\r\n}\r\n\r\nObject.defineProperties(ImageMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof ImageMaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n Property.isConstant(this._image) && Property.isConstant(this._repeat)\r\n );\r\n },\r\n },\r\n\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof ImageMaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the Property specifying Image, URL, Canvas, or Video to use.\r\n * @memberof ImageMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n */\r\n image: createPropertyDescriptor(\"image\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying the number of times the image repeats in each direction.\r\n * @memberof ImageMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default new Cartesian2(1, 1)\r\n */\r\n repeat: createPropertyDescriptor(\"repeat\"),\r\n\r\n /**\r\n * Gets or sets the Color Property specifying the desired color applied to the image.\r\n * @memberof ImageMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n\r\n /**\r\n * Gets or sets the Boolean Property specifying whether the image has transparency\r\n * @memberof ImageMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n transparent: createPropertyDescriptor(\"transparent\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nImageMaterialProperty.prototype.getType = function (time) {\r\n return \"Image\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nImageMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n\r\n result.image = Property.getValueOrUndefined(this._image, time);\r\n result.repeat = Property.getValueOrClonedDefault(\r\n this._repeat,\r\n time,\r\n defaultRepeat,\r\n result.repeat\r\n );\r\n result.color = Property.getValueOrClonedDefault(\r\n this._color,\r\n time,\r\n defaultColor,\r\n result.color\r\n );\r\n if (Property.getValueOrDefault(this._transparent, time, defaultTransparent)) {\r\n result.color.alpha = Math.min(0.99, result.color.alpha);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nImageMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (other instanceof ImageMaterialProperty &&\r\n Property.equals(this._image, other._image) &&\r\n Property.equals(this._repeat, other._repeat) &&\r\n Property.equals(this._color, other._color) &&\r\n Property.equals(this._transparent, other._transparent))\r\n );\r\n};\r\nexport default ImageMaterialProperty;\r\n","import Color from \"../Core/Color.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport ImageMaterialProperty from \"./ImageMaterialProperty.js\";\r\n\r\nfunction createMaterialProperty(value) {\r\n if (value instanceof Color) {\r\n return new ColorMaterialProperty(value);\r\n }\r\n\r\n if (\r\n typeof value === \"string\" ||\r\n value instanceof Resource ||\r\n value instanceof HTMLCanvasElement ||\r\n value instanceof HTMLVideoElement\r\n ) {\r\n var result = new ImageMaterialProperty();\r\n result.image = value;\r\n return result;\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\"Unable to infer material type: \" + value);\r\n //>>includeEnd('debug');\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction createMaterialPropertyDescriptor(name, configurable) {\r\n return createPropertyDescriptor(name, configurable, createMaterialProperty);\r\n}\r\nexport default createMaterialPropertyDescriptor;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} BoxGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the BoxGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the box.\r\n * @property {Property | Cartesian3} [dimensions] A {@link Cartesian3} Property specifying the length, width, and height of the box.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height from the entity position is relative to.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the box is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the box.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the box is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the box casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this box will be displayed.\r\n *\r\n */\r\n\r\n/**\r\n * Describes a box. The center position and orientation are determined by the containing {@link Entity}.\r\n *\r\n * @alias BoxGraphics\r\n * @constructor\r\n *\r\n * @param {BoxGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Box.html|Cesium Sandcastle Box Demo}\r\n */\r\nfunction BoxGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._dimensions = undefined;\r\n this._dimensionsSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(BoxGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the box.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets {@link Cartesian3} Property property specifying the length, width, and height of the box.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n dimensions: createPropertyDescriptor(\"dimensions\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the box is filled with the provided material.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the material used to fill the box.\r\n * @memberof BoxGraphics.prototype\r\n * @type {MaterialProperty|undefined}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the box is outlined.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the box\r\n * casts or receives shadows from light sources.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this box will be displayed.\r\n * @memberof BoxGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {BoxGraphics} [result] The object onto which to store the result.\r\n * @returns {BoxGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nBoxGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new BoxGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.dimensions = this.dimensions;\r\n result.heightReference = this.heightReference;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {BoxGraphics} source The object to be merged into this object.\r\n */\r\nBoxGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.dimensions = defaultValue(this.dimensions, source.dimensions);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n};\r\nexport default BoxGraphics;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\n\r\n/**\r\n * The interface for all {@link Property} objects that define a world\r\n * location as a {@link Cartesian3} with an associated {@link ReferenceFrame}.\r\n * This type defines an interface and cannot be instantiated directly.\r\n *\r\n * @alias PositionProperty\r\n * @constructor\r\n * @abstract\r\n *\r\n * @see CompositePositionProperty\r\n * @see ConstantPositionProperty\r\n * @see SampledPositionProperty\r\n * @see TimeIntervalCollectionPositionProperty\r\n */\r\nfunction PositionProperty() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\nObject.defineProperties(PositionProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof PositionProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof PositionProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets the reference frame that the position is defined in.\r\n * @memberof PositionProperty.prototype\r\n * @type {ReferenceFrame}\r\n */\r\n referenceFrame: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time in the fixed frame.\r\n * @function\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPositionProperty.prototype.getValue = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Gets the value of the property at the provided time and in the provided reference frame.\r\n * @function\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {ReferenceFrame} referenceFrame The desired referenceFrame of the result.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPositionProperty.prototype.getValueInReferenceFrame =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n * @function\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPositionProperty.prototype.equals = DeveloperError.throwInstantiationError;\r\n\r\nvar scratchMatrix3 = new Matrix3();\r\n\r\n/**\r\n * @private\r\n */\r\nPositionProperty.convertToReferenceFrame = function (\r\n time,\r\n value,\r\n inputFrame,\r\n outputFrame,\r\n result\r\n) {\r\n if (!defined(value)) {\r\n return value;\r\n }\r\n if (!defined(result)) {\r\n result = new Cartesian3();\r\n }\r\n\r\n if (inputFrame === outputFrame) {\r\n return Cartesian3.clone(value, result);\r\n }\r\n\r\n var icrfToFixed = Transforms.computeIcrfToFixedMatrix(time, scratchMatrix3);\r\n if (!defined(icrfToFixed)) {\r\n icrfToFixed = Transforms.computeTemeToPseudoFixedMatrix(\r\n time,\r\n scratchMatrix3\r\n );\r\n }\r\n if (inputFrame === ReferenceFrame.INERTIAL) {\r\n return Matrix3.multiplyByVector(icrfToFixed, value, result);\r\n }\r\n if (inputFrame === ReferenceFrame.FIXED) {\r\n return Matrix3.multiplyByVector(\r\n Matrix3.transpose(icrfToFixed, scratchMatrix3),\r\n value,\r\n result\r\n );\r\n }\r\n};\r\nexport default PositionProperty;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport PositionProperty from \"./PositionProperty.js\";\r\n\r\n/**\r\n * A {@link PositionProperty} whose value does not change in respect to the\r\n * {@link ReferenceFrame} in which is it defined.\r\n *\r\n * @alias ConstantPositionProperty\r\n * @constructor\r\n *\r\n * @param {Cartesian3} [value] The property value.\r\n * @param {ReferenceFrame} [referenceFrame=ReferenceFrame.FIXED] The reference frame in which the position is defined.\r\n */\r\nfunction ConstantPositionProperty(value, referenceFrame) {\r\n this._definitionChanged = new Event();\r\n this._value = Cartesian3.clone(value);\r\n this._referenceFrame = defaultValue(referenceFrame, ReferenceFrame.FIXED);\r\n}\r\n\r\nObject.defineProperties(ConstantPositionProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof ConstantPositionProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n !defined(this._value) || this._referenceFrame === ReferenceFrame.FIXED\r\n );\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof ConstantPositionProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the reference frame in which the position is defined.\r\n * @memberof ConstantPositionProperty.prototype\r\n * @type {ReferenceFrame}\r\n * @default ReferenceFrame.FIXED;\r\n */\r\n referenceFrame: {\r\n get: function () {\r\n return this._referenceFrame;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time in the fixed frame.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nConstantPositionProperty.prototype.getValue = function (time, result) {\r\n return this.getValueInReferenceFrame(time, ReferenceFrame.FIXED, result);\r\n};\r\n\r\n/**\r\n * Sets the value of the property.\r\n *\r\n * @param {Cartesian3} value The property value.\r\n * @param {ReferenceFrame} [referenceFrame=this.referenceFrame] The reference frame in which the position is defined.\r\n */\r\nConstantPositionProperty.prototype.setValue = function (value, referenceFrame) {\r\n var definitionChanged = false;\r\n if (!Cartesian3.equals(this._value, value)) {\r\n definitionChanged = true;\r\n this._value = Cartesian3.clone(value);\r\n }\r\n if (defined(referenceFrame) && this._referenceFrame !== referenceFrame) {\r\n definitionChanged = true;\r\n this._referenceFrame = referenceFrame;\r\n }\r\n if (definitionChanged) {\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time and in the provided reference frame.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {ReferenceFrame} referenceFrame The desired referenceFrame of the result.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nConstantPositionProperty.prototype.getValueInReferenceFrame = function (\r\n time,\r\n referenceFrame,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n if (!defined(referenceFrame)) {\r\n throw new DeveloperError(\"referenceFrame is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return PositionProperty.convertToReferenceFrame(\r\n time,\r\n this._value,\r\n this._referenceFrame,\r\n referenceFrame,\r\n result\r\n );\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nConstantPositionProperty.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (other instanceof ConstantPositionProperty &&\r\n Cartesian3.equals(this._value, other._value) &&\r\n this._referenceFrame === other._referenceFrame)\r\n );\r\n};\r\nexport default ConstantPositionProperty;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} CorridorGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the CorridorGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the corridor.\r\n * @property {Property | Cartesian3} [positions] A Property specifying the array of {@link Cartesian3} positions that define the centerline of the corridor.\r\n * @property {Property | number} [width] A numeric Property specifying the distance between the edges of the corridor.\r\n * @property {Property | number} [height=0] A numeric Property specifying the altitude of the corridor relative to the ellipsoid surface.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height is relative to.\r\n * @property {Property | number} [extrudedHeight] A numeric Property specifying the altitude of the corridor's extruded face relative to the ellipsoid surface.\r\n * @property {Property | HeightReference} [extrudedHeightReference=HeightReference.NONE] A Property specifying what the extrudedHeight is relative to.\r\n * @property {Property | CornerType} [cornerType=CornerType.ROUNDED] A {@link CornerType} Property specifying the style of the corners.\r\n * @property {Property | number} [granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the distance between each latitude and longitude.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the corridor is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the corridor.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the corridor is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the corridor casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this corridor will be displayed.\r\n * @property {Property | ClassificationType} [classificationType=ClassificationType.BOTH] An enum Property specifying whether this corridor will classify terrain, 3D Tiles, or both when on the ground.\r\n * @property {ConstantProperty | number} [zIndex] A Property specifying the zIndex of the corridor, used for ordering. Only has an effect if height and extrudedHeight are undefined, and if the corridor is static.\r\n */\r\n\r\n/**\r\n * Describes a corridor, which is a shape defined by a centerline and width that\r\n * conforms to the curvature of the globe. It can be placed on the surface or at altitude\r\n * and can optionally be extruded into a volume.\r\n *\r\n * @alias CorridorGraphics\r\n * @constructor\r\n *\r\n * @param {CorridorGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @see Entity\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Corridor.html|Cesium Sandcastle Corridor Demo}\r\n */\r\nfunction CorridorGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._positions = undefined;\r\n this._positionsSubscription = undefined;\r\n this._width = undefined;\r\n this._widthSubscription = undefined;\r\n this._height = undefined;\r\n this._heightSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._extrudedHeight = undefined;\r\n this._extrudedHeightSubscription = undefined;\r\n this._extrudedHeightReference = undefined;\r\n this._extrudedHeightReferenceSubscription = undefined;\r\n this._cornerType = undefined;\r\n this._cornerTypeSubscription = undefined;\r\n this._granularity = undefined;\r\n this._granularitySubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n this._classificationType = undefined;\r\n this._classificationTypeSubscription = undefined;\r\n this._zIndex = undefined;\r\n this._zIndexSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(CorridorGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the corridor.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets a Property specifying the array of {@link Cartesian3} positions that define the centerline of the corridor.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n positions: createPropertyDescriptor(\"positions\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the corridor.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n width: createPropertyDescriptor(\"width\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the altitude of the corridor.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n height: createPropertyDescriptor(\"height\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the altitude of the corridor extrusion.\r\n * Setting this property creates a corridor shaped volume starting at height and ending\r\n * at this altitude.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n extrudedHeight: createPropertyDescriptor(\"extrudedHeight\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the extruded {@link HeightReference}.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n extrudedHeightReference: createPropertyDescriptor(\"extrudedHeightReference\"),\r\n\r\n /**\r\n * Gets or sets the {@link CornerType} Property specifying how corners are styled.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default CornerType.ROUNDED\r\n */\r\n cornerType: createPropertyDescriptor(\"cornerType\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the sampling distance between each latitude and longitude point.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default {CesiumMath.RADIANS_PER_DEGREE}\r\n */\r\n granularity: createPropertyDescriptor(\"granularity\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the corridor is filled with the provided material.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to fill the corridor.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {MaterialProperty|undefined}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the corridor is outlined.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the corridor\r\n * casts or receives shadows from light sources.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this corridor will be displayed.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the {@link ClassificationType} Property specifying whether this corridor will classify terrain, 3D Tiles, or both when on the ground.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ClassificationType.BOTH\r\n */\r\n classificationType: createPropertyDescriptor(\"classificationType\"),\r\n\r\n /**\r\n * Gets or sets the zIndex Property specifying the ordering of the corridor. Only has an effect if the coridor is static and neither height or exturdedHeight are specified.\r\n * @memberof CorridorGraphics.prototype\r\n * @type {ConstantProperty|undefined}\r\n * @default 0\r\n */\r\n zIndex: createPropertyDescriptor(\"zIndex\"),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {CorridorGraphics} [result] The object onto which to store the result.\r\n * @returns {CorridorGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nCorridorGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new CorridorGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.positions = this.positions;\r\n result.width = this.width;\r\n result.height = this.height;\r\n result.heightReference = this.heightReference;\r\n result.extrudedHeight = this.extrudedHeight;\r\n result.extrudedHeightReference = this.extrudedHeightReference;\r\n result.cornerType = this.cornerType;\r\n result.granularity = this.granularity;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n result.classificationType = this.classificationType;\r\n result.zIndex = this.zIndex;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {CorridorGraphics} source The object to be merged into this object.\r\n */\r\nCorridorGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.positions = defaultValue(this.positions, source.positions);\r\n this.width = defaultValue(this.width, source.width);\r\n this.height = defaultValue(this.height, source.height);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.extrudedHeight = defaultValue(\r\n this.extrudedHeight,\r\n source.extrudedHeight\r\n );\r\n this.extrudedHeightReference = defaultValue(\r\n this.extrudedHeightReference,\r\n source.extrudedHeightReference\r\n );\r\n this.cornerType = defaultValue(this.cornerType, source.cornerType);\r\n this.granularity = defaultValue(this.granularity, source.granularity);\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.classificationType = defaultValue(\r\n this.classificationType,\r\n source.classificationType\r\n );\r\n this.zIndex = defaultValue(this.zIndex, source.zIndex);\r\n};\r\nexport default CorridorGraphics;\r\n","import createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\nfunction createRawProperty(value) {\r\n return value;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nfunction createRawPropertyDescriptor(name, configurable) {\r\n return createPropertyDescriptor(name, configurable, createRawProperty);\r\n}\r\nexport default createRawPropertyDescriptor;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} CylinderGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the CylinderGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the cylinder.\r\n * @property {Property | number} [length] A numeric Property specifying the length of the cylinder.\r\n * @property {Property | number} [topRadius] A numeric Property specifying the radius of the top of the cylinder.\r\n * @property {Property | number} [bottomRadius] A numeric Property specifying the radius of the bottom of the cylinder.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height from the entity position is relative to.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the cylinder is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the cylinder.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the cylinder is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | number} [numberOfVerticalLines=16] A numeric Property specifying the number of vertical lines to draw along the perimeter for the outline.\r\n * @property {Property | number} [slices=128] The number of edges around the perimeter of the cylinder.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the cylinder casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this cylinder will be displayed.\r\n */\r\n\r\n/**\r\n * Describes a cylinder, truncated cone, or cone defined by a length, top radius, and bottom radius.\r\n * The center position and orientation are determined by the containing {@link Entity}.\r\n *\r\n * @alias CylinderGraphics\r\n * @constructor\r\n *\r\n * @param {CylinderGraphics.ConstructorOptions} [options] Object describing initialization options\r\n */\r\nfunction CylinderGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._length = undefined;\r\n this._lengthSubscription = undefined;\r\n this._topRadius = undefined;\r\n this._topRadiusSubscription = undefined;\r\n this._bottomRadius = undefined;\r\n this._bottomRadiusSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._numberOfVerticalLines = undefined;\r\n this._numberOfVerticalLinesSubscription = undefined;\r\n this._slices = undefined;\r\n this._slicesSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(CylinderGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof CylinderGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the cylinder.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the length of the cylinder.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n length: createPropertyDescriptor(\"length\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the radius of the top of the cylinder.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n topRadius: createPropertyDescriptor(\"topRadius\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the radius of the bottom of the cylinder.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n bottomRadius: createPropertyDescriptor(\"bottomRadius\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the cylinder is filled with the provided material.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to fill the cylinder.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {MaterialProperty|undefined}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the cylinder is outlined.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the number of vertical lines to draw along the perimeter for the outline.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 16\r\n */\r\n numberOfVerticalLines: createPropertyDescriptor(\"numberOfVerticalLines\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the number of edges around the perimeter of the cylinder.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 128\r\n */\r\n slices: createPropertyDescriptor(\"slices\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the cylinder\r\n * casts or receives shadows from light sources.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this cylinder will be displayed.\r\n * @memberof CylinderGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {CylinderGraphics} [result] The object onto which to store the result.\r\n * @returns {CylinderGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nCylinderGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new CylinderGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.length = this.length;\r\n result.topRadius = this.topRadius;\r\n result.bottomRadius = this.bottomRadius;\r\n result.heightReference = this.heightReference;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.numberOfVerticalLines = this.numberOfVerticalLines;\r\n result.slices = this.slices;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {CylinderGraphics} source The object to be merged into this object.\r\n */\r\nCylinderGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.length = defaultValue(this.length, source.length);\r\n this.topRadius = defaultValue(this.topRadius, source.topRadius);\r\n this.bottomRadius = defaultValue(this.bottomRadius, source.bottomRadius);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.numberOfVerticalLines = defaultValue(\r\n this.numberOfVerticalLines,\r\n source.numberOfVerticalLines\r\n );\r\n this.slices = defaultValue(this.slices, source.slices);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n};\r\nexport default CylinderGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} EllipseGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the EllipseGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the ellipse.\r\n * @property {Property | number} [semiMajorAxis] The numeric Property specifying the semi-major axis.\r\n * @property {Property | number} [semiMinorAxis] The numeric Property specifying the semi-minor axis.\r\n * @property {Property | number} [height=0] A numeric Property specifying the altitude of the ellipse relative to the ellipsoid surface.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height is relative to.\r\n * @property {Property | number} [extrudedHeight] A numeric Property specifying the altitude of the ellipse's extruded face relative to the ellipsoid surface.\r\n * @property {Property | HeightReference} [extrudedHeightReference=HeightReference.NONE] A Property specifying what the extrudedHeight is relative to.\r\n * @property {Property | number} [rotation=0.0] A numeric property specifying the rotation of the ellipse counter-clockwise from north.\r\n * @property {Property | number} [stRotation=0.0] A numeric property specifying the rotation of the ellipse texture counter-clockwise from north.\r\n * @property {Property | number} [granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between points on the ellipse.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the ellipse is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the ellipse.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the ellipse is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | number} [numberOfVerticalLines=16] A numeric Property specifying the number of vertical lines to draw along the perimeter for the outline.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the ellipse casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this ellipse will be displayed.\r\n * @property {Property | ClassificationType} [classificationType=ClassificationType.BOTH] An enum Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground.\r\n * @property {ConstantProperty | number} [zIndex=0] A property specifying the zIndex of the Ellipse. Used for ordering ground geometry. Only has an effect if the ellipse is constant and neither height or exturdedHeight are specified.\r\n */\r\n\r\n/**\r\n * Describes an ellipse defined by a center point and semi-major and semi-minor axes.\r\n * The ellipse conforms to the curvature of the globe and can be placed on the surface or\r\n * at altitude and can optionally be extruded into a volume.\r\n * The center point is determined by the containing {@link Entity}.\r\n *\r\n * @alias EllipseGraphics\r\n * @constructor\r\n *\r\n * @param {EllipseGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Circles and Ellipses.html|Cesium Sandcastle Circles and Ellipses Demo}\r\n */\r\nfunction EllipseGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._semiMajorAxis = undefined;\r\n this._semiMajorAxisSubscription = undefined;\r\n this._semiMinorAxis = undefined;\r\n this._semiMinorAxisSubscription = undefined;\r\n this._height = undefined;\r\n this._heightSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._extrudedHeight = undefined;\r\n this._extrudedHeightSubscription = undefined;\r\n this._extrudedHeightReference = undefined;\r\n this._extrudedHeightReferenceSubscription = undefined;\r\n this._rotation = undefined;\r\n this._rotationSubscription = undefined;\r\n this._stRotation = undefined;\r\n this._stRotationSubscription = undefined;\r\n this._granularity = undefined;\r\n this._granularitySubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._numberOfVerticalLines = undefined;\r\n this._numberOfVerticalLinesSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n this._classificationType = undefined;\r\n this._classificationTypeSubscription = undefined;\r\n this._zIndex = undefined;\r\n this._zIndexSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(EllipseGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof EllipseGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the ellipse.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the semi-major axis.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n semiMajorAxis: createPropertyDescriptor(\"semiMajorAxis\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the semi-minor axis.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n semiMinorAxis: createPropertyDescriptor(\"semiMinorAxis\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the altitude of the ellipse.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n height: createPropertyDescriptor(\"height\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the altitude of the ellipse extrusion.\r\n * Setting this property creates volume starting at height and ending at this altitude.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n extrudedHeight: createPropertyDescriptor(\"extrudedHeight\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the extruded {@link HeightReference}.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n extrudedHeightReference: createPropertyDescriptor(\"extrudedHeightReference\"),\r\n\r\n /**\r\n * Gets or sets the numeric property specifying the rotation of the ellipse counter-clockwise from north.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0\r\n */\r\n rotation: createPropertyDescriptor(\"rotation\"),\r\n\r\n /**\r\n * Gets or sets the numeric property specifying the rotation of the ellipse texture counter-clockwise from north.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0\r\n */\r\n stRotation: createPropertyDescriptor(\"stRotation\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the angular distance between points on the ellipse.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default {CesiumMath.RADIANS_PER_DEGREE}\r\n */\r\n granularity: createPropertyDescriptor(\"granularity\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the ellipse is filled with the provided material.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to fill the ellipse.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {MaterialProperty|undefined}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the ellipse is outlined.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the number of vertical lines to draw along the perimeter for the outline.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 16\r\n */\r\n numberOfVerticalLines: createPropertyDescriptor(\"numberOfVerticalLines\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the ellipse\r\n * casts or receives shadows from light sources.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this ellipse will be displayed.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the {@link ClassificationType} Property specifying whether this ellipse will classify terrain, 3D Tiles, or both when on the ground.\r\n * @memberof EllipseGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ClassificationType.BOTH\r\n */\r\n classificationType: createPropertyDescriptor(\"classificationType\"),\r\n\r\n /**\r\n * Gets or sets the zIndex Property specifying the ellipse ordering. Only has an effect if the ellipse is constant and neither height or extrudedHeight are specified\r\n * @memberof EllipseGraphics.prototype\r\n * @type {ConstantProperty|undefined}\r\n * @default 0\r\n */\r\n zIndex: createPropertyDescriptor(\"zIndex\"),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {EllipseGraphics} [result] The object onto which to store the result.\r\n * @returns {EllipseGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nEllipseGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new EllipseGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.semiMajorAxis = this.semiMajorAxis;\r\n result.semiMinorAxis = this.semiMinorAxis;\r\n result.height = this.height;\r\n result.heightReference = this.heightReference;\r\n result.extrudedHeight = this.extrudedHeight;\r\n result.extrudedHeightReference = this.extrudedHeightReference;\r\n result.rotation = this.rotation;\r\n result.stRotation = this.stRotation;\r\n result.granularity = this.granularity;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.numberOfVerticalLines = this.numberOfVerticalLines;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n result.classificationType = this.classificationType;\r\n result.zIndex = this.zIndex;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {EllipseGraphics} source The object to be merged into this object.\r\n */\r\nEllipseGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.semiMajorAxis = defaultValue(this.semiMajorAxis, source.semiMajorAxis);\r\n this.semiMinorAxis = defaultValue(this.semiMinorAxis, source.semiMinorAxis);\r\n this.height = defaultValue(this.height, source.height);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.extrudedHeight = defaultValue(\r\n this.extrudedHeight,\r\n source.extrudedHeight\r\n );\r\n this.extrudedHeightReference = defaultValue(\r\n this.extrudedHeightReference,\r\n source.extrudedHeightReference\r\n );\r\n this.rotation = defaultValue(this.rotation, source.rotation);\r\n this.stRotation = defaultValue(this.stRotation, source.stRotation);\r\n this.granularity = defaultValue(this.granularity, source.granularity);\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.numberOfVerticalLines = defaultValue(\r\n this.numberOfVerticalLines,\r\n source.numberOfVerticalLines\r\n );\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.classificationType = defaultValue(\r\n this.classificationType,\r\n source.classificationType\r\n );\r\n this.zIndex = defaultValue(this.zIndex, source.zIndex);\r\n};\r\nexport default EllipseGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} EllipsoidGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the EllipsoidGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the ellipsoid.\r\n * @property {Property | Cartesian3} [radii] A {@link Cartesian3} Property specifying the radii of the ellipsoid.\r\n * @property {Property | Cartesian3} [innerRadii] A {@link Cartesian3} Property specifying the inner radii of the ellipsoid.\r\n * @property {Property | number} [minimumClock=0.0] A Property specifying the minimum clock angle of the ellipsoid.\r\n * @property {Property | number} [maximumClock=2*PI] A Property specifying the maximum clock angle of the ellipsoid.\r\n * @property {Property | number} [minimumCone=0.0] A Property specifying the minimum cone angle of the ellipsoid.\r\n * @property {Property | number} [maximumCone=PI] A Property specifying the maximum cone angle of the ellipsoid.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height from the entity position is relative to.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the ellipsoid is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the ellipsoid.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the ellipsoid is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | number} [stackPartitions=64] A Property specifying the number of stacks.\r\n * @property {Property | number} [slicePartitions=64] A Property specifying the number of radial slices.\r\n * @property {Property | number} [subdivisions=128] A Property specifying the number of samples per outline ring, determining the granularity of the curvature.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the ellipsoid casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this ellipsoid will be displayed.\r\n */\r\n\r\n/**\r\n * Describe an ellipsoid or sphere. The center position and orientation are determined by the containing {@link Entity}.\r\n *\r\n * @alias EllipsoidGraphics\r\n * @constructor\r\n *\r\n * @param {EllipsoidGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Spheres%20and%20Ellipsoids.html|Cesium Sandcastle Spheres and Ellipsoids Demo}\r\n */\r\nfunction EllipsoidGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._radii = undefined;\r\n this._radiiSubscription = undefined;\r\n this._innerRadii = undefined;\r\n this._innerRadiiSubscription = undefined;\r\n this._minimumClock = undefined;\r\n this._minimumClockSubscription = undefined;\r\n this._maximumClock = undefined;\r\n this._maximumClockSubscription = undefined;\r\n this._minimumCone = undefined;\r\n this._minimumConeSubscription = undefined;\r\n this._maximumCone = undefined;\r\n this._maximumConeSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._stackPartitions = undefined;\r\n this._stackPartitionsSubscription = undefined;\r\n this._slicePartitions = undefined;\r\n this._slicePartitionsSubscription = undefined;\r\n this._subdivisions = undefined;\r\n this._subdivisionsSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(EllipsoidGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof EllipsoidGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the ellipsoid.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian3} {@link Property} specifying the radii of the ellipsoid.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n radii: createPropertyDescriptor(\"radii\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian3} {@link Property} specifying the inner radii of the ellipsoid.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default radii\r\n */\r\n innerRadii: createPropertyDescriptor(\"innerRadii\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the minimum clock angle of the ellipsoid.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n minimumClock: createPropertyDescriptor(\"minimumClock\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the maximum clock angle of the ellipsoid.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 2*PI\r\n */\r\n maximumClock: createPropertyDescriptor(\"maximumClock\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the minimum cone angle of the ellipsoid.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n minimumCone: createPropertyDescriptor(\"minimumCone\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the maximum cone angle of the ellipsoid.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default PI\r\n */\r\n maximumCone: createPropertyDescriptor(\"maximumCone\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the ellipsoid is filled with the provided material.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to fill the ellipsoid.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the ellipsoid is outlined.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the number of stacks.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 64\r\n */\r\n stackPartitions: createPropertyDescriptor(\"stackPartitions\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the number of radial slices per 360 degrees.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 64\r\n */\r\n slicePartitions: createPropertyDescriptor(\"slicePartitions\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the number of samples per outline ring, determining the granularity of the curvature.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 128\r\n */\r\n subdivisions: createPropertyDescriptor(\"subdivisions\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the ellipsoid\r\n * casts or receives shadows from light sources.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this ellipsoid will be displayed.\r\n * @memberof EllipsoidGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {EllipsoidGraphics} [result] The object onto which to store the result.\r\n * @returns {EllipsoidGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nEllipsoidGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new EllipsoidGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.radii = this.radii;\r\n result.innerRadii = this.innerRadii;\r\n result.minimumClock = this.minimumClock;\r\n result.maximumClock = this.maximumClock;\r\n result.minimumCone = this.minimumCone;\r\n result.maximumCone = this.maximumCone;\r\n result.heightReference = this.heightReference;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.stackPartitions = this.stackPartitions;\r\n result.slicePartitions = this.slicePartitions;\r\n result.subdivisions = this.subdivisions;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {EllipsoidGraphics} source The object to be merged into this object.\r\n */\r\nEllipsoidGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.radii = defaultValue(this.radii, source.radii);\r\n this.innerRadii = defaultValue(this.innerRadii, source.innerRadii);\r\n this.minimumClock = defaultValue(this.minimumClock, source.minimumClock);\r\n this.maximumClock = defaultValue(this.maximumClock, source.maximumClock);\r\n this.minimumCone = defaultValue(this.minimumCone, source.minimumCone);\r\n this.maximumCone = defaultValue(this.maximumCone, source.maximumCone);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.stackPartitions = defaultValue(\r\n this.stackPartitions,\r\n source.stackPartitions\r\n );\r\n this.slicePartitions = defaultValue(\r\n this.slicePartitions,\r\n source.slicePartitions\r\n );\r\n this.subdivisions = defaultValue(this.subdivisions, source.subdivisions);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n};\r\nexport default EllipsoidGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} LabelGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the LabelGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the label.\r\n * @property {Property | string} [text] A Property specifying the text. Explicit newlines '\\n' are supported.\r\n * @property {Property | string} [font='30px sans-serif'] A Property specifying the CSS font.\r\n * @property {Property | LabelStyle} [style=LabelStyle.FILL] A Property specifying the {@link LabelStyle}.\r\n * @property {Property | number} [scale=1.0] A numeric Property specifying the scale to apply to the text.\r\n * @property {Property | boolean} [showBackground=false] A boolean Property specifying the visibility of the background behind the label.\r\n * @property {Property | Color} [backgroundColor=new Color(0.165, 0.165, 0.165, 0.8)] A Property specifying the background {@link Color}.\r\n * @property {Property | Cartesian2} [backgroundPadding=new Cartesian2(7, 5)] A {@link Cartesian2} Property specifying the horizontal and vertical background padding in pixels.\r\n * @property {Property | Cartesian2} [pixelOffset=Cartesian2.ZERO] A {@link Cartesian2} Property specifying the pixel offset.\r\n * @property {Property | Cartesian3} [eyeOffset=Cartesian3.ZERO] A {@link Cartesian3} Property specifying the eye offset.\r\n * @property {Property | HorizontalOrigin} [horizontalOrigin=HorizontalOrigin.CENTER] A Property specifying the {@link HorizontalOrigin}.\r\n * @property {Property | VerticalOrigin} [verticalOrigin=VerticalOrigin.CENTER] A Property specifying the {@link VerticalOrigin}.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height is relative to.\r\n * @property {Property | Color} [fillColor=Color.WHITE] A Property specifying the fill {@link Color}.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the outline {@link Color}.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the outline width.\r\n * @property {Property | NearFarScalar} [translucencyByDistance] A {@link NearFarScalar} Property used to set translucency based on distance from the camera.\r\n * @property {Property | NearFarScalar} [pixelOffsetScaleByDistance] A {@link NearFarScalar} Property used to set pixelOffset based on distance from the camera.\r\n * @property {Property | NearFarScalar} [scaleByDistance] A {@link NearFarScalar} Property used to set scale based on distance from the camera.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this label will be displayed.\r\n * @property {Property | number} [disableDepthTestDistance] A Property specifying the distance from the camera at which to disable the depth test to.\r\n */\r\n\r\n/**\r\n * Describes a two dimensional label located at the position of the containing {@link Entity}.\r\n *

\r\n *

\r\n *
\r\n * Example labels\r\n *
\r\n *

\r\n *\r\n * @alias LabelGraphics\r\n * @constructor\r\n *\r\n * @param {LabelGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Labels.html|Cesium Sandcastle Labels Demo}\r\n */\r\nfunction LabelGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._text = undefined;\r\n this._textSubscription = undefined;\r\n this._font = undefined;\r\n this._fontSubscription = undefined;\r\n this._style = undefined;\r\n this._styleSubscription = undefined;\r\n this._scale = undefined;\r\n this._scaleSubscription = undefined;\r\n this._showBackground = undefined;\r\n this._showBackgroundSubscription = undefined;\r\n this._backgroundColor = undefined;\r\n this._backgroundColorSubscription = undefined;\r\n this._backgroundPadding = undefined;\r\n this._backgroundPaddingSubscription = undefined;\r\n this._pixelOffset = undefined;\r\n this._pixelOffsetSubscription = undefined;\r\n this._eyeOffset = undefined;\r\n this._eyeOffsetSubscription = undefined;\r\n this._horizontalOrigin = undefined;\r\n this._horizontalOriginSubscription = undefined;\r\n this._verticalOrigin = undefined;\r\n this._verticalOriginSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._fillColor = undefined;\r\n this._fillColorSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._translucencyByDistance = undefined;\r\n this._translucencyByDistanceSubscription = undefined;\r\n this._pixelOffsetScaleByDistance = undefined;\r\n this._pixelOffsetScaleByDistanceSubscription = undefined;\r\n this._scaleByDistance = undefined;\r\n this._scaleByDistanceSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n this._disableDepthTestDistance = undefined;\r\n this._disableDepthTestDistanceSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(LabelGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof LabelGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the label.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the string Property specifying the text of the label.\r\n * Explicit newlines '\\n' are supported.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n text: createPropertyDescriptor(\"text\"),\r\n\r\n /**\r\n * Gets or sets the string Property specifying the font in CSS syntax.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/CSS/font|CSS font on MDN}\r\n */\r\n font: createPropertyDescriptor(\"font\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link LabelStyle}.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n style: createPropertyDescriptor(\"style\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the uniform scale to apply to the image.\r\n * A scale greater than 1.0 enlarges the label while a scale less than 1.0 shrinks it.\r\n *

\r\n *

\r\n *
\r\n * From left to right in the above image, the scales are 0.5, 1.0,\r\n * and 2.0.\r\n *
\r\n *

\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n scale: createPropertyDescriptor(\"scale\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the background behind the label.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n showBackground: createPropertyDescriptor(\"showBackground\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the background {@link Color}.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default new Color(0.165, 0.165, 0.165, 0.8)\r\n */\r\n backgroundColor: createPropertyDescriptor(\"backgroundColor\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying the label's horizontal and vertical\r\n * background padding in pixels.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default new Cartesian2(7, 5)\r\n */\r\n backgroundPadding: createPropertyDescriptor(\"backgroundPadding\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying the label's pixel offset in screen space\r\n * from the origin of this label. This is commonly used to align multiple labels and labels at\r\n * the same position, e.g., an image and text. The screen space origin is the top, left corner of the\r\n * canvas; x increases from left to right, and y increases from top to bottom.\r\n *

\r\n *

\r\n * \r\n * \r\n * \r\n *
default
l.pixeloffset = new Cartesian2(25, 75);
\r\n * The label's origin is indicated by the yellow point.\r\n *
\r\n *

\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Cartesian2.ZERO\r\n */\r\n pixelOffset: createPropertyDescriptor(\"pixelOffset\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian3} Property specifying the label's offset in eye coordinates.\r\n * Eye coordinates is a left-handed coordinate system, where x points towards the viewer's\r\n * right, y points up, and z points into the screen.\r\n *

\r\n * An eye offset is commonly used to arrange multiple labels or objects at the same position, e.g., to\r\n * arrange a label above its corresponding 3D model.\r\n *

\r\n * Below, the label is positioned at the center of the Earth but an eye offset makes it always\r\n * appear on top of the Earth regardless of the viewer's or Earth's orientation.\r\n *

\r\n *

\r\n * \r\n * \r\n * \r\n *
\r\n * l.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);

\r\n *
\r\n *

\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Cartesian3.ZERO\r\n */\r\n eyeOffset: createPropertyDescriptor(\"eyeOffset\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HorizontalOrigin}.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n horizontalOrigin: createPropertyDescriptor(\"horizontalOrigin\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link VerticalOrigin}.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n verticalOrigin: createPropertyDescriptor(\"verticalOrigin\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the fill {@link Color}.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n fillColor: createPropertyDescriptor(\"fillColor\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the outline {@link Color}.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the outline width.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Gets or sets {@link NearFarScalar} Property specifying the translucency of the label based on the distance from the camera.\r\n * A label's translucency will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the label's translucency remains clamped to the nearest bound.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n translucencyByDistance: createPropertyDescriptor(\"translucencyByDistance\"),\r\n\r\n /**\r\n * Gets or sets {@link NearFarScalar} Property specifying the pixel offset of the label based on the distance from the camera.\r\n * A label's pixel offset will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the label's pixel offset remains clamped to the nearest bound.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n pixelOffsetScaleByDistance: createPropertyDescriptor(\r\n \"pixelOffsetScaleByDistance\"\r\n ),\r\n\r\n /**\r\n * Gets or sets near and far scaling properties of a Label based on the label's distance from the camera.\r\n * A label's scale will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the label's scale remains clamped to the nearest bound. If undefined,\r\n * scaleByDistance will be disabled.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n scaleByDistance: createPropertyDescriptor(\"scaleByDistance\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this label will be displayed.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.\r\n * When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.\r\n * @memberof LabelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n disableDepthTestDistance: createPropertyDescriptor(\r\n \"disableDepthTestDistance\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {LabelGraphics} [result] The object onto which to store the result.\r\n * @returns {LabelGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nLabelGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new LabelGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.text = this.text;\r\n result.font = this.font;\r\n result.style = this.style;\r\n result.scale = this.scale;\r\n result.showBackground = this.showBackground;\r\n result.backgroundColor = this.backgroundColor;\r\n result.backgroundPadding = this.backgroundPadding;\r\n result.pixelOffset = this.pixelOffset;\r\n result.eyeOffset = this.eyeOffset;\r\n result.horizontalOrigin = this.horizontalOrigin;\r\n result.verticalOrigin = this.verticalOrigin;\r\n result.heightReference = this.heightReference;\r\n result.fillColor = this.fillColor;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.translucencyByDistance = this.translucencyByDistance;\r\n result.pixelOffsetScaleByDistance = this.pixelOffsetScaleByDistance;\r\n result.scaleByDistance = this.scaleByDistance;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n result.disableDepthTestDistance = this.disableDepthTestDistance;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {LabelGraphics} source The object to be merged into this object.\r\n */\r\nLabelGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.text = defaultValue(this.text, source.text);\r\n this.font = defaultValue(this.font, source.font);\r\n this.style = defaultValue(this.style, source.style);\r\n this.scale = defaultValue(this.scale, source.scale);\r\n this.showBackground = defaultValue(\r\n this.showBackground,\r\n source.showBackground\r\n );\r\n this.backgroundColor = defaultValue(\r\n this.backgroundColor,\r\n source.backgroundColor\r\n );\r\n this.backgroundPadding = defaultValue(\r\n this.backgroundPadding,\r\n source.backgroundPadding\r\n );\r\n this.pixelOffset = defaultValue(this.pixelOffset, source.pixelOffset);\r\n this.eyeOffset = defaultValue(this.eyeOffset, source.eyeOffset);\r\n this.horizontalOrigin = defaultValue(\r\n this.horizontalOrigin,\r\n source.horizontalOrigin\r\n );\r\n this.verticalOrigin = defaultValue(\r\n this.verticalOrigin,\r\n source.verticalOrigin\r\n );\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.fillColor = defaultValue(this.fillColor, source.fillColor);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.translucencyByDistance = defaultValue(\r\n this.translucencyByDistance,\r\n source.translucencyByDistance\r\n );\r\n this.pixelOffsetScaleByDistance = defaultValue(\r\n this.pixelOffsetScaleByDistance,\r\n source.pixelOffsetScaleByDistance\r\n );\r\n this.scaleByDistance = defaultValue(\r\n this.scaleByDistance,\r\n source.scaleByDistance\r\n );\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.disableDepthTestDistance = defaultValue(\r\n this.disableDepthTestDistance,\r\n source.disableDepthTestDistance\r\n );\r\n};\r\nexport default LabelGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport TranslationRotationScale from \"../Core/TranslationRotationScale.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultNodeTransformation = new TranslationRotationScale();\r\n\r\n/**\r\n * A {@link Property} that produces {@link TranslationRotationScale} data.\r\n * @alias NodeTransformationProperty\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Property|Cartesian3} [options.translation=Cartesian3.ZERO] A {@link Cartesian3} Property specifying the (x, y, z) translation to apply to the node.\r\n * @param {Property|Quaternion} [options.rotation=Quaternion.IDENTITY] A {@link Quaternion} Property specifying the (x, y, z, w) rotation to apply to the node.\r\n * @param {Property|Cartesian3} [options.scale=new Cartesian3(1.0, 1.0, 1.0)] A {@link Cartesian3} Property specifying the (x, y, z) scaling to apply to the node.\r\n */\r\nfunction NodeTransformationProperty(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._definitionChanged = new Event();\r\n this._translation = undefined;\r\n this._translationSubscription = undefined;\r\n this._rotation = undefined;\r\n this._rotationSubscription = undefined;\r\n this._scale = undefined;\r\n this._scaleSubscription = undefined;\r\n\r\n this.translation = options.translation;\r\n this.rotation = options.rotation;\r\n this.scale = options.scale;\r\n}\r\n\r\nObject.defineProperties(NodeTransformationProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof NodeTransformationProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n Property.isConstant(this._translation) &&\r\n Property.isConstant(this._rotation) &&\r\n Property.isConstant(this._scale)\r\n );\r\n },\r\n },\r\n\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof NodeTransformationProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian3} Property specifying the (x, y, z) translation to apply to the node.\r\n * @memberof NodeTransformationProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Cartesian3.ZERO\r\n */\r\n translation: createPropertyDescriptor(\"translation\"),\r\n\r\n /**\r\n * Gets or sets the {@link Quaternion} Property specifying the (x, y, z, w) rotation to apply to the node.\r\n * @memberof NodeTransformationProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Quaternion.IDENTITY\r\n */\r\n rotation: createPropertyDescriptor(\"rotation\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian3} Property specifying the (x, y, z) scaling to apply to the node.\r\n * @memberof NodeTransformationProperty.prototype\r\n * @type {Property|undefined}\r\n * @default new Cartesian3(1.0, 1.0, 1.0)\r\n */\r\n scale: createPropertyDescriptor(\"scale\"),\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {TranslationRotationScale} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {TranslationRotationScale} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nNodeTransformationProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = new TranslationRotationScale();\r\n }\r\n\r\n result.translation = Property.getValueOrClonedDefault(\r\n this._translation,\r\n time,\r\n defaultNodeTransformation.translation,\r\n result.translation\r\n );\r\n result.rotation = Property.getValueOrClonedDefault(\r\n this._rotation,\r\n time,\r\n defaultNodeTransformation.rotation,\r\n result.rotation\r\n );\r\n result.scale = Property.getValueOrClonedDefault(\r\n this._scale,\r\n time,\r\n defaultNodeTransformation.scale,\r\n result.scale\r\n );\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nNodeTransformationProperty.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (other instanceof NodeTransformationProperty &&\r\n Property.equals(this._translation, other._translation) &&\r\n Property.equals(this._rotation, other._rotation) &&\r\n Property.equals(this._scale, other._scale))\r\n );\r\n};\r\nexport default NodeTransformationProperty;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport ConstantProperty from \"./ConstantProperty.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link Property} whose value is a key-value mapping of property names to the computed value of other properties.\r\n *\r\n * @alias PropertyBag\r\n * @constructor\r\n * @implements {DictionaryLike}\r\n *\r\n * @param {Object} [value] An object, containing key-value mapping of property names to properties.\r\n * @param {Function} [createPropertyCallback] A function that will be called when the value of any of the properties in value are not a Property.\r\n */\r\nfunction PropertyBag(value, createPropertyCallback) {\r\n this._propertyNames = [];\r\n this._definitionChanged = new Event();\r\n\r\n if (defined(value)) {\r\n this.merge(value, createPropertyCallback);\r\n }\r\n}\r\n\r\nObject.defineProperties(PropertyBag.prototype, {\r\n /**\r\n * Gets the names of all properties registered on this instance.\r\n * @memberof PropertyBag.prototype\r\n * @type {Array}\r\n */\r\n propertyNames: {\r\n get: function () {\r\n return this._propertyNames;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if this property is constant. This property\r\n * is considered constant if all property items in this object are constant.\r\n * @memberof PropertyBag.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n var propertyNames = this._propertyNames;\r\n for (var i = 0, len = propertyNames.length; i < len; i++) {\r\n if (!Property.isConstant(this[propertyNames[i]])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the set of properties contained in this\r\n * object changes, or one of the properties itself changes.\r\n *\r\n * @memberof PropertyBag.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Determines if this object has defined a property with the given name.\r\n *\r\n * @param {String} propertyName The name of the property to check for.\r\n *\r\n * @returns {Boolean} True if this object has defined a property with the given name, false otherwise.\r\n */\r\nPropertyBag.prototype.hasProperty = function (propertyName) {\r\n return this._propertyNames.indexOf(propertyName) !== -1;\r\n};\r\n\r\nfunction createConstantProperty(value) {\r\n return new ConstantProperty(value);\r\n}\r\n\r\n/**\r\n * Adds a property to this object.\r\n *\r\n * @param {String} propertyName The name of the property to add.\r\n * @param {*} [value] The value of the new property, if provided.\r\n * @param {Function} [createPropertyCallback] A function that will be called when the value of this new property is set to a value that is not a Property.\r\n *\r\n * @exception {DeveloperError} \"propertyName\" is already a registered property.\r\n */\r\nPropertyBag.prototype.addProperty = function (\r\n propertyName,\r\n value,\r\n createPropertyCallback\r\n) {\r\n var propertyNames = this._propertyNames;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(propertyName)) {\r\n throw new DeveloperError(\"propertyName is required.\");\r\n }\r\n if (propertyNames.indexOf(propertyName) !== -1) {\r\n throw new DeveloperError(\r\n propertyName + \" is already a registered property.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n propertyNames.push(propertyName);\r\n Object.defineProperty(\r\n this,\r\n propertyName,\r\n createPropertyDescriptor(\r\n propertyName,\r\n true,\r\n defaultValue(createPropertyCallback, createConstantProperty)\r\n )\r\n );\r\n\r\n if (defined(value)) {\r\n this[propertyName] = value;\r\n }\r\n\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\n\r\n/**\r\n * Removed a property previously added with addProperty.\r\n *\r\n * @param {String} propertyName The name of the property to remove.\r\n *\r\n * @exception {DeveloperError} \"propertyName\" is not a registered property.\r\n */\r\nPropertyBag.prototype.removeProperty = function (propertyName) {\r\n var propertyNames = this._propertyNames;\r\n var index = propertyNames.indexOf(propertyName);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(propertyName)) {\r\n throw new DeveloperError(\"propertyName is required.\");\r\n }\r\n if (index === -1) {\r\n throw new DeveloperError(propertyName + \" is not a registered property.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._propertyNames.splice(index, 1);\r\n delete this[propertyName];\r\n\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\n\r\n/**\r\n * Gets the value of this property. Each contained property will be evaluated at the given time, and the overall\r\n * result will be an object, mapping property names to those values.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * Note that any properties in result which are not part of this PropertyBag will be left as-is.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPropertyBag.prototype.getValue = function (time, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n\r\n var propertyNames = this._propertyNames;\r\n for (var i = 0, len = propertyNames.length; i < len; i++) {\r\n var propertyName = propertyNames[i];\r\n result[propertyName] = Property.getValueOrUndefined(\r\n this[propertyName],\r\n time,\r\n result[propertyName]\r\n );\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {Object} source The object to be merged into this object.\r\n * @param {Function} [createPropertyCallback] A function that will be called when the value of any of the properties in value are not a Property.\r\n */\r\nPropertyBag.prototype.merge = function (source, createPropertyCallback) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var propertyNames = this._propertyNames;\r\n var sourcePropertyNames = defined(source._propertyNames)\r\n ? source._propertyNames\r\n : Object.keys(source);\r\n for (var i = 0, len = sourcePropertyNames.length; i < len; i++) {\r\n var name = sourcePropertyNames[i];\r\n\r\n var targetProperty = this[name];\r\n var sourceProperty = source[name];\r\n\r\n //Custom properties that are registered on the source must also be added to this.\r\n if (targetProperty === undefined && propertyNames.indexOf(name) === -1) {\r\n this.addProperty(name, undefined, createPropertyCallback);\r\n }\r\n\r\n if (sourceProperty !== undefined) {\r\n if (targetProperty !== undefined) {\r\n if (defined(targetProperty) && defined(targetProperty.merge)) {\r\n targetProperty.merge(sourceProperty);\r\n }\r\n } else if (\r\n defined(sourceProperty) &&\r\n defined(sourceProperty.merge) &&\r\n defined(sourceProperty.clone)\r\n ) {\r\n this[name] = sourceProperty.clone();\r\n } else {\r\n this[name] = sourceProperty;\r\n }\r\n }\r\n }\r\n};\r\n\r\nfunction propertiesEqual(a, b) {\r\n var aPropertyNames = a._propertyNames;\r\n var bPropertyNames = b._propertyNames;\r\n\r\n var len = aPropertyNames.length;\r\n if (len !== bPropertyNames.length) {\r\n return false;\r\n }\r\n\r\n for (var aIndex = 0; aIndex < len; ++aIndex) {\r\n var name = aPropertyNames[aIndex];\r\n var bIndex = bPropertyNames.indexOf(name);\r\n if (bIndex === -1) {\r\n return false;\r\n }\r\n if (!Property.equals(a[name], b[name])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPropertyBag.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof PropertyBag && //\r\n propertiesEqual(this, other))\r\n );\r\n};\r\nexport default PropertyBag;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport NodeTransformationProperty from \"./NodeTransformationProperty.js\";\r\nimport PropertyBag from \"./PropertyBag.js\";\r\n\r\nfunction createNodeTransformationProperty(value) {\r\n return new NodeTransformationProperty(value);\r\n}\r\n\r\nfunction createNodeTransformationPropertyBag(value) {\r\n return new PropertyBag(value, createNodeTransformationProperty);\r\n}\r\n\r\nfunction createArticulationStagePropertyBag(value) {\r\n return new PropertyBag(value);\r\n}\r\n\r\n/**\r\n * @typedef {Object} ModelGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the ModelGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the model.\r\n * @property {Property | string | Resource} [uri] A string or Resource Property specifying the URI of the glTF asset.\r\n * @property {Property | number} [scale=1.0] A numeric Property specifying a uniform linear scale.\r\n * @property {Property | number} [minimumPixelSize=0.0] A numeric Property specifying the approximate minimum pixel size of the model regardless of zoom.\r\n * @property {Property | number} [maximumScale] The maximum scale size of a model. An upper limit for minimumPixelSize.\r\n * @property {Property | boolean} [incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded.\r\n * @property {Property | boolean} [runAnimations=true] A boolean Property specifying if glTF animations specified in the model should be started.\r\n * @property {Property | boolean} [clampAnimations=true] A boolean Property specifying if glTF animations should hold the last pose for time durations with no keyframes.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.ENABLED] An enum Property specifying whether the model casts or receives shadows from light sources.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height is relative to.\r\n * @property {Property | Color} [silhouetteColor=Color.RED] A Property specifying the {@link Color} of the silhouette.\r\n * @property {Property | number} [silhouetteSize=0.0] A numeric Property specifying the size of the silhouette in pixels.\r\n * @property {Property | Color} [color=Color.WHITE] A Property specifying the {@link Color} that blends with the model's rendered color.\r\n * @property {Property | ColorBlendMode} [colorBlendMode=ColorBlendMode.HIGHLIGHT] An enum Property specifying how the color blends with the model.\r\n * @property {Property | number} [colorBlendAmount=0.5] A numeric Property specifying the color strength when the colorBlendMode is MIX. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.\r\n * @property {Property | Cartesian2} [imageBasedLightingFactor=new Cartesian2(1.0, 1.0)] A property specifying the contribution from diffuse and specular image-based lighting.\r\n * @property {Property | Color} [lightColor] A property specifying the light color when shading the model. When undefined the scene's light color is used instead.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this model will be displayed.\r\n * @property {PropertyBag | Object.} [nodeTransformations] An object, where keys are names of nodes, and values are {@link TranslationRotationScale} Properties describing the transformation to apply to that node. The transformation is applied after the node's existing transformation as specified in the glTF, and does not replace the node's existing transformation.\r\n * @property {PropertyBag | Object.} [articulations] An object, where keys are composed of an articulation name, a single space, and a stage name, and the values are numeric properties.\r\n * @property {Property | ClippingPlaneCollection} [clippingPlanes] A property specifying the {@link ClippingPlaneCollection} used to selectively disable rendering the model.\r\n */\r\n\r\n/**\r\n * A 3D model based on {@link https://github.com/KhronosGroup/glTF|glTF}, the runtime asset format for WebGL, OpenGL ES, and OpenGL.\r\n * The position and orientation of the model is determined by the containing {@link Entity}.\r\n *

\r\n * Cesium includes support for glTF geometry, materials, animations, and skinning.\r\n * Cameras and lights are not currently supported.\r\n *

\r\n *\r\n * @alias ModelGraphics\r\n * @constructor\r\n *\r\n * @param {ModelGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @see {@link https://cesium.com/docs/tutorials/3d-models/|3D Models Tutorial}\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=3D%20Models.html|Cesium Sandcastle 3D Models Demo}\r\n */\r\nfunction ModelGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._uri = undefined;\r\n this._uriSubscription = undefined;\r\n this._scale = undefined;\r\n this._scaleSubscription = undefined;\r\n this._minimumPixelSize = undefined;\r\n this._minimumPixelSizeSubscription = undefined;\r\n this._maximumScale = undefined;\r\n this._maximumScaleSubscription = undefined;\r\n this._incrementallyLoadTextures = undefined;\r\n this._incrementallyLoadTexturesSubscription = undefined;\r\n this._runAnimations = undefined;\r\n this._runAnimationsSubscription = undefined;\r\n this._clampAnimations = undefined;\r\n this._clampAnimationsSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._silhouetteColor = undefined;\r\n this._silhouetteColorSubscription = undefined;\r\n this._silhouetteSize = undefined;\r\n this._silhouetteSizeSubscription = undefined;\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n this._colorBlendMode = undefined;\r\n this._colorBlendModeSubscription = undefined;\r\n this._colorBlendAmount = undefined;\r\n this._colorBlendAmountSubscription = undefined;\r\n this._imageBasedLightingFactor = undefined;\r\n this._imageBasedLightingFactorSubscription = undefined;\r\n this._lightColor = undefined;\r\n this._lightColorSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n this._nodeTransformations = undefined;\r\n this._nodeTransformationsSubscription = undefined;\r\n this._articulations = undefined;\r\n this._articulationsSubscription = undefined;\r\n this._clippingPlanes = undefined;\r\n this._clippingPlanesSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(ModelGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the model.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the string Property specifying the URI of the glTF asset.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n uri: createPropertyDescriptor(\"uri\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying a uniform linear scale\r\n * for this model. Values greater than 1.0 increase the size of the model while\r\n * values less than 1.0 decrease it.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n scale: createPropertyDescriptor(\"scale\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the approximate minimum\r\n * pixel size of the model regardless of zoom. This can be used to ensure that\r\n * a model is visible even when the viewer zooms out. When 0.0,\r\n * no minimum size is enforced.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n minimumPixelSize: createPropertyDescriptor(\"minimumPixelSize\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the maximum scale\r\n * size of a model. This property is used as an upper limit for\r\n * {@link ModelGraphics#minimumPixelSize}.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n maximumScale: createPropertyDescriptor(\"maximumScale\"),\r\n\r\n /**\r\n * Get or sets the boolean Property specifying whether textures\r\n * may continue to stream in after the model is loaded.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n incrementallyLoadTextures: createPropertyDescriptor(\r\n \"incrementallyLoadTextures\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying if glTF animations should be run.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n runAnimations: createPropertyDescriptor(\"runAnimations\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying if glTF animations should hold the last pose for time durations with no keyframes.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n clampAnimations: createPropertyDescriptor(\"clampAnimations\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the model\r\n * casts or receives shadows from light sources.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.ENABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the silhouette.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.RED\r\n */\r\n silhouetteColor: createPropertyDescriptor(\"silhouetteColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the size of the silhouette in pixels.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n silhouetteSize: createPropertyDescriptor(\"silhouetteSize\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} that blends with the model's rendered color.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n\r\n /**\r\n * Gets or sets the enum Property specifying how the color blends with the model.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ColorBlendMode.HIGHLIGHT\r\n */\r\n colorBlendMode: createPropertyDescriptor(\"colorBlendMode\"),\r\n\r\n /**\r\n * A numeric Property specifying the color strength when the colorBlendMode is MIX.\r\n * A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with\r\n * any value in-between resulting in a mix of the two.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.5\r\n */\r\n colorBlendAmount: createPropertyDescriptor(\"colorBlendAmount\"),\r\n\r\n /**\r\n * A property specifying the {@link Cartesian2} used to scale the diffuse and specular image-based lighting contribution to the final color.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n imageBasedLightingFactor: createPropertyDescriptor(\r\n \"imageBasedLightingFactor\"\r\n ),\r\n\r\n /**\r\n * A property specifying the {@link Cartesian3} light color when shading the model. When undefined the scene's light color is used instead.\r\n * @memberOf ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n lightColor: createPropertyDescriptor(\"lightColor\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this model will be displayed.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the set of node transformations to apply to this model. This is represented as an {@link PropertyBag}, where keys are\r\n * names of nodes, and values are {@link TranslationRotationScale} Properties describing the transformation to apply to that node.\r\n * The transformation is applied after the node's existing transformation as specified in the glTF, and does not replace the node's existing transformation.\r\n * @memberof ModelGraphics.prototype\r\n * @type {PropertyBag}\r\n */\r\n nodeTransformations: createPropertyDescriptor(\r\n \"nodeTransformations\",\r\n undefined,\r\n createNodeTransformationPropertyBag\r\n ),\r\n\r\n /**\r\n * Gets or sets the set of articulation values to apply to this model. This is represented as an {@link PropertyBag}, where keys are\r\n * composed as the name of the articulation, a single space, and the name of the stage.\r\n * @memberof ModelGraphics.prototype\r\n * @type {PropertyBag}\r\n */\r\n articulations: createPropertyDescriptor(\r\n \"articulations\",\r\n undefined,\r\n createArticulationStagePropertyBag\r\n ),\r\n\r\n /**\r\n * A property specifying the {@link ClippingPlaneCollection} used to selectively disable rendering the model.\r\n * @memberof ModelGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n clippingPlanes: createPropertyDescriptor(\"clippingPlanes\"),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {ModelGraphics} [result] The object onto which to store the result.\r\n * @returns {ModelGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nModelGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new ModelGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.uri = this.uri;\r\n result.scale = this.scale;\r\n result.minimumPixelSize = this.minimumPixelSize;\r\n result.maximumScale = this.maximumScale;\r\n result.incrementallyLoadTextures = this.incrementallyLoadTextures;\r\n result.runAnimations = this.runAnimations;\r\n result.clampAnimations = this.clampAnimations;\r\n result.heightReference = this._heightReference;\r\n result.silhouetteColor = this.silhouetteColor;\r\n result.silhouetteSize = this.silhouetteSize;\r\n result.color = this.color;\r\n result.colorBlendMode = this.colorBlendMode;\r\n result.colorBlendAmount = this.colorBlendAmount;\r\n result.imageBasedLightingFactor = this.imageBasedLightingFactor;\r\n result.lightColor = this.lightColor;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n result.nodeTransformations = this.nodeTransformations;\r\n result.articulations = this.articulations;\r\n result.clippingPlanes = this.clippingPlanes;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {ModelGraphics} source The object to be merged into this object.\r\n */\r\nModelGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.uri = defaultValue(this.uri, source.uri);\r\n this.scale = defaultValue(this.scale, source.scale);\r\n this.minimumPixelSize = defaultValue(\r\n this.minimumPixelSize,\r\n source.minimumPixelSize\r\n );\r\n this.maximumScale = defaultValue(this.maximumScale, source.maximumScale);\r\n this.incrementallyLoadTextures = defaultValue(\r\n this.incrementallyLoadTextures,\r\n source.incrementallyLoadTextures\r\n );\r\n this.runAnimations = defaultValue(this.runAnimations, source.runAnimations);\r\n this.clampAnimations = defaultValue(\r\n this.clampAnimations,\r\n source.clampAnimations\r\n );\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.silhouetteColor = defaultValue(\r\n this.silhouetteColor,\r\n source.silhouetteColor\r\n );\r\n this.silhouetteSize = defaultValue(\r\n this.silhouetteSize,\r\n source.silhouetteSize\r\n );\r\n this.color = defaultValue(this.color, source.color);\r\n this.colorBlendMode = defaultValue(\r\n this.colorBlendMode,\r\n source.colorBlendMode\r\n );\r\n this.colorBlendAmount = defaultValue(\r\n this.colorBlendAmount,\r\n source.colorBlendAmount\r\n );\r\n this.imageBasedLightingFactor = defaultValue(\r\n this.imageBasedLightingFactor,\r\n source.imageBasedLightingFactor\r\n );\r\n this.lightColor = defaultValue(this.lightColor, source.lightColor);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.clippingPlanes = defaultValue(\r\n this.clippingPlanes,\r\n source.clippingPlanes\r\n );\r\n\r\n var sourceNodeTransformations = source.nodeTransformations;\r\n if (defined(sourceNodeTransformations)) {\r\n var targetNodeTransformations = this.nodeTransformations;\r\n if (defined(targetNodeTransformations)) {\r\n targetNodeTransformations.merge(sourceNodeTransformations);\r\n } else {\r\n this.nodeTransformations = new PropertyBag(\r\n sourceNodeTransformations,\r\n createNodeTransformationProperty\r\n );\r\n }\r\n }\r\n\r\n var sourceArticulations = source.articulations;\r\n if (defined(sourceArticulations)) {\r\n var targetArticulations = this.articulations;\r\n if (defined(targetArticulations)) {\r\n targetArticulations.merge(sourceArticulations);\r\n } else {\r\n this.articulations = new PropertyBag(sourceArticulations);\r\n }\r\n }\r\n};\r\nexport default ModelGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} Cesium3DTilesetGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the Cesium3DTilesetGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the tileset.\r\n * @property {Property | string | Resource} [uri] A string or Resource Property specifying the URI of the tileset.\r\n * @property {Property | number} [maximumScreenSpaceError] A number or Property specifying the maximum screen space error used to drive level of detail refinement.\r\n */\r\n\r\n/**\r\n * A 3D Tiles tileset represented by an {@link Entity}.\r\n * The tileset modelMatrix is determined by the containing Entity position and orientation\r\n * or is left unset if position is undefined.\r\n *\r\n * @alias Cesium3DTilesetGraphics\r\n * @constructor\r\n *\r\n * @param {Cesium3DTilesetGraphics.ConstructorOptions} [options] Object describing initialization options\r\n */\r\nfunction Cesium3DTilesetGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._uri = undefined;\r\n this._uriSubscription = undefined;\r\n this._maximumScreenSpaceError = undefined;\r\n this._maximumScreenSpaceErrorSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(Cesium3DTilesetGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof Cesium3DTilesetGraphics.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the model.\r\n * @memberof Cesium3DTilesetGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the string Property specifying the URI of the glTF asset.\r\n * @memberof Cesium3DTilesetGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n uri: createPropertyDescriptor(\"uri\"),\r\n\r\n /**\r\n * Gets or sets the maximum screen space error used to drive level of detail refinement.\r\n * @memberof Cesium3DTilesetGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n maximumScreenSpaceError: createPropertyDescriptor(\"maximumScreenSpaceError\"),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {Cesium3DTilesetGraphics} [result] The object onto which to store the result.\r\n * @returns {Cesium3DTilesetGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nCesium3DTilesetGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new Cesium3DTilesetGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.uri = this.uri;\r\n result.maximumScreenSpaceError = this.maximumScreenSpaceError;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {Cesium3DTilesetGraphics} source The object to be merged into this object.\r\n */\r\nCesium3DTilesetGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.uri = defaultValue(this.uri, source.uri);\r\n this.maximumScreenSpaceError = defaultValue(\r\n this.maximumScreenSpaceError,\r\n source.maximumScreenSpaceError\r\n );\r\n};\r\n\r\nexport default Cesium3DTilesetGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} PathGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the PathGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the path.\r\n * @property {Property | number} [leadTime] A Property specifying the number of seconds in front the object to show.\r\n * @property {Property | number} [trailTime] A Property specifying the number of seconds behind of the object to show.\r\n * @property {Property | number} [width=1.0] A numeric Property specifying the width in pixels.\r\n * @property {Property | number} [resolution=60] A numeric Property specifying the maximum number of seconds to step when sampling the position.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to draw the path.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this path will be displayed.\r\n */\r\n\r\n/**\r\n * Describes a polyline defined as the path made by an {@link Entity} as it moves over time.\r\n *\r\n * @alias PathGraphics\r\n * @constructor\r\n *\r\n * @param {PathGraphics.ConstructorOptions} [options] Object describing initialization options\r\n */\r\nfunction PathGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._leadTime = undefined;\r\n this._leadTimeSubscription = undefined;\r\n this._trailTime = undefined;\r\n this._trailTimeSubscription = undefined;\r\n this._width = undefined;\r\n this._widthSubscription = undefined;\r\n this._resolution = undefined;\r\n this._resolutionSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(PathGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof PathGraphics.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the path.\r\n * @memberof PathGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the number of seconds in front of the object to show.\r\n * @memberof PathGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n leadTime: createPropertyDescriptor(\"leadTime\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the number of seconds behind the object to show.\r\n * @memberof PathGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n trailTime: createPropertyDescriptor(\"trailTime\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width in pixels.\r\n * @memberof PathGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n width: createPropertyDescriptor(\"width\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the maximum number of seconds to step when sampling the position.\r\n * @memberof PathGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 60\r\n */\r\n resolution: createPropertyDescriptor(\"resolution\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to draw the path.\r\n * @memberof PathGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this path will be displayed.\r\n * @memberof PathGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {PathGraphics} [result] The object onto which to store the result.\r\n * @returns {PathGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nPathGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new PathGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.leadTime = this.leadTime;\r\n result.trailTime = this.trailTime;\r\n result.width = this.width;\r\n result.resolution = this.resolution;\r\n result.material = this.material;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {PathGraphics} source The object to be merged into this object.\r\n */\r\nPathGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.leadTime = defaultValue(this.leadTime, source.leadTime);\r\n this.trailTime = defaultValue(this.trailTime, source.trailTime);\r\n this.width = defaultValue(this.width, source.width);\r\n this.resolution = defaultValue(this.resolution, source.resolution);\r\n this.material = defaultValue(this.material, source.material);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n};\r\nexport default PathGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} PlaneGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the PlaneGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the plane.\r\n * @property {Property | Plane} [plane] A {@link Plane} Property specifying the normal and distance for the plane.\r\n * @property {Property | Cartesian2} [dimensions] A {@link Cartesian2} Property specifying the width and height of the plane.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the plane is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the plane.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the plane is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the plane casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this plane will be displayed.\r\n */\r\n\r\n/**\r\n * Describes a plane. The center position and orientation are determined by the containing {@link Entity}.\r\n *\r\n * @alias PlaneGraphics\r\n * @constructor\r\n *\r\n * @param {PlaneGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Plane.html|Cesium Sandcastle Plane Demo}\r\n */\r\nfunction PlaneGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._plane = undefined;\r\n this._planeSubscription = undefined;\r\n this._dimensions = undefined;\r\n this._dimensionsSubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(PlaneGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the plane.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the {@link Plane} Property specifying the normal and distance of the plane.\r\n *\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n plane: createPropertyDescriptor(\"plane\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying the width and height of the plane.\r\n *\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n dimensions: createPropertyDescriptor(\"dimensions\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the plane is filled with the provided material.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the material used to fill the plane.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the plane is outlined.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the plane\r\n * casts or receives shadows from light sources.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this plane will be displayed.\r\n * @memberof PlaneGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {PlaneGraphics} [result] The object onto which to store the result.\r\n * @returns {PlaneGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nPlaneGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new PlaneGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.plane = this.plane;\r\n result.dimensions = this.dimensions;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {PlaneGraphics} source The object to be merged into this object.\r\n */\r\nPlaneGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.plane = defaultValue(this.plane, source.plane);\r\n this.dimensions = defaultValue(this.dimensions, source.dimensions);\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n};\r\nexport default PlaneGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} PointGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the PointGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the point.\r\n * @property {Property | number} [pixelSize=1] A numeric Property specifying the size in pixels.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height is relative to.\r\n * @property {Property | Color} [color=Color.WHITE] A Property specifying the {@link Color} of the point.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=0] A numeric Property specifying the the outline width in pixels.\r\n * @property {Property | NearFarScalar} [scaleByDistance] A {@link NearFarScalar} Property used to scale the point based on distance.\r\n * @property {Property | NearFarScalar} [translucencyByDistance] A {@link NearFarScalar} Property used to set translucency based on distance from the camera.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this point will be displayed.\r\n * @property {Property | number} [disableDepthTestDistance] A Property specifying the distance from the camera at which to disable the depth test to.\r\n */\r\n\r\n/**\r\n * Describes a graphical point located at the position of the containing {@link Entity}.\r\n *\r\n * @alias PointGraphics\r\n * @constructor\r\n *\r\n * @param {PointGraphics.ConstructorOptions} [options] Object describing initialization options\r\n */\r\nfunction PointGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._pixelSize = undefined;\r\n this._pixelSizeSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._scaleByDistance = undefined;\r\n this._scaleByDistanceSubscription = undefined;\r\n this._translucencyByDistance = undefined;\r\n this._translucencyByDistanceSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n this._disableDepthTestDistance = undefined;\r\n this._disableDepthTestDistanceSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(PointGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof PointGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the point.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the size in pixels.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1\r\n */\r\n pixelSize: createPropertyDescriptor(\"pixelSize\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the point.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the the outline width in pixels.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Gets or sets the {@link NearFarScalar} Property used to scale the point based on distance.\r\n * If undefined, a constant size is used.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n scaleByDistance: createPropertyDescriptor(\"scaleByDistance\"),\r\n\r\n /**\r\n * Gets or sets {@link NearFarScalar} Property specifying the translucency of the point based on the distance from the camera.\r\n * A point's translucency will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the points's translucency remains clamped to the nearest bound.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n translucencyByDistance: createPropertyDescriptor(\"translucencyByDistance\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this point will be displayed.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.\r\n * When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.\r\n * @memberof PointGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n disableDepthTestDistance: createPropertyDescriptor(\r\n \"disableDepthTestDistance\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {PointGraphics} [result] The object onto which to store the result.\r\n * @returns {PointGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nPointGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new PointGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.pixelSize = this.pixelSize;\r\n result.heightReference = this.heightReference;\r\n result.color = this.color;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.scaleByDistance = this.scaleByDistance;\r\n result.translucencyByDistance = this._translucencyByDistance;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n result.disableDepthTestDistance = this.disableDepthTestDistance;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {PointGraphics} source The object to be merged into this object.\r\n */\r\nPointGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.pixelSize = defaultValue(this.pixelSize, source.pixelSize);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.color = defaultValue(this.color, source.color);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.scaleByDistance = defaultValue(\r\n this.scaleByDistance,\r\n source.scaleByDistance\r\n );\r\n this.translucencyByDistance = defaultValue(\r\n this._translucencyByDistance,\r\n source.translucencyByDistance\r\n );\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.disableDepthTestDistance = defaultValue(\r\n this.disableDepthTestDistance,\r\n source.disableDepthTestDistance\r\n );\r\n};\r\nexport default PointGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport PolygonHierarchy from \"../Core/PolygonHierarchy.js\";\r\nimport ConstantProperty from \"./ConstantProperty.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\nfunction createPolygonHierarchyProperty(value) {\r\n if (Array.isArray(value)) {\r\n // convert array of positions to PolygonHierarchy object\r\n value = new PolygonHierarchy(value);\r\n }\r\n return new ConstantProperty(value);\r\n}\r\n\r\n/**\r\n * @typedef {Object} PolygonGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the PolygonGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the polygon.\r\n * @property {Property | PolygonHierarchy} [hierarchy] A Property specifying the {@link PolygonHierarchy}.\r\n * @property {Property | number} [height=0] A numeric Property specifying the altitude of the polygon relative to the ellipsoid surface.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height is relative to.\r\n * @property {Property | number} [extrudedHeight] A numeric Property specifying the altitude of the polygon's extruded face relative to the ellipsoid surface.\r\n * @property {Property | HeightReference} [extrudedHeightReference=HeightReference.NONE] A Property specifying what the extrudedHeight is relative to.\r\n * @property {Property | number} [stRotation=0.0] A numeric property specifying the rotation of the polygon texture counter-clockwise from north.\r\n * @property {Property | number} [granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude point.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the polygon is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the polygon.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the polygon is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | boolean} [perPositionHeight=false] A boolean specifying whether or not the height of each position is used.\r\n * @property {Boolean | boolean} [closeTop=true] When false, leaves off the top of an extruded polygon open.\r\n * @property {Boolean | boolean} [closeBottom=true] When false, leaves off the bottom of an extruded polygon open.\r\n * @property {Property | ArcType} [arcType=ArcType.GEODESIC] The type of line the polygon edges must follow.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the polygon casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this polygon will be displayed.\r\n * @property {Property | ClassificationType} [classificationType=ClassificationType.BOTH] An enum Property specifying whether this polygon will classify terrain, 3D Tiles, or both when on the ground.\r\n * @property {ConstantProperty | number} [zIndex=0] A property specifying the zIndex used for ordering ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified.\r\n */\r\n\r\n/**\r\n * Describes a polygon defined by an hierarchy of linear rings which make up the outer shape and any nested holes.\r\n * The polygon conforms to the curvature of the globe and can be placed on the surface or\r\n * at altitude and can optionally be extruded into a volume.\r\n *\r\n * @alias PolygonGraphics\r\n * @constructor\r\n *\r\n * @param {PolygonGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @see Entity\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Polygon.html|Cesium Sandcastle Polygon Demo}\r\n */\r\nfunction PolygonGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._hierarchy = undefined;\r\n this._hierarchySubscription = undefined;\r\n this._height = undefined;\r\n this._heightSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._extrudedHeight = undefined;\r\n this._extrudedHeightSubscription = undefined;\r\n this._extrudedHeightReference = undefined;\r\n this._extrudedHeightReferenceSubscription = undefined;\r\n this._stRotation = undefined;\r\n this._stRotationSubscription = undefined;\r\n this._granularity = undefined;\r\n this._granularitySubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._perPositionHeight = undefined;\r\n this._perPositionHeightSubscription = undefined;\r\n this._closeTop = undefined;\r\n this._closeTopSubscription = undefined;\r\n this._closeBottom = undefined;\r\n this._closeBottomSubscription = undefined;\r\n this._arcType = undefined;\r\n this._arcTypeSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n this._classificationType = undefined;\r\n this._classificationTypeSubscription = undefined;\r\n this._zIndex = undefined;\r\n this._zIndexSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(PolygonGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof PolygonGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the polygon.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link PolygonHierarchy}.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n hierarchy: createPropertyDescriptor(\r\n \"hierarchy\",\r\n undefined,\r\n createPolygonHierarchyProperty\r\n ),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the constant altitude of the polygon.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n height: createPropertyDescriptor(\"height\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the altitude of the polygon extrusion.\r\n * If {@link PolygonGraphics#perPositionHeight} is false, the volume starts at {@link PolygonGraphics#height} and ends at this altitude.\r\n * If {@link PolygonGraphics#perPositionHeight} is true, the volume starts at the height of each {@link PolygonGraphics#hierarchy} position and ends at this altitude.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n extrudedHeight: createPropertyDescriptor(\"extrudedHeight\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the extruded {@link HeightReference}.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n extrudedHeightReference: createPropertyDescriptor(\"extrudedHeightReference\"),\r\n\r\n /**\r\n * Gets or sets the numeric property specifying the rotation of the polygon texture counter-clockwise from north.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0\r\n */\r\n stRotation: createPropertyDescriptor(\"stRotation\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the angular distance between points on the polygon.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default {CesiumMath.RADIANS_PER_DEGREE}\r\n */\r\n granularity: createPropertyDescriptor(\"granularity\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the polygon is filled with the provided material.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to fill the polygon.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the polygon is outlined.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Gets or sets the boolean specifying whether or not the the height of each position is used.\r\n * If true, the shape will have non-uniform altitude defined by the height of each {@link PolygonGraphics#hierarchy} position.\r\n * If false, the shape will have a constant altitude as specified by {@link PolygonGraphics#height}.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n perPositionHeight: createPropertyDescriptor(\"perPositionHeight\"),\r\n\r\n /**\r\n * Gets or sets a boolean specifying whether or not the top of an extruded polygon is included.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n closeTop: createPropertyDescriptor(\"closeTop\"),\r\n\r\n /**\r\n * Gets or sets a boolean specifying whether or not the bottom of an extruded polygon is included.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n closeBottom: createPropertyDescriptor(\"closeBottom\"),\r\n\r\n /**\r\n * Gets or sets the {@link ArcType} Property specifying the type of lines the polygon edges use.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ArcType.GEODESIC\r\n */\r\n arcType: createPropertyDescriptor(\"arcType\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the polygon\r\n * casts or receives shadows from light sources.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this polygon will be displayed.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the {@link ClassificationType} Property specifying whether this polygon will classify terrain, 3D Tiles, or both when on the ground.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ClassificationType.BOTH\r\n */\r\n classificationType: createPropertyDescriptor(\"classificationType\"),\r\n\r\n /**\r\n * Gets or sets the zIndex Prperty specifying the ordering of ground geometry. Only has an effect if the polygon is constant and neither height or extrudedHeight are specified.\r\n * @memberof PolygonGraphics.prototype\r\n * @type {ConstantProperty|undefined}\r\n * @default 0\r\n */\r\n zIndex: createPropertyDescriptor(\"zIndex\"),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {PolygonGraphics} [result] The object onto which to store the result.\r\n * @returns {PolygonGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nPolygonGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new PolygonGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.hierarchy = this.hierarchy;\r\n result.height = this.height;\r\n result.heightReference = this.heightReference;\r\n result.extrudedHeight = this.extrudedHeight;\r\n result.extrudedHeightReference = this.extrudedHeightReference;\r\n result.stRotation = this.stRotation;\r\n result.granularity = this.granularity;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.perPositionHeight = this.perPositionHeight;\r\n result.closeTop = this.closeTop;\r\n result.closeBottom = this.closeBottom;\r\n result.arcType = this.arcType;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n result.classificationType = this.classificationType;\r\n result.zIndex = this.zIndex;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {PolygonGraphics} source The object to be merged into this object.\r\n */\r\nPolygonGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.hierarchy = defaultValue(this.hierarchy, source.hierarchy);\r\n this.height = defaultValue(this.height, source.height);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.extrudedHeight = defaultValue(\r\n this.extrudedHeight,\r\n source.extrudedHeight\r\n );\r\n this.extrudedHeightReference = defaultValue(\r\n this.extrudedHeightReference,\r\n source.extrudedHeightReference\r\n );\r\n this.stRotation = defaultValue(this.stRotation, source.stRotation);\r\n this.granularity = defaultValue(this.granularity, source.granularity);\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.perPositionHeight = defaultValue(\r\n this.perPositionHeight,\r\n source.perPositionHeight\r\n );\r\n this.closeTop = defaultValue(this.closeTop, source.closeTop);\r\n this.closeBottom = defaultValue(this.closeBottom, source.closeBottom);\r\n this.arcType = defaultValue(this.arcType, source.arcType);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.classificationType = defaultValue(\r\n this.classificationType,\r\n source.classificationType\r\n );\r\n this.zIndex = defaultValue(this.zIndex, source.zIndex);\r\n};\r\nexport default PolygonGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} PolylineGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the PolylineGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the polyline.\r\n * @property {Property | Array} [positions] A Property specifying the array of {@link Cartesian3} positions that define the line strip.\r\n * @property {Property | number} [width=1.0] A numeric Property specifying the width in pixels.\r\n * @property {Property | number} [granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude if arcType is not ArcType.NONE.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to draw the polyline.\r\n * @property {MaterialProperty | Color} [depthFailMaterial] A property specifying the material used to draw the polyline when it is below the terrain.\r\n * @property {Property | ArcType} [arcType=ArcType.GEODESIC] The type of line the polyline segments must follow.\r\n * @property {Property | boolean} [clampToGround=false] A boolean Property specifying whether the Polyline should be clamped to the ground.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the polyline casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this polyline will be displayed.\r\n * @property {Property | ClassificationType} [classificationType=ClassificationType.BOTH] An enum Property specifying whether this polyline will classify terrain, 3D Tiles, or both when on the ground.\r\n * @property {Property | number} [zIndex=0] A Property specifying the zIndex used for ordering ground geometry. Only has an effect if `clampToGround` is true and polylines on terrain is supported.\r\n */\r\n\r\n/**\r\n * Describes a polyline. The first two positions define a line segment,\r\n * and each additional position defines a line segment from the previous position. The segments\r\n * can be linear connected points, great arcs, or clamped to terrain.\r\n *\r\n * @alias PolylineGraphics\r\n * @constructor\r\n *\r\n * @param {PolylineGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @see Entity\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Polyline.html|Cesium Sandcastle Polyline Demo}\r\n */\r\nfunction PolylineGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._positions = undefined;\r\n this._positionsSubscription = undefined;\r\n this._width = undefined;\r\n this._widthSubscription = undefined;\r\n this._granularity = undefined;\r\n this._granularitySubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._depthFailMaterial = undefined;\r\n this._depthFailMaterialSubscription = undefined;\r\n this._arcType = undefined;\r\n this._arcTypeSubscription = undefined;\r\n this._clampToGround = undefined;\r\n this._clampToGroundSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n this._classificationType = undefined;\r\n this._classificationTypeSubscription = undefined;\r\n this._zIndex = undefined;\r\n this._zIndexSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(PolylineGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof PolylineGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the polyline.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the array of {@link Cartesian3}\r\n * positions that define the line strip.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n positions: createPropertyDescriptor(\"positions\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width in pixels.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n width: createPropertyDescriptor(\"width\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the angular distance between each latitude and longitude if arcType is not ArcType.NONE and clampToGround is false.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Cesium.Math.RADIANS_PER_DEGREE\r\n */\r\n granularity: createPropertyDescriptor(\"granularity\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to draw the polyline.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to draw the polyline when it fails the depth test.\r\n *

\r\n * Requires the EXT_frag_depth WebGL extension to render properly. If the extension is not supported,\r\n * there may be artifacts.\r\n *

\r\n * @memberof PolylineGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default undefined\r\n */\r\n depthFailMaterial: createMaterialPropertyDescriptor(\"depthFailMaterial\"),\r\n\r\n /**\r\n * Gets or sets the {@link ArcType} Property specifying whether the line segments should be great arcs, rhumb lines or linearly connected.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ArcType.GEODESIC\r\n */\r\n arcType: createPropertyDescriptor(\"arcType\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the polyline\r\n * should be clamped to the ground.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n clampToGround: createPropertyDescriptor(\"clampToGround\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the polyline\r\n * casts or receives shadows from light sources.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this polyline will be displayed.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the {@link ClassificationType} Property specifying whether this polyline will classify terrain, 3D Tiles, or both when on the ground.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ClassificationType.BOTH\r\n */\r\n classificationType: createPropertyDescriptor(\"classificationType\"),\r\n\r\n /**\r\n * Gets or sets the zIndex Property specifying the ordering of the polyline. Only has an effect if `clampToGround` is true and polylines on terrain is supported.\r\n * @memberof PolylineGraphics.prototype\r\n * @type {ConstantProperty|undefined}\r\n * @default 0\r\n */\r\n zIndex: createPropertyDescriptor(\"zIndex\"),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {PolylineGraphics} [result] The object onto which to store the result.\r\n * @returns {PolylineGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nPolylineGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new PolylineGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.positions = this.positions;\r\n result.width = this.width;\r\n result.granularity = this.granularity;\r\n result.material = this.material;\r\n result.depthFailMaterial = this.depthFailMaterial;\r\n result.arcType = this.arcType;\r\n result.clampToGround = this.clampToGround;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n result.classificationType = this.classificationType;\r\n result.zIndex = this.zIndex;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {PolylineGraphics} source The object to be merged into this object.\r\n */\r\nPolylineGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.positions = defaultValue(this.positions, source.positions);\r\n this.width = defaultValue(this.width, source.width);\r\n this.granularity = defaultValue(this.granularity, source.granularity);\r\n this.material = defaultValue(this.material, source.material);\r\n this.depthFailMaterial = defaultValue(\r\n this.depthFailMaterial,\r\n source.depthFailMaterial\r\n );\r\n this.arcType = defaultValue(this.arcType, source.arcType);\r\n this.clampToGround = defaultValue(this.clampToGround, source.clampToGround);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.classificationType = defaultValue(\r\n this.classificationType,\r\n source.classificationType\r\n );\r\n this.zIndex = defaultValue(this.zIndex, source.zIndex);\r\n};\r\nexport default PolylineGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} PolylineVolumeGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the PolylineVolumeGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the volume.\r\n * @property {Property | Array} [positions] A Property specifying the array of {@link Cartesian3} positions which define the line strip.\r\n * @property {Property | Array} [shape] A Property specifying the array of {@link Cartesian2} positions which define the shape to be extruded.\r\n * @property {Property | CornerType} [cornerType=CornerType.ROUNDED] A {@link CornerType} Property specifying the style of the corners.\r\n * @property {Property | number} [granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude point.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the volume is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the volume.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the volume is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the volume casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this volume will be displayed.\r\n */\r\n\r\n/**\r\n * Describes a polyline volume defined as a line strip and corresponding two dimensional shape which is extruded along it.\r\n * The resulting volume conforms to the curvature of the globe.\r\n *\r\n * @alias PolylineVolumeGraphics\r\n * @constructor\r\n *\r\n * @param {PolylineVolumeGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @see Entity\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Polyline%20Volume.html|Cesium Sandcastle Polyline Volume Demo}\r\n */\r\nfunction PolylineVolumeGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._positions = undefined;\r\n this._positionsSubscription = undefined;\r\n this._shape = undefined;\r\n this._shapeSubscription = undefined;\r\n this._cornerType = undefined;\r\n this._cornerTypeSubscription = undefined;\r\n this._granularity = undefined;\r\n this._granularitySubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubsription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(PolylineVolumeGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the volume.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the array of {@link Cartesian3} positions which define the line strip.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n positions: createPropertyDescriptor(\"positions\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the array of {@link Cartesian2} positions which define the shape to be extruded.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n shape: createPropertyDescriptor(\"shape\"),\r\n\r\n /**\r\n * Gets or sets the {@link CornerType} Property specifying the style of the corners.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default CornerType.ROUNDED\r\n */\r\n cornerType: createPropertyDescriptor(\"cornerType\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the angular distance between points on the volume.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default {CesiumMath.RADIANS_PER_DEGREE}\r\n */\r\n granularity: createPropertyDescriptor(\"granularity\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the volume is filled with the provided material.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to fill the volume.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the volume is outlined.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the volume\r\n * casts or receives shadows from light sources.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this volume will be displayed.\r\n * @memberof PolylineVolumeGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {PolylineVolumeGraphics} [result] The object onto which to store the result.\r\n * @returns {PolylineVolumeGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nPolylineVolumeGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new PolylineVolumeGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.positions = this.positions;\r\n result.shape = this.shape;\r\n result.cornerType = this.cornerType;\r\n result.granularity = this.granularity;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {PolylineVolumeGraphics} source The object to be merged into this object.\r\n */\r\nPolylineVolumeGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.positions = defaultValue(this.positions, source.positions);\r\n this.shape = defaultValue(this.shape, source.shape);\r\n this.cornerType = defaultValue(this.cornerType, source.cornerType);\r\n this.granularity = defaultValue(this.granularity, source.granularity);\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n};\r\nexport default PolylineVolumeGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} RectangleGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the RectangleGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the rectangle.\r\n * @property {Property | Rectangle} [coordinates] The Property specifying the {@link Rectangle}.\r\n * @property {Property | number} [height=0] A numeric Property specifying the altitude of the rectangle relative to the ellipsoid surface.\r\n * @property {Property | HeightReference} [heightReference=HeightReference.NONE] A Property specifying what the height is relative to.\r\n * @property {Property | number} [extrudedHeight] A numeric Property specifying the altitude of the rectangle's extruded face relative to the ellipsoid surface.\r\n * @property {Property | HeightReference} [extrudedHeightReference=HeightReference.NONE] A Property specifying what the extrudedHeight is relative to.\r\n * @property {Property | number} [rotation=0.0] A numeric property specifying the rotation of the rectangle clockwise from north.\r\n * @property {Property | number} [stRotation=0.0] A numeric property specifying the rotation of the rectangle texture counter-clockwise from north.\r\n * @property {Property | number} [granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between points on the rectangle.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the rectangle is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the rectangle.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the rectangle is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the rectangle casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this rectangle will be displayed.\r\n * @property {Property | ClassificationType} [classificationType=ClassificationType.BOTH] An enum Property specifying whether this rectangle will classify terrain, 3D Tiles, or both when on the ground.\r\n * @property {Property | number} [zIndex=0] A Property specifying the zIndex used for ordering ground geometry. Only has an effect if the rectangle is constant and neither height or extrudedHeight are specified.\r\n */\r\n\r\n/**\r\n * Describes graphics for a {@link Rectangle}.\r\n * The rectangle conforms to the curvature of the globe and can be placed on the surface or\r\n * at altitude and can optionally be extruded into a volume.\r\n *\r\n * @alias RectangleGraphics\r\n * @constructor\r\n *\r\n * @param {RectangleGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @see Entity\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Rectangle.html|Cesium Sandcastle Rectangle Demo}\r\n */\r\nfunction RectangleGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._coordinates = undefined;\r\n this._coordinatesSubscription = undefined;\r\n this._height = undefined;\r\n this._heightSubscription = undefined;\r\n this._heightReference = undefined;\r\n this._heightReferenceSubscription = undefined;\r\n this._extrudedHeight = undefined;\r\n this._extrudedHeightSubscription = undefined;\r\n this._extrudedHeightReference = undefined;\r\n this._extrudedHeightReferenceSubscription = undefined;\r\n this._rotation = undefined;\r\n this._rotationSubscription = undefined;\r\n this._stRotation = undefined;\r\n this._stRotationSubscription = undefined;\r\n this._granularity = undefined;\r\n this._granularitySubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distancedisplayConditionSubscription = undefined;\r\n this._classificationType = undefined;\r\n this._classificationTypeSubscription = undefined;\r\n this._zIndex = undefined;\r\n this._zIndexSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(RectangleGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof RectangleGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the rectangle.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Rectangle}.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n coordinates: createPropertyDescriptor(\"coordinates\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the altitude of the rectangle.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n height: createPropertyDescriptor(\"height\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link HeightReference}.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: createPropertyDescriptor(\"heightReference\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the altitude of the rectangle extrusion.\r\n * Setting this property creates volume starting at height and ending at this altitude.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n extrudedHeight: createPropertyDescriptor(\"extrudedHeight\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the extruded {@link HeightReference}.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default HeightReference.NONE\r\n */\r\n extrudedHeightReference: createPropertyDescriptor(\"extrudedHeightReference\"),\r\n\r\n /**\r\n * Gets or sets the numeric property specifying the rotation of the rectangle clockwise from north.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0\r\n */\r\n rotation: createPropertyDescriptor(\"rotation\"),\r\n\r\n /**\r\n * Gets or sets the numeric property specifying the rotation of the rectangle texture counter-clockwise from north.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 0\r\n */\r\n stRotation: createPropertyDescriptor(\"stRotation\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the angular distance between points on the rectangle.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default {CesiumMath.RADIANS_PER_DEGREE}\r\n */\r\n granularity: createPropertyDescriptor(\"granularity\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the rectangle is filled with the provided material.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to fill the rectangle.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the rectangle is outlined.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the rectangle\r\n * casts or receives shadows from light sources.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this rectangle will be displayed.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n\r\n /**\r\n * Gets or sets the {@link ClassificationType} Property specifying whether this rectangle will classify terrain, 3D Tiles, or both when on the ground.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ClassificationType.BOTH\r\n */\r\n classificationType: createPropertyDescriptor(\"classificationType\"),\r\n\r\n /**\r\n * Gets or sets the zIndex Property specifying the ordering of the rectangle. Only has an effect if the rectangle is constant and neither height or extrudedHeight are specified.\r\n * @memberof RectangleGraphics.prototype\r\n * @type {ConstantProperty|undefined}\r\n * @default 0\r\n */\r\n zIndex: createPropertyDescriptor(\"zIndex\"),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {RectangleGraphics} [result] The object onto which to store the result.\r\n * @returns {RectangleGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nRectangleGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new RectangleGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.coordinates = this.coordinates;\r\n result.height = this.height;\r\n result.heightReference = this.heightReference;\r\n result.extrudedHeight = this.extrudedHeight;\r\n result.extrudedHeightReference = this.extrudedHeightReference;\r\n result.rotation = this.rotation;\r\n result.stRotation = this.stRotation;\r\n result.granularity = this.granularity;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n result.classificationType = this.classificationType;\r\n result.zIndex = this.zIndex;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {RectangleGraphics} source The object to be merged into this object.\r\n */\r\nRectangleGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.coordinates = defaultValue(this.coordinates, source.coordinates);\r\n this.height = defaultValue(this.height, source.height);\r\n this.heightReference = defaultValue(\r\n this.heightReference,\r\n source.heightReference\r\n );\r\n this.extrudedHeight = defaultValue(\r\n this.extrudedHeight,\r\n source.extrudedHeight\r\n );\r\n this.extrudedHeightReference = defaultValue(\r\n this.extrudedHeightReference,\r\n source.extrudedHeightReference\r\n );\r\n this.rotation = defaultValue(this.rotation, source.rotation);\r\n this.stRotation = defaultValue(this.stRotation, source.stRotation);\r\n this.granularity = defaultValue(this.granularity, source.granularity);\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n this.classificationType = defaultValue(\r\n this.classificationType,\r\n source.classificationType\r\n );\r\n this.zIndex = defaultValue(this.zIndex, source.zIndex);\r\n};\r\nexport default RectangleGraphics;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createMaterialPropertyDescriptor from \"./createMaterialPropertyDescriptor.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\n\r\n/**\r\n * @typedef {Object} WallGraphics.ConstructorOptions\r\n *\r\n * Initialization options for the WallGraphics constructor\r\n *\r\n * @property {Property | boolean} [show=true] A boolean Property specifying the visibility of the wall.\r\n * @property {Property | Array} [positions] A Property specifying the array of {@link Cartesian3} positions which define the top of the wall.\r\n * @property {Property | Array} [minimumHeights] A Property specifying an array of heights to be used for the bottom of the wall instead of the globe surface.\r\n * @property {Property | Array} [maximumHeights] A Property specifying an array of heights to be used for the top of the wall instead of the height of each position.\r\n * @property {Property | number} [granularity=Cesium.Math.RADIANS_PER_DEGREE] A numeric Property specifying the angular distance between each latitude and longitude point.\r\n * @property {Property | boolean} [fill=true] A boolean Property specifying whether the wall is filled with the provided material.\r\n * @property {MaterialProperty | Color} [material=Color.WHITE] A Property specifying the material used to fill the wall.\r\n * @property {Property | boolean} [outline=false] A boolean Property specifying whether the wall is outlined.\r\n * @property {Property | Color} [outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @property {Property | number} [outlineWidth=1.0] A numeric Property specifying the width of the outline.\r\n * @property {Property | ShadowMode} [shadows=ShadowMode.DISABLED] An enum Property specifying whether the wall casts or receives shadows from light sources.\r\n * @property {Property | DistanceDisplayCondition} [distanceDisplayCondition] A Property specifying at what distance from the camera that this wall will be displayed.\r\n */\r\n\r\n/**\r\n * Describes a two dimensional wall defined as a line strip and optional maximum and minimum heights.\r\n * The wall conforms to the curvature of the globe and can be placed along the surface or at altitude.\r\n *\r\n * @alias WallGraphics\r\n * @constructor\r\n *\r\n * @param {WallGraphics.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @see Entity\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Wall.html|Cesium Sandcastle Wall Demo}\r\n */\r\nfunction WallGraphics(options) {\r\n this._definitionChanged = new Event();\r\n this._show = undefined;\r\n this._showSubscription = undefined;\r\n this._positions = undefined;\r\n this._positionsSubscription = undefined;\r\n this._minimumHeights = undefined;\r\n this._minimumHeightsSubscription = undefined;\r\n this._maximumHeights = undefined;\r\n this._maximumHeightsSubscription = undefined;\r\n this._granularity = undefined;\r\n this._granularitySubscription = undefined;\r\n this._fill = undefined;\r\n this._fillSubscription = undefined;\r\n this._material = undefined;\r\n this._materialSubscription = undefined;\r\n this._outline = undefined;\r\n this._outlineSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n this._shadows = undefined;\r\n this._shadowsSubscription = undefined;\r\n this._distanceDisplayCondition = undefined;\r\n this._distanceDisplayConditionSubscription = undefined;\r\n\r\n this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));\r\n}\r\n\r\nObject.defineProperties(WallGraphics.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof WallGraphics.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying the visibility of the wall.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n show: createPropertyDescriptor(\"show\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the array of {@link Cartesian3} positions which define the top of the wall.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n positions: createPropertyDescriptor(\"positions\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying an array of heights to be used for the bottom of the wall instead of the surface of the globe.\r\n * If defined, the array must be the same length as {@link Wall#positions}.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n minimumHeights: createPropertyDescriptor(\"minimumHeights\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying an array of heights to be used for the top of the wall instead of the height of each position.\r\n * If defined, the array must be the same length as {@link Wall#positions}.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n maximumHeights: createPropertyDescriptor(\"maximumHeights\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the angular distance between points on the wall.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default {CesiumMath.RADIANS_PER_DEGREE}\r\n */\r\n granularity: createPropertyDescriptor(\"granularity\"),\r\n\r\n /**\r\n * Gets or sets the boolean Property specifying whether the wall is filled with the provided material.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default true\r\n */\r\n fill: createPropertyDescriptor(\"fill\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the material used to fill the wall.\r\n * @memberof WallGraphics.prototype\r\n * @type {MaterialProperty}\r\n * @default Color.WHITE\r\n */\r\n material: createMaterialPropertyDescriptor(\"material\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying whether the wall is outlined.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default false\r\n */\r\n outline: createPropertyDescriptor(\"outline\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n\r\n /**\r\n * Get or sets the enum Property specifying whether the wall\r\n * casts or receives shadows from light sources.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n * @default ShadowMode.DISABLED\r\n */\r\n shadows: createPropertyDescriptor(\"shadows\"),\r\n\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this wall will be displayed.\r\n * @memberof WallGraphics.prototype\r\n * @type {Property|undefined}\r\n */\r\n distanceDisplayCondition: createPropertyDescriptor(\r\n \"distanceDisplayCondition\"\r\n ),\r\n});\r\n\r\n/**\r\n * Duplicates this instance.\r\n *\r\n * @param {WallGraphics} [result] The object onto which to store the result.\r\n * @returns {WallGraphics} The modified result parameter or a new instance if one was not provided.\r\n */\r\nWallGraphics.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n return new WallGraphics(this);\r\n }\r\n result.show = this.show;\r\n result.positions = this.positions;\r\n result.minimumHeights = this.minimumHeights;\r\n result.maximumHeights = this.maximumHeights;\r\n result.granularity = this.granularity;\r\n result.fill = this.fill;\r\n result.material = this.material;\r\n result.outline = this.outline;\r\n result.outlineColor = this.outlineColor;\r\n result.outlineWidth = this.outlineWidth;\r\n result.shadows = this.shadows;\r\n result.distanceDisplayCondition = this.distanceDisplayCondition;\r\n return result;\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {WallGraphics} source The object to be merged into this object.\r\n */\r\nWallGraphics.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(this.show, source.show);\r\n this.positions = defaultValue(this.positions, source.positions);\r\n this.minimumHeights = defaultValue(\r\n this.minimumHeights,\r\n source.minimumHeights\r\n );\r\n this.maximumHeights = defaultValue(\r\n this.maximumHeights,\r\n source.maximumHeights\r\n );\r\n this.granularity = defaultValue(this.granularity, source.granularity);\r\n this.fill = defaultValue(this.fill, source.fill);\r\n this.material = defaultValue(this.material, source.material);\r\n this.outline = defaultValue(this.outline, source.outline);\r\n this.outlineColor = defaultValue(this.outlineColor, source.outlineColor);\r\n this.outlineWidth = defaultValue(this.outlineWidth, source.outlineWidth);\r\n this.shadows = defaultValue(this.shadows, source.shadows);\r\n this.distanceDisplayCondition = defaultValue(\r\n this.distanceDisplayCondition,\r\n source.distanceDisplayCondition\r\n );\r\n};\r\nexport default WallGraphics;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Quaternion from \"../Core/Quaternion.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport GroundPolylinePrimitive from \"../Scene/GroundPolylinePrimitive.js\";\r\nimport GroundPrimitive from \"../Scene/GroundPrimitive.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport BillboardGraphics from \"./BillboardGraphics.js\";\r\nimport BoxGraphics from \"./BoxGraphics.js\";\r\nimport ConstantPositionProperty from \"./ConstantPositionProperty.js\";\r\nimport CorridorGraphics from \"./CorridorGraphics.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport createRawPropertyDescriptor from \"./createRawPropertyDescriptor.js\";\r\nimport CylinderGraphics from \"./CylinderGraphics.js\";\r\nimport EllipseGraphics from \"./EllipseGraphics.js\";\r\nimport EllipsoidGraphics from \"./EllipsoidGraphics.js\";\r\nimport LabelGraphics from \"./LabelGraphics.js\";\r\nimport ModelGraphics from \"./ModelGraphics.js\";\r\nimport Cesium3DTilesetGraphics from \"./Cesium3DTilesetGraphics.js\";\r\nimport PathGraphics from \"./PathGraphics.js\";\r\nimport PlaneGraphics from \"./PlaneGraphics.js\";\r\nimport PointGraphics from \"./PointGraphics.js\";\r\nimport PolygonGraphics from \"./PolygonGraphics.js\";\r\nimport PolylineGraphics from \"./PolylineGraphics.js\";\r\nimport PolylineVolumeGraphics from \"./PolylineVolumeGraphics.js\";\r\nimport Property from \"./Property.js\";\r\nimport PropertyBag from \"./PropertyBag.js\";\r\nimport RectangleGraphics from \"./RectangleGraphics.js\";\r\nimport WallGraphics from \"./WallGraphics.js\";\r\n\r\nvar cartoScratch = new Cartographic();\r\n\r\nfunction createConstantPositionProperty(value) {\r\n return new ConstantPositionProperty(value);\r\n}\r\n\r\nfunction createPositionPropertyDescriptor(name) {\r\n return createPropertyDescriptor(\r\n name,\r\n undefined,\r\n createConstantPositionProperty\r\n );\r\n}\r\n\r\nfunction createPropertyTypeDescriptor(name, Type) {\r\n return createPropertyDescriptor(name, undefined, function (value) {\r\n if (value instanceof Type) {\r\n return value;\r\n }\r\n return new Type(value);\r\n });\r\n}\r\n\r\n/**\r\n * @typedef {Object} Entity.ConstructorOptions\r\n *\r\n * Initialization options for the Entity constructor\r\n *\r\n * @property {String} [id] A unique identifier for this object. If none is provided, a GUID is generated.\r\n * @property {String} [name] A human readable name to display to users. It does not have to be unique.\r\n * @property {TimeIntervalCollection} [availability] The availability, if any, associated with this object.\r\n * @property {Boolean} [show] A boolean value indicating if the entity and its children are displayed.\r\n * @property {Property | string} [description] A string Property specifying an HTML description for this entity.\r\n * @property {PositionProperty | Cartesian3} [position] A Property specifying the entity position.\r\n * @property {Property} [orientation] A Property specifying the entity orientation.\r\n * @property {Property} [viewFrom] A suggested initial offset for viewing this object.\r\n * @property {Entity} [parent] A parent entity to associate with this entity.\r\n * @property {BillboardGraphics | BillboardGraphics.ConstructorOptions} [billboard] A billboard to associate with this entity.\r\n * @property {BoxGraphics | BoxGraphics.ConstructorOptions} [box] A box to associate with this entity.\r\n * @property {CorridorGraphics | CorridorGraphics.ConstructorOptions} [corridor] A corridor to associate with this entity.\r\n * @property {CylinderGraphics | CylinderGraphics.ConstructorOptions} [cylinder] A cylinder to associate with this entity.\r\n * @property {EllipseGraphics | EllipseGraphics.ConstructorOptions} [ellipse] A ellipse to associate with this entity.\r\n * @property {EllipsoidGraphics | EllipsoidGraphics.ConstructorOptions} [ellipsoid] A ellipsoid to associate with this entity.\r\n * @property {LabelGraphics | LabelGraphics.ConstructorOptions} [label] A options.label to associate with this entity.\r\n * @property {ModelGraphics | ModelGraphics.ConstructorOptions} [model] A model to associate with this entity.\r\n * @property {Cesium3DTilesetGraphics | Cesium3DTilesetGraphics.ConstructorOptions} [tileset] A 3D Tiles tileset to associate with this entity.\r\n * @property {PathGraphics | PathGraphics.ConstructorOptions} [path] A path to associate with this entity.\r\n * @property {PlaneGraphics | PlaneGraphics.ConstructorOptions} [plane] A plane to associate with this entity.\r\n * @property {PointGraphics | PointGraphics.ConstructorOptions} [point] A point to associate with this entity.\r\n * @property {PolygonGraphics | PolygonGraphics.ConstructorOptions} [polygon] A polygon to associate with this entity.\r\n * @property {PolylineGraphics | PolylineGraphics.ConstructorOptions} [polyline] A polyline to associate with this entity.\r\n * @property {PropertyBag | Object.} [properties] Arbitrary properties to associate with this entity.\r\n * @property {PolylineVolumeGraphics | PolylineVolumeGraphics.ConstructorOptions} [polylineVolume] A polylineVolume to associate with this entity.\r\n * @property {RectangleGraphics | RectangleGraphics.ConstructorOptions} [rectangle] A rectangle to associate with this entity.\r\n * @property {WallGraphics | WallGraphics.ConstructorOptions} [wall] A wall to associate with this entity.\r\n */\r\n\r\n/**\r\n * Entity instances aggregate multiple forms of visualization into a single high-level object.\r\n * They can be created manually and added to {@link Viewer#entities} or be produced by\r\n * data sources, such as {@link CzmlDataSource} and {@link GeoJsonDataSource}.\r\n * @alias Entity\r\n * @constructor\r\n *\r\n * @param {Entity.ConstructorOptions} [options] Object describing initialization options\r\n *\r\n * @see {@link https://cesium.com/docs/tutorials/creating-entities/|Creating Entities}\r\n */\r\nfunction Entity(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var id = options.id;\r\n if (!defined(id)) {\r\n id = createGuid();\r\n }\r\n\r\n this._availability = undefined;\r\n this._id = id;\r\n this._definitionChanged = new Event();\r\n this._name = options.name;\r\n this._show = defaultValue(options.show, true);\r\n this._parent = undefined;\r\n this._propertyNames = [\r\n \"billboard\",\r\n \"box\",\r\n \"corridor\",\r\n \"cylinder\",\r\n \"description\",\r\n \"ellipse\", //\r\n \"ellipsoid\",\r\n \"label\",\r\n \"model\",\r\n \"tileset\",\r\n \"orientation\",\r\n \"path\",\r\n \"plane\",\r\n \"point\",\r\n \"polygon\", //\r\n \"polyline\",\r\n \"polylineVolume\",\r\n \"position\",\r\n \"properties\",\r\n \"rectangle\",\r\n \"viewFrom\",\r\n \"wall\",\r\n ];\r\n\r\n this._billboard = undefined;\r\n this._billboardSubscription = undefined;\r\n this._box = undefined;\r\n this._boxSubscription = undefined;\r\n this._corridor = undefined;\r\n this._corridorSubscription = undefined;\r\n this._cylinder = undefined;\r\n this._cylinderSubscription = undefined;\r\n this._description = undefined;\r\n this._descriptionSubscription = undefined;\r\n this._ellipse = undefined;\r\n this._ellipseSubscription = undefined;\r\n this._ellipsoid = undefined;\r\n this._ellipsoidSubscription = undefined;\r\n this._label = undefined;\r\n this._labelSubscription = undefined;\r\n this._model = undefined;\r\n this._modelSubscription = undefined;\r\n this._tileset = undefined;\r\n this._tilesetSubscription = undefined;\r\n this._orientation = undefined;\r\n this._orientationSubscription = undefined;\r\n this._path = undefined;\r\n this._pathSubscription = undefined;\r\n this._plane = undefined;\r\n this._planeSubscription = undefined;\r\n this._point = undefined;\r\n this._pointSubscription = undefined;\r\n this._polygon = undefined;\r\n this._polygonSubscription = undefined;\r\n this._polyline = undefined;\r\n this._polylineSubscription = undefined;\r\n this._polylineVolume = undefined;\r\n this._polylineVolumeSubscription = undefined;\r\n this._position = undefined;\r\n this._positionSubscription = undefined;\r\n this._properties = undefined;\r\n this._propertiesSubscription = undefined;\r\n this._rectangle = undefined;\r\n this._rectangleSubscription = undefined;\r\n this._viewFrom = undefined;\r\n this._viewFromSubscription = undefined;\r\n this._wall = undefined;\r\n this._wallSubscription = undefined;\r\n this._children = [];\r\n\r\n /**\r\n * Gets or sets the entity collection that this entity belongs to.\r\n * @type {EntityCollection}\r\n */\r\n this.entityCollection = undefined;\r\n\r\n this.parent = options.parent;\r\n this.merge(options);\r\n}\r\n\r\nfunction updateShow(entity, children, isShowing) {\r\n var length = children.length;\r\n for (var i = 0; i < length; i++) {\r\n var child = children[i];\r\n var childShow = child._show;\r\n var oldValue = !isShowing && childShow;\r\n var newValue = isShowing && childShow;\r\n if (oldValue !== newValue) {\r\n updateShow(child, child._children, isShowing);\r\n }\r\n }\r\n entity._definitionChanged.raiseEvent(\r\n entity,\r\n \"isShowing\",\r\n isShowing,\r\n !isShowing\r\n );\r\n}\r\n\r\nObject.defineProperties(Entity.prototype, {\r\n /**\r\n * The availability, if any, associated with this object.\r\n * If availability is undefined, it is assumed that this object's\r\n * other properties will return valid data for any provided time.\r\n * If availability exists, the objects other properties will only\r\n * provide valid data if queried within the given interval.\r\n * @memberof Entity.prototype\r\n * @type {TimeIntervalCollection|undefined}\r\n */\r\n availability: createRawPropertyDescriptor(\"availability\"),\r\n /**\r\n * Gets the unique ID associated with this object.\r\n * @memberof Entity.prototype\r\n * @type {String}\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever a property or sub-property is changed or modified.\r\n * @memberof Entity.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets or sets the name of the object. The name is intended for end-user\r\n * consumption and does not need to be unique.\r\n * @memberof Entity.prototype\r\n * @type {String|undefined}\r\n */\r\n name: createRawPropertyDescriptor(\"name\"),\r\n /**\r\n * Gets or sets whether this entity should be displayed. When set to true,\r\n * the entity is only displayed if the parent entity's show property is also true.\r\n * @memberof Entity.prototype\r\n * @type {Boolean}\r\n */\r\n show: {\r\n get: function () {\r\n return this._show;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (value === this._show) {\r\n return;\r\n }\r\n\r\n var wasShowing = this.isShowing;\r\n this._show = value;\r\n var isShowing = this.isShowing;\r\n\r\n if (wasShowing !== isShowing) {\r\n updateShow(this, this._children, isShowing);\r\n }\r\n\r\n this._definitionChanged.raiseEvent(this, \"show\", value, !value);\r\n },\r\n },\r\n /**\r\n * Gets whether this entity is being displayed, taking into account\r\n * the visibility of any ancestor entities.\r\n * @memberof Entity.prototype\r\n * @type {Boolean}\r\n */\r\n isShowing: {\r\n get: function () {\r\n return (\r\n this._show &&\r\n (!defined(this.entityCollection) || this.entityCollection.show) &&\r\n (!defined(this._parent) || this._parent.isShowing)\r\n );\r\n },\r\n },\r\n /**\r\n * Gets or sets the parent object.\r\n * @memberof Entity.prototype\r\n * @type {Entity|undefined}\r\n */\r\n parent: {\r\n get: function () {\r\n return this._parent;\r\n },\r\n set: function (value) {\r\n var oldValue = this._parent;\r\n\r\n if (oldValue === value) {\r\n return;\r\n }\r\n\r\n var wasShowing = this.isShowing;\r\n if (defined(oldValue)) {\r\n var index = oldValue._children.indexOf(this);\r\n oldValue._children.splice(index, 1);\r\n }\r\n\r\n this._parent = value;\r\n if (defined(value)) {\r\n value._children.push(this);\r\n }\r\n\r\n var isShowing = this.isShowing;\r\n\r\n if (wasShowing !== isShowing) {\r\n updateShow(this, this._children, isShowing);\r\n }\r\n\r\n this._definitionChanged.raiseEvent(this, \"parent\", value, oldValue);\r\n },\r\n },\r\n /**\r\n * Gets the names of all properties registered on this instance.\r\n * @memberof Entity.prototype\r\n * @type {string[]}\r\n */\r\n propertyNames: {\r\n get: function () {\r\n return this._propertyNames;\r\n },\r\n },\r\n /**\r\n * Gets or sets the billboard.\r\n * @memberof Entity.prototype\r\n * @type {BillboardGraphics|undefined}\r\n */\r\n billboard: createPropertyTypeDescriptor(\"billboard\", BillboardGraphics),\r\n /**\r\n * Gets or sets the box.\r\n * @memberof Entity.prototype\r\n * @type {BoxGraphics|undefined}\r\n */\r\n box: createPropertyTypeDescriptor(\"box\", BoxGraphics),\r\n /**\r\n * Gets or sets the corridor.\r\n * @memberof Entity.prototype\r\n * @type {CorridorGraphics|undefined}\r\n */\r\n corridor: createPropertyTypeDescriptor(\"corridor\", CorridorGraphics),\r\n /**\r\n * Gets or sets the cylinder.\r\n * @memberof Entity.prototype\r\n * @type {CylinderGraphics|undefined}\r\n */\r\n cylinder: createPropertyTypeDescriptor(\"cylinder\", CylinderGraphics),\r\n /**\r\n * Gets or sets the description.\r\n * @memberof Entity.prototype\r\n * @type {Property|undefined}\r\n */\r\n description: createPropertyDescriptor(\"description\"),\r\n /**\r\n * Gets or sets the ellipse.\r\n * @memberof Entity.prototype\r\n * @type {EllipseGraphics|undefined}\r\n */\r\n ellipse: createPropertyTypeDescriptor(\"ellipse\", EllipseGraphics),\r\n /**\r\n * Gets or sets the ellipsoid.\r\n * @memberof Entity.prototype\r\n * @type {EllipsoidGraphics|undefined}\r\n */\r\n ellipsoid: createPropertyTypeDescriptor(\"ellipsoid\", EllipsoidGraphics),\r\n /**\r\n * Gets or sets the label.\r\n * @memberof Entity.prototype\r\n * @type {LabelGraphics|undefined}\r\n */\r\n label: createPropertyTypeDescriptor(\"label\", LabelGraphics),\r\n /**\r\n * Gets or sets the model.\r\n * @memberof Entity.prototype\r\n * @type {ModelGraphics|undefined}\r\n */\r\n model: createPropertyTypeDescriptor(\"model\", ModelGraphics),\r\n /**\r\n * Gets or sets the tileset.\r\n * @memberof Entity.prototype\r\n * @type {Cesium3DTilesetGraphics|undefined}\r\n */\r\n tileset: createPropertyTypeDescriptor(\"tileset\", Cesium3DTilesetGraphics),\r\n /**\r\n * Gets or sets the orientation.\r\n * @memberof Entity.prototype\r\n * @type {Property|undefined}\r\n */\r\n orientation: createPropertyDescriptor(\"orientation\"),\r\n /**\r\n * Gets or sets the path.\r\n * @memberof Entity.prototype\r\n * @type {PathGraphics|undefined}\r\n */\r\n path: createPropertyTypeDescriptor(\"path\", PathGraphics),\r\n /**\r\n * Gets or sets the plane.\r\n * @memberof Entity.prototype\r\n * @type {PlaneGraphics|undefined}\r\n */\r\n plane: createPropertyTypeDescriptor(\"plane\", PlaneGraphics),\r\n /**\r\n * Gets or sets the point graphic.\r\n * @memberof Entity.prototype\r\n * @type {PointGraphics|undefined}\r\n */\r\n point: createPropertyTypeDescriptor(\"point\", PointGraphics),\r\n /**\r\n * Gets or sets the polygon.\r\n * @memberof Entity.prototype\r\n * @type {PolygonGraphics|undefined}\r\n */\r\n polygon: createPropertyTypeDescriptor(\"polygon\", PolygonGraphics),\r\n /**\r\n * Gets or sets the polyline.\r\n * @memberof Entity.prototype\r\n * @type {PolylineGraphics|undefined}\r\n */\r\n polyline: createPropertyTypeDescriptor(\"polyline\", PolylineGraphics),\r\n /**\r\n * Gets or sets the polyline volume.\r\n * @memberof Entity.prototype\r\n * @type {PolylineVolumeGraphics|undefined}\r\n */\r\n polylineVolume: createPropertyTypeDescriptor(\r\n \"polylineVolume\",\r\n PolylineVolumeGraphics\r\n ),\r\n /**\r\n * Gets or sets the bag of arbitrary properties associated with this entity.\r\n * @memberof Entity.prototype\r\n * @type {PropertyBag|undefined}\r\n */\r\n properties: createPropertyTypeDescriptor(\"properties\", PropertyBag),\r\n /**\r\n * Gets or sets the position.\r\n * @memberof Entity.prototype\r\n * @type {PositionProperty|undefined}\r\n */\r\n position: createPositionPropertyDescriptor(\"position\"),\r\n /**\r\n * Gets or sets the rectangle.\r\n * @memberof Entity.prototype\r\n * @type {RectangleGraphics|undefined}\r\n */\r\n rectangle: createPropertyTypeDescriptor(\"rectangle\", RectangleGraphics),\r\n /**\r\n * Gets or sets the suggested initial offset when tracking this object.\r\n * The offset is typically defined in the east-north-up reference frame,\r\n * but may be another frame depending on the object's velocity.\r\n * @memberof Entity.prototype\r\n * @type {Property|undefined}\r\n */\r\n viewFrom: createPropertyDescriptor(\"viewFrom\"),\r\n /**\r\n * Gets or sets the wall.\r\n * @memberof Entity.prototype\r\n * @type {WallGraphics|undefined}\r\n */\r\n wall: createPropertyTypeDescriptor(\"wall\", WallGraphics),\r\n});\r\n\r\n/**\r\n * Given a time, returns true if this object should have data during that time.\r\n *\r\n * @param {JulianDate} time The time to check availability for.\r\n * @returns {Boolean} true if the object should have data during the provided time, false otherwise.\r\n */\r\nEntity.prototype.isAvailable = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var availability = this._availability;\r\n return !defined(availability) || availability.contains(time);\r\n};\r\n\r\n/**\r\n * Adds a property to this object. Once a property is added, it can be\r\n * observed with {@link Entity#definitionChanged} and composited\r\n * with {@link CompositeEntityCollection}\r\n *\r\n * @param {String} propertyName The name of the property to add.\r\n *\r\n * @exception {DeveloperError} \"propertyName\" is a reserved property name.\r\n * @exception {DeveloperError} \"propertyName\" is already a registered property.\r\n */\r\nEntity.prototype.addProperty = function (propertyName) {\r\n var propertyNames = this._propertyNames;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(propertyName)) {\r\n throw new DeveloperError(\"propertyName is required.\");\r\n }\r\n if (propertyNames.indexOf(propertyName) !== -1) {\r\n throw new DeveloperError(\r\n propertyName + \" is already a registered property.\"\r\n );\r\n }\r\n if (propertyName in this) {\r\n throw new DeveloperError(propertyName + \" is a reserved property name.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n propertyNames.push(propertyName);\r\n Object.defineProperty(\r\n this,\r\n propertyName,\r\n createRawPropertyDescriptor(propertyName, true)\r\n );\r\n};\r\n\r\n/**\r\n * Removed a property previously added with addProperty.\r\n *\r\n * @param {String} propertyName The name of the property to remove.\r\n *\r\n * @exception {DeveloperError} \"propertyName\" is a reserved property name.\r\n * @exception {DeveloperError} \"propertyName\" is not a registered property.\r\n */\r\nEntity.prototype.removeProperty = function (propertyName) {\r\n var propertyNames = this._propertyNames;\r\n var index = propertyNames.indexOf(propertyName);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(propertyName)) {\r\n throw new DeveloperError(\"propertyName is required.\");\r\n }\r\n if (index === -1) {\r\n throw new DeveloperError(propertyName + \" is not a registered property.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._propertyNames.splice(index, 1);\r\n delete this[propertyName];\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {Entity} source The object to be merged into this object.\r\n */\r\nEntity.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n //Name, show, and availability are not Property objects and are currently handled differently.\r\n //source.show is intentionally ignored because this.show always has a value.\r\n this.name = defaultValue(this.name, source.name);\r\n this.availability = defaultValue(this.availability, source.availability);\r\n\r\n var propertyNames = this._propertyNames;\r\n var sourcePropertyNames = defined(source._propertyNames)\r\n ? source._propertyNames\r\n : Object.keys(source);\r\n var propertyNamesLength = sourcePropertyNames.length;\r\n for (var i = 0; i < propertyNamesLength; i++) {\r\n var name = sourcePropertyNames[i];\r\n\r\n //While source is required by the API to be an Entity, we internally call this method from the\r\n //constructor with an options object to configure initial custom properties.\r\n //So we need to ignore reserved-non-property.\r\n if (name === \"parent\" || name === \"name\" || name === \"availability\") {\r\n continue;\r\n }\r\n\r\n var targetProperty = this[name];\r\n var sourceProperty = source[name];\r\n\r\n //Custom properties that are registered on the source entity must also\r\n //get registered on this entity.\r\n if (!defined(targetProperty) && propertyNames.indexOf(name) === -1) {\r\n this.addProperty(name);\r\n }\r\n\r\n if (defined(sourceProperty)) {\r\n if (defined(targetProperty)) {\r\n if (defined(targetProperty.merge)) {\r\n targetProperty.merge(sourceProperty);\r\n }\r\n } else if (\r\n defined(sourceProperty.merge) &&\r\n defined(sourceProperty.clone)\r\n ) {\r\n this[name] = sourceProperty.clone();\r\n } else {\r\n this[name] = sourceProperty;\r\n }\r\n }\r\n }\r\n};\r\n\r\nvar matrix3Scratch = new Matrix3();\r\nvar positionScratch = new Cartesian3();\r\nvar orientationScratch = new Quaternion();\r\n\r\n/**\r\n * Computes the model matrix for the entity's transform at specified time. Returns undefined if orientation or position\r\n * are undefined.\r\n *\r\n * @param {JulianDate} time The time to retrieve model matrix for.\r\n * @param {Matrix4} [result] The object onto which to store the result.\r\n *\r\n * @returns {Matrix4} The modified result parameter or a new Matrix4 instance if one was not provided. Result is undefined if position or orientation are undefined.\r\n */\r\nEntity.prototype.computeModelMatrix = function (time, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"time\", time);\r\n //>>includeEnd('debug');\r\n var position = Property.getValueOrUndefined(\r\n this._position,\r\n time,\r\n positionScratch\r\n );\r\n if (!defined(position)) {\r\n return undefined;\r\n }\r\n\r\n var orientation = Property.getValueOrUndefined(\r\n this._orientation,\r\n time,\r\n orientationScratch\r\n );\r\n if (!defined(orientation)) {\r\n result = Transforms.eastNorthUpToFixedFrame(position, undefined, result);\r\n } else {\r\n result = Matrix4.fromRotationTranslation(\r\n Matrix3.fromQuaternion(orientation, matrix3Scratch),\r\n position,\r\n result\r\n );\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nEntity.prototype.computeModelMatrixForHeightReference = function (\r\n time,\r\n heightReferenceProperty,\r\n heightOffset,\r\n ellipsoid,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"time\", time);\r\n //>>includeEnd('debug');\r\n var heightReference = Property.getValueOrDefault(\r\n heightReferenceProperty,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var position = Property.getValueOrUndefined(\r\n this._position,\r\n time,\r\n positionScratch\r\n );\r\n if (\r\n heightReference === HeightReference.NONE ||\r\n !defined(position) ||\r\n Cartesian3.equalsEpsilon(position, Cartesian3.ZERO, CesiumMath.EPSILON8)\r\n ) {\r\n return this.computeModelMatrix(time, result);\r\n }\r\n\r\n var carto = ellipsoid.cartesianToCartographic(position, cartoScratch);\r\n if (heightReference === HeightReference.CLAMP_TO_GROUND) {\r\n carto.height = heightOffset;\r\n } else {\r\n carto.height += heightOffset;\r\n }\r\n position = ellipsoid.cartographicToCartesian(carto, position);\r\n\r\n var orientation = Property.getValueOrUndefined(\r\n this._orientation,\r\n time,\r\n orientationScratch\r\n );\r\n if (!defined(orientation)) {\r\n result = Transforms.eastNorthUpToFixedFrame(position, undefined, result);\r\n } else {\r\n result = Matrix4.fromRotationTranslation(\r\n Matrix3.fromQuaternion(orientation, matrix3Scratch),\r\n position,\r\n result\r\n );\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Checks if the given Scene supports materials besides Color on Entities draped on terrain or 3D Tiles.\r\n * If this feature is not supported, Entities with non-color materials but no `height` will\r\n * instead be rendered as if height is 0.\r\n *\r\n * @param {Scene} scene The current scene.\r\n * @returns {Boolean} Whether or not the current scene supports materials for entities on terrain.\r\n */\r\nEntity.supportsMaterialsforEntitiesOnTerrain = function (scene) {\r\n return GroundPrimitive.supportsMaterials(scene);\r\n};\r\n\r\n/**\r\n * Checks if the given Scene supports polylines clamped to terrain or 3D Tiles.\r\n * If this feature is not supported, Entities with PolylineGraphics will be rendered with vertices at\r\n * the provided heights and using the `arcType` parameter instead of clamped to the ground.\r\n *\r\n * @param {Scene} scene The current scene.\r\n * @returns {Boolean} Whether or not the current scene supports polylines on terrain or 3D TIles.\r\n */\r\nEntity.supportsPolylinesOnTerrain = function (scene) {\r\n return GroundPolylinePrimitive.isSupported(scene);\r\n};\r\nexport default Entity;\r\n","import Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport oneTimeWarning from \"../Core/oneTimeWarning.js\";\r\nimport ClassificationType from \"../Scene/ClassificationType.js\";\r\nimport ShadowMode from \"../Scene/ShadowMode.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport ConstantProperty from \"./ConstantProperty.js\";\r\nimport Entity from \"./Entity.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultMaterial = new ColorMaterialProperty(Color.WHITE);\r\nvar defaultShow = new ConstantProperty(true);\r\nvar defaultFill = new ConstantProperty(true);\r\nvar defaultOutline = new ConstantProperty(false);\r\nvar defaultOutlineColor = new ConstantProperty(Color.BLACK);\r\nvar defaultShadows = new ConstantProperty(ShadowMode.DISABLED);\r\nvar defaultDistanceDisplayCondition = new ConstantProperty(\r\n new DistanceDisplayCondition()\r\n);\r\nvar defaultClassificationType = new ConstantProperty(ClassificationType.BOTH);\r\n\r\n/**\r\n * An abstract class for updating geometry entities.\r\n * @alias GeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Object} options An object with the following properties:\r\n * @param {Entity} options.entity The entity containing the geometry to be visualized.\r\n * @param {Scene} options.scene The scene where visualization is taking place.\r\n * @param {Object} options.geometryOptions Options for the geometry\r\n * @param {String} options.geometryPropertyName The geometry property name\r\n * @param {String[]} options.observedPropertyNames The entity properties this geometry cares about\r\n */\r\nfunction GeometryUpdater(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.entity\", options.entity);\r\n Check.defined(\"options.scene\", options.scene);\r\n Check.defined(\"options.geometryOptions\", options.geometryOptions);\r\n Check.defined(\"options.geometryPropertyName\", options.geometryPropertyName);\r\n Check.defined(\"options.observedPropertyNames\", options.observedPropertyNames);\r\n //>>includeEnd('debug');\r\n\r\n var entity = options.entity;\r\n var geometryPropertyName = options.geometryPropertyName;\r\n\r\n this._entity = entity;\r\n this._scene = options.scene;\r\n this._fillEnabled = false;\r\n this._isClosed = false;\r\n this._onTerrain = false;\r\n this._dynamic = false;\r\n this._outlineEnabled = false;\r\n this._geometryChanged = new Event();\r\n this._showProperty = undefined;\r\n this._materialProperty = undefined;\r\n this._showOutlineProperty = undefined;\r\n this._outlineColorProperty = undefined;\r\n this._outlineWidth = 1.0;\r\n this._shadowsProperty = undefined;\r\n this._distanceDisplayConditionProperty = undefined;\r\n this._classificationTypeProperty = undefined;\r\n this._options = options.geometryOptions;\r\n this._geometryPropertyName = geometryPropertyName;\r\n this._id = geometryPropertyName + \"-\" + entity.id;\r\n this._observedPropertyNames = options.observedPropertyNames;\r\n this._supportsMaterialsforEntitiesOnTerrain = Entity.supportsMaterialsforEntitiesOnTerrain(\r\n options.scene\r\n );\r\n}\r\n\r\nObject.defineProperties(GeometryUpdater.prototype, {\r\n /**\r\n * Gets the unique ID associated with this updater\r\n * @memberof GeometryUpdater.prototype\r\n * @type {String}\r\n * @readonly\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n /**\r\n * Gets the entity associated with this geometry.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Entity}\r\n * @readonly\r\n */\r\n entity: {\r\n get: function () {\r\n return this._entity;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry has a fill component.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n fillEnabled: {\r\n get: function () {\r\n return this._fillEnabled;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if fill visibility varies with simulation time.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n hasConstantFill: {\r\n get: function () {\r\n return (\r\n !this._fillEnabled ||\r\n (!defined(this._entity.availability) &&\r\n Property.isConstant(this._showProperty) &&\r\n Property.isConstant(this._fillProperty))\r\n );\r\n },\r\n },\r\n /**\r\n * Gets the material property used to fill the geometry.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {MaterialProperty}\r\n * @readonly\r\n */\r\n fillMaterialProperty: {\r\n get: function () {\r\n return this._materialProperty;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry has an outline component.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n outlineEnabled: {\r\n get: function () {\r\n return this._outlineEnabled;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry has an outline component.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n hasConstantOutline: {\r\n get: function () {\r\n return (\r\n !this._outlineEnabled ||\r\n (!defined(this._entity.availability) &&\r\n Property.isConstant(this._showProperty) &&\r\n Property.isConstant(this._showOutlineProperty))\r\n );\r\n },\r\n },\r\n /**\r\n * Gets the {@link Color} property for the geometry outline.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Property}\r\n * @readonly\r\n */\r\n outlineColorProperty: {\r\n get: function () {\r\n return this._outlineColorProperty;\r\n },\r\n },\r\n /**\r\n * Gets the constant with of the geometry outline, in pixels.\r\n * This value is only valid if isDynamic is false.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n outlineWidth: {\r\n get: function () {\r\n return this._outlineWidth;\r\n },\r\n },\r\n /**\r\n * Gets the property specifying whether the geometry\r\n * casts or receives shadows from light sources.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Property}\r\n * @readonly\r\n */\r\n shadowsProperty: {\r\n get: function () {\r\n return this._shadowsProperty;\r\n },\r\n },\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this geometry will be displayed.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Property}\r\n * @readonly\r\n */\r\n distanceDisplayConditionProperty: {\r\n get: function () {\r\n return this._distanceDisplayConditionProperty;\r\n },\r\n },\r\n /**\r\n * Gets or sets the {@link ClassificationType} Property specifying if this geometry will classify terrain, 3D Tiles, or both when on the ground.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Property}\r\n * @readonly\r\n */\r\n classificationTypeProperty: {\r\n get: function () {\r\n return this._classificationTypeProperty;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry is time-varying.\r\n * If true, all visualization is delegated to a DynamicGeometryUpdater\r\n * returned by GeometryUpdater#createDynamicUpdater.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isDynamic: {\r\n get: function () {\r\n return this._dynamic;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry is closed.\r\n * This property is only valid for static geometry.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isClosed: {\r\n get: function () {\r\n return this._isClosed;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry should be drawn on terrain.\r\n * @memberof EllipseGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n onTerrain: {\r\n get: function () {\r\n return this._onTerrain;\r\n },\r\n },\r\n /**\r\n * Gets an event that is raised whenever the public properties\r\n * of this updater change.\r\n * @memberof GeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n geometryChanged: {\r\n get: function () {\r\n return this._geometryChanged;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Checks if the geometry is outlined at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve visibility.\r\n * @returns {Boolean} true if geometry is outlined at the provided time, false otherwise.\r\n */\r\nGeometryUpdater.prototype.isOutlineVisible = function (time) {\r\n var entity = this._entity;\r\n var visible =\r\n this._outlineEnabled &&\r\n entity.isAvailable(time) &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time);\r\n return defaultValue(visible, false);\r\n};\r\n\r\n/**\r\n * Checks if the geometry is filled at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve visibility.\r\n * @returns {Boolean} true if geometry is filled at the provided time, false otherwise.\r\n */\r\nGeometryUpdater.prototype.isFilled = function (time) {\r\n var entity = this._entity;\r\n var visible =\r\n this._fillEnabled &&\r\n entity.isAvailable(time) &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time);\r\n return defaultValue(visible, false);\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @function\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nGeometryUpdater.prototype.createFillGeometryInstance =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @function\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nGeometryUpdater.prototype.createOutlineGeometryInstance =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nGeometryUpdater.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys and resources used by the object. Once an object is destroyed, it should not be used.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nGeometryUpdater.prototype.destroy = function () {\r\n destroyObject(this);\r\n};\r\n/**\r\n * @param {Entity} entity\r\n * @param {Object} geometry\r\n * @private\r\n */\r\nGeometryUpdater.prototype._isHidden = function (entity, geometry) {\r\n var show = geometry.show;\r\n return (\r\n defined(show) && show.isConstant && !show.getValue(Iso8601.MINIMUM_VALUE)\r\n );\r\n};\r\n\r\n/**\r\n * @param {Entity} entity\r\n * @param {Object} geometry\r\n * @private\r\n */\r\nGeometryUpdater.prototype._isOnTerrain = function (entity, geometry) {\r\n return false;\r\n};\r\n\r\n/**\r\n * @param {GeometryOptions} options\r\n * @private\r\n */\r\nGeometryUpdater.prototype._getIsClosed = function (options) {\r\n return true;\r\n};\r\n\r\n/**\r\n * @param {Entity} entity\r\n * @param {Object} geometry\r\n * @private\r\n */\r\nGeometryUpdater.prototype._isDynamic = DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * @param {Entity} entity\r\n * @param {Object} geometry\r\n * @private\r\n */\r\nGeometryUpdater.prototype._setStaticOptions =\r\n DeveloperError.throwInstantiationError;\r\n\r\n/**\r\n * @param {Entity} entity\r\n * @param {String} propertyName\r\n * @param {*} newValue\r\n * @param {*} oldValue\r\n * @private\r\n */\r\nGeometryUpdater.prototype._onEntityPropertyChanged = function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n) {\r\n if (this._observedPropertyNames.indexOf(propertyName) === -1) {\r\n return;\r\n }\r\n\r\n var geometry = this._entity[this._geometryPropertyName];\r\n\r\n if (!defined(geometry)) {\r\n if (this._fillEnabled || this._outlineEnabled) {\r\n this._fillEnabled = false;\r\n this._outlineEnabled = false;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n return;\r\n }\r\n\r\n var fillProperty = geometry.fill;\r\n var fillEnabled =\r\n defined(fillProperty) && fillProperty.isConstant\r\n ? fillProperty.getValue(Iso8601.MINIMUM_VALUE)\r\n : true;\r\n\r\n var outlineProperty = geometry.outline;\r\n var outlineEnabled = defined(outlineProperty);\r\n if (outlineEnabled && outlineProperty.isConstant) {\r\n outlineEnabled = outlineProperty.getValue(Iso8601.MINIMUM_VALUE);\r\n }\r\n\r\n if (!fillEnabled && !outlineEnabled) {\r\n if (this._fillEnabled || this._outlineEnabled) {\r\n this._fillEnabled = false;\r\n this._outlineEnabled = false;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n return;\r\n }\r\n\r\n var show = geometry.show;\r\n if (this._isHidden(entity, geometry)) {\r\n if (this._fillEnabled || this._outlineEnabled) {\r\n this._fillEnabled = false;\r\n this._outlineEnabled = false;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n return;\r\n }\r\n\r\n this._materialProperty = defaultValue(geometry.material, defaultMaterial);\r\n this._fillProperty = defaultValue(fillProperty, defaultFill);\r\n this._showProperty = defaultValue(show, defaultShow);\r\n this._showOutlineProperty = defaultValue(geometry.outline, defaultOutline);\r\n this._outlineColorProperty = outlineEnabled\r\n ? defaultValue(geometry.outlineColor, defaultOutlineColor)\r\n : undefined;\r\n this._shadowsProperty = defaultValue(geometry.shadows, defaultShadows);\r\n this._distanceDisplayConditionProperty = defaultValue(\r\n geometry.distanceDisplayCondition,\r\n defaultDistanceDisplayCondition\r\n );\r\n this._classificationTypeProperty = defaultValue(\r\n geometry.classificationType,\r\n defaultClassificationType\r\n );\r\n\r\n this._fillEnabled = fillEnabled;\r\n\r\n var onTerrain =\r\n this._isOnTerrain(entity, geometry) &&\r\n (this._supportsMaterialsforEntitiesOnTerrain ||\r\n this._materialProperty instanceof ColorMaterialProperty);\r\n\r\n if (outlineEnabled && onTerrain) {\r\n oneTimeWarning(oneTimeWarning.geometryOutlines);\r\n outlineEnabled = false;\r\n }\r\n\r\n this._onTerrain = onTerrain;\r\n this._outlineEnabled = outlineEnabled;\r\n\r\n if (this._isDynamic(entity, geometry)) {\r\n if (!this._dynamic) {\r\n this._dynamic = true;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n } else {\r\n this._setStaticOptions(entity, geometry);\r\n this._isClosed = this._getIsClosed(this._options);\r\n var outlineWidth = geometry.outlineWidth;\r\n this._outlineWidth = defined(outlineWidth)\r\n ? outlineWidth.getValue(Iso8601.MINIMUM_VALUE)\r\n : 1.0;\r\n this._dynamic = false;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n};\r\n\r\n/**\r\n * Creates the dynamic updater to be used when GeometryUpdater#isDynamic is true.\r\n *\r\n * @param {PrimitiveCollection} primitives The primitive collection to use.\r\n * @param {PrimitiveCollection} [groundPrimitives] The primitive collection to use for ground primitives.\r\n *\r\n * @returns {DynamicGeometryUpdater} The dynamic updater used to update the geometry each frame.\r\n *\r\n * @exception {DeveloperError} This instance does not represent dynamic geometry.\r\n * @private\r\n */\r\nGeometryUpdater.prototype.createDynamicUpdater = function (\r\n primitives,\r\n groundPrimitives\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"primitives\", primitives);\r\n Check.defined(\"groundPrimitives\", groundPrimitives);\r\n\r\n if (!this._dynamic) {\r\n throw new DeveloperError(\r\n \"This instance does not represent dynamic geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return new this.constructor.DynamicGeometryUpdater(\r\n this,\r\n primitives,\r\n groundPrimitives\r\n );\r\n};\r\nexport default GeometryUpdater;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\n\r\n/**\r\n * A {@link Property} whose value is lazily evaluated by a callback function.\r\n *\r\n * @alias CallbackProperty\r\n * @constructor\r\n *\r\n * @param {CallbackProperty.Callback} callback The function to be called when the property is evaluated.\r\n * @param {Boolean} isConstant true when the callback function returns the same value every time, false if the value will change.\r\n */\r\nfunction CallbackProperty(callback, isConstant) {\r\n this._callback = undefined;\r\n this._isConstant = undefined;\r\n this._definitionChanged = new Event();\r\n this.setCallback(callback, isConstant);\r\n}\r\n\r\nObject.defineProperties(CallbackProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant.\r\n * @memberof CallbackProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return this._isConstant;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever setCallback is called.\r\n * @memberof CallbackProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property.\r\n *\r\n * @param {JulianDate} [time] The time for which to retrieve the value. This parameter is unused since the value does not change with respect to time.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied or is unsupported.\r\n */\r\nCallbackProperty.prototype.getValue = function (time, result) {\r\n return this._callback(time, result);\r\n};\r\n\r\n/**\r\n * Sets the callback to be used.\r\n *\r\n * @param {CallbackProperty.Callback} callback The function to be called when the property is evaluated.\r\n * @param {Boolean} isConstant true when the callback function returns the same value every time, false if the value will change.\r\n */\r\nCallbackProperty.prototype.setCallback = function (callback, isConstant) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(callback)) {\r\n throw new DeveloperError(\"callback is required.\");\r\n }\r\n if (!defined(isConstant)) {\r\n throw new DeveloperError(\"isConstant is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var changed = this._callback !== callback || this._isConstant !== isConstant;\r\n\r\n this._callback = callback;\r\n this._isConstant = isConstant;\r\n\r\n if (changed) {\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCallbackProperty.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (other instanceof CallbackProperty &&\r\n this._callback === other._callback &&\r\n this._isConstant === other._isConstant)\r\n );\r\n};\r\n\r\n/**\r\n * A function that returns the value of the property.\r\n * @callback CallbackProperty.Callback\r\n *\r\n * @param {JulianDate} [time] The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied or is unsupported.\r\n */\r\nexport default CallbackProperty;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport SceneMode from \"../Scene/SceneMode.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar scratchPosition = new Cartesian3();\r\nvar scratchCarto = new Cartographic();\r\n\r\n/**\r\n * @private\r\n */\r\nfunction TerrainOffsetProperty(\r\n scene,\r\n positionProperty,\r\n heightReferenceProperty,\r\n extrudedHeightReferenceProperty\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"scene\", scene);\r\n Check.defined(\"positionProperty\", positionProperty);\r\n //>>includeEnd('debug');\r\n\r\n this._scene = scene;\r\n this._heightReference = heightReferenceProperty;\r\n this._extrudedHeightReference = extrudedHeightReferenceProperty;\r\n this._positionProperty = positionProperty;\r\n\r\n this._position = new Cartesian3();\r\n this._cartographicPosition = new Cartographic();\r\n this._normal = new Cartesian3();\r\n\r\n this._definitionChanged = new Event();\r\n this._terrainHeight = 0;\r\n this._removeCallbackFunc = undefined;\r\n this._removeEventListener = undefined;\r\n this._removeModeListener = undefined;\r\n\r\n var that = this;\r\n if (defined(scene.globe)) {\r\n this._removeEventListener = scene.terrainProviderChanged.addEventListener(\r\n function () {\r\n that._updateClamping();\r\n }\r\n );\r\n this._removeModeListener = scene.morphComplete.addEventListener(\r\n function () {\r\n that._updateClamping();\r\n }\r\n );\r\n }\r\n\r\n if (positionProperty.isConstant) {\r\n var position = positionProperty.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n scratchPosition\r\n );\r\n if (\r\n !defined(position) ||\r\n Cartesian3.equals(position, Cartesian3.ZERO) ||\r\n !defined(scene.globe)\r\n ) {\r\n return;\r\n }\r\n this._position = Cartesian3.clone(position, this._position);\r\n\r\n this._updateClamping();\r\n\r\n this._normal = scene.globe.ellipsoid.geodeticSurfaceNormal(\r\n position,\r\n this._normal\r\n );\r\n }\r\n}\r\n\r\nObject.defineProperties(TerrainOffsetProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant.\r\n * @memberof TerrainOffsetProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return false;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * @memberof TerrainOffsetProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @private\r\n */\r\nTerrainOffsetProperty.prototype._updateClamping = function () {\r\n if (defined(this._removeCallbackFunc)) {\r\n this._removeCallbackFunc();\r\n }\r\n\r\n var scene = this._scene;\r\n var globe = scene.globe;\r\n var position = this._position;\r\n\r\n if (!defined(globe) || Cartesian3.equals(position, Cartesian3.ZERO)) {\r\n this._terrainHeight = 0;\r\n return;\r\n }\r\n var ellipsoid = globe.ellipsoid;\r\n var surface = globe._surface;\r\n\r\n var that = this;\r\n var cartographicPosition = ellipsoid.cartesianToCartographic(\r\n position,\r\n this._cartographicPosition\r\n );\r\n var height = globe.getHeight(cartographicPosition);\r\n if (defined(height)) {\r\n this._terrainHeight = height;\r\n } else {\r\n this._terrainHeight = 0;\r\n }\r\n\r\n function updateFunction(clampedPosition) {\r\n if (scene.mode === SceneMode.SCENE3D) {\r\n var carto = ellipsoid.cartesianToCartographic(\r\n clampedPosition,\r\n scratchCarto\r\n );\r\n that._terrainHeight = carto.height;\r\n } else {\r\n that._terrainHeight = clampedPosition.x;\r\n }\r\n that.definitionChanged.raiseEvent();\r\n }\r\n this._removeCallbackFunc = surface.updateHeight(\r\n cartographicPosition,\r\n updateFunction\r\n );\r\n};\r\n\r\n/**\r\n * Gets the height relative to the terrain based on the positions.\r\n *\r\n * @returns {Cartesian3} The offset\r\n */\r\nTerrainOffsetProperty.prototype.getValue = function (time, result) {\r\n var heightReference = Property.getValueOrDefault(\r\n this._heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightReference = Property.getValueOrDefault(\r\n this._extrudedHeightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n\r\n if (\r\n heightReference === HeightReference.NONE &&\r\n extrudedHeightReference !== HeightReference.RELATIVE_TO_GROUND\r\n ) {\r\n this._position = Cartesian3.clone(Cartesian3.ZERO, this._position);\r\n return Cartesian3.clone(Cartesian3.ZERO, result);\r\n }\r\n\r\n if (this._positionProperty.isConstant) {\r\n return Cartesian3.multiplyByScalar(\r\n this._normal,\r\n this._terrainHeight,\r\n result\r\n );\r\n }\r\n\r\n var scene = this._scene;\r\n var position = this._positionProperty.getValue(time, scratchPosition);\r\n if (\r\n !defined(position) ||\r\n Cartesian3.equals(position, Cartesian3.ZERO) ||\r\n !defined(scene.globe)\r\n ) {\r\n return Cartesian3.clone(Cartesian3.ZERO, result);\r\n }\r\n\r\n if (\r\n Cartesian3.equalsEpsilon(this._position, position, CesiumMath.EPSILON10)\r\n ) {\r\n return Cartesian3.multiplyByScalar(\r\n this._normal,\r\n this._terrainHeight,\r\n result\r\n );\r\n }\r\n\r\n this._position = Cartesian3.clone(position, this._position);\r\n\r\n this._updateClamping();\r\n\r\n var normal = scene.globe.ellipsoid.geodeticSurfaceNormal(\r\n position,\r\n this._normal\r\n );\r\n return Cartesian3.multiplyByScalar(normal, this._terrainHeight, result);\r\n};\r\n\r\nTerrainOffsetProperty.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nTerrainOffsetProperty.prototype.destroy = function () {\r\n if (defined(this._removeEventListener)) {\r\n this._removeEventListener();\r\n }\r\n if (defined(this._removeModeListener)) {\r\n this._removeModeListener();\r\n }\r\n if (defined(this._removeCallbackFunc)) {\r\n this._removeCallbackFunc();\r\n }\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * A function which creates one or more providers.\r\n * @callback TerrainOffsetProperty.PositionFunction\r\n * @param {JulianDate} time The clock time at which to retrieve the position\r\n * @param {Cartesian3} result The result position\r\n * @returns {Cartesian3} The position at which to do the terrain height check\r\n */\r\nexport default TerrainOffsetProperty;\r\n","import defined from \"../Core/defined.js\";\r\nimport CallbackProperty from \"./CallbackProperty.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport TerrainOffsetProperty from \"./TerrainOffsetProperty.js\";\r\n\r\nfunction heightReferenceOnEntityPropertyChanged(\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n) {\r\n GeometryUpdater.prototype._onEntityPropertyChanged.call(\r\n this,\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n );\r\n if (this._observedPropertyNames.indexOf(propertyName) === -1) {\r\n return;\r\n }\r\n\r\n var geometry = this._entity[this._geometryPropertyName];\r\n if (!defined(geometry)) {\r\n return;\r\n }\r\n\r\n if (defined(this._terrainOffsetProperty)) {\r\n this._terrainOffsetProperty.destroy();\r\n this._terrainOffsetProperty = undefined;\r\n }\r\n\r\n var heightReferenceProperty = geometry.heightReference;\r\n\r\n if (defined(heightReferenceProperty)) {\r\n var centerPosition = new CallbackProperty(\r\n this._computeCenter.bind(this),\r\n !this._dynamic\r\n );\r\n this._terrainOffsetProperty = new TerrainOffsetProperty(\r\n this._scene,\r\n centerPosition,\r\n heightReferenceProperty\r\n );\r\n }\r\n}\r\nexport default heightReferenceOnEntityPropertyChanged;\r\n","import BoxGeometry from \"../Core/BoxGeometry.js\";\r\nimport BoxOutlineGeometry from \"../Core/BoxOutlineGeometry.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport GeometryOffsetAttribute from \"../Core/GeometryOffsetAttribute.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport heightReferenceOnEntityPropertyChanged from \"./heightReferenceOnEntityPropertyChanged.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultOffset = Cartesian3.ZERO;\r\n\r\nvar offsetScratch = new Cartesian3();\r\nvar positionScratch = new Cartesian3();\r\nvar scratchColor = new Color();\r\n\r\nfunction BoxGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.dimensions = undefined;\r\n this.offsetAttribute = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for boxes.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias BoxGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction BoxGeometryUpdater(entity, scene) {\r\n GeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new BoxGeometryOptions(entity),\r\n geometryPropertyName: \"box\",\r\n observedPropertyNames: [\"availability\", \"position\", \"orientation\", \"box\"],\r\n });\r\n\r\n this._onEntityPropertyChanged(entity, \"box\", entity.box, undefined);\r\n}\r\n\r\nif (defined(Object.create)) {\r\n BoxGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);\r\n BoxGeometryUpdater.prototype.constructor = BoxGeometryUpdater;\r\n}\r\n\r\nObject.defineProperties(BoxGeometryUpdater.prototype, {\r\n /**\r\n * Gets the terrain offset property\r\n * @type {TerrainOffsetProperty}\r\n * @memberof BoxGeometryUpdater.prototype\r\n * @readonly\r\n * @private\r\n */\r\n terrainOffsetProperty: {\r\n get: function () {\r\n return this._terrainOffsetProperty;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nBoxGeometryUpdater.prototype.createFillGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var show = new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n );\r\n\r\n var attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n color: undefined,\r\n offset: undefined,\r\n };\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n }\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: BoxGeometry.fromDimensions(this._options),\r\n modelMatrix: entity.computeModelMatrixForHeightReference(\r\n time,\r\n entity.box.heightReference,\r\n this._options.dimensions.z * 0.5,\r\n this._scene.mapProjection.ellipsoid\r\n ),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nBoxGeometryUpdater.prototype.createOutlineGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n offset: undefined,\r\n };\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: BoxOutlineGeometry.fromDimensions(this._options),\r\n modelMatrix: entity.computeModelMatrixForHeightReference(\r\n time,\r\n entity.box.heightReference,\r\n this._options.dimensions.z * 0.5,\r\n this._scene.mapProjection.ellipsoid\r\n ),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\nBoxGeometryUpdater.prototype._computeCenter = function (time, result) {\r\n return Property.getValueOrUndefined(this._entity.position, time, result);\r\n};\r\n\r\nBoxGeometryUpdater.prototype._isHidden = function (entity, box) {\r\n return (\r\n !defined(box.dimensions) ||\r\n !defined(entity.position) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, box)\r\n );\r\n};\r\n\r\nBoxGeometryUpdater.prototype._isDynamic = function (entity, box) {\r\n return (\r\n !entity.position.isConstant ||\r\n !Property.isConstant(entity.orientation) ||\r\n !box.dimensions.isConstant ||\r\n !Property.isConstant(box.outlineWidth)\r\n );\r\n};\r\n\r\nBoxGeometryUpdater.prototype._setStaticOptions = function (entity, box) {\r\n var heightReference = Property.getValueOrDefault(\r\n box.heightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n\r\n var options = this._options;\r\n options.vertexFormat =\r\n this._materialProperty instanceof ColorMaterialProperty\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.dimensions = box.dimensions.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.dimensions\r\n );\r\n options.offsetAttribute =\r\n heightReference !== HeightReference.NONE\r\n ? GeometryOffsetAttribute.ALL\r\n : undefined;\r\n};\r\n\r\nBoxGeometryUpdater.prototype._onEntityPropertyChanged = heightReferenceOnEntityPropertyChanged;\r\n\r\nBoxGeometryUpdater.DynamicGeometryUpdater = DynamicBoxGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicBoxGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicBoxGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicBoxGeometryUpdater.prototype.constructor = DynamicBoxGeometryUpdater;\r\n}\r\n\r\nDynamicBoxGeometryUpdater.prototype._isHidden = function (entity, box, time) {\r\n var position = Property.getValueOrUndefined(\r\n entity.position,\r\n time,\r\n positionScratch\r\n );\r\n var dimensions = this._options.dimensions;\r\n return (\r\n !defined(position) ||\r\n !defined(dimensions) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(this, entity, box, time)\r\n );\r\n};\r\n\r\nDynamicBoxGeometryUpdater.prototype._setOptions = function (entity, box, time) {\r\n var heightReference = Property.getValueOrDefault(\r\n box.heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var options = this._options;\r\n options.dimensions = Property.getValueOrUndefined(\r\n box.dimensions,\r\n time,\r\n options.dimensions\r\n );\r\n options.offsetAttribute =\r\n heightReference !== HeightReference.NONE\r\n ? GeometryOffsetAttribute.ALL\r\n : undefined;\r\n};\r\nexport default BoxGeometryUpdater;\r\n","import Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\n\r\n/**\r\n * Represents a command to the renderer for clearing a framebuffer.\r\n *\r\n * @private\r\n * @constructor\r\n */\r\nfunction ClearCommand(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * The value to clear the color buffer to. When undefined, the color buffer is not cleared.\r\n *\r\n * @type {Color}\r\n *\r\n * @default undefined\r\n */\r\n this.color = options.color;\r\n\r\n /**\r\n * The value to clear the depth buffer to. When undefined, the depth buffer is not cleared.\r\n *\r\n * @type {Number}\r\n *\r\n * @default undefined\r\n */\r\n this.depth = options.depth;\r\n\r\n /**\r\n * The value to clear the stencil buffer to. When undefined, the stencil buffer is not cleared.\r\n *\r\n * @type {Number}\r\n *\r\n * @default undefined\r\n */\r\n this.stencil = options.stencil;\r\n\r\n /**\r\n * The render state to apply when executing the clear command. The following states affect clearing:\r\n * scissor test, color mask, depth mask, and stencil mask. When the render state is\r\n * undefined, the default render state is used.\r\n *\r\n * @type {RenderState}\r\n *\r\n * @default undefined\r\n */\r\n this.renderState = options.renderState;\r\n\r\n /**\r\n * The framebuffer to clear.\r\n *\r\n * @type {Framebuffer}\r\n *\r\n * @default undefined\r\n */\r\n this.framebuffer = options.framebuffer;\r\n\r\n /**\r\n * The object who created this command. This is useful for debugging command\r\n * execution; it allows you to see who created a command when you only have a\r\n * reference to the command, and can be used to selectively execute commands\r\n * with {@link Scene#debugCommandFilter}.\r\n *\r\n * @type {Object}\r\n *\r\n * @default undefined\r\n *\r\n * @see Scene#debugCommandFilter\r\n */\r\n this.owner = options.owner;\r\n\r\n /**\r\n * The pass in which to run this command.\r\n *\r\n * @type {Pass}\r\n *\r\n * @default undefined\r\n */\r\n this.pass = options.pass;\r\n}\r\n\r\n/**\r\n * Clears color to (0.0, 0.0, 0.0, 0.0); depth to 1.0; and stencil to 0.\r\n *\r\n * @type {ClearCommand}\r\n *\r\n * @constant\r\n */\r\nClearCommand.ALL = Object.freeze(\r\n new ClearCommand({\r\n color: new Color(0.0, 0.0, 0.0, 0.0),\r\n depth: 1.0,\r\n stencil: 0.0,\r\n })\r\n);\r\n\r\nClearCommand.prototype.execute = function (context, passState) {\r\n context.clear(this, passState);\r\n};\r\nexport default ClearCommand;\r\n","import Check from \"../Core/Check.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\n\r\n/**\r\n * An enum describing the x, y, and z axes and helper conversion functions.\r\n *\r\n * @enum {Number}\r\n */\r\nvar Axis = {\r\n /**\r\n * Denotes the x-axis.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n X: 0,\r\n\r\n /**\r\n * Denotes the y-axis.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n Y: 1,\r\n\r\n /**\r\n * Denotes the z-axis.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n Z: 2,\r\n};\r\n\r\n/**\r\n * Matrix used to convert from y-up to z-up\r\n *\r\n * @type {Matrix4}\r\n * @constant\r\n */\r\nAxis.Y_UP_TO_Z_UP = Matrix4.fromRotationTranslation(\r\n Matrix3.fromRotationX(CesiumMath.PI_OVER_TWO)\r\n);\r\n\r\n/**\r\n * Matrix used to convert from z-up to y-up\r\n *\r\n * @type {Matrix4}\r\n * @constant\r\n */\r\nAxis.Z_UP_TO_Y_UP = Matrix4.fromRotationTranslation(\r\n Matrix3.fromRotationX(-CesiumMath.PI_OVER_TWO)\r\n);\r\n\r\n/**\r\n * Matrix used to convert from x-up to z-up\r\n *\r\n * @type {Matrix4}\r\n * @constant\r\n */\r\nAxis.X_UP_TO_Z_UP = Matrix4.fromRotationTranslation(\r\n Matrix3.fromRotationY(-CesiumMath.PI_OVER_TWO)\r\n);\r\n\r\n/**\r\n * Matrix used to convert from z-up to x-up\r\n *\r\n * @type {Matrix4}\r\n * @constant\r\n */\r\nAxis.Z_UP_TO_X_UP = Matrix4.fromRotationTranslation(\r\n Matrix3.fromRotationY(CesiumMath.PI_OVER_TWO)\r\n);\r\n\r\n/**\r\n * Matrix used to convert from x-up to y-up\r\n *\r\n * @type {Matrix4}\r\n * @constant\r\n */\r\nAxis.X_UP_TO_Y_UP = Matrix4.fromRotationTranslation(\r\n Matrix3.fromRotationZ(CesiumMath.PI_OVER_TWO)\r\n);\r\n\r\n/**\r\n * Matrix used to convert from y-up to x-up\r\n *\r\n * @type {Matrix4}\r\n * @constant\r\n */\r\nAxis.Y_UP_TO_X_UP = Matrix4.fromRotationTranslation(\r\n Matrix3.fromRotationZ(-CesiumMath.PI_OVER_TWO)\r\n);\r\n\r\n/**\r\n * Gets the axis by name\r\n *\r\n * @param {String} name The name of the axis.\r\n * @returns {Number} The axis enum.\r\n */\r\nAxis.fromName = function (name) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"name\", name);\r\n //>>includeEnd('debug');\r\n\r\n return Axis[name];\r\n};\r\n\r\nexport default Object.freeze(Axis);\r\n","/**\r\n * An enum describing the attribute type for glTF and 3D Tiles.\r\n *\r\n * @enum {String}\r\n *\r\n * @private\r\n */\r\nvar AttributeType = {\r\n /**\r\n * The attribute is a single component.\r\n *\r\n * @type {String}\r\n * @constant\r\n */\r\n SCALAR: \"SCALAR\",\r\n\r\n /**\r\n * The attribute is a two-component vector.\r\n *\r\n * @type {String}\r\n * @constant\r\n */\r\n VEC2: \"VEC2\",\r\n\r\n /**\r\n * The attribute is a three-component vector.\r\n *\r\n * @type {String}\r\n * @constant\r\n */\r\n VEC3: \"VEC3\",\r\n\r\n /**\r\n * The attribute is a four-component vector.\r\n *\r\n * @type {String}\r\n * @constant\r\n */\r\n VEC4: \"VEC4\",\r\n\r\n /**\r\n * The attribute is a 2x2 matrix.\r\n *\r\n * @type {String}\r\n * @constant\r\n */\r\n MAT2: \"MAT2\",\r\n\r\n /**\r\n * The attribute is a 3x3 matrix.\r\n *\r\n * @type {String}\r\n * @constant\r\n */\r\n MAT3: \"MAT3\",\r\n\r\n /**\r\n * The attribute is a 4x4 matrix.\r\n *\r\n * @type {String}\r\n * @constant\r\n */\r\n MAT4: \"MAT4\",\r\n};\r\nexport default Object.freeze(AttributeType);\r\n","/**\r\n * Defines how per-feature colors set from the Cesium API or declarative styling blend with the source colors from\r\n * the original feature, e.g. glTF material or per-point color in the tile.\r\n *

\r\n * When REPLACE or MIX are used and the source color is a glTF material, the technique must assign the\r\n * _3DTILESDIFFUSE semantic to the diffuse color parameter. Otherwise only HIGHLIGHT is supported.\r\n *

\r\n *

\r\n * A feature whose color evaluates to white (1.0, 1.0, 1.0) is always rendered without color blending, regardless of the\r\n * tileset's color blend mode.\r\n *

\r\n *
\r\n * \"techniques\": {\r\n *   \"technique0\": {\r\n *     \"parameters\": {\r\n *       \"diffuse\": {\r\n *         \"semantic\": \"_3DTILESDIFFUSE\",\r\n *         \"type\": 35666\r\n *       }\r\n *     }\r\n *   }\r\n * }\r\n * 
\r\n *\r\n * @enum {Number}\r\n */\r\nvar Cesium3DTileColorBlendMode = {\r\n /**\r\n * Multiplies the source color by the feature color.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n HIGHLIGHT: 0,\r\n\r\n /**\r\n * Replaces the source color with the feature color.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n REPLACE: 1,\r\n\r\n /**\r\n * Blends the source color and feature color together.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MIX: 2,\r\n};\r\nexport default Object.freeze(Cesium3DTileColorBlendMode);\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport Matrix2 from \"../Core/Matrix2.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\n\r\nvar ComponentsPerAttribute = {\r\n SCALAR: 1,\r\n VEC2: 2,\r\n VEC3: 3,\r\n VEC4: 4,\r\n MAT2: 4,\r\n MAT3: 9,\r\n MAT4: 16,\r\n};\r\n\r\nvar ClassPerType = {\r\n SCALAR: undefined,\r\n VEC2: Cartesian2,\r\n VEC3: Cartesian3,\r\n VEC4: Cartesian4,\r\n MAT2: Matrix2,\r\n MAT3: Matrix3,\r\n MAT4: Matrix4,\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nfunction getBinaryAccessor(accessor) {\r\n var componentType = accessor.componentType;\r\n var componentDatatype;\r\n if (typeof componentType === \"string\") {\r\n componentDatatype = ComponentDatatype.fromName(componentType);\r\n } else {\r\n componentDatatype = componentType;\r\n }\r\n\r\n var componentsPerAttribute = ComponentsPerAttribute[accessor.type];\r\n var classType = ClassPerType[accessor.type];\r\n return {\r\n componentsPerAttribute: componentsPerAttribute,\r\n classType: classType,\r\n createArrayBufferView: function (buffer, byteOffset, length) {\r\n return ComponentDatatype.createArrayBufferView(\r\n componentDatatype,\r\n buffer,\r\n byteOffset,\r\n componentsPerAttribute * length\r\n );\r\n },\r\n };\r\n}\r\nexport default getBinaryAccessor;\r\n","import arrayFill from \"../Core/arrayFill.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport clone from \"../Core/clone.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport deprecationWarning from \"../Core/deprecationWarning.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport ContextLimits from \"../Renderer/ContextLimits.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport PixelDatatype from \"../Renderer/PixelDatatype.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport Sampler from \"../Renderer/Sampler.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport AttributeType from \"./AttributeType.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport Cesium3DTileColorBlendMode from \"./Cesium3DTileColorBlendMode.js\";\r\nimport CullFace from \"./CullFace.js\";\r\nimport getBinaryAccessor from \"./getBinaryAccessor.js\";\r\nimport StencilConstants from \"./StencilConstants.js\";\r\nimport StencilFunction from \"./StencilFunction.js\";\r\nimport StencilOperation from \"./StencilOperation.js\";\r\n\r\nvar DEFAULT_COLOR_VALUE = Color.WHITE;\r\nvar DEFAULT_SHOW_VALUE = true;\r\n\r\n/**\r\n * @private\r\n * @constructor\r\n */\r\nfunction Cesium3DTileBatchTable(\r\n content,\r\n featuresLength,\r\n batchTableJson,\r\n batchTableBinary,\r\n colorChangedCallback\r\n) {\r\n /**\r\n * @readonly\r\n */\r\n this.featuresLength = featuresLength;\r\n\r\n this._translucentFeaturesLength = 0; // Number of features in the tile that are translucent\r\n\r\n var extensions;\r\n if (defined(batchTableJson)) {\r\n extensions = batchTableJson.extensions;\r\n }\r\n this._extensions = defaultValue(extensions, {});\r\n\r\n var properties = initializeProperties(batchTableJson);\r\n this._properties = properties;\r\n\r\n this._batchTableHierarchy = initializeHierarchy(\r\n this,\r\n batchTableJson,\r\n batchTableBinary\r\n );\r\n this._batchTableBinaryProperties = getBinaryProperties(\r\n featuresLength,\r\n properties,\r\n batchTableBinary\r\n );\r\n\r\n // PERFORMANCE_IDEA: These parallel arrays probably generate cache misses in get/set color/show\r\n // and use A LOT of memory. How can we use less memory?\r\n this._showAlphaProperties = undefined; // [Show (0 or 255), Alpha (0 to 255)] property for each feature\r\n this._batchValues = undefined; // Per-feature RGBA (A is based on the color's alpha and feature's show property)\r\n\r\n this._batchValuesDirty = false;\r\n this._batchTexture = undefined;\r\n this._defaultTexture = undefined;\r\n\r\n this._pickTexture = undefined;\r\n this._pickIds = [];\r\n\r\n this._content = content;\r\n\r\n this._colorChangedCallback = colorChangedCallback;\r\n\r\n // Dimensions for batch and pick textures\r\n var textureDimensions;\r\n var textureStep;\r\n\r\n if (featuresLength > 0) {\r\n // PERFORMANCE_IDEA: this can waste memory in the last row in the uncommon case\r\n // when more than one row is needed (e.g., > 16K features in one tile)\r\n var width = Math.min(featuresLength, ContextLimits.maximumTextureSize);\r\n var height = Math.ceil(featuresLength / ContextLimits.maximumTextureSize);\r\n var stepX = 1.0 / width;\r\n var centerX = stepX * 0.5;\r\n var stepY = 1.0 / height;\r\n var centerY = stepY * 0.5;\r\n\r\n textureDimensions = new Cartesian2(width, height);\r\n textureStep = new Cartesian4(stepX, centerX, stepY, centerY);\r\n }\r\n\r\n this._textureDimensions = textureDimensions;\r\n this._textureStep = textureStep;\r\n}\r\n\r\n// This can be overridden for testing purposes\r\nCesium3DTileBatchTable._deprecationWarning = deprecationWarning;\r\n\r\nObject.defineProperties(Cesium3DTileBatchTable.prototype, {\r\n memorySizeInBytes: {\r\n get: function () {\r\n var memory = 0;\r\n if (defined(this._pickTexture)) {\r\n memory += this._pickTexture.sizeInBytes;\r\n }\r\n if (defined(this._batchTexture)) {\r\n memory += this._batchTexture.sizeInBytes;\r\n }\r\n return memory;\r\n },\r\n },\r\n});\r\n\r\nfunction initializeProperties(jsonHeader) {\r\n var properties = {};\r\n\r\n if (!defined(jsonHeader)) {\r\n return properties;\r\n }\r\n\r\n for (var propertyName in jsonHeader) {\r\n if (\r\n jsonHeader.hasOwnProperty(propertyName) &&\r\n propertyName !== \"HIERARCHY\" && // Deprecated HIERARCHY property\r\n propertyName !== \"extensions\" &&\r\n propertyName !== \"extras\"\r\n ) {\r\n properties[propertyName] = clone(jsonHeader[propertyName], true);\r\n }\r\n }\r\n\r\n return properties;\r\n}\r\n\r\nfunction initializeHierarchy(batchTable, jsonHeader, binaryBody) {\r\n if (!defined(jsonHeader)) {\r\n return;\r\n }\r\n\r\n var hierarchy = batchTable._extensions[\"3DTILES_batch_table_hierarchy\"];\r\n\r\n var legacyHierarchy = jsonHeader.HIERARCHY;\r\n if (defined(legacyHierarchy)) {\r\n Cesium3DTileBatchTable._deprecationWarning(\r\n \"batchTableHierarchyExtension\",\r\n \"The batch table HIERARCHY property has been moved to an extension. Use extensions.3DTILES_batch_table_hierarchy instead.\"\r\n );\r\n batchTable._extensions[\"3DTILES_batch_table_hierarchy\"] = legacyHierarchy;\r\n hierarchy = legacyHierarchy;\r\n }\r\n\r\n if (!defined(hierarchy)) {\r\n return;\r\n }\r\n\r\n return initializeHierarchyValues(hierarchy, binaryBody);\r\n}\r\n\r\nfunction initializeHierarchyValues(hierarchyJson, binaryBody) {\r\n var i;\r\n var classId;\r\n var binaryAccessor;\r\n\r\n var instancesLength = hierarchyJson.instancesLength;\r\n var classes = hierarchyJson.classes;\r\n var classIds = hierarchyJson.classIds;\r\n var parentCounts = hierarchyJson.parentCounts;\r\n var parentIds = hierarchyJson.parentIds;\r\n var parentIdsLength = instancesLength;\r\n\r\n if (defined(classIds.byteOffset)) {\r\n classIds.componentType = defaultValue(\r\n classIds.componentType,\r\n ComponentDatatype.UNSIGNED_SHORT\r\n );\r\n classIds.type = AttributeType.SCALAR;\r\n binaryAccessor = getBinaryAccessor(classIds);\r\n classIds = binaryAccessor.createArrayBufferView(\r\n binaryBody.buffer,\r\n binaryBody.byteOffset + classIds.byteOffset,\r\n instancesLength\r\n );\r\n }\r\n\r\n var parentIndexes;\r\n if (defined(parentCounts)) {\r\n if (defined(parentCounts.byteOffset)) {\r\n parentCounts.componentType = defaultValue(\r\n parentCounts.componentType,\r\n ComponentDatatype.UNSIGNED_SHORT\r\n );\r\n parentCounts.type = AttributeType.SCALAR;\r\n binaryAccessor = getBinaryAccessor(parentCounts);\r\n parentCounts = binaryAccessor.createArrayBufferView(\r\n binaryBody.buffer,\r\n binaryBody.byteOffset + parentCounts.byteOffset,\r\n instancesLength\r\n );\r\n }\r\n parentIndexes = new Uint16Array(instancesLength);\r\n parentIdsLength = 0;\r\n for (i = 0; i < instancesLength; ++i) {\r\n parentIndexes[i] = parentIdsLength;\r\n parentIdsLength += parentCounts[i];\r\n }\r\n }\r\n\r\n if (defined(parentIds) && defined(parentIds.byteOffset)) {\r\n parentIds.componentType = defaultValue(\r\n parentIds.componentType,\r\n ComponentDatatype.UNSIGNED_SHORT\r\n );\r\n parentIds.type = AttributeType.SCALAR;\r\n binaryAccessor = getBinaryAccessor(parentIds);\r\n parentIds = binaryAccessor.createArrayBufferView(\r\n binaryBody.buffer,\r\n binaryBody.byteOffset + parentIds.byteOffset,\r\n parentIdsLength\r\n );\r\n }\r\n\r\n var classesLength = classes.length;\r\n for (i = 0; i < classesLength; ++i) {\r\n var classInstancesLength = classes[i].length;\r\n var properties = classes[i].instances;\r\n var binaryProperties = getBinaryProperties(\r\n classInstancesLength,\r\n properties,\r\n binaryBody\r\n );\r\n classes[i].instances = combine(binaryProperties, properties);\r\n }\r\n\r\n var classCounts = arrayFill(new Array(classesLength), 0);\r\n var classIndexes = new Uint16Array(instancesLength);\r\n for (i = 0; i < instancesLength; ++i) {\r\n classId = classIds[i];\r\n classIndexes[i] = classCounts[classId];\r\n ++classCounts[classId];\r\n }\r\n\r\n var hierarchy = {\r\n classes: classes,\r\n classIds: classIds,\r\n classIndexes: classIndexes,\r\n parentCounts: parentCounts,\r\n parentIndexes: parentIndexes,\r\n parentIds: parentIds,\r\n };\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n validateHierarchy(hierarchy);\r\n //>>includeEnd('debug');\r\n\r\n return hierarchy;\r\n}\r\n\r\n//>>includeStart('debug', pragmas.debug);\r\nvar scratchValidateStack = [];\r\nfunction validateHierarchy(hierarchy) {\r\n var stack = scratchValidateStack;\r\n stack.length = 0;\r\n\r\n var classIds = hierarchy.classIds;\r\n var instancesLength = classIds.length;\r\n\r\n for (var i = 0; i < instancesLength; ++i) {\r\n validateInstance(hierarchy, i, stack);\r\n }\r\n}\r\n\r\nfunction validateInstance(hierarchy, instanceIndex, stack) {\r\n var parentCounts = hierarchy.parentCounts;\r\n var parentIds = hierarchy.parentIds;\r\n var parentIndexes = hierarchy.parentIndexes;\r\n var classIds = hierarchy.classIds;\r\n var instancesLength = classIds.length;\r\n\r\n if (!defined(parentIds)) {\r\n // No need to validate if there are no parents\r\n return;\r\n }\r\n\r\n if (instanceIndex >= instancesLength) {\r\n throw new DeveloperError(\r\n \"Parent index \" +\r\n instanceIndex +\r\n \" exceeds the total number of instances: \" +\r\n instancesLength\r\n );\r\n }\r\n if (stack.indexOf(instanceIndex) > -1) {\r\n throw new DeveloperError(\r\n \"Circular dependency detected in the batch table hierarchy.\"\r\n );\r\n }\r\n\r\n stack.push(instanceIndex);\r\n var parentCount = defined(parentCounts) ? parentCounts[instanceIndex] : 1;\r\n var parentIndex = defined(parentCounts)\r\n ? parentIndexes[instanceIndex]\r\n : instanceIndex;\r\n for (var i = 0; i < parentCount; ++i) {\r\n var parentId = parentIds[parentIndex + i];\r\n // Stop the traversal when the instance has no parent (its parentId equals itself), else continue the traversal.\r\n if (parentId !== instanceIndex) {\r\n validateInstance(hierarchy, parentId, stack);\r\n }\r\n }\r\n stack.pop(instanceIndex);\r\n}\r\n//>>includeEnd('debug');\r\n\r\nfunction getBinaryProperties(featuresLength, properties, binaryBody) {\r\n var binaryProperties;\r\n for (var name in properties) {\r\n if (properties.hasOwnProperty(name)) {\r\n var property = properties[name];\r\n var byteOffset = property.byteOffset;\r\n if (defined(byteOffset)) {\r\n // This is a binary property\r\n var componentType = property.componentType;\r\n var type = property.type;\r\n if (!defined(componentType)) {\r\n throw new RuntimeError(\"componentType is required.\");\r\n }\r\n if (!defined(type)) {\r\n throw new RuntimeError(\"type is required.\");\r\n }\r\n if (!defined(binaryBody)) {\r\n throw new RuntimeError(\r\n \"Property \" + name + \" requires a batch table binary.\"\r\n );\r\n }\r\n\r\n var binaryAccessor = getBinaryAccessor(property);\r\n var componentCount = binaryAccessor.componentsPerAttribute;\r\n var classType = binaryAccessor.classType;\r\n var typedArray = binaryAccessor.createArrayBufferView(\r\n binaryBody.buffer,\r\n binaryBody.byteOffset + byteOffset,\r\n featuresLength\r\n );\r\n\r\n if (!defined(binaryProperties)) {\r\n binaryProperties = {};\r\n }\r\n\r\n // Store any information needed to access the binary data, including the typed array,\r\n // componentCount (e.g. a VEC4 would be 4), and the type used to pack and unpack (e.g. Cartesian4).\r\n binaryProperties[name] = {\r\n typedArray: typedArray,\r\n componentCount: componentCount,\r\n type: classType,\r\n };\r\n }\r\n }\r\n }\r\n return binaryProperties;\r\n}\r\n\r\nCesium3DTileBatchTable.getBinaryProperties = function (\r\n featuresLength,\r\n batchTableJson,\r\n batchTableBinary\r\n) {\r\n return getBinaryProperties(featuresLength, batchTableJson, batchTableBinary);\r\n};\r\n\r\nfunction getByteLength(batchTable) {\r\n var dimensions = batchTable._textureDimensions;\r\n return dimensions.x * dimensions.y * 4;\r\n}\r\n\r\nfunction getBatchValues(batchTable) {\r\n if (!defined(batchTable._batchValues)) {\r\n // Default batch texture to RGBA = 255: white highlight (RGB) and show/alpha = true/255 (A).\r\n var byteLength = getByteLength(batchTable);\r\n var bytes = new Uint8Array(byteLength);\r\n arrayFill(bytes, 255);\r\n batchTable._batchValues = bytes;\r\n }\r\n\r\n return batchTable._batchValues;\r\n}\r\n\r\nfunction getShowAlphaProperties(batchTable) {\r\n if (!defined(batchTable._showAlphaProperties)) {\r\n var byteLength = 2 * batchTable.featuresLength;\r\n var bytes = new Uint8Array(byteLength);\r\n // [Show = true, Alpha = 255]\r\n arrayFill(bytes, 255);\r\n batchTable._showAlphaProperties = bytes;\r\n }\r\n return batchTable._showAlphaProperties;\r\n}\r\n\r\nfunction checkBatchId(batchId, featuresLength) {\r\n if (!defined(batchId) || batchId < 0 || batchId > featuresLength) {\r\n throw new DeveloperError(\r\n \"batchId is required and between zero and featuresLength - 1 (\" +\r\n featuresLength -\r\n +\").\"\r\n );\r\n }\r\n}\r\n\r\nCesium3DTileBatchTable.prototype.setShow = function (batchId, show) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n Check.typeOf.bool(\"show\", show);\r\n //>>includeEnd('debug');\r\n\r\n if (show && !defined(this._showAlphaProperties)) {\r\n // Avoid allocating since the default is show = true\r\n return;\r\n }\r\n\r\n var showAlphaProperties = getShowAlphaProperties(this);\r\n var propertyOffset = batchId * 2;\r\n\r\n var newShow = show ? 255 : 0;\r\n if (showAlphaProperties[propertyOffset] !== newShow) {\r\n showAlphaProperties[propertyOffset] = newShow;\r\n\r\n var batchValues = getBatchValues(this);\r\n\r\n // Compute alpha used in the shader based on show and color.alpha properties\r\n var offset = batchId * 4 + 3;\r\n batchValues[offset] = show ? showAlphaProperties[propertyOffset + 1] : 0;\r\n\r\n this._batchValuesDirty = true;\r\n }\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.setAllShow = function (show) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.bool(\"show\", show);\r\n //>>includeEnd('debug');\r\n\r\n var featuresLength = this.featuresLength;\r\n for (var i = 0; i < featuresLength; ++i) {\r\n this.setShow(i, show);\r\n }\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.getShow = function (batchId) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(this._showAlphaProperties)) {\r\n // Avoid allocating since the default is show = true\r\n return true;\r\n }\r\n\r\n var offset = batchId * 2;\r\n return this._showAlphaProperties[offset] === 255;\r\n};\r\n\r\nvar scratchColorBytes = new Array(4);\r\n\r\nCesium3DTileBatchTable.prototype.setColor = function (batchId, color) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n Check.typeOf.object(\"color\", color);\r\n //>>includeEnd('debug');\r\n\r\n if (Color.equals(color, DEFAULT_COLOR_VALUE) && !defined(this._batchValues)) {\r\n // Avoid allocating since the default is white\r\n return;\r\n }\r\n\r\n var newColor = color.toBytes(scratchColorBytes);\r\n var newAlpha = newColor[3];\r\n\r\n var batchValues = getBatchValues(this);\r\n var offset = batchId * 4;\r\n\r\n var showAlphaProperties = getShowAlphaProperties(this);\r\n var propertyOffset = batchId * 2;\r\n\r\n if (\r\n batchValues[offset] !== newColor[0] ||\r\n batchValues[offset + 1] !== newColor[1] ||\r\n batchValues[offset + 2] !== newColor[2] ||\r\n showAlphaProperties[propertyOffset + 1] !== newAlpha\r\n ) {\r\n batchValues[offset] = newColor[0];\r\n batchValues[offset + 1] = newColor[1];\r\n batchValues[offset + 2] = newColor[2];\r\n\r\n var wasTranslucent = showAlphaProperties[propertyOffset + 1] !== 255;\r\n\r\n // Compute alpha used in the shader based on show and color.alpha properties\r\n var show = showAlphaProperties[propertyOffset] !== 0;\r\n batchValues[offset + 3] = show ? newAlpha : 0;\r\n showAlphaProperties[propertyOffset + 1] = newAlpha;\r\n\r\n // Track number of translucent features so we know if this tile needs\r\n // opaque commands, translucent commands, or both for rendering.\r\n var isTranslucent = newAlpha !== 255;\r\n if (isTranslucent && !wasTranslucent) {\r\n ++this._translucentFeaturesLength;\r\n } else if (!isTranslucent && wasTranslucent) {\r\n --this._translucentFeaturesLength;\r\n }\r\n\r\n this._batchValuesDirty = true;\r\n\r\n if (defined(this._colorChangedCallback)) {\r\n this._colorChangedCallback(batchId, color);\r\n }\r\n }\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.setAllColor = function (color) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"color\", color);\r\n //>>includeEnd('debug');\r\n\r\n var featuresLength = this.featuresLength;\r\n for (var i = 0; i < featuresLength; ++i) {\r\n this.setColor(i, color);\r\n }\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.getColor = function (batchId, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(this._batchValues)) {\r\n return Color.clone(DEFAULT_COLOR_VALUE, result);\r\n }\r\n\r\n var batchValues = this._batchValues;\r\n var offset = batchId * 4;\r\n\r\n var showAlphaProperties = this._showAlphaProperties;\r\n var propertyOffset = batchId * 2;\r\n\r\n return Color.fromBytes(\r\n batchValues[offset],\r\n batchValues[offset + 1],\r\n batchValues[offset + 2],\r\n showAlphaProperties[propertyOffset + 1],\r\n result\r\n );\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.getPickColor = function (batchId) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n //>>includeEnd('debug');\r\n return this._pickIds[batchId];\r\n};\r\n\r\nvar scratchColor = new Color();\r\n\r\nCesium3DTileBatchTable.prototype.applyStyle = function (style) {\r\n if (!defined(style)) {\r\n this.setAllColor(DEFAULT_COLOR_VALUE);\r\n this.setAllShow(DEFAULT_SHOW_VALUE);\r\n return;\r\n }\r\n\r\n var content = this._content;\r\n var length = this.featuresLength;\r\n for (var i = 0; i < length; ++i) {\r\n var feature = content.getFeature(i);\r\n var color = defined(style.color)\r\n ? style.color.evaluateColor(feature, scratchColor)\r\n : DEFAULT_COLOR_VALUE;\r\n var show = defined(style.show)\r\n ? style.show.evaluate(feature)\r\n : DEFAULT_SHOW_VALUE;\r\n this.setColor(i, color);\r\n this.setShow(i, show);\r\n }\r\n};\r\n\r\nfunction getBinaryProperty(binaryProperty, index) {\r\n var typedArray = binaryProperty.typedArray;\r\n var componentCount = binaryProperty.componentCount;\r\n if (componentCount === 1) {\r\n return typedArray[index];\r\n }\r\n return binaryProperty.type.unpack(typedArray, index * componentCount);\r\n}\r\n\r\nfunction setBinaryProperty(binaryProperty, index, value) {\r\n var typedArray = binaryProperty.typedArray;\r\n var componentCount = binaryProperty.componentCount;\r\n if (componentCount === 1) {\r\n typedArray[index] = value;\r\n } else {\r\n binaryProperty.type.pack(value, typedArray, index * componentCount);\r\n }\r\n}\r\n\r\n// The size of this array equals the maximum instance count among all loaded tiles, which has the potential to be large.\r\nvar scratchVisited = [];\r\nvar scratchStack = [];\r\nvar marker = 0;\r\nfunction traverseHierarchyMultipleParents(\r\n hierarchy,\r\n instanceIndex,\r\n endConditionCallback\r\n) {\r\n var classIds = hierarchy.classIds;\r\n var parentCounts = hierarchy.parentCounts;\r\n var parentIds = hierarchy.parentIds;\r\n var parentIndexes = hierarchy.parentIndexes;\r\n var instancesLength = classIds.length;\r\n\r\n // Ignore instances that have already been visited. This occurs in diamond inheritance situations.\r\n // Use a marker value to indicate that an instance has been visited, which increments with each run.\r\n // This is more efficient than clearing the visited array every time.\r\n var visited = scratchVisited;\r\n visited.length = Math.max(visited.length, instancesLength);\r\n var visitedMarker = ++marker;\r\n\r\n var stack = scratchStack;\r\n stack.length = 0;\r\n stack.push(instanceIndex);\r\n\r\n while (stack.length > 0) {\r\n instanceIndex = stack.pop();\r\n if (visited[instanceIndex] === visitedMarker) {\r\n // This instance has already been visited, stop traversal\r\n continue;\r\n }\r\n visited[instanceIndex] = visitedMarker;\r\n var result = endConditionCallback(hierarchy, instanceIndex);\r\n if (defined(result)) {\r\n // The end condition was met, stop the traversal and return the result\r\n return result;\r\n }\r\n var parentCount = parentCounts[instanceIndex];\r\n var parentIndex = parentIndexes[instanceIndex];\r\n for (var i = 0; i < parentCount; ++i) {\r\n var parentId = parentIds[parentIndex + i];\r\n // Stop the traversal when the instance has no parent (its parentId equals itself)\r\n // else add the parent to the stack to continue the traversal.\r\n if (parentId !== instanceIndex) {\r\n stack.push(parentId);\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction traverseHierarchySingleParent(\r\n hierarchy,\r\n instanceIndex,\r\n endConditionCallback\r\n) {\r\n var hasParent = true;\r\n while (hasParent) {\r\n var result = endConditionCallback(hierarchy, instanceIndex);\r\n if (defined(result)) {\r\n // The end condition was met, stop the traversal and return the result\r\n return result;\r\n }\r\n var parentId = hierarchy.parentIds[instanceIndex];\r\n hasParent = parentId !== instanceIndex;\r\n instanceIndex = parentId;\r\n }\r\n}\r\n\r\nfunction traverseHierarchy(hierarchy, instanceIndex, endConditionCallback) {\r\n // Traverse over the hierarchy and process each instance with the endConditionCallback.\r\n // When the endConditionCallback returns a value, the traversal stops and that value is returned.\r\n var parentCounts = hierarchy.parentCounts;\r\n var parentIds = hierarchy.parentIds;\r\n if (!defined(parentIds)) {\r\n return endConditionCallback(hierarchy, instanceIndex);\r\n } else if (defined(parentCounts)) {\r\n return traverseHierarchyMultipleParents(\r\n hierarchy,\r\n instanceIndex,\r\n endConditionCallback\r\n );\r\n }\r\n return traverseHierarchySingleParent(\r\n hierarchy,\r\n instanceIndex,\r\n endConditionCallback\r\n );\r\n}\r\n\r\nfunction hasPropertyInHierarchy(batchTable, batchId, name) {\r\n var hierarchy = batchTable._batchTableHierarchy;\r\n var result = traverseHierarchy(hierarchy, batchId, function (\r\n hierarchy,\r\n instanceIndex\r\n ) {\r\n var classId = hierarchy.classIds[instanceIndex];\r\n var instances = hierarchy.classes[classId].instances;\r\n if (defined(instances[name])) {\r\n return true;\r\n }\r\n });\r\n return defined(result);\r\n}\r\n\r\nfunction getPropertyNamesInHierarchy(batchTable, batchId, results) {\r\n var hierarchy = batchTable._batchTableHierarchy;\r\n traverseHierarchy(hierarchy, batchId, function (hierarchy, instanceIndex) {\r\n var classId = hierarchy.classIds[instanceIndex];\r\n var instances = hierarchy.classes[classId].instances;\r\n for (var name in instances) {\r\n if (instances.hasOwnProperty(name)) {\r\n if (results.indexOf(name) === -1) {\r\n results.push(name);\r\n }\r\n }\r\n }\r\n });\r\n}\r\n\r\nfunction getHierarchyProperty(batchTable, batchId, name) {\r\n var hierarchy = batchTable._batchTableHierarchy;\r\n return traverseHierarchy(hierarchy, batchId, function (\r\n hierarchy,\r\n instanceIndex\r\n ) {\r\n var classId = hierarchy.classIds[instanceIndex];\r\n var instanceClass = hierarchy.classes[classId];\r\n var indexInClass = hierarchy.classIndexes[instanceIndex];\r\n var propertyValues = instanceClass.instances[name];\r\n if (defined(propertyValues)) {\r\n if (defined(propertyValues.typedArray)) {\r\n return getBinaryProperty(propertyValues, indexInClass);\r\n }\r\n return clone(propertyValues[indexInClass], true);\r\n }\r\n });\r\n}\r\n\r\nfunction setHierarchyProperty(batchTable, batchId, name, value) {\r\n var hierarchy = batchTable._batchTableHierarchy;\r\n var result = traverseHierarchy(hierarchy, batchId, function (\r\n hierarchy,\r\n instanceIndex\r\n ) {\r\n var classId = hierarchy.classIds[instanceIndex];\r\n var instanceClass = hierarchy.classes[classId];\r\n var indexInClass = hierarchy.classIndexes[instanceIndex];\r\n var propertyValues = instanceClass.instances[name];\r\n if (defined(propertyValues)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (instanceIndex !== batchId) {\r\n throw new DeveloperError(\r\n 'Inherited property \"' + name + '\" is read-only.'\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n if (defined(propertyValues.typedArray)) {\r\n setBinaryProperty(propertyValues, indexInClass, value);\r\n } else {\r\n propertyValues[indexInClass] = clone(value, true);\r\n }\r\n return true;\r\n }\r\n });\r\n return defined(result);\r\n}\r\n\r\nCesium3DTileBatchTable.prototype.isClass = function (batchId, className) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n Check.typeOf.string(\"className\", className);\r\n //>>includeEnd('debug');\r\n\r\n // PERFORMANCE_IDEA : cache results in the ancestor classes to speed up this check if this area becomes a hotspot\r\n var hierarchy = this._batchTableHierarchy;\r\n if (!defined(hierarchy)) {\r\n return false;\r\n }\r\n\r\n // PERFORMANCE_IDEA : treat class names as integers for faster comparisons\r\n var result = traverseHierarchy(hierarchy, batchId, function (\r\n hierarchy,\r\n instanceIndex\r\n ) {\r\n var classId = hierarchy.classIds[instanceIndex];\r\n var instanceClass = hierarchy.classes[classId];\r\n if (instanceClass.name === className) {\r\n return true;\r\n }\r\n });\r\n return defined(result);\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.isExactClass = function (batchId, className) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"className\", className);\r\n //>>includeEnd('debug');\r\n\r\n return this.getExactClassName(batchId) === className;\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.getExactClassName = function (batchId) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n //>>includeEnd('debug');\r\n\r\n var hierarchy = this._batchTableHierarchy;\r\n if (!defined(hierarchy)) {\r\n return undefined;\r\n }\r\n var classId = hierarchy.classIds[batchId];\r\n var instanceClass = hierarchy.classes[classId];\r\n return instanceClass.name;\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.hasProperty = function (batchId, name) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n Check.typeOf.string(\"name\", name);\r\n //>>includeEnd('debug');\r\n\r\n return (\r\n defined(this._properties[name]) ||\r\n (defined(this._batchTableHierarchy) &&\r\n hasPropertyInHierarchy(this, batchId, name))\r\n );\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.getPropertyNames = function (\r\n batchId,\r\n results\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n //>>includeEnd('debug');\r\n\r\n results = defined(results) ? results : [];\r\n results.length = 0;\r\n\r\n var propertyNames = Object.keys(this._properties);\r\n results.push.apply(results, propertyNames);\r\n\r\n if (defined(this._batchTableHierarchy)) {\r\n getPropertyNamesInHierarchy(this, batchId, results);\r\n }\r\n\r\n return results;\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.getProperty = function (batchId, name) {\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, this.featuresLength);\r\n Check.typeOf.string(\"name\", name);\r\n //>>includeEnd('debug');\r\n\r\n if (defined(this._batchTableBinaryProperties)) {\r\n var binaryProperty = this._batchTableBinaryProperties[name];\r\n if (defined(binaryProperty)) {\r\n return getBinaryProperty(binaryProperty, batchId);\r\n }\r\n }\r\n\r\n var propertyValues = this._properties[name];\r\n if (defined(propertyValues)) {\r\n return clone(propertyValues[batchId], true);\r\n }\r\n\r\n if (defined(this._batchTableHierarchy)) {\r\n var hierarchyProperty = getHierarchyProperty(this, batchId, name);\r\n if (defined(hierarchyProperty)) {\r\n return hierarchyProperty;\r\n }\r\n }\r\n\r\n return undefined;\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.setProperty = function (batchId, name, value) {\r\n var featuresLength = this.featuresLength;\r\n //>>includeStart('debug', pragmas.debug);\r\n checkBatchId(batchId, featuresLength);\r\n Check.typeOf.string(\"name\", name);\r\n //>>includeEnd('debug');\r\n\r\n if (defined(this._batchTableBinaryProperties)) {\r\n var binaryProperty = this._batchTableBinaryProperties[name];\r\n if (defined(binaryProperty)) {\r\n setBinaryProperty(binaryProperty, batchId, value);\r\n return;\r\n }\r\n }\r\n\r\n if (defined(this._batchTableHierarchy)) {\r\n if (setHierarchyProperty(this, batchId, name, value)) {\r\n return;\r\n }\r\n }\r\n\r\n var propertyValues = this._properties[name];\r\n if (!defined(propertyValues)) {\r\n // Property does not exist. Create it.\r\n this._properties[name] = new Array(featuresLength);\r\n propertyValues = this._properties[name];\r\n }\r\n\r\n propertyValues[batchId] = clone(value, true);\r\n};\r\n\r\nfunction getGlslComputeSt(batchTable) {\r\n // GLSL batchId is zero-based: [0, featuresLength - 1]\r\n if (batchTable._textureDimensions.y === 1) {\r\n return (\r\n \"uniform vec4 tile_textureStep; \\n\" +\r\n \"vec2 computeSt(float batchId) \\n\" +\r\n \"{ \\n\" +\r\n \" float stepX = tile_textureStep.x; \\n\" +\r\n \" float centerX = tile_textureStep.y; \\n\" +\r\n \" return vec2(centerX + (batchId * stepX), 0.5); \\n\" +\r\n \"} \\n\"\r\n );\r\n }\r\n\r\n return (\r\n \"uniform vec4 tile_textureStep; \\n\" +\r\n \"uniform vec2 tile_textureDimensions; \\n\" +\r\n \"vec2 computeSt(float batchId) \\n\" +\r\n \"{ \\n\" +\r\n \" float stepX = tile_textureStep.x; \\n\" +\r\n \" float centerX = tile_textureStep.y; \\n\" +\r\n \" float stepY = tile_textureStep.z; \\n\" +\r\n \" float centerY = tile_textureStep.w; \\n\" +\r\n \" float xId = mod(batchId, tile_textureDimensions.x); \\n\" +\r\n \" float yId = floor(batchId / tile_textureDimensions.x); \\n\" +\r\n \" return vec2(centerX + (xId * stepX), centerY + (yId * stepY)); \\n\" +\r\n \"} \\n\"\r\n );\r\n}\r\n\r\nCesium3DTileBatchTable.prototype.getVertexShaderCallback = function (\r\n handleTranslucent,\r\n batchIdAttributeName,\r\n diffuseAttributeOrUniformName\r\n) {\r\n if (this.featuresLength === 0) {\r\n return;\r\n }\r\n\r\n var that = this;\r\n return function (source) {\r\n // If the color blend mode is HIGHLIGHT, the highlight color will always be applied in the fragment shader.\r\n // No need to apply the highlight color in the vertex shader as well.\r\n var renamedSource = modifyDiffuse(\r\n source,\r\n diffuseAttributeOrUniformName,\r\n false\r\n );\r\n var newMain;\r\n\r\n if (ContextLimits.maximumVertexTextureImageUnits > 0) {\r\n // When VTF is supported, perform per-feature show/hide in the vertex shader\r\n newMain = \"\";\r\n if (handleTranslucent) {\r\n newMain += \"uniform bool tile_translucentCommand; \\n\";\r\n }\r\n newMain +=\r\n \"uniform sampler2D tile_batchTexture; \\n\" +\r\n \"varying vec4 tile_featureColor; \\n\" +\r\n \"varying vec2 tile_featureSt; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" vec2 st = computeSt(\" +\r\n batchIdAttributeName +\r\n \"); \\n\" +\r\n \" vec4 featureProperties = texture2D(tile_batchTexture, st); \\n\" +\r\n \" tile_color(featureProperties); \\n\" +\r\n \" float show = ceil(featureProperties.a); \\n\" + // 0 - false, non-zeo - true\r\n \" gl_Position *= show; \\n\"; // Per-feature show/hide\r\n if (handleTranslucent) {\r\n newMain +=\r\n \" bool isStyleTranslucent = (featureProperties.a != 1.0); \\n\" +\r\n \" if (czm_pass == czm_passTranslucent) \\n\" +\r\n \" { \\n\" +\r\n \" if (!isStyleTranslucent && !tile_translucentCommand) \\n\" + // Do not render opaque features in the translucent pass\r\n \" { \\n\" +\r\n \" gl_Position *= 0.0; \\n\" +\r\n \" } \\n\" +\r\n \" } \\n\" +\r\n \" else \\n\" +\r\n \" { \\n\" +\r\n \" if (isStyleTranslucent) \\n\" + // Do not render translucent features in the opaque pass\r\n \" { \\n\" +\r\n \" gl_Position *= 0.0; \\n\" +\r\n \" } \\n\" +\r\n \" } \\n\";\r\n }\r\n newMain +=\r\n \" tile_featureColor = featureProperties; \\n\" +\r\n \" tile_featureSt = st; \\n\" +\r\n \"}\";\r\n } else {\r\n // When VTF is not supported, color blend mode MIX will look incorrect due to the feature's color not being available in the vertex shader\r\n newMain =\r\n \"varying vec2 tile_featureSt; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" tile_color(vec4(1.0)); \\n\" +\r\n \" tile_featureSt = computeSt(\" +\r\n batchIdAttributeName +\r\n \"); \\n\" +\r\n \"}\";\r\n }\r\n\r\n return renamedSource + \"\\n\" + getGlslComputeSt(that) + newMain;\r\n };\r\n};\r\n\r\nfunction getDefaultShader(source, applyHighlight) {\r\n source = ShaderSource.replaceMain(source, \"tile_main\");\r\n\r\n if (!applyHighlight) {\r\n return (\r\n source +\r\n \"void tile_color(vec4 tile_featureColor) \\n\" +\r\n \"{ \\n\" +\r\n \" tile_main(); \\n\" +\r\n \"} \\n\"\r\n );\r\n }\r\n\r\n // The color blend mode is intended for the RGB channels so alpha is always just multiplied.\r\n // gl_FragColor is multiplied by the tile color only when tile_colorBlend is 0.0 (highlight)\r\n return (\r\n source +\r\n \"uniform float tile_colorBlend; \\n\" +\r\n \"void tile_color(vec4 tile_featureColor) \\n\" +\r\n \"{ \\n\" +\r\n \" tile_main(); \\n\" +\r\n \" tile_featureColor = czm_gammaCorrect(tile_featureColor); \\n\" +\r\n \" gl_FragColor.a *= tile_featureColor.a; \\n\" +\r\n \" float highlight = ceil(tile_colorBlend); \\n\" +\r\n \" gl_FragColor.rgb *= mix(tile_featureColor.rgb, vec3(1.0), highlight); \\n\" +\r\n \"} \\n\"\r\n );\r\n}\r\n\r\nfunction replaceDiffuseTextureCalls(source, diffuseAttributeOrUniformName) {\r\n var functionCall = \"texture2D(\" + diffuseAttributeOrUniformName;\r\n\r\n var fromIndex = 0;\r\n var startIndex = source.indexOf(functionCall, fromIndex);\r\n var endIndex;\r\n\r\n while (startIndex > -1) {\r\n var nestedLevel = 0;\r\n for (var i = startIndex; i < source.length; ++i) {\r\n var character = source.charAt(i);\r\n if (character === \"(\") {\r\n ++nestedLevel;\r\n } else if (character === \")\") {\r\n --nestedLevel;\r\n if (nestedLevel === 0) {\r\n endIndex = i + 1;\r\n break;\r\n }\r\n }\r\n }\r\n var extractedFunction = source.slice(startIndex, endIndex);\r\n var replacedFunction =\r\n \"tile_diffuse_final(\" + extractedFunction + \", tile_diffuse)\";\r\n\r\n source =\r\n source.slice(0, startIndex) + replacedFunction + source.slice(endIndex);\r\n fromIndex = startIndex + replacedFunction.length;\r\n startIndex = source.indexOf(functionCall, fromIndex);\r\n }\r\n\r\n return source;\r\n}\r\n\r\nfunction modifyDiffuse(source, diffuseAttributeOrUniformName, applyHighlight) {\r\n // If the glTF does not specify the _3DTILESDIFFUSE semantic, return the default shader.\r\n // Otherwise if _3DTILESDIFFUSE is defined prefer the shader below that can switch the color mode at runtime.\r\n if (!defined(diffuseAttributeOrUniformName)) {\r\n return getDefaultShader(source, applyHighlight);\r\n }\r\n\r\n // Find the diffuse uniform. Examples matches:\r\n // uniform vec3 u_diffuseColor;\r\n // uniform sampler2D diffuseTexture;\r\n var regex = new RegExp(\r\n \"(uniform|attribute|in)\\\\s+(vec[34]|sampler2D)\\\\s+\" +\r\n diffuseAttributeOrUniformName +\r\n \";\"\r\n );\r\n var uniformMatch = source.match(regex);\r\n\r\n if (!defined(uniformMatch)) {\r\n // Could not find uniform declaration of type vec3, vec4, or sampler2D\r\n return getDefaultShader(source, applyHighlight);\r\n }\r\n\r\n var declaration = uniformMatch[0];\r\n var type = uniformMatch[2];\r\n\r\n source = ShaderSource.replaceMain(source, \"tile_main\");\r\n source = source.replace(declaration, \"\"); // Remove uniform declaration for now so the replace below doesn't affect it\r\n\r\n // If the tile color is white, use the source color. This implies the feature has not been styled.\r\n // Highlight: tile_colorBlend is 0.0 and the source color is used\r\n // Replace: tile_colorBlend is 1.0 and the tile color is used\r\n // Mix: tile_colorBlend is between 0.0 and 1.0, causing the source color and tile color to mix\r\n var finalDiffuseFunction =\r\n \"bool isWhite(vec3 color) \\n\" +\r\n \"{ \\n\" +\r\n \" return all(greaterThan(color, vec3(1.0 - czm_epsilon3))); \\n\" +\r\n \"} \\n\" +\r\n \"vec4 tile_diffuse_final(vec4 sourceDiffuse, vec4 tileDiffuse) \\n\" +\r\n \"{ \\n\" +\r\n \" vec4 blendDiffuse = mix(sourceDiffuse, tileDiffuse, tile_colorBlend); \\n\" +\r\n \" vec4 diffuse = isWhite(tileDiffuse.rgb) ? sourceDiffuse : blendDiffuse; \\n\" +\r\n \" return vec4(diffuse.rgb, sourceDiffuse.a); \\n\" +\r\n \"} \\n\";\r\n\r\n // The color blend mode is intended for the RGB channels so alpha is always just multiplied.\r\n // gl_FragColor is multiplied by the tile color only when tile_colorBlend is 0.0 (highlight)\r\n var highlight =\r\n \" tile_featureColor = czm_gammaCorrect(tile_featureColor); \\n\" +\r\n \" gl_FragColor.a *= tile_featureColor.a; \\n\" +\r\n \" float highlight = ceil(tile_colorBlend); \\n\" +\r\n \" gl_FragColor.rgb *= mix(tile_featureColor.rgb, vec3(1.0), highlight); \\n\";\r\n\r\n var setColor;\r\n if (type === \"vec3\" || type === \"vec4\") {\r\n var sourceDiffuse =\r\n type === \"vec3\"\r\n ? \"vec4(\" + diffuseAttributeOrUniformName + \", 1.0)\"\r\n : diffuseAttributeOrUniformName;\r\n var replaceDiffuse = type === \"vec3\" ? \"tile_diffuse.xyz\" : \"tile_diffuse\";\r\n regex = new RegExp(diffuseAttributeOrUniformName, \"g\");\r\n source = source.replace(regex, replaceDiffuse);\r\n setColor =\r\n \" vec4 source = \" +\r\n sourceDiffuse +\r\n \"; \\n\" +\r\n \" tile_diffuse = tile_diffuse_final(source, tile_featureColor); \\n\" +\r\n \" tile_main(); \\n\";\r\n } else if (type === \"sampler2D\") {\r\n // Handles any number of nested parentheses\r\n // E.g. texture2D(u_diffuse, uv)\r\n // E.g. texture2D(u_diffuse, computeUV(index))\r\n source = replaceDiffuseTextureCalls(source, diffuseAttributeOrUniformName);\r\n setColor =\r\n \" tile_diffuse = tile_featureColor; \\n\" + \" tile_main(); \\n\";\r\n }\r\n\r\n source =\r\n \"uniform float tile_colorBlend; \\n\" +\r\n \"vec4 tile_diffuse = vec4(1.0); \\n\" +\r\n finalDiffuseFunction +\r\n declaration +\r\n \"\\n\" +\r\n source +\r\n \"\\n\" +\r\n \"void tile_color(vec4 tile_featureColor) \\n\" +\r\n \"{ \\n\" +\r\n setColor;\r\n\r\n if (applyHighlight) {\r\n source += highlight;\r\n }\r\n\r\n source += \"} \\n\";\r\n return source;\r\n}\r\n\r\nCesium3DTileBatchTable.prototype.getFragmentShaderCallback = function (\r\n handleTranslucent,\r\n diffuseAttributeOrUniformName,\r\n hasPremultipliedAlpha\r\n) {\r\n if (this.featuresLength === 0) {\r\n return;\r\n }\r\n return function (source) {\r\n source = modifyDiffuse(source, diffuseAttributeOrUniformName, true);\r\n if (ContextLimits.maximumVertexTextureImageUnits > 0) {\r\n // When VTF is supported, per-feature show/hide already happened in the fragment shader\r\n source +=\r\n \"uniform sampler2D tile_pickTexture; \\n\" +\r\n \"varying vec2 tile_featureSt; \\n\" +\r\n \"varying vec4 tile_featureColor; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" tile_color(tile_featureColor); \\n\";\r\n\r\n if (hasPremultipliedAlpha) {\r\n source += \" gl_FragColor.rgb *= gl_FragColor.a; \\n\";\r\n }\r\n\r\n source += \"}\";\r\n } else {\r\n if (handleTranslucent) {\r\n source += \"uniform bool tile_translucentCommand; \\n\";\r\n }\r\n source +=\r\n \"uniform sampler2D tile_pickTexture; \\n\" +\r\n \"uniform sampler2D tile_batchTexture; \\n\" +\r\n \"varying vec2 tile_featureSt; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" vec4 featureProperties = texture2D(tile_batchTexture, tile_featureSt); \\n\" +\r\n \" if (featureProperties.a == 0.0) { \\n\" + // show: alpha == 0 - false, non-zeo - true\r\n \" discard; \\n\" +\r\n \" } \\n\";\r\n\r\n if (handleTranslucent) {\r\n source +=\r\n \" bool isStyleTranslucent = (featureProperties.a != 1.0); \\n\" +\r\n \" if (czm_pass == czm_passTranslucent) \\n\" +\r\n \" { \\n\" +\r\n \" if (!isStyleTranslucent && !tile_translucentCommand) \\n\" + // Do not render opaque features in the translucent pass\r\n \" { \\n\" +\r\n \" discard; \\n\" +\r\n \" } \\n\" +\r\n \" } \\n\" +\r\n \" else \\n\" +\r\n \" { \\n\" +\r\n \" if (isStyleTranslucent) \\n\" + // Do not render translucent features in the opaque pass\r\n \" { \\n\" +\r\n \" discard; \\n\" +\r\n \" } \\n\" +\r\n \" } \\n\";\r\n }\r\n\r\n source += \" tile_color(featureProperties); \\n\";\r\n\r\n if (hasPremultipliedAlpha) {\r\n source += \" gl_FragColor.rgb *= gl_FragColor.a; \\n\";\r\n }\r\n\r\n source += \"} \\n\";\r\n }\r\n return source;\r\n };\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.getClassificationFragmentShaderCallback = function () {\r\n if (this.featuresLength === 0) {\r\n return;\r\n }\r\n return function (source) {\r\n source = ShaderSource.replaceMain(source, \"tile_main\");\r\n if (ContextLimits.maximumVertexTextureImageUnits > 0) {\r\n // When VTF is supported, per-feature show/hide already happened in the fragment shader\r\n source +=\r\n \"uniform sampler2D tile_pickTexture;\\n\" +\r\n \"varying vec2 tile_featureSt; \\n\" +\r\n \"varying vec4 tile_featureColor; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" tile_main(); \\n\" +\r\n \" gl_FragColor = tile_featureColor; \\n\" +\r\n \" gl_FragColor.rgb *= gl_FragColor.a; \\n\" +\r\n \"}\";\r\n } else {\r\n source +=\r\n \"uniform sampler2D tile_batchTexture; \\n\" +\r\n \"uniform sampler2D tile_pickTexture;\\n\" +\r\n \"varying vec2 tile_featureSt; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" tile_main(); \\n\" +\r\n \" vec4 featureProperties = texture2D(tile_batchTexture, tile_featureSt); \\n\" +\r\n \" if (featureProperties.a == 0.0) { \\n\" + // show: alpha == 0 - false, non-zeo - true\r\n \" discard; \\n\" +\r\n \" } \\n\" +\r\n \" gl_FragColor = featureProperties; \\n\" +\r\n \" gl_FragColor.rgb *= gl_FragColor.a; \\n\" +\r\n \"} \\n\";\r\n }\r\n return source;\r\n };\r\n};\r\n\r\nfunction getColorBlend(batchTable) {\r\n var tileset = batchTable._content.tileset;\r\n var colorBlendMode = tileset.colorBlendMode;\r\n var colorBlendAmount = tileset.colorBlendAmount;\r\n if (colorBlendMode === Cesium3DTileColorBlendMode.HIGHLIGHT) {\r\n return 0.0;\r\n }\r\n if (colorBlendMode === Cesium3DTileColorBlendMode.REPLACE) {\r\n return 1.0;\r\n }\r\n if (colorBlendMode === Cesium3DTileColorBlendMode.MIX) {\r\n // The value 0.0 is reserved for highlight, so clamp to just above 0.0.\r\n return CesiumMath.clamp(colorBlendAmount, CesiumMath.EPSILON4, 1.0);\r\n }\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\r\n 'Invalid color blend mode \"' + colorBlendMode + '\".'\r\n );\r\n //>>includeEnd('debug');\r\n}\r\n\r\nCesium3DTileBatchTable.prototype.getUniformMapCallback = function () {\r\n if (this.featuresLength === 0) {\r\n return;\r\n }\r\n\r\n var that = this;\r\n return function (uniformMap) {\r\n var batchUniformMap = {\r\n tile_batchTexture: function () {\r\n // PERFORMANCE_IDEA: we could also use a custom shader that avoids the texture read.\r\n return defaultValue(that._batchTexture, that._defaultTexture);\r\n },\r\n tile_textureDimensions: function () {\r\n return that._textureDimensions;\r\n },\r\n tile_textureStep: function () {\r\n return that._textureStep;\r\n },\r\n tile_colorBlend: function () {\r\n return getColorBlend(that);\r\n },\r\n tile_pickTexture: function () {\r\n return that._pickTexture;\r\n },\r\n };\r\n\r\n return combine(uniformMap, batchUniformMap);\r\n };\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.getPickId = function () {\r\n return \"texture2D(tile_pickTexture, tile_featureSt)\";\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar StyleCommandsNeeded = {\r\n ALL_OPAQUE: 0,\r\n ALL_TRANSLUCENT: 1,\r\n OPAQUE_AND_TRANSLUCENT: 2,\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.addDerivedCommands = function (\r\n frameState,\r\n commandStart\r\n) {\r\n var commandList = frameState.commandList;\r\n var commandEnd = commandList.length;\r\n var tile = this._content._tile;\r\n var finalResolution = tile._finalResolution;\r\n var tileset = tile.tileset;\r\n var bivariateVisibilityTest =\r\n tileset._skipLevelOfDetail &&\r\n tileset._hasMixedContent &&\r\n frameState.context.stencilBuffer;\r\n var styleCommandsNeeded = getStyleCommandsNeeded(this);\r\n\r\n for (var i = commandStart; i < commandEnd; ++i) {\r\n var command = commandList[i];\r\n var derivedCommands = command.derivedCommands.tileset;\r\n if (!defined(derivedCommands) || command.dirty) {\r\n derivedCommands = {};\r\n command.derivedCommands.tileset = derivedCommands;\r\n derivedCommands.originalCommand = deriveCommand(command);\r\n command.dirty = false;\r\n }\r\n var originalCommand = derivedCommands.originalCommand;\r\n\r\n if (\r\n styleCommandsNeeded !== StyleCommandsNeeded.ALL_OPAQUE &&\r\n command.pass !== Pass.TRANSLUCENT\r\n ) {\r\n if (!defined(derivedCommands.translucent)) {\r\n derivedCommands.translucent = deriveTranslucentCommand(originalCommand);\r\n }\r\n }\r\n\r\n if (\r\n styleCommandsNeeded !== StyleCommandsNeeded.ALL_TRANSLUCENT &&\r\n command.pass !== Pass.TRANSLUCENT\r\n ) {\r\n if (!defined(derivedCommands.opaque)) {\r\n derivedCommands.opaque = deriveOpaqueCommand(originalCommand);\r\n }\r\n\r\n if (bivariateVisibilityTest) {\r\n if (!finalResolution) {\r\n if (!defined(derivedCommands.zback)) {\r\n derivedCommands.zback = deriveZBackfaceCommand(\r\n frameState.context,\r\n originalCommand\r\n );\r\n }\r\n tileset._backfaceCommands.push(derivedCommands.zback);\r\n }\r\n if (\r\n !defined(derivedCommands.stencil) ||\r\n tile._selectionDepth !==\r\n getLastSelectionDepth(derivedCommands.stencil)\r\n ) {\r\n if (command.renderState.depthMask) {\r\n derivedCommands.stencil = deriveStencilCommand(\r\n originalCommand,\r\n tile._selectionDepth\r\n );\r\n } else {\r\n // Ignore if tile does not write depth\r\n derivedCommands.stencil = derivedCommands.opaque;\r\n }\r\n }\r\n }\r\n }\r\n\r\n var opaqueCommand = bivariateVisibilityTest\r\n ? derivedCommands.stencil\r\n : derivedCommands.opaque;\r\n var translucentCommand = derivedCommands.translucent;\r\n\r\n // If the command was originally opaque:\r\n // * If the styling applied to the tile is all opaque, use the opaque command\r\n // (with one additional uniform needed for the shader).\r\n // * If the styling is all translucent, use new (cached) derived commands (front\r\n // and back faces) with a translucent render state.\r\n // * If the styling causes both opaque and translucent features in this tile,\r\n // then use both sets of commands.\r\n if (command.pass !== Pass.TRANSLUCENT) {\r\n if (styleCommandsNeeded === StyleCommandsNeeded.ALL_OPAQUE) {\r\n commandList[i] = opaqueCommand;\r\n }\r\n if (styleCommandsNeeded === StyleCommandsNeeded.ALL_TRANSLUCENT) {\r\n commandList[i] = translucentCommand;\r\n }\r\n if (styleCommandsNeeded === StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT) {\r\n // PERFORMANCE_IDEA: if the tile has multiple commands, we do not know what features are in what\r\n // commands so this case may be overkill.\r\n commandList[i] = opaqueCommand;\r\n commandList.push(translucentCommand);\r\n }\r\n } else {\r\n // Command was originally translucent so no need to derive new commands;\r\n // as of now, a style can't change an originally translucent feature to\r\n // opaque since the style's alpha is modulated, not a replacement. When\r\n // this changes, we need to derive new opaque commands here.\r\n commandList[i] = originalCommand;\r\n }\r\n }\r\n};\r\n\r\nfunction getStyleCommandsNeeded(batchTable) {\r\n var translucentFeaturesLength = batchTable._translucentFeaturesLength;\r\n\r\n if (translucentFeaturesLength === 0) {\r\n return StyleCommandsNeeded.ALL_OPAQUE;\r\n } else if (translucentFeaturesLength === batchTable.featuresLength) {\r\n return StyleCommandsNeeded.ALL_TRANSLUCENT;\r\n }\r\n\r\n return StyleCommandsNeeded.OPAQUE_AND_TRANSLUCENT;\r\n}\r\n\r\nfunction deriveCommand(command) {\r\n var derivedCommand = DrawCommand.shallowClone(command);\r\n\r\n // Add a uniform to indicate if the original command was translucent so\r\n // the shader knows not to cull vertices that were originally transparent\r\n // even though their style is opaque.\r\n var translucentCommand = derivedCommand.pass === Pass.TRANSLUCENT;\r\n\r\n derivedCommand.uniformMap = defined(derivedCommand.uniformMap)\r\n ? derivedCommand.uniformMap\r\n : {};\r\n derivedCommand.uniformMap.tile_translucentCommand = function () {\r\n return translucentCommand;\r\n };\r\n\r\n return derivedCommand;\r\n}\r\n\r\nfunction deriveTranslucentCommand(command) {\r\n var derivedCommand = DrawCommand.shallowClone(command);\r\n derivedCommand.pass = Pass.TRANSLUCENT;\r\n derivedCommand.renderState = getTranslucentRenderState(command.renderState);\r\n return derivedCommand;\r\n}\r\n\r\nfunction deriveOpaqueCommand(command) {\r\n var derivedCommand = DrawCommand.shallowClone(command);\r\n derivedCommand.renderState = getOpaqueRenderState(command.renderState);\r\n return derivedCommand;\r\n}\r\n\r\nfunction getLogDepthPolygonOffsetFragmentShaderProgram(context, shaderProgram) {\r\n var shader = context.shaderCache.getDerivedShaderProgram(\r\n shaderProgram,\r\n \"zBackfaceLogDepth\"\r\n );\r\n if (!defined(shader)) {\r\n var fs = shaderProgram.fragmentShaderSource.clone();\r\n fs.defines = defined(fs.defines) ? fs.defines.slice(0) : [];\r\n fs.defines.push(\"POLYGON_OFFSET\");\r\n\r\n fs.sources.unshift(\r\n \"#ifdef GL_OES_standard_derivatives\\n#extension GL_OES_standard_derivatives : enable\\n#endif\\n\"\r\n );\r\n shader = context.shaderCache.createDerivedShaderProgram(\r\n shaderProgram,\r\n \"zBackfaceLogDepth\",\r\n {\r\n vertexShaderSource: shaderProgram.vertexShaderSource,\r\n fragmentShaderSource: fs,\r\n attributeLocations: shaderProgram._attributeLocations,\r\n }\r\n );\r\n }\r\n\r\n return shader;\r\n}\r\n\r\nfunction deriveZBackfaceCommand(context, command) {\r\n // Write just backface depth of unresolved tiles so resolved stenciled tiles do not appear in front\r\n var derivedCommand = DrawCommand.shallowClone(command);\r\n var rs = clone(derivedCommand.renderState, true);\r\n rs.cull.enabled = true;\r\n rs.cull.face = CullFace.FRONT;\r\n // Back faces do not need to write color.\r\n rs.colorMask = {\r\n red: false,\r\n green: false,\r\n blue: false,\r\n alpha: false,\r\n };\r\n // Push back face depth away from the camera so it is less likely that back faces and front faces of the same tile\r\n // intersect and overlap. This helps avoid flickering for very thin double-sided walls.\r\n rs.polygonOffset = {\r\n enabled: true,\r\n factor: 5.0,\r\n units: 5.0,\r\n };\r\n // Set the 3D Tiles bit\r\n rs.stencilTest = StencilConstants.setCesium3DTileBit();\r\n rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;\r\n\r\n derivedCommand.renderState = RenderState.fromCache(rs);\r\n derivedCommand.castShadows = false;\r\n derivedCommand.receiveShadows = false;\r\n derivedCommand.uniformMap = clone(command.uniformMap);\r\n\r\n var polygonOffset = new Cartesian2(5.0, 5.0);\r\n derivedCommand.uniformMap.u_polygonOffset = function () {\r\n return polygonOffset;\r\n };\r\n\r\n // Make the log depth depth fragment write account for the polygon offset, too.\r\n // Otherwise, the back face commands will cause the higher resolution\r\n // tiles to disappear.\r\n derivedCommand.shaderProgram = getLogDepthPolygonOffsetFragmentShaderProgram(\r\n context,\r\n command.shaderProgram\r\n );\r\n return derivedCommand;\r\n}\r\n\r\nfunction deriveStencilCommand(command, reference) {\r\n // Tiles only draw if their selection depth is >= the tile drawn already. They write their\r\n // selection depth to the stencil buffer to prevent ancestor tiles from drawing on top\r\n var derivedCommand = DrawCommand.shallowClone(command);\r\n var rs = clone(derivedCommand.renderState, true);\r\n // Stencil test is masked to the most significant 3 bits so the reference is shifted. Writes 0 for the terrain bit\r\n rs.stencilTest.enabled = true;\r\n rs.stencilTest.mask = StencilConstants.SKIP_LOD_MASK;\r\n rs.stencilTest.reference =\r\n StencilConstants.CESIUM_3D_TILE_MASK |\r\n (reference << StencilConstants.SKIP_LOD_BIT_SHIFT);\r\n rs.stencilTest.frontFunction = StencilFunction.GREATER_OR_EQUAL;\r\n rs.stencilTest.frontOperation.zPass = StencilOperation.REPLACE;\r\n rs.stencilTest.backFunction = StencilFunction.GREATER_OR_EQUAL;\r\n rs.stencilTest.backOperation.zPass = StencilOperation.REPLACE;\r\n rs.stencilMask =\r\n StencilConstants.CESIUM_3D_TILE_MASK | StencilConstants.SKIP_LOD_MASK;\r\n derivedCommand.renderState = RenderState.fromCache(rs);\r\n return derivedCommand;\r\n}\r\n\r\nfunction getLastSelectionDepth(stencilCommand) {\r\n // Isolate the selection depth from the stencil reference.\r\n var reference = stencilCommand.renderState.stencilTest.reference;\r\n return (\r\n (reference & StencilConstants.SKIP_LOD_MASK) >>>\r\n StencilConstants.SKIP_LOD_BIT_SHIFT\r\n );\r\n}\r\n\r\nfunction getTranslucentRenderState(renderState) {\r\n var rs = clone(renderState, true);\r\n rs.cull.enabled = false;\r\n rs.depthTest.enabled = true;\r\n rs.depthMask = false;\r\n rs.blending = BlendingState.ALPHA_BLEND;\r\n rs.stencilTest = StencilConstants.setCesium3DTileBit();\r\n rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;\r\n\r\n return RenderState.fromCache(rs);\r\n}\r\n\r\nfunction getOpaqueRenderState(renderState) {\r\n var rs = clone(renderState, true);\r\n rs.stencilTest = StencilConstants.setCesium3DTileBit();\r\n rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;\r\n\r\n return RenderState.fromCache(rs);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction createTexture(batchTable, context, bytes) {\r\n var dimensions = batchTable._textureDimensions;\r\n return new Texture({\r\n context: context,\r\n pixelFormat: PixelFormat.RGBA,\r\n pixelDatatype: PixelDatatype.UNSIGNED_BYTE,\r\n source: {\r\n width: dimensions.x,\r\n height: dimensions.y,\r\n arrayBufferView: bytes,\r\n },\r\n flipY: false,\r\n sampler: Sampler.NEAREST,\r\n });\r\n}\r\n\r\nfunction createPickTexture(batchTable, context) {\r\n var featuresLength = batchTable.featuresLength;\r\n if (!defined(batchTable._pickTexture) && featuresLength > 0) {\r\n var pickIds = batchTable._pickIds;\r\n var byteLength = getByteLength(batchTable);\r\n var bytes = new Uint8Array(byteLength);\r\n var content = batchTable._content;\r\n\r\n // PERFORMANCE_IDEA: we could skip the pick texture completely by allocating\r\n // a continuous range of pickIds and then converting the base pickId + batchId\r\n // to RGBA in the shader. The only consider is precision issues, which might\r\n // not be an issue in WebGL 2.\r\n for (var i = 0; i < featuresLength; ++i) {\r\n var pickId = context.createPickId(content.getFeature(i));\r\n pickIds.push(pickId);\r\n\r\n var pickColor = pickId.color;\r\n var offset = i * 4;\r\n bytes[offset] = Color.floatToByte(pickColor.red);\r\n bytes[offset + 1] = Color.floatToByte(pickColor.green);\r\n bytes[offset + 2] = Color.floatToByte(pickColor.blue);\r\n bytes[offset + 3] = Color.floatToByte(pickColor.alpha);\r\n }\r\n\r\n batchTable._pickTexture = createTexture(batchTable, context, bytes);\r\n content.tileset._statistics.batchTableByteLength +=\r\n batchTable._pickTexture.sizeInBytes;\r\n }\r\n}\r\n\r\nfunction updateBatchTexture(batchTable) {\r\n var dimensions = batchTable._textureDimensions;\r\n // PERFORMANCE_IDEA: Instead of rewriting the entire texture, use fine-grained\r\n // texture updates when less than, for example, 10%, of the values changed. Or\r\n // even just optimize the common case when one feature show/color changed.\r\n batchTable._batchTexture.copyFrom({\r\n width: dimensions.x,\r\n height: dimensions.y,\r\n arrayBufferView: batchTable._batchValues,\r\n });\r\n}\r\n\r\nCesium3DTileBatchTable.prototype.update = function (tileset, frameState) {\r\n var context = frameState.context;\r\n this._defaultTexture = context.defaultTexture;\r\n\r\n var passes = frameState.passes;\r\n if (passes.pick || passes.postProcess) {\r\n createPickTexture(this, context);\r\n }\r\n\r\n if (this._batchValuesDirty) {\r\n this._batchValuesDirty = false;\r\n\r\n // Create batch texture on-demand\r\n if (!defined(this._batchTexture)) {\r\n this._batchTexture = createTexture(this, context, this._batchValues);\r\n tileset._statistics.batchTableByteLength += this._batchTexture.sizeInBytes;\r\n }\r\n\r\n updateBatchTexture(this); // Apply per-feature show/color updates\r\n }\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nCesium3DTileBatchTable.prototype.destroy = function () {\r\n this._batchTexture = this._batchTexture && this._batchTexture.destroy();\r\n this._pickTexture = this._pickTexture && this._pickTexture.destroy();\r\n\r\n var pickIds = this._pickIds;\r\n var length = pickIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n pickIds[i].destroy();\r\n }\r\n\r\n return destroyObject(this);\r\n};\r\nexport default Cesium3DTileBatchTable;\r\n","import Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\n\r\n/**\r\n * A feature of a {@link Cesium3DTileset}.\r\n *

\r\n * Provides access to a feature's properties stored in the tile's batch table, as well\r\n * as the ability to show/hide a feature and change its highlight color via\r\n * {@link Cesium3DTileFeature#show} and {@link Cesium3DTileFeature#color}, respectively.\r\n *

\r\n *

\r\n * Modifications to a Cesium3DTileFeature object have the lifetime of the tile's\r\n * content. If the tile's content is unloaded, e.g., due to it going out of view and needing\r\n * to free space in the cache for visible tiles, listen to the {@link Cesium3DTileset#tileUnload} event to save any\r\n * modifications. Also listen to the {@link Cesium3DTileset#tileVisible} event to reapply any modifications.\r\n *

\r\n *

\r\n * Do not construct this directly. Access it through {@link Cesium3DTileContent#getFeature}\r\n * or picking using {@link Scene#pick} and {@link Scene#pickPosition}.\r\n *

\r\n *\r\n * @alias Cesium3DTileFeature\r\n * @constructor\r\n *\r\n * @example\r\n * // On mouse over, display all the properties for a feature in the console log.\r\n * handler.setInputAction(function(movement) {\r\n * var feature = scene.pick(movement.endPosition);\r\n * if (feature instanceof Cesium.Cesium3DTileFeature) {\r\n * var propertyNames = feature.getPropertyNames();\r\n * var length = propertyNames.length;\r\n * for (var i = 0; i < length; ++i) {\r\n * var propertyName = propertyNames[i];\r\n * console.log(propertyName + ': ' + feature.getProperty(propertyName));\r\n * }\r\n * }\r\n * }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);\r\n */\r\nfunction Cesium3DTileFeature(content, batchId) {\r\n this._content = content;\r\n this._batchId = batchId;\r\n this._color = undefined; // for calling getColor\r\n}\r\n\r\nObject.defineProperties(Cesium3DTileFeature.prototype, {\r\n /**\r\n * Gets or sets if the feature will be shown. This is set for all features\r\n * when a style's show is evaluated.\r\n *\r\n * @memberof Cesium3DTileFeature.prototype\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n show: {\r\n get: function () {\r\n return this._content.batchTable.getShow(this._batchId);\r\n },\r\n set: function (value) {\r\n this._content.batchTable.setShow(this._batchId, value);\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the highlight color multiplied with the feature's color. When\r\n * this is white, the feature's color is not changed. This is set for all features\r\n * when a style's color is evaluated.\r\n *\r\n * @memberof Cesium3DTileFeature.prototype\r\n *\r\n * @type {Color}\r\n *\r\n * @default {@link Color.WHITE}\r\n */\r\n color: {\r\n get: function () {\r\n if (!defined(this._color)) {\r\n this._color = new Color();\r\n }\r\n return this._content.batchTable.getColor(this._batchId, this._color);\r\n },\r\n set: function (value) {\r\n this._content.batchTable.setColor(this._batchId, value);\r\n },\r\n },\r\n\r\n /**\r\n * Gets the content of the tile containing the feature.\r\n *\r\n * @memberof Cesium3DTileFeature.prototype\r\n *\r\n * @type {Cesium3DTileContent}\r\n *\r\n * @readonly\r\n * @private\r\n */\r\n content: {\r\n get: function () {\r\n return this._content;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tileset containing the feature.\r\n *\r\n * @memberof Cesium3DTileFeature.prototype\r\n *\r\n * @type {Cesium3DTileset}\r\n *\r\n * @readonly\r\n */\r\n tileset: {\r\n get: function () {\r\n return this._content.tileset;\r\n },\r\n },\r\n\r\n /**\r\n * All objects returned by {@link Scene#pick} have a primitive property. This returns\r\n * the tileset containing the feature.\r\n *\r\n * @memberof Cesium3DTileFeature.prototype\r\n *\r\n * @type {Cesium3DTileset}\r\n *\r\n * @readonly\r\n */\r\n primitive: {\r\n get: function () {\r\n return this._content.tileset;\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n pickId: {\r\n get: function () {\r\n return this._content.batchTable.getPickColor(this._batchId);\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Returns whether the feature contains this property. This includes properties from this feature's\r\n * class and inherited classes when using a batch table hierarchy.\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy}\r\n *\r\n * @param {String} name The case-sensitive name of the property.\r\n * @returns {Boolean} Whether the feature contains this property.\r\n */\r\nCesium3DTileFeature.prototype.hasProperty = function (name) {\r\n return this._content.batchTable.hasProperty(this._batchId, name);\r\n};\r\n\r\n/**\r\n * Returns an array of property names for the feature. This includes properties from this feature's\r\n * class and inherited classes when using a batch table hierarchy.\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy}\r\n *\r\n * @param {String[]} [results] An array into which to store the results.\r\n * @returns {String[]} The names of the feature's properties.\r\n */\r\nCesium3DTileFeature.prototype.getPropertyNames = function (results) {\r\n return this._content.batchTable.getPropertyNames(this._batchId, results);\r\n};\r\n\r\n/**\r\n * Returns a copy of the value of the feature's property with the given name. This includes properties from this feature's\r\n * class and inherited classes when using a batch table hierarchy.\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy}\r\n *\r\n * @param {String} name The case-sensitive name of the property.\r\n * @returns {*} The value of the property or undefined if the property does not exist.\r\n *\r\n * @example\r\n * // Display all the properties for a feature in the console log.\r\n * var propertyNames = feature.getPropertyNames();\r\n * var length = propertyNames.length;\r\n * for (var i = 0; i < length; ++i) {\r\n * var propertyName = propertyNames[i];\r\n * console.log(propertyName + ': ' + feature.getProperty(propertyName));\r\n * }\r\n */\r\nCesium3DTileFeature.prototype.getProperty = function (name) {\r\n return this._content.batchTable.getProperty(this._batchId, name);\r\n};\r\n\r\n/**\r\n * Sets the value of the feature's property with the given name.\r\n *

\r\n * If a property with the given name doesn't exist, it is created.\r\n *

\r\n *\r\n * @param {String} name The case-sensitive name of the property.\r\n * @param {*} value The value of the property that will be copied.\r\n *\r\n * @exception {DeveloperError} Inherited batch table hierarchy property is read only.\r\n *\r\n * @example\r\n * var height = feature.getProperty('Height'); // e.g., the height of a building\r\n *\r\n * @example\r\n * var name = 'clicked';\r\n * if (feature.getProperty(name)) {\r\n * console.log('already clicked');\r\n * } else {\r\n * feature.setProperty(name, true);\r\n * console.log('first click');\r\n * }\r\n */\r\nCesium3DTileFeature.prototype.setProperty = function (name, value) {\r\n this._content.batchTable.setProperty(this._batchId, name, value);\r\n\r\n // PERFORMANCE_IDEA: Probably overkill, but maybe only mark the tile dirty if the\r\n // property is in one of the style's expressions or - if it can be done quickly -\r\n // if the new property value changed the result of an expression.\r\n this._content.featurePropertiesDirty = true;\r\n};\r\n\r\n/**\r\n * Returns whether the feature's class name equals className. Unlike {@link Cesium3DTileFeature#isClass}\r\n * this function only checks the feature's exact class and not inherited classes.\r\n *

\r\n * This function returns false if no batch table hierarchy is present.\r\n *

\r\n *\r\n * @param {String} className The name to check against.\r\n * @returns {Boolean} Whether the feature's class name equals className\r\n *\r\n * @private\r\n */\r\nCesium3DTileFeature.prototype.isExactClass = function (className) {\r\n return this._content.batchTable.isExactClass(this._batchId, className);\r\n};\r\n\r\n/**\r\n * Returns whether the feature's class or any inherited classes are named className.\r\n *

\r\n * This function returns false if no batch table hierarchy is present.\r\n *

\r\n *\r\n * @param {String} className The name to check against.\r\n * @returns {Boolean} Whether the feature's class or inherited classes are named className\r\n *\r\n * @private\r\n */\r\nCesium3DTileFeature.prototype.isClass = function (className) {\r\n return this._content.batchTable.isClass(this._batchId, className);\r\n};\r\n\r\n/**\r\n * Returns the feature's class name.\r\n *

\r\n * This function returns undefined if no batch table hierarchy is present.\r\n *

\r\n *\r\n * @returns {String} The feature's class name.\r\n *\r\n * @private\r\n */\r\nCesium3DTileFeature.prototype.getExactClassName = function () {\r\n return this._content.batchTable.getExactClassName(this._batchId);\r\n};\r\nexport default Cesium3DTileFeature;\r\n","import ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Cesium3DTileFeatureTable(featureTableJson, featureTableBinary) {\r\n this.json = featureTableJson;\r\n this.buffer = featureTableBinary;\r\n this._cachedTypedArrays = {};\r\n this.featuresLength = 0;\r\n}\r\n\r\nfunction getTypedArrayFromBinary(\r\n featureTable,\r\n semantic,\r\n componentType,\r\n componentLength,\r\n count,\r\n byteOffset\r\n) {\r\n var cachedTypedArrays = featureTable._cachedTypedArrays;\r\n var typedArray = cachedTypedArrays[semantic];\r\n if (!defined(typedArray)) {\r\n typedArray = ComponentDatatype.createArrayBufferView(\r\n componentType,\r\n featureTable.buffer.buffer,\r\n featureTable.buffer.byteOffset + byteOffset,\r\n count * componentLength\r\n );\r\n cachedTypedArrays[semantic] = typedArray;\r\n }\r\n return typedArray;\r\n}\r\n\r\nfunction getTypedArrayFromArray(featureTable, semantic, componentType, array) {\r\n var cachedTypedArrays = featureTable._cachedTypedArrays;\r\n var typedArray = cachedTypedArrays[semantic];\r\n if (!defined(typedArray)) {\r\n typedArray = ComponentDatatype.createTypedArray(componentType, array);\r\n cachedTypedArrays[semantic] = typedArray;\r\n }\r\n return typedArray;\r\n}\r\n\r\nCesium3DTileFeatureTable.prototype.getGlobalProperty = function (\r\n semantic,\r\n componentType,\r\n componentLength\r\n) {\r\n var jsonValue = this.json[semantic];\r\n if (!defined(jsonValue)) {\r\n return undefined;\r\n }\r\n\r\n if (defined(jsonValue.byteOffset)) {\r\n componentType = defaultValue(componentType, ComponentDatatype.UNSIGNED_INT);\r\n componentLength = defaultValue(componentLength, 1);\r\n return getTypedArrayFromBinary(\r\n this,\r\n semantic,\r\n componentType,\r\n componentLength,\r\n 1,\r\n jsonValue.byteOffset\r\n );\r\n }\r\n\r\n return jsonValue;\r\n};\r\n\r\nCesium3DTileFeatureTable.prototype.getPropertyArray = function (\r\n semantic,\r\n componentType,\r\n componentLength\r\n) {\r\n var jsonValue = this.json[semantic];\r\n if (!defined(jsonValue)) {\r\n return undefined;\r\n }\r\n\r\n if (defined(jsonValue.byteOffset)) {\r\n if (defined(jsonValue.componentType)) {\r\n componentType = ComponentDatatype.fromName(jsonValue.componentType);\r\n }\r\n return getTypedArrayFromBinary(\r\n this,\r\n semantic,\r\n componentType,\r\n componentLength,\r\n this.featuresLength,\r\n jsonValue.byteOffset\r\n );\r\n }\r\n\r\n return getTypedArrayFromArray(this, semantic, componentType, jsonValue);\r\n};\r\n\r\nCesium3DTileFeatureTable.prototype.getProperty = function (\r\n semantic,\r\n componentType,\r\n componentLength,\r\n featureId,\r\n result\r\n) {\r\n var jsonValue = this.json[semantic];\r\n if (!defined(jsonValue)) {\r\n return undefined;\r\n }\r\n\r\n var typedArray = this.getPropertyArray(\r\n semantic,\r\n componentType,\r\n componentLength\r\n );\r\n\r\n if (componentLength === 1) {\r\n return typedArray[featureId];\r\n }\r\n\r\n for (var i = 0; i < componentLength; ++i) {\r\n result[i] = typedArray[componentLength * featureId + i];\r\n }\r\n\r\n return result;\r\n};\r\nexport default Cesium3DTileFeatureTable;\r\n","import defaultValue from '../../Core/defaultValue.js'\r\n\r\n /**\r\n * Adds an element to an array and returns the element's index.\r\n *\r\n * @param {Array} array The array to add to.\r\n * @param {Object} element The element to add.\r\n * @param {Boolean} [checkDuplicates=false] When true, if a duplicate element is found its index is returned and element is not added to the array.\r\n *\r\n * @private\r\n */\r\n function addToArray(array, element, checkDuplicates) {\r\n checkDuplicates = defaultValue(checkDuplicates, false);\r\n if (checkDuplicates) {\r\n var index = array.indexOf(element);\r\n if (index > -1) {\r\n return index;\r\n }\r\n }\r\n\r\n array.push(element);\r\n return array.length - 1;\r\n }\r\n\r\n export default addToArray;\r\n","import defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Checks whether the glTF has the given extension.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {String} extension The name of the extension.\r\n * @returns {Boolean} Whether the glTF has the given extension.\r\n *\r\n * @private\r\n */\r\n function hasExtension(gltf, extension) {\r\n return defined(gltf.extensionsUsed) && (gltf.extensionsUsed.indexOf(extension) >= 0);\r\n }\r\n\r\n export default hasExtension;\r\n","import hasExtension from './hasExtension.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Contains traversal functions for processing elements of the glTF hierarchy.\r\n * @constructor\r\n *\r\n * @private\r\n */\r\n function ForEach() {\r\n }\r\n\r\n /**\r\n * Fallback for glTF 1.0\r\n * @private\r\n */\r\n ForEach.objectLegacy = function(objects, handler) {\r\n if (defined(objects)) {\r\n for (var objectId in objects) {\r\n if (Object.prototype.hasOwnProperty.call(objects, objectId)) {\r\n var object = objects[objectId];\r\n var value = handler(object, objectId);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * @private\r\n */\r\n ForEach.object = function(arrayOfObjects, handler) {\r\n if (defined(arrayOfObjects)) {\r\n var length = arrayOfObjects.length;\r\n for (var i = 0; i < length; i++) {\r\n var object = arrayOfObjects[i];\r\n var value = handler(object, i);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n /**\r\n * Supports glTF 1.0 and 2.0\r\n * @private\r\n */\r\n ForEach.topLevel = function(gltf, name, handler) {\r\n var gltfProperty = gltf[name];\r\n if (defined(gltfProperty) && !Array.isArray(gltfProperty)) {\r\n return ForEach.objectLegacy(gltfProperty, handler);\r\n }\r\n\r\n return ForEach.object(gltfProperty, handler);\r\n };\r\n\r\n ForEach.accessor = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'accessors', handler);\r\n };\r\n\r\n ForEach.accessorWithSemantic = function(gltf, semantic, handler) {\r\n var visited = {};\r\n return ForEach.mesh(gltf, function(mesh) {\r\n return ForEach.meshPrimitive(mesh, function(primitive) {\r\n var valueForEach = ForEach.meshPrimitiveAttribute(primitive, function(accessorId, attributeSemantic) {\r\n if (attributeSemantic.indexOf(semantic) === 0 && !defined(visited[accessorId])) {\r\n visited[accessorId] = true;\r\n var value = handler(accessorId);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n });\r\n\r\n if (defined(valueForEach)) {\r\n return valueForEach;\r\n }\r\n\r\n return ForEach.meshPrimitiveTarget(primitive, function(target) {\r\n return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId, attributeSemantic) {\r\n if (attributeSemantic.indexOf(semantic) === 0 && !defined(visited[accessorId])) {\r\n visited[accessorId] = true;\r\n var value = handler(accessorId);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n });\r\n });\r\n });\r\n });\r\n };\r\n\r\n ForEach.accessorContainingVertexAttributeData = function(gltf, handler) {\r\n var visited = {};\r\n return ForEach.mesh(gltf, function(mesh) {\r\n return ForEach.meshPrimitive(mesh, function(primitive) {\r\n var valueForEach = ForEach.meshPrimitiveAttribute(primitive, function(accessorId) {\r\n if (!defined(visited[accessorId])) {\r\n visited[accessorId] = true;\r\n var value = handler(accessorId);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n });\r\n\r\n if (defined(valueForEach)) {\r\n return valueForEach;\r\n }\r\n\r\n return ForEach.meshPrimitiveTarget(primitive, function(target) {\r\n return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) {\r\n if (!defined(visited[accessorId])) {\r\n visited[accessorId] = true;\r\n var value = handler(accessorId);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n });\r\n });\r\n });\r\n });\r\n };\r\n\r\n ForEach.accessorContainingIndexData = function(gltf, handler) {\r\n var visited = {};\r\n return ForEach.mesh(gltf, function(mesh) {\r\n return ForEach.meshPrimitive(mesh, function(primitive) {\r\n var indices = primitive.indices;\r\n if (defined(indices) && !defined(visited[indices])) {\r\n visited[indices] = true;\r\n var value = handler(indices);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n });\r\n });\r\n };\r\n\r\n ForEach.animation = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'animations', handler);\r\n };\r\n\r\n ForEach.animationChannel = function(animation, handler) {\r\n var channels = animation.channels;\r\n return ForEach.object(channels, handler);\r\n };\r\n\r\n ForEach.animationSampler = function(animation, handler) {\r\n var samplers = animation.samplers;\r\n return ForEach.object(samplers, handler);\r\n };\r\n\r\n ForEach.buffer = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'buffers', handler);\r\n };\r\n\r\n ForEach.bufferView = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'bufferViews', handler);\r\n };\r\n\r\n ForEach.camera = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'cameras', handler);\r\n };\r\n\r\n ForEach.image = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'images', handler);\r\n };\r\n\r\n ForEach.compressedImage = function(image, handler) {\r\n if (defined(image.extras)) {\r\n var compressedImages = image.extras.compressedImage3DTiles;\r\n for (var type in compressedImages) {\r\n if (Object.prototype.hasOwnProperty.call(compressedImages, type)) {\r\n var compressedImage = compressedImages[type];\r\n var value = handler(compressedImage, type);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.material = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'materials', handler);\r\n };\r\n\r\n ForEach.materialValue = function(material, handler) {\r\n var values = material.values;\r\n if (defined(material.extensions) && defined(material.extensions.KHR_techniques_webgl)) {\r\n values = material.extensions.KHR_techniques_webgl.values;\r\n }\r\n\r\n for (var name in values) {\r\n if (Object.prototype.hasOwnProperty.call(values, name)) {\r\n var value = handler(values[name], name);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.mesh = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'meshes', handler);\r\n };\r\n\r\n ForEach.meshPrimitive = function(mesh, handler) {\r\n var primitives = mesh.primitives;\r\n if (defined(primitives)) {\r\n var primitivesLength = primitives.length;\r\n for (var i = 0; i < primitivesLength; i++) {\r\n var primitive = primitives[i];\r\n var value = handler(primitive, i);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.meshPrimitiveAttribute = function(primitive, handler) {\r\n var attributes = primitive.attributes;\r\n for (var semantic in attributes) {\r\n if (Object.prototype.hasOwnProperty.call(attributes, semantic)) {\r\n var value = handler(attributes[semantic], semantic);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.meshPrimitiveTarget = function(primitive, handler) {\r\n var targets = primitive.targets;\r\n if (defined(targets)) {\r\n var length = targets.length;\r\n for (var i = 0; i < length; ++i) {\r\n var value = handler(targets[i], i);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.meshPrimitiveTargetAttribute = function(target, handler) {\r\n for (var semantic in target) {\r\n if (Object.prototype.hasOwnProperty.call(target, semantic)) {\r\n var accessorId = target[semantic];\r\n var value = handler(accessorId, semantic);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.node = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'nodes', handler);\r\n };\r\n\r\n ForEach.nodeInTree = function(gltf, nodeIds, handler) {\r\n var nodes = gltf.nodes;\r\n if (defined(nodes)) {\r\n var length = nodeIds.length;\r\n for (var i = 0; i < length; i++) {\r\n var nodeId = nodeIds[i];\r\n var node = nodes[nodeId];\r\n if (defined(node)) {\r\n var value = handler(node, nodeId);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n\r\n var children = node.children;\r\n if (defined(children)) {\r\n value = ForEach.nodeInTree(gltf, children, handler);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.nodeInScene = function(gltf, scene, handler) {\r\n var sceneNodeIds = scene.nodes;\r\n if (defined(sceneNodeIds)) {\r\n return ForEach.nodeInTree(gltf, sceneNodeIds, handler);\r\n }\r\n };\r\n\r\n ForEach.program = function(gltf, handler) {\r\n if (hasExtension(gltf, 'KHR_techniques_webgl')) {\r\n return ForEach.object(gltf.extensions.KHR_techniques_webgl.programs, handler);\r\n }\r\n\r\n return ForEach.topLevel(gltf, 'programs', handler);\r\n };\r\n\r\n ForEach.sampler = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'samplers', handler);\r\n };\r\n\r\n ForEach.scene = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'scenes', handler);\r\n };\r\n\r\n ForEach.shader = function(gltf, handler) {\r\n if (hasExtension(gltf, 'KHR_techniques_webgl')) {\r\n return ForEach.object(gltf.extensions.KHR_techniques_webgl.shaders, handler);\r\n }\r\n\r\n return ForEach.topLevel(gltf, 'shaders', handler);\r\n };\r\n\r\n ForEach.skin = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'skins', handler);\r\n };\r\n\r\n ForEach.skinJoint = function(skin, handler) {\r\n var joints = skin.joints;\r\n if (defined(joints)) {\r\n var jointsLength = joints.length;\r\n for (var i = 0; i < jointsLength; i++) {\r\n var joint = joints[i];\r\n var value = handler(joint);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.techniqueAttribute = function(technique, handler) {\r\n var attributes = technique.attributes;\r\n for (var attributeName in attributes) {\r\n if (Object.prototype.hasOwnProperty.call(attributes, attributeName)) {\r\n var value = handler(attributes[attributeName], attributeName);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.techniqueUniform = function(technique, handler) {\r\n var uniforms = technique.uniforms;\r\n for (var uniformName in uniforms) {\r\n if (Object.prototype.hasOwnProperty.call(uniforms, uniformName)) {\r\n var value = handler(uniforms[uniformName], uniformName);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.techniqueParameter = function(technique, handler) {\r\n var parameters = technique.parameters;\r\n for (var parameterName in parameters) {\r\n if (Object.prototype.hasOwnProperty.call(parameters, parameterName)) {\r\n var value = handler(parameters[parameterName], parameterName);\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n }\r\n }\r\n };\r\n\r\n ForEach.technique = function(gltf, handler) {\r\n if (hasExtension(gltf, 'KHR_techniques_webgl')) {\r\n return ForEach.object(gltf.extensions.KHR_techniques_webgl.techniques, handler);\r\n }\r\n\r\n return ForEach.topLevel(gltf, 'techniques', handler);\r\n };\r\n\r\n ForEach.texture = function(gltf, handler) {\r\n return ForEach.topLevel(gltf, 'textures', handler);\r\n };\r\n\r\n export default ForEach;\r\n","\r\n\r\n /**\r\n * Utility function for retrieving the number of components in a given type.\r\n *\r\n * @param {String} type glTF type\r\n * @returns {Number} The number of components in that type.\r\n *\r\n * @private\r\n */\r\n function numberOfComponentsForType(type) {\r\n switch (type) {\r\n case 'SCALAR':\r\n return 1;\r\n case 'VEC2':\r\n return 2;\r\n case 'VEC3':\r\n return 3;\r\n case 'VEC4':\r\n case 'MAT2':\r\n return 4;\r\n case 'MAT3':\r\n return 9;\r\n case 'MAT4':\r\n return 16;\r\n }\r\n }\r\n\r\n export default numberOfComponentsForType;\r\n","import numberOfComponentsForType from './numberOfComponentsForType.js'\r\nimport ComponentDatatype from '../../Core/ComponentDatatype.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Returns the byte stride of the provided accessor.\r\n * If the byteStride is 0, it is calculated based on type and componentType\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {Object} accessor The accessor.\r\n * @returns {Number} The byte stride of the accessor.\r\n *\r\n * @private\r\n */\r\n function getAccessorByteStride(gltf, accessor) {\r\n var bufferViewId = accessor.bufferView;\r\n if (defined(bufferViewId)) {\r\n var bufferView = gltf.bufferViews[bufferViewId];\r\n if (defined(bufferView.byteStride) && bufferView.byteStride > 0) {\r\n return bufferView.byteStride;\r\n }\r\n }\r\n return ComponentDatatype.getSizeInBytes(accessor.componentType) * numberOfComponentsForType(accessor.type);\r\n }\r\n\r\n export default getAccessorByteStride;\r\n","import addToArray from './addToArray.js'\r\nimport ForEach from './ForEach.js'\r\nimport getAccessorByteStride from './getAccessorByteStride.js'\r\nimport defaultValue from '../../Core/defaultValue.js'\r\nimport defined from '../../Core/defined.js'\r\nimport WebGLConstants from '../../Core/WebGLConstants.js'\r\n\r\n /**\r\n * Adds default glTF values if they don't exist.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @returns {Object} The modified glTF.\r\n *\r\n * @private\r\n */\r\n function addDefaults(gltf) {\r\n ForEach.accessor(gltf, function(accessor) {\r\n if (defined(accessor.bufferView)) {\r\n accessor.byteOffset = defaultValue(accessor.byteOffset, 0);\r\n }\r\n });\r\n\r\n ForEach.bufferView(gltf, function(bufferView) {\r\n if (defined(bufferView.buffer)) {\r\n bufferView.byteOffset = defaultValue(bufferView.byteOffset, 0);\r\n }\r\n });\r\n\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n primitive.mode = defaultValue(primitive.mode, WebGLConstants.TRIANGLES);\r\n if (!defined(primitive.material)) {\r\n if (!defined(gltf.materials)) {\r\n gltf.materials = [];\r\n }\r\n var defaultMaterial = {\r\n name: 'default'\r\n };\r\n primitive.material = addToArray(gltf.materials, defaultMaterial);\r\n }\r\n });\r\n });\r\n\r\n ForEach.accessorContainingVertexAttributeData(gltf, function(accessorId) {\r\n var accessor = gltf.accessors[accessorId];\r\n var bufferViewId = accessor.bufferView;\r\n accessor.normalized = defaultValue(accessor.normalized, false);\r\n if (defined(bufferViewId)) {\r\n var bufferView = gltf.bufferViews[bufferViewId];\r\n bufferView.byteStride = getAccessorByteStride(gltf, accessor);\r\n bufferView.target = WebGLConstants.ARRAY_BUFFER;\r\n }\r\n });\r\n\r\n ForEach.accessorContainingIndexData(gltf, function(accessorId) {\r\n var accessor = gltf.accessors[accessorId];\r\n var bufferViewId = accessor.bufferView;\r\n if (defined(bufferViewId)) {\r\n var bufferView = gltf.bufferViews[bufferViewId];\r\n bufferView.target = WebGLConstants.ELEMENT_ARRAY_BUFFER;\r\n }\r\n });\r\n\r\n ForEach.material(gltf, function(material) {\r\n var extensions = defaultValue(material.extensions, defaultValue.EMPTY_OBJECT);\r\n var materialsCommon = extensions.KHR_materials_common;\r\n if (defined(materialsCommon)) {\r\n var technique = materialsCommon.technique;\r\n var values = defined(materialsCommon.values) ? materialsCommon.values : {};\r\n materialsCommon.values = values;\r\n\r\n values.ambient = defined(values.ambient) ? values.ambient : [0.0, 0.0, 0.0, 1.0];\r\n values.emission = defined(values.emission) ? values.emission : [0.0, 0.0, 0.0, 1.0];\r\n\r\n values.transparency = defaultValue(values.transparency, 1.0);\r\n values.transparent = defaultValue(values.transparent, false);\r\n values.doubleSided = defaultValue(values.doubleSided, false);\r\n\r\n if (technique !== 'CONSTANT') {\r\n values.diffuse = defined(values.diffuse) ? values.diffuse : [0.0, 0.0, 0.0, 1.0];\r\n if (technique !== 'LAMBERT') {\r\n values.specular = defined(values.specular) ? values.specular : [0.0, 0.0, 0.0, 1.0];\r\n values.shininess = defaultValue(values.shininess, 0.0);\r\n }\r\n }\r\n return;\r\n }\r\n\r\n material.emissiveFactor = defaultValue(material.emissiveFactor, [0.0, 0.0, 0.0]);\r\n material.alphaMode = defaultValue(material.alphaMode, 'OPAQUE');\r\n material.doubleSided = defaultValue(material.doubleSided, false);\r\n\r\n if (material.alphaMode === 'MASK') {\r\n material.alphaCutoff = defaultValue(material.alphaCutoff, 0.5);\r\n }\r\n\r\n var techniquesExtension = extensions.KHR_techniques_webgl;\r\n if (defined(techniquesExtension)) {\r\n ForEach.materialValue(material, function (materialValue) {\r\n // Check if material value is a TextureInfo object\r\n if (defined(materialValue.index)) {\r\n addTextureDefaults(materialValue);\r\n }\r\n });\r\n }\r\n\r\n addTextureDefaults(material.emissiveTexture);\r\n addTextureDefaults(material.normalTexture);\r\n addTextureDefaults(material.occlusionTexture);\r\n\r\n var pbrMetallicRoughness = material.pbrMetallicRoughness;\r\n if (defined(pbrMetallicRoughness)) {\r\n pbrMetallicRoughness.baseColorFactor = defaultValue(pbrMetallicRoughness.baseColorFactor, [1.0, 1.0, 1.0, 1.0]);\r\n pbrMetallicRoughness.metallicFactor = defaultValue(pbrMetallicRoughness.metallicFactor, 1.0);\r\n pbrMetallicRoughness.roughnessFactor = defaultValue(pbrMetallicRoughness.roughnessFactor, 1.0);\r\n addTextureDefaults(pbrMetallicRoughness.baseColorTexture);\r\n addTextureDefaults(pbrMetallicRoughness.metallicRoughnessTexture);\r\n }\r\n\r\n var pbrSpecularGlossiness = extensions.pbrSpecularGlossiness;\r\n if (defined(pbrSpecularGlossiness)) {\r\n pbrSpecularGlossiness.diffuseFactor = defaultValue(pbrSpecularGlossiness.diffuseFactor, [1.0, 1.0, 1.0, 1.0]);\r\n pbrSpecularGlossiness.specularFactor = defaultValue(pbrSpecularGlossiness.specularFactor, [1.0, 1.0, 1.0]);\r\n pbrSpecularGlossiness.glossinessFactor = defaultValue(pbrSpecularGlossiness.glossinessFactor, 1.0);\r\n addTextureDefaults(pbrSpecularGlossiness.specularGlossinessTexture);\r\n }\r\n });\r\n\r\n ForEach.animation(gltf, function(animation) {\r\n ForEach.animationSampler(animation, function(sampler) {\r\n sampler.interpolation = defaultValue(sampler.interpolation, 'LINEAR');\r\n });\r\n });\r\n\r\n var animatedNodes = getAnimatedNodes(gltf);\r\n ForEach.node(gltf, function(node, id) {\r\n var animated = defined(animatedNodes[id]);\r\n if (animated || defined(node.translation) || defined(node.rotation) || defined(node.scale)) {\r\n node.translation = defaultValue(node.translation, [0.0, 0.0, 0.0]);\r\n node.rotation = defaultValue(node.rotation, [0.0, 0.0, 0.0, 1.0]);\r\n node.scale = defaultValue(node.scale, [1.0, 1.0, 1.0]);\r\n } else {\r\n node.matrix = defaultValue(node.matrix, [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]);\r\n }\r\n });\r\n\r\n ForEach.sampler(gltf, function(sampler) {\r\n sampler.wrapS = defaultValue(sampler.wrapS, WebGLConstants.REPEAT);\r\n sampler.wrapT = defaultValue(sampler.wrapT, WebGLConstants.REPEAT);\r\n });\r\n\r\n if (defined(gltf.scenes) && !defined(gltf.scene)) {\r\n gltf.scene = 0;\r\n }\r\n\r\n return gltf;\r\n }\r\n\r\n function getAnimatedNodes(gltf) {\r\n var nodes = {};\r\n ForEach.animation(gltf, function(animation) {\r\n ForEach.animationChannel(animation, function(channel) {\r\n var target = channel.target;\r\n var nodeId = target.node;\r\n var path = target.path;\r\n // Ignore animations that target 'weights'\r\n if (path === 'translation' || path === 'rotation' || path === 'scale') {\r\n nodes[nodeId] = true;\r\n }\r\n });\r\n });\r\n return nodes;\r\n }\r\n\r\n function addTextureDefaults(texture) {\r\n if (defined(texture)) {\r\n texture.texCoord = defaultValue(texture.texCoord, 0);\r\n }\r\n }\r\n\r\n export default addDefaults;\r\n","import ForEach from './ForEach.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Adds extras._pipeline to each object that can have extras in the glTF asset.\r\n * This stage runs before updateVersion and handles both glTF 1.0 and glTF 2.0 assets.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @returns {Object} The glTF asset with the added pipeline extras.\r\n *\r\n * @private\r\n */\r\n function addPipelineExtras(gltf) {\r\n ForEach.shader(gltf, function(shader) {\r\n addExtras(shader);\r\n });\r\n ForEach.buffer(gltf, function(buffer) {\r\n addExtras(buffer);\r\n });\r\n ForEach.image(gltf, function (image) {\r\n addExtras(image);\r\n ForEach.compressedImage(image, function(compressedImage) {\r\n addExtras(compressedImage);\r\n });\r\n });\r\n\r\n addExtras(gltf);\r\n\r\n return gltf;\r\n }\r\n\r\n function addExtras(object) {\r\n object.extras = defined(object.extras) ? object.extras : {};\r\n object.extras._pipeline = defined(object.extras._pipeline) ? object.extras._pipeline : {};\r\n }\r\n\r\n export default addPipelineExtras;\r\n","import defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Removes an extension from gltf.extensionsRequired if it is present.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {String} extension The extension to remove.\r\n *\r\n * @private\r\n */\r\n function removeExtensionsRequired(gltf, extension) {\r\n var extensionsRequired = gltf.extensionsRequired;\r\n if (defined(extensionsRequired)) {\r\n var index = extensionsRequired.indexOf(extension);\r\n if (index >= 0) {\r\n extensionsRequired.splice(index, 1);\r\n }\r\n if (extensionsRequired.length === 0) {\r\n delete gltf.extensionsRequired;\r\n }\r\n }\r\n }\r\n\r\n export default removeExtensionsRequired;\r\n","import removeExtensionsRequired from './removeExtensionsRequired.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Removes an extension from gltf.extensionsUsed and gltf.extensionsRequired if it is present.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {String} extension The extension to remove.\r\n *\r\n * @private\r\n */\r\n function removeExtensionsUsed(gltf, extension) {\r\n var extensionsUsed = gltf.extensionsUsed;\r\n if (defined(extensionsUsed)) {\r\n var index = extensionsUsed.indexOf(extension);\r\n if (index >= 0) {\r\n extensionsUsed.splice(index, 1);\r\n }\r\n removeExtensionsRequired(gltf, extension);\r\n if (extensionsUsed.length === 0) {\r\n delete gltf.extensionsUsed;\r\n }\r\n }\r\n }\r\n\r\n export default removeExtensionsUsed;\r\n","import addPipelineExtras from './addPipelineExtras.js'\r\nimport removeExtensionsUsed from './removeExtensionsUsed.js'\r\nimport defaultValue from '../../Core/defaultValue.js'\r\nimport defined from '../../Core/defined.js'\r\nimport getJsonFromTypedArray from '../../Core/getJsonFromTypedArray.js'\r\nimport getMagic from '../../Core/getMagic.js'\r\nimport RuntimeError from '../../Core/RuntimeError.js'\r\n\r\n var sizeOfUint32 = 4;\r\n\r\n /**\r\n * Convert a binary glTF to glTF.\r\n *\r\n * The returned glTF has pipeline extras included. The embedded binary data is stored in gltf.buffers[0].extras._pipeline.source.\r\n *\r\n * @param {Buffer} glb The glb data to parse.\r\n * @returns {Object} A javascript object containing a glTF asset with pipeline extras included.\r\n *\r\n * @private\r\n */\r\n function parseGlb(glb) {\r\n // Check that the magic string is present\r\n var magic = getMagic(glb);\r\n if (magic !== 'glTF') {\r\n throw new RuntimeError('File is not valid binary glTF');\r\n }\r\n\r\n var header = readHeader(glb, 0, 5);\r\n var version = header[1];\r\n if (version !== 1 && version !== 2) {\r\n throw new RuntimeError('Binary glTF version is not 1 or 2');\r\n }\r\n\r\n if (version === 1) {\r\n return parseGlbVersion1(glb, header);\r\n }\r\n\r\n return parseGlbVersion2(glb, header);\r\n }\r\n\r\n function readHeader(glb, byteOffset, count) {\r\n var dataView = new DataView(glb.buffer);\r\n var header = new Array(count);\r\n for (var i = 0; i < count; ++i) {\r\n header[i] = dataView.getUint32(glb.byteOffset + byteOffset + i * sizeOfUint32, true);\r\n }\r\n return header;\r\n }\r\n\r\n function parseGlbVersion1(glb, header) {\r\n var length = header[2];\r\n var contentLength = header[3];\r\n var contentFormat = header[4];\r\n\r\n // Check that the content format is 0, indicating that it is JSON\r\n if (contentFormat !== 0) {\r\n throw new RuntimeError('Binary glTF scene format is not JSON');\r\n }\r\n\r\n var jsonStart = 20;\r\n var binaryStart = jsonStart + contentLength;\r\n\r\n var gltf = getJsonFromTypedArray(glb, jsonStart, contentLength);\r\n addPipelineExtras(gltf);\r\n\r\n var binaryBuffer = glb.subarray(binaryStart, length);\r\n\r\n var buffers = gltf.buffers;\r\n if (defined(buffers) && Object.keys(buffers).length > 0) {\r\n // In some older models, the binary glTF buffer is named KHR_binary_glTF\r\n var binaryGltfBuffer = defaultValue(buffers.binary_glTF, buffers.KHR_binary_glTF);\r\n if (defined(binaryGltfBuffer)) {\r\n binaryGltfBuffer.extras._pipeline.source = binaryBuffer;\r\n }\r\n }\r\n // Remove the KHR_binary_glTF extension\r\n removeExtensionsUsed(gltf, 'KHR_binary_glTF');\r\n return gltf;\r\n }\r\n\r\n function parseGlbVersion2(glb, header) {\r\n var length = header[2];\r\n var byteOffset = 12;\r\n var gltf;\r\n var binaryBuffer;\r\n while (byteOffset < length) {\r\n var chunkHeader = readHeader(glb, byteOffset, 2);\r\n var chunkLength = chunkHeader[0];\r\n var chunkType = chunkHeader[1];\r\n byteOffset += 8;\r\n var chunkBuffer = glb.subarray(byteOffset, byteOffset + chunkLength);\r\n byteOffset += chunkLength;\r\n // Load JSON chunk\r\n if (chunkType === 0x4E4F534A) {\r\n gltf = getJsonFromTypedArray(chunkBuffer);\r\n addPipelineExtras(gltf);\r\n }\r\n // Load Binary chunk\r\n else if (chunkType === 0x004E4942) {\r\n binaryBuffer = chunkBuffer;\r\n }\r\n }\r\n if (defined(gltf) && defined(binaryBuffer)) {\r\n var buffers = gltf.buffers;\r\n if (defined(buffers) && buffers.length > 0) {\r\n var buffer = buffers[0];\r\n buffer.extras._pipeline.source = binaryBuffer;\r\n }\r\n }\r\n return gltf;\r\n }\r\n\r\n export default parseGlb;\r\n","import addToArray from './addToArray.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Adds an extension to gltf.extensionsUsed if it does not already exist.\r\n * Initializes extensionsUsed if it is not defined.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {String} extension The extension to add.\r\n *\r\n * @private\r\n */\r\n function addExtensionsUsed(gltf, extension) {\r\n var extensionsUsed = gltf.extensionsUsed;\r\n if (!defined(extensionsUsed)) {\r\n extensionsUsed = [];\r\n gltf.extensionsUsed = extensionsUsed;\r\n }\r\n addToArray(extensionsUsed, extension, true);\r\n }\r\n\r\n export default addExtensionsUsed;\r\n","import ComponentDatatype from '../../Core/ComponentDatatype.js'\r\n\r\n /**\r\n * Returns a function to read and convert data from a DataView into an array.\r\n *\r\n * @param {Number} componentType Type to convert the data to.\r\n * @returns {ComponentReader} Function that reads and converts data.\r\n *\r\n * @private\r\n */\r\n function getComponentReader(componentType) {\r\n switch (componentType) {\r\n case ComponentDatatype.BYTE:\r\n return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {\r\n for (var i = 0; i < numberOfComponents; ++i) {\r\n result[i] = dataView.getInt8(byteOffset + i * componentTypeByteLength);\r\n }\r\n };\r\n case ComponentDatatype.UNSIGNED_BYTE:\r\n return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {\r\n for (var i = 0; i < numberOfComponents; ++i) {\r\n result[i] = dataView.getUint8(byteOffset + i * componentTypeByteLength);\r\n }\r\n };\r\n case ComponentDatatype.SHORT:\r\n return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {\r\n for (var i = 0; i < numberOfComponents; ++i) {\r\n result[i] = dataView.getInt16(byteOffset + i * componentTypeByteLength, true);\r\n }\r\n };\r\n case ComponentDatatype.UNSIGNED_SHORT:\r\n return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {\r\n for (var i = 0; i < numberOfComponents; ++i) {\r\n result[i] = dataView.getUint16(byteOffset + i * componentTypeByteLength, true);\r\n }\r\n };\r\n case ComponentDatatype.INT:\r\n return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {\r\n for (var i = 0; i < numberOfComponents; ++i) {\r\n result[i] = dataView.getInt32(byteOffset + i * componentTypeByteLength, true);\r\n }\r\n };\r\n case ComponentDatatype.UNSIGNED_INT:\r\n return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {\r\n for (var i = 0; i < numberOfComponents; ++i) {\r\n result[i] = dataView.getUint32(byteOffset + i * componentTypeByteLength, true);\r\n }\r\n };\r\n case ComponentDatatype.FLOAT:\r\n return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {\r\n for (var i = 0; i < numberOfComponents; ++i) {\r\n result[i] = dataView.getFloat32(byteOffset + i * componentTypeByteLength, true);\r\n }\r\n };\r\n case ComponentDatatype.DOUBLE:\r\n return function (dataView, byteOffset, numberOfComponents, componentTypeByteLength, result) {\r\n for (var i = 0; i < numberOfComponents; ++i) {\r\n result[i] = dataView.getFloat64(byteOffset + i * componentTypeByteLength, true);\r\n }\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * A callback function that logs messages.\r\n * @callback ComponentReader\r\n *\r\n * @param {DataView} dataView The data view to read from.\r\n * @param {Number} byteOffset The byte offset applied when reading from the data view.\r\n * @param {Number} numberOfComponents The number of components to read.\r\n * @param {Number} componentTypeByteLength The byte length of each component.\r\n * @param {Number} result An array storing the components that are read.\r\n */\r\n\r\n export default getComponentReader;\r\n","import getAccessorByteStride from './getAccessorByteStride.js'\r\nimport getComponentReader from './getComponentReader.js'\r\nimport numberOfComponentsForType from './numberOfComponentsForType.js'\r\nimport arrayFill from '../../Core/arrayFill.js'\r\nimport ComponentDatatype from '../../Core/ComponentDatatype.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Finds the min and max values of the accessor.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {Object} accessor The accessor object from the glTF asset to read.\r\n * @returns {{min: Array, max: Array}} min holding the array of minimum values and max holding the array of maximum values.\r\n *\r\n * @private\r\n */\r\n function findAccessorMinMax(gltf, accessor) {\r\n var bufferViews = gltf.bufferViews;\r\n var buffers = gltf.buffers;\r\n var bufferViewId = accessor.bufferView;\r\n var numberOfComponents = numberOfComponentsForType(accessor.type);\r\n\r\n // According to the spec, when bufferView is not defined, accessor must be initialized with zeros\r\n if (!defined(accessor.bufferView)) {\r\n return {\r\n min: arrayFill(new Array(numberOfComponents), 0.0),\r\n max: arrayFill(new Array(numberOfComponents), 0.0)\r\n };\r\n }\r\n\r\n var min = arrayFill(new Array(numberOfComponents), Number.POSITIVE_INFINITY);\r\n var max = arrayFill(new Array(numberOfComponents), Number.NEGATIVE_INFINITY);\r\n\r\n var bufferView = bufferViews[bufferViewId];\r\n var bufferId = bufferView.buffer;\r\n var buffer = buffers[bufferId];\r\n var source = buffer.extras._pipeline.source;\r\n\r\n var count = accessor.count;\r\n var byteStride = getAccessorByteStride(gltf, accessor);\r\n var byteOffset = accessor.byteOffset + bufferView.byteOffset + source.byteOffset;\r\n var componentType = accessor.componentType;\r\n var componentTypeByteLength = ComponentDatatype.getSizeInBytes(componentType);\r\n var dataView = new DataView(source.buffer);\r\n var components = new Array(numberOfComponents);\r\n var componentReader = getComponentReader(componentType);\r\n\r\n for (var i = 0; i < count; i++) {\r\n componentReader(dataView, byteOffset, numberOfComponents, componentTypeByteLength, components);\r\n for (var j = 0; j < numberOfComponents; j++) {\r\n var value = components[j];\r\n min[j] = Math.min(min[j], value);\r\n max[j] = Math.max(max[j], value);\r\n }\r\n byteOffset += byteStride;\r\n }\r\n\r\n return {\r\n min: min,\r\n max: max\r\n };\r\n }\r\n\r\n export default findAccessorMinMax;\r\n","import addExtensionsUsed from './addExtensionsUsed.js'\r\nimport ForEach from './ForEach.js'\r\nimport defaultValue from '../../Core/defaultValue.js'\r\nimport defined from '../../Core/defined.js'\r\nimport WebGLConstants from '../../Core/WebGLConstants.js'\r\n\r\n var defaultBlendEquation = [\r\n WebGLConstants.FUNC_ADD,\r\n WebGLConstants.FUNC_ADD\r\n ];\r\n\r\n var defaultBlendFactors = [\r\n WebGLConstants.ONE,\r\n WebGLConstants.ZERO,\r\n WebGLConstants.ONE,\r\n WebGLConstants.ZERO\r\n ];\r\n\r\n function isStateEnabled(renderStates, state) {\r\n var enabled = renderStates.enable;\r\n if (!defined(enabled)) {\r\n return false;\r\n }\r\n\r\n return (enabled.indexOf(state) > -1);\r\n }\r\n\r\n var supportedBlendFactors = [\r\n WebGLConstants.ZERO,\r\n WebGLConstants.ONE,\r\n WebGLConstants.SRC_COLOR,\r\n WebGLConstants.ONE_MINUS_SRC_COLOR,\r\n WebGLConstants.SRC_ALPHA,\r\n WebGLConstants.ONE_MINUS_SRC_ALPHA,\r\n WebGLConstants.DST_ALPHA,\r\n WebGLConstants.ONE_MINUS_DST_ALPHA,\r\n WebGLConstants.DST_COLOR,\r\n WebGLConstants.ONE_MINUS_DST_COLOR\r\n ];\r\n\r\n // If any of the blend factors are not supported, return the default\r\n function getSupportedBlendFactors(value, defaultValue) {\r\n if (!defined(value)) {\r\n return defaultValue;\r\n }\r\n\r\n for (var i = 0; i < 4; i++) {\r\n if (supportedBlendFactors.indexOf(value[i]) === -1) {\r\n return defaultValue;\r\n }\r\n }\r\n\r\n return value;\r\n }\r\n\r\n /**\r\n * Move glTF 1.0 technique render states to glTF 2.0 materials properties and KHR_blend extension.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @returns {Object} The updated glTF asset.\r\n *\r\n * @private\r\n */\r\n function moveTechniqueRenderStates(gltf) {\r\n var blendingForTechnique = {};\r\n var materialPropertiesForTechnique = {};\r\n var techniquesLegacy = gltf.techniques;\r\n if (!defined(techniquesLegacy)) {\r\n return gltf;\r\n }\r\n\r\n ForEach.technique(gltf, function (techniqueLegacy, techniqueIndex) {\r\n var renderStates = techniqueLegacy.states;\r\n if (defined(renderStates)) {\r\n var materialProperties = materialPropertiesForTechnique[techniqueIndex] = {};\r\n\r\n // If BLEND is enabled, the material should have alpha mode BLEND\r\n if (isStateEnabled(renderStates, WebGLConstants.BLEND)) {\r\n materialProperties.alphaMode = 'BLEND';\r\n\r\n var blendFunctions = renderStates.functions;\r\n if (defined(blendFunctions) && (defined(blendFunctions.blendEquationSeparate)\r\n || defined(blendFunctions.blendFuncSeparate))) {\r\n blendingForTechnique[techniqueIndex] = {\r\n blendEquation: defaultValue(blendFunctions.blendEquationSeparate, defaultBlendEquation),\r\n blendFactors: getSupportedBlendFactors(blendFunctions.blendFuncSeparate, defaultBlendFactors)\r\n };\r\n }\r\n }\r\n\r\n // If CULL_FACE is not enabled, the material should be doubleSided\r\n if (!isStateEnabled(renderStates, WebGLConstants.CULL_FACE)) {\r\n materialProperties.doubleSided = true;\r\n }\r\n\r\n delete techniqueLegacy.states;\r\n }\r\n });\r\n\r\n if (Object.keys(blendingForTechnique).length > 0) {\r\n if (!defined(gltf.extensions)) {\r\n gltf.extensions = {};\r\n }\r\n\r\n addExtensionsUsed(gltf, 'KHR_blend');\r\n }\r\n\r\n ForEach.material(gltf, function (material) {\r\n if (defined(material.technique)) {\r\n var materialProperties = materialPropertiesForTechnique[material.technique];\r\n ForEach.objectLegacy(materialProperties, function (value, property) {\r\n material[property] = value;\r\n });\r\n\r\n var blending = blendingForTechnique[material.technique];\r\n if (defined(blending)) {\r\n if (!defined(material.extensions)) {\r\n material.extensions = {};\r\n }\r\n\r\n material.extensions.KHR_blend = blending;\r\n }\r\n }\r\n });\r\n\r\n return gltf;\r\n }\r\n\r\n export default moveTechniqueRenderStates;\r\n","import addExtensionsUsed from './addExtensionsUsed.js'\r\nimport addToArray from './addToArray.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Adds an extension to gltf.extensionsRequired if it does not already exist.\r\n * Initializes extensionsRequired if it is not defined.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {String} extension The extension to add.\r\n *\r\n * @private\r\n */\r\n function addExtensionsRequired(gltf, extension) {\r\n var extensionsRequired = gltf.extensionsRequired;\r\n if (!defined(extensionsRequired)) {\r\n extensionsRequired = [];\r\n gltf.extensionsRequired = extensionsRequired;\r\n }\r\n addToArray(extensionsRequired, extension, true);\r\n addExtensionsUsed(gltf, extension);\r\n }\r\n\r\n export default addExtensionsRequired;\r\n","import addExtensionsUsed from './addExtensionsUsed.js'\r\nimport addExtensionsRequired from './addExtensionsRequired.js'\r\nimport addToArray from './addToArray.js'\r\nimport ForEach from './ForEach.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Move glTF 1.0 material techniques to glTF 2.0 KHR_techniques_webgl extension.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @returns {Object} The updated glTF asset.\r\n *\r\n * @private\r\n */\r\n function moveTechniquesToExtension(gltf) {\r\n var techniquesLegacy = gltf.techniques;\r\n var mappedUniforms = {};\r\n var updatedTechniqueIndices = {};\r\n if (defined(techniquesLegacy)) {\r\n var extension = {\r\n programs: [],\r\n shaders: [],\r\n techniques: []\r\n };\r\n\r\n // Some 1.1 models have a glExtensionsUsed property that can be transferred to program.glExtensions\r\n var glExtensions = gltf.glExtensionsUsed;\r\n delete gltf.glExtensionsUsed;\r\n\r\n ForEach.technique(gltf, function (techniqueLegacy, techniqueIndex) {\r\n var technique = {\r\n name: techniqueLegacy.name,\r\n program: undefined,\r\n attributes: {},\r\n uniforms: {}\r\n };\r\n\r\n var parameterLegacy;\r\n ForEach.techniqueAttribute(techniqueLegacy, function (parameterName, attributeName) {\r\n parameterLegacy = techniqueLegacy.parameters[parameterName];\r\n technique.attributes[attributeName] = {\r\n semantic: parameterLegacy.semantic\r\n };\r\n });\r\n\r\n ForEach.techniqueUniform(techniqueLegacy, function (parameterName, uniformName) {\r\n parameterLegacy = techniqueLegacy.parameters[parameterName];\r\n technique.uniforms[uniformName] = {\r\n count: parameterLegacy.count,\r\n node: parameterLegacy.node,\r\n type: parameterLegacy.type,\r\n semantic: parameterLegacy.semantic,\r\n value: parameterLegacy.value\r\n };\r\n\r\n // Store the name of the uniform to update material values.\r\n mappedUniforms[parameterName] = uniformName;\r\n });\r\n\r\n var programLegacy = gltf.programs[techniqueLegacy.program];\r\n var program = {\r\n name: programLegacy.name,\r\n fragmentShader: undefined,\r\n vertexShader: undefined,\r\n glExtensions: glExtensions\r\n };\r\n\r\n var fs = gltf.shaders[programLegacy.fragmentShader];\r\n program.fragmentShader = addToArray(extension.shaders, fs, true);\r\n\r\n var vs = gltf.shaders[programLegacy.vertexShader];\r\n program.vertexShader = addToArray(extension.shaders, vs, true);\r\n\r\n technique.program = addToArray(extension.programs, program);\r\n\r\n // Store the index of the new technique to reference instead.\r\n updatedTechniqueIndices[techniqueIndex] = addToArray(extension.techniques, technique);\r\n });\r\n\r\n if (extension.techniques.length > 0) {\r\n if (!defined(gltf.extensions)) {\r\n gltf.extensions = {};\r\n }\r\n\r\n gltf.extensions.KHR_techniques_webgl = extension;\r\n addExtensionsUsed(gltf, 'KHR_techniques_webgl');\r\n addExtensionsRequired(gltf, 'KHR_techniques_webgl');\r\n }\r\n }\r\n\r\n ForEach.material(gltf, function (material) {\r\n if (defined(material.technique)) {\r\n var materialExtension = {\r\n technique: updatedTechniqueIndices[material.technique]\r\n };\r\n\r\n ForEach.objectLegacy(material.values, function (value, parameterName) {\r\n if (!defined(materialExtension.values)) {\r\n materialExtension.values = {};\r\n }\r\n\r\n var uniformName = mappedUniforms[parameterName];\r\n materialExtension.values[uniformName] = value;\r\n });\r\n\r\n if (!defined(material.extensions)) {\r\n material.extensions = {};\r\n }\r\n\r\n material.extensions.KHR_techniques_webgl = materialExtension;\r\n }\r\n\r\n delete material.technique;\r\n delete material.values;\r\n });\r\n\r\n delete gltf.techniques;\r\n delete gltf.programs;\r\n delete gltf.shaders;\r\n\r\n return gltf;\r\n }\r\n\r\n export default moveTechniquesToExtension;\r\n","import ForEach from './ForEach.js'\r\nimport hasExtension from './hasExtension.js'\r\nimport defaultValue from '../../Core/defaultValue.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n var allElementTypes = ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'];\r\n\r\n /**\r\n * Removes unused elements from gltf.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {String[]} [elementTypes=['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer']] Element types to be removed. Needs to be a subset of ['mesh', 'node', 'material', 'accessor', 'bufferView', 'buffer'], other items will be ignored.\r\n *\r\n * @private\r\n */\r\n function removeUnusedElements(gltf, elementTypes) {\r\n elementTypes = defaultValue(elementTypes, allElementTypes);\r\n allElementTypes.forEach(function(type) {\r\n if (elementTypes.indexOf(type) > -1) {\r\n removeUnusedElementsByType(gltf, type);\r\n }\r\n });\r\n return gltf;\r\n }\r\n\r\n var TypeToGltfElementName = {\r\n accessor: 'accessors',\r\n buffer: 'buffers',\r\n bufferView: 'bufferViews',\r\n node: 'nodes',\r\n material: 'materials',\r\n mesh: 'meshes'\r\n };\r\n\r\n function removeUnusedElementsByType(gltf, type) {\r\n var name = TypeToGltfElementName[type];\r\n var arrayOfObjects = gltf[name];\r\n\r\n if (defined(arrayOfObjects)) {\r\n var removed = 0;\r\n var usedIds = getListOfElementsIdsInUse[type](gltf);\r\n var length = arrayOfObjects.length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n if (!usedIds[i]) {\r\n Remove[type](gltf, i - removed);\r\n removed++;\r\n }\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Contains functions for removing elements from a glTF hierarchy.\r\n * Since top-level glTF elements are arrays, when something is removed, referring\r\n * indices need to be updated.\r\n * @constructor\r\n *\r\n * @private\r\n */\r\n function Remove() {}\r\n\r\n Remove.accessor = function(gltf, accessorId) {\r\n var accessors = gltf.accessors;\r\n\r\n accessors.splice(accessorId, 1);\r\n\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n // Update accessor ids for the primitives.\r\n ForEach.meshPrimitiveAttribute(primitive, function(attributeAccessorId, semantic) {\r\n if (attributeAccessorId > accessorId) {\r\n primitive.attributes[semantic]--;\r\n }\r\n });\r\n\r\n // Update accessor ids for the targets.\r\n ForEach.meshPrimitiveTarget(primitive, function(target) {\r\n ForEach.meshPrimitiveTargetAttribute(target, function(attributeAccessorId, semantic) {\r\n if (attributeAccessorId > accessorId) {\r\n target[semantic]--;\r\n }\r\n });\r\n });\r\n var indices = primitive.indices;\r\n if (defined(indices) && indices > accessorId) {\r\n primitive.indices--;\r\n }\r\n });\r\n });\r\n\r\n ForEach.skin(gltf, function(skin) {\r\n if (defined(skin.inverseBindMatrices) && skin.inverseBindMatrices > accessorId) {\r\n skin.inverseBindMatrices--;\r\n }\r\n });\r\n\r\n ForEach.animation(gltf, function(animation) {\r\n ForEach.animationSampler(animation, function(sampler) {\r\n if (defined(sampler.input) && sampler.input > accessorId) {\r\n sampler.input--;\r\n }\r\n if (defined(sampler.output) && sampler.output > accessorId) {\r\n sampler.output--;\r\n }\r\n });\r\n });\r\n };\r\n\r\n Remove.buffer = function(gltf, bufferId) {\r\n var buffers = gltf.buffers;\r\n\r\n buffers.splice(bufferId, 1);\r\n\r\n ForEach.bufferView(gltf, function(bufferView) {\r\n if (defined(bufferView.buffer) && bufferView.buffer > bufferId) {\r\n bufferView.buffer--;\r\n }\r\n });\r\n };\r\n\r\n Remove.bufferView = function(gltf, bufferViewId) {\r\n var bufferViews = gltf.bufferViews;\r\n\r\n bufferViews.splice(bufferViewId, 1);\r\n\r\n ForEach.accessor(gltf, function(accessor) {\r\n if (defined(accessor.bufferView) && accessor.bufferView > bufferViewId) {\r\n accessor.bufferView--;\r\n }\r\n });\r\n\r\n ForEach.shader(gltf, function(shader) {\r\n if (defined(shader.bufferView) && shader.bufferView > bufferViewId) {\r\n shader.bufferView--;\r\n }\r\n });\r\n\r\n ForEach.image(gltf, function(image) {\r\n if (defined(image.bufferView) && image.bufferView > bufferViewId) {\r\n image.bufferView--;\r\n }\r\n ForEach.compressedImage(image, function(compressedImage) {\r\n var compressedImageBufferView = compressedImage.bufferView;\r\n if (defined(compressedImageBufferView) && compressedImageBufferView > bufferViewId) {\r\n compressedImage.bufferView--;\r\n }\r\n });\r\n });\r\n\r\n if (hasExtension(gltf, 'KHR_draco_mesh_compression')) {\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n if (defined(primitive.extensions) &&\r\n defined(primitive.extensions.KHR_draco_mesh_compression)) {\r\n if (primitive.extensions.KHR_draco_mesh_compression.bufferView > bufferViewId) {\r\n primitive.extensions.KHR_draco_mesh_compression.bufferView--;\r\n }\r\n }\r\n });\r\n });\r\n }\r\n };\r\n\r\n Remove.mesh = function(gltf, meshId) {\r\n var meshes = gltf.meshes;\r\n meshes.splice(meshId, 1);\r\n\r\n ForEach.node(gltf, function(node) {\r\n if (defined(node.mesh)) {\r\n if (node.mesh > meshId) {\r\n node.mesh--;\r\n } else if (node.mesh === meshId) {\r\n // Remove reference to deleted mesh\r\n delete node.mesh;\r\n }\r\n }\r\n });\r\n };\r\n\r\n Remove.node = function(gltf, nodeId) {\r\n var nodes = gltf.nodes;\r\n nodes.splice(nodeId, 1);\r\n\r\n // Shift all node references\r\n ForEach.skin(gltf, function(skin) {\r\n if (defined(skin.skeleton) && skin.skeleton > nodeId) {\r\n skin.skeleton--;\r\n }\r\n\r\n skin.joints = skin.joints.map(function(x) {\r\n return x > nodeId ? x - 1 : x;\r\n });\r\n });\r\n ForEach.animation(gltf, function(animation) {\r\n ForEach.animationChannel(animation, function(channel) {\r\n if (defined(channel.target) && defined(channel.target.node) && (channel.target.node > nodeId)) {\r\n channel.target.node--;\r\n }\r\n });\r\n });\r\n ForEach.technique(gltf, function(technique) {\r\n ForEach.techniqueUniform(technique, function(uniform) {\r\n if (defined(uniform.node) && uniform.node > nodeId) {\r\n uniform.node--;\r\n }\r\n });\r\n });\r\n ForEach.node(gltf, function(node) {\r\n if (!defined(node.children)) {\r\n return;\r\n }\r\n\r\n node.children = node.children\r\n .filter(function(x) {\r\n return x !== nodeId; // Remove\r\n })\r\n .map(function(x) {\r\n return x > nodeId ? x - 1 : x; // Shift indices\r\n });\r\n });\r\n ForEach.scene(gltf, function(scene) {\r\n scene.nodes = scene.nodes\r\n .filter(function(x) {\r\n return x !== nodeId; // Remove\r\n })\r\n .map(function(x) {\r\n return x > nodeId ? x - 1 : x; // Shift indices\r\n });\r\n });\r\n };\r\n\r\n Remove.material = function(gltf, materialId) {\r\n var materials = gltf.materials;\r\n materials.splice(materialId, 1);\r\n\r\n // Shift other material ids\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n if (defined(primitive.material) && primitive.material > materialId) {\r\n primitive.material--;\r\n }\r\n });\r\n });\r\n };\r\n\r\n /**\r\n * Contains functions for getting a list of element ids in use by the glTF asset.\r\n * @constructor\r\n *\r\n * @private\r\n */\r\n function getListOfElementsIdsInUse() {}\r\n\r\n getListOfElementsIdsInUse.accessor = function(gltf) {\r\n // Calculate accessor's that are currently in use.\r\n var usedAccessorIds = {};\r\n\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n ForEach.meshPrimitiveAttribute(primitive, function(accessorId) {\r\n usedAccessorIds[accessorId] = true;\r\n });\r\n ForEach.meshPrimitiveTarget(primitive, function(target) {\r\n ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) {\r\n usedAccessorIds[accessorId] = true;\r\n });\r\n });\r\n var indices = primitive.indices;\r\n if (defined(indices)) {\r\n usedAccessorIds[indices] = true;\r\n }\r\n });\r\n });\r\n\r\n ForEach.skin(gltf, function(skin) {\r\n if (defined(skin.inverseBindMatrices)) {\r\n usedAccessorIds[skin.inverseBindMatrices] = true;\r\n }\r\n });\r\n\r\n ForEach.animation(gltf, function(animation) {\r\n ForEach.animationSampler(animation, function(sampler) {\r\n if (defined(sampler.input)) {\r\n usedAccessorIds[sampler.input] = true;\r\n }\r\n if (defined(sampler.output)) {\r\n usedAccessorIds[sampler.output] = true;\r\n }\r\n });\r\n });\r\n\r\n return usedAccessorIds;\r\n };\r\n\r\n getListOfElementsIdsInUse.buffer = function(gltf) {\r\n // Calculate buffer's that are currently in use.\r\n var usedBufferIds = {};\r\n\r\n ForEach.bufferView(gltf, function(bufferView) {\r\n if (defined(bufferView.buffer)) {\r\n usedBufferIds[bufferView.buffer] = true;\r\n }\r\n });\r\n\r\n return usedBufferIds;\r\n };\r\n\r\n getListOfElementsIdsInUse.bufferView = function(gltf) {\r\n // Calculate bufferView's that are currently in use.\r\n var usedBufferViewIds = {};\r\n\r\n ForEach.accessor(gltf, function(accessor) {\r\n if (defined(accessor.bufferView)) {\r\n usedBufferViewIds[accessor.bufferView] = true;\r\n }\r\n });\r\n\r\n ForEach.shader(gltf, function(shader) {\r\n if (defined(shader.bufferView)) {\r\n usedBufferViewIds[shader.bufferView] = true;\r\n }\r\n });\r\n\r\n ForEach.image(gltf, function(image) {\r\n if (defined(image.bufferView)) {\r\n usedBufferViewIds[image.bufferView] = true;\r\n }\r\n ForEach.compressedImage(image, function(compressedImage) {\r\n if (defined(compressedImage.bufferView)) {\r\n usedBufferViewIds[compressedImage.bufferView] = true;\r\n }\r\n });\r\n });\r\n\r\n if (hasExtension(gltf, 'KHR_draco_mesh_compression')) {\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n if (defined(primitive.extensions) &&\r\n defined(primitive.extensions.KHR_draco_mesh_compression)) {\r\n usedBufferViewIds[primitive.extensions.KHR_draco_mesh_compression.bufferView] = true;\r\n }\r\n });\r\n });\r\n }\r\n\r\n return usedBufferViewIds;\r\n };\r\n\r\n getListOfElementsIdsInUse.mesh = function(gltf) {\r\n var usedMeshIds = {};\r\n ForEach.node(gltf, function(node) {\r\n if (defined(node.mesh && defined(gltf.meshes))) {\r\n var mesh = gltf.meshes[node.mesh];\r\n if (defined(mesh) && defined(mesh.primitives) && (mesh.primitives.length > 0)) {\r\n usedMeshIds[node.mesh] = true;\r\n }\r\n }\r\n });\r\n\r\n return usedMeshIds;\r\n };\r\n\r\n // Check if node is empty. It is considered empty if neither referencing\r\n // mesh, camera, extensions and has no children\r\n function nodeIsEmpty(gltf, node) {\r\n if (defined(node.mesh) || defined(node.camera) || defined(node.skin)\r\n || defined(node.weights) || defined(node.extras)\r\n || (defined(node.extensions) && node.extensions.length !== 0)) {\r\n return false;\r\n }\r\n\r\n // Empty if no children or children are all empty nodes\r\n return !defined(node.children)\r\n || node.children.filter(function(n) {\r\n return !nodeIsEmpty(gltf, gltf.nodes[n]);\r\n }).length === 0;\r\n }\r\n\r\n getListOfElementsIdsInUse.node = function(gltf) {\r\n var usedNodeIds = {};\r\n ForEach.node(gltf, function(node, nodeId) {\r\n if (!nodeIsEmpty(gltf, node)) {\r\n usedNodeIds[nodeId] = true;\r\n }\r\n });\r\n ForEach.skin(gltf, function(skin) {\r\n if (defined(skin.skeleton)) {\r\n usedNodeIds[skin.skeleton] = true;\r\n }\r\n\r\n ForEach.skinJoint(skin, function(joint) {\r\n usedNodeIds[joint] = true;\r\n });\r\n });\r\n ForEach.animation(gltf, function(animation) {\r\n ForEach.animationChannel(animation, function(channel) {\r\n if (defined(channel.target) && defined(channel.target.node)) {\r\n usedNodeIds[channel.target.node] = true;\r\n }\r\n });\r\n });\r\n ForEach.technique(gltf, function(technique) {\r\n ForEach.techniqueUniform(technique, function(uniform) {\r\n if (defined(uniform.node)) {\r\n usedNodeIds[uniform.node] = true;\r\n }\r\n });\r\n });\r\n\r\n return usedNodeIds;\r\n };\r\n\r\n getListOfElementsIdsInUse.material = function(gltf) {\r\n var usedMaterialIds = {};\r\n\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n if (defined(primitive.material)) {\r\n usedMaterialIds[primitive.material] = true;\r\n }\r\n });\r\n });\r\n\r\n return usedMaterialIds;\r\n };\r\n\r\n export default removeUnusedElements;\r\n","import addToArray from './addToArray.js'\r\n\r\n /**\r\n * Adds buffer to gltf.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {Buffer} buffer A Buffer object which will be added to gltf.buffers.\r\n * @returns {Number} The bufferView id of the newly added bufferView.\r\n *\r\n * @private\r\n */\r\n function addBuffer(gltf, buffer) {\r\n var newBuffer = {\r\n byteLength: buffer.length,\r\n extras: {\r\n _pipeline: {\r\n source: buffer\r\n }\r\n }\r\n };\r\n var bufferId = addToArray(gltf.buffers, newBuffer);\r\n var bufferView = {\r\n buffer: bufferId,\r\n byteOffset: 0,\r\n byteLength: buffer.length\r\n };\r\n return addToArray(gltf.bufferViews, bufferView);\r\n }\r\n\r\n export default addBuffer;\r\n","import getAccessorByteStride from './getAccessorByteStride.js'\r\nimport getComponentReader from './getComponentReader.js'\r\nimport numberOfComponentsForType from './numberOfComponentsForType.js'\r\nimport arrayFill from '../../Core/arrayFill.js'\r\nimport ComponentDatatype from '../../Core/ComponentDatatype.js'\r\nimport defined from '../../Core/defined.js'\r\n\r\n /**\r\n * Returns the accessor data in a contiguous array.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {Object} accessor The accessor.\r\n * @returns {Array} The accessor values in a contiguous array.\r\n *\r\n * @private\r\n */\r\n function readAccessorPacked(gltf, accessor) {\r\n var byteStride = getAccessorByteStride(gltf, accessor);\r\n var componentTypeByteLength = ComponentDatatype.getSizeInBytes(accessor.componentType);\r\n var numberOfComponents = numberOfComponentsForType(accessor.type);\r\n var count = accessor.count;\r\n var values = new Array(numberOfComponents * count);\r\n\r\n if (!defined(accessor.bufferView)) {\r\n arrayFill(values, 0);\r\n return values;\r\n }\r\n\r\n var bufferView = gltf.bufferViews[accessor.bufferView];\r\n var source = gltf.buffers[bufferView.buffer].extras._pipeline.source;\r\n var byteOffset = accessor.byteOffset + bufferView.byteOffset + source.byteOffset;\r\n\r\n var dataView = new DataView(source.buffer);\r\n var components = new Array(numberOfComponents);\r\n var componentReader = getComponentReader(accessor.componentType);\r\n\r\n for (var i = 0; i < count; ++i) {\r\n componentReader(dataView, byteOffset, numberOfComponents, componentTypeByteLength, components);\r\n for (var j = 0; j < numberOfComponents; ++j) {\r\n values[i * numberOfComponents + j] = components[j];\r\n }\r\n byteOffset += byteStride;\r\n }\r\n return values;\r\n }\r\n\r\n export default readAccessorPacked;\r\n","import addBuffer from './addBuffer.js'\r\nimport ForEach from './ForEach.js'\r\nimport readAccessorPacked from './readAccessorPacked.js'\r\nimport ComponentDatatype from '../../Core/ComponentDatatype.js'\r\nimport WebGLConstants from '../../Core/WebGLConstants.js'\r\n\r\n /**\r\n * Update accessors referenced by JOINTS_0 and WEIGHTS_0 attributes to use correct component types.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @returns {Object} The glTF asset with compressed meshes.\r\n *\r\n * @private\r\n */\r\n function updateAccessorComponentTypes(gltf) {\r\n var componentType;\r\n ForEach.accessorWithSemantic(gltf, 'JOINTS_0', function(accessorId) {\r\n var accessor = gltf.accessors[accessorId];\r\n componentType = accessor.componentType;\r\n if (componentType === WebGLConstants.BYTE) {\r\n convertType(gltf, accessor, ComponentDatatype.UNSIGNED_BYTE);\r\n } else if (componentType !== WebGLConstants.UNSIGNED_BYTE\r\n && componentType !== WebGLConstants.UNSIGNED_SHORT) {\r\n convertType(gltf, accessor, ComponentDatatype.UNSIGNED_SHORT);\r\n }\r\n });\r\n ForEach.accessorWithSemantic(gltf, 'WEIGHTS_0', function(accessorId) {\r\n var accessor = gltf.accessors[accessorId];\r\n componentType = accessor.componentType;\r\n if (componentType === WebGLConstants.BYTE) {\r\n convertType(gltf, accessor, ComponentDatatype.UNSIGNED_BYTE);\r\n } else if (componentType === WebGLConstants.SHORT) {\r\n convertType(gltf, accessor, ComponentDatatype.UNSIGNED_SHORT);\r\n }\r\n });\r\n\r\n return gltf;\r\n }\r\n\r\n function convertType(gltf, accessor, updatedComponentType) {\r\n var typedArray = ComponentDatatype.createTypedArray(updatedComponentType, readAccessorPacked(gltf, accessor));\r\n var newBuffer = new Uint8Array(typedArray.buffer);\r\n accessor.bufferView = addBuffer(gltf, newBuffer);\r\n accessor.componentType = updatedComponentType;\r\n accessor.byteOffset = 0;\r\n }\r\n\r\n export default updateAccessorComponentTypes;\r\n","import addExtensionsUsed from './addExtensionsUsed.js'\r\nimport addToArray from './addToArray.js'\r\nimport findAccessorMinMax from './findAccessorMinMax.js'\r\nimport ForEach from './ForEach.js'\r\nimport getAccessorByteStride from './getAccessorByteStride.js'\r\nimport numberOfComponentsForType from './numberOfComponentsForType.js'\r\nimport moveTechniqueRenderStates from './moveTechniqueRenderStates.js'\r\nimport moveTechniquesToExtension from './moveTechniquesToExtension.js'\r\nimport removeUnusedElements from './removeUnusedElements.js'\r\nimport updateAccessorComponentTypes from './updateAccessorComponentTypes.js'\r\nimport Cartesian3 from '../../Core/Cartesian3.js'\r\nimport Cartesian4 from '../../Core/Cartesian4.js'\r\nimport clone from '../../Core/clone.js'\r\nimport ComponentDatatype from '../../Core/ComponentDatatype.js'\r\nimport defaultValue from '../../Core/defaultValue.js'\r\nimport defined from '../../Core/defined.js'\r\nimport Matrix4 from '../../Core/Matrix4.js'\r\nimport Quaternion from '../../Core/Quaternion.js'\r\nimport WebGLConstants from '../../Core/WebGLConstants.js'\r\n\r\n var updateFunctions = {\r\n '0.8': glTF08to10,\r\n '1.0': glTF10to20,\r\n '2.0': undefined\r\n };\r\n\r\n /**\r\n * Update the glTF version to the latest version (2.0), or targetVersion if specified.\r\n * Applies changes made to the glTF spec between revisions so that the core library\r\n * only has to handle the latest version.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @param {Object} [options] Options for updating the glTF.\r\n * @param {String} [options.targetVersion] The glTF will be upgraded until it hits the specified version.\r\n * @returns {Object} The updated glTF asset.\r\n *\r\n * @private\r\n */\r\n function updateVersion(gltf, options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var targetVersion = options.targetVersion;\r\n var version = gltf.version;\r\n\r\n gltf.asset = defaultValue(gltf.asset, {\r\n version: '1.0'\r\n });\r\n\r\n gltf.asset.version = defaultValue(gltf.asset.version, '1.0');\r\n version = defaultValue(version, gltf.asset.version).toString();\r\n\r\n // Invalid version\r\n if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {\r\n // Try truncating trailing version numbers, could be a number as well if it is 0.8\r\n if (defined(version)) {\r\n version = version.substring(0, 3);\r\n }\r\n // Default to 1.0 if it cannot be determined\r\n if (!Object.prototype.hasOwnProperty.call(updateFunctions, version)) {\r\n version = '1.0';\r\n }\r\n }\r\n\r\n var updateFunction = updateFunctions[version];\r\n\r\n while (defined(updateFunction)) {\r\n if (version === targetVersion) {\r\n break;\r\n }\r\n updateFunction(gltf, options);\r\n version = gltf.asset.version;\r\n updateFunction = updateFunctions[version];\r\n }\r\n return gltf;\r\n }\r\n\r\n function updateInstanceTechniques(gltf) {\r\n var materials = gltf.materials;\r\n for (var materialId in materials) {\r\n if (Object.prototype.hasOwnProperty.call(materials, materialId)) {\r\n var material = materials[materialId];\r\n var instanceTechnique = material.instanceTechnique;\r\n if (defined(instanceTechnique)) {\r\n material.technique = instanceTechnique.technique;\r\n material.values = instanceTechnique.values;\r\n delete material.instanceTechnique;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function setPrimitiveModes(gltf) {\r\n var meshes = gltf.meshes;\r\n for (var meshId in meshes) {\r\n if (Object.prototype.hasOwnProperty.call(meshes, meshId)) {\r\n var mesh = meshes[meshId];\r\n var primitives = mesh.primitives;\r\n if (defined(primitives)) {\r\n var primitivesLength = primitives.length;\r\n for (var i = 0; i < primitivesLength; ++i) {\r\n var primitive = primitives[i];\r\n var defaultMode = defaultValue(primitive.primitive, WebGLConstants.TRIANGLES);\r\n primitive.mode = defaultValue(primitive.mode, defaultMode);\r\n delete primitive.primitive;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n function updateNodes(gltf) {\r\n var nodes = gltf.nodes;\r\n var axis = new Cartesian3();\r\n var quat = new Quaternion();\r\n for (var nodeId in nodes) {\r\n if (Object.prototype.hasOwnProperty.call(nodes, nodeId)) {\r\n var node = nodes[nodeId];\r\n if (defined(node.rotation)) {\r\n var rotation = node.rotation;\r\n Cartesian3.fromArray(rotation, 0, axis);\r\n Quaternion.fromAxisAngle(axis, rotation[3], quat);\r\n node.rotation = [quat.x, quat.y, quat.z, quat.w];\r\n }\r\n var instanceSkin = node.instanceSkin;\r\n if (defined(instanceSkin)) {\r\n node.skeletons = instanceSkin.skeletons;\r\n node.skin = instanceSkin.skin;\r\n node.meshes = instanceSkin.meshes;\r\n delete node.instanceSkin;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function updateAnimations(gltf) {\r\n var animations = gltf.animations;\r\n var accessors = gltf.accessors;\r\n var bufferViews = gltf.bufferViews;\r\n var buffers = gltf.buffers;\r\n var updatedAccessors = {};\r\n var axis = new Cartesian3();\r\n var quat = new Quaternion();\r\n for (var animationId in animations) {\r\n if (Object.prototype.hasOwnProperty.call(animations, animationId)) {\r\n var animation = animations[animationId];\r\n var channels = animation.channels;\r\n var parameters = animation.parameters;\r\n var samplers = animation.samplers;\r\n if (defined(channels)) {\r\n var channelsLength = channels.length;\r\n for (var i = 0; i < channelsLength; ++i) {\r\n var channel = channels[i];\r\n if (channel.target.path === 'rotation') {\r\n var accessorId = parameters[samplers[channel.sampler].output];\r\n if (defined(updatedAccessors[accessorId])) {\r\n continue;\r\n }\r\n updatedAccessors[accessorId] = true;\r\n var accessor = accessors[accessorId];\r\n var bufferView = bufferViews[accessor.bufferView];\r\n var buffer = buffers[bufferView.buffer];\r\n var source = buffer.extras._pipeline.source;\r\n var byteOffset = source.byteOffset + bufferView.byteOffset + accessor.byteOffset;\r\n var componentType = accessor.componentType;\r\n var count = accessor.count;\r\n var componentsLength = numberOfComponentsForType(accessor.type);\r\n var length = accessor.count * componentsLength;\r\n var typedArray = ComponentDatatype.createArrayBufferView(componentType, source.buffer, byteOffset, length);\r\n\r\n for (var j = 0; j < count; j++) {\r\n var offset = j * componentsLength;\r\n Cartesian3.unpack(typedArray, offset, axis);\r\n var angle = typedArray[offset + 3];\r\n Quaternion.fromAxisAngle(axis, angle, quat);\r\n Quaternion.pack(quat, typedArray, offset);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n function removeTechniquePasses(gltf) {\r\n var techniques = gltf.techniques;\r\n for (var techniqueId in techniques) {\r\n if (Object.prototype.hasOwnProperty.call(techniques, techniqueId)) {\r\n var technique = techniques[techniqueId];\r\n var passes = technique.passes;\r\n if (defined(passes)) {\r\n var passName = defaultValue(technique.pass, 'defaultPass');\r\n if (Object.prototype.hasOwnProperty.call(passes, passName)) {\r\n var pass = passes[passName];\r\n var instanceProgram = pass.instanceProgram;\r\n technique.attributes = defaultValue(technique.attributes, instanceProgram.attributes);\r\n technique.program = defaultValue(technique.program, instanceProgram.program);\r\n technique.uniforms = defaultValue(technique.uniforms, instanceProgram.uniforms);\r\n technique.states = defaultValue(technique.states, pass.states);\r\n }\r\n delete technique.passes;\r\n delete technique.pass;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function glTF08to10(gltf) {\r\n if (!defined(gltf.asset)) {\r\n gltf.asset = {};\r\n }\r\n var asset = gltf.asset;\r\n asset.version = '1.0';\r\n // Profile should be an object, not a string\r\n if (typeof asset.profile === 'string') {\r\n var split = asset.profile.split(' ');\r\n asset.profile = {\r\n api: split[0],\r\n version: split[1]\r\n };\r\n } else {\r\n asset.profile = {};\r\n }\r\n\r\n // Version property should be in asset, not on the root element\r\n if (defined(gltf.version)) {\r\n delete gltf.version;\r\n }\r\n // material.instanceTechnique properties should be directly on the material\r\n updateInstanceTechniques(gltf);\r\n // primitive.primitive should be primitive.mode\r\n setPrimitiveModes(gltf);\r\n // Node rotation should be quaternion, not axis-angle\r\n // node.instanceSkin is deprecated\r\n updateNodes(gltf);\r\n // Animations that target rotations should be quaternion, not axis-angle\r\n updateAnimations(gltf);\r\n // technique.pass and techniques.passes are deprecated\r\n removeTechniquePasses(gltf);\r\n // gltf.allExtensions -> extensionsUsed\r\n if (defined(gltf.allExtensions)) {\r\n gltf.extensionsUsed = gltf.allExtensions;\r\n delete gltf.allExtensions;\r\n }\r\n // gltf.lights -> khrMaterialsCommon.lights\r\n if (defined(gltf.lights)) {\r\n var extensions = defaultValue(gltf.extensions, {});\r\n gltf.extensions = extensions;\r\n var materialsCommon = defaultValue(extensions.KHR_materials_common, {});\r\n extensions.KHR_materials_common = materialsCommon;\r\n materialsCommon.lights = gltf.lights;\r\n delete gltf.lights;\r\n addExtensionsUsed(gltf, 'KHR_materials_common');\r\n }\r\n }\r\n\r\n function removeAnimationSamplersIndirection(gltf) {\r\n var animations = gltf.animations;\r\n for (var animationId in animations) {\r\n if (Object.prototype.hasOwnProperty.call(animations, animationId)) {\r\n var animation = animations[animationId];\r\n var parameters = animation.parameters;\r\n if (defined(parameters)) {\r\n var samplers = animation.samplers;\r\n for (var samplerId in samplers) {\r\n if (Object.prototype.hasOwnProperty.call(samplers, samplerId)) {\r\n var sampler = samplers[samplerId];\r\n sampler.input = parameters[sampler.input];\r\n sampler.output = parameters[sampler.output];\r\n }\r\n }\r\n delete animation.parameters;\r\n }\r\n }\r\n }\r\n }\r\n\r\n function objectToArray(object, mapping) {\r\n var array = [];\r\n for (var id in object) {\r\n if (Object.prototype.hasOwnProperty.call(object, id)) {\r\n var value = object[id];\r\n mapping[id] = array.length;\r\n array.push(value);\r\n if (!defined(value.name)) {\r\n value.name = id;\r\n }\r\n }\r\n }\r\n return array;\r\n }\r\n\r\n function objectsToArrays(gltf) {\r\n var i;\r\n var globalMapping = {\r\n accessors: {},\r\n animations: {},\r\n buffers: {},\r\n bufferViews: {},\r\n cameras: {},\r\n images: {},\r\n materials: {},\r\n meshes: {},\r\n nodes: {},\r\n programs: {},\r\n samplers: {},\r\n scenes: {},\r\n shaders: {},\r\n skins: {},\r\n textures: {},\r\n techniques: {}\r\n };\r\n\r\n // Map joint names to id names\r\n var jointName;\r\n var jointNameToId = {};\r\n var nodes = gltf.nodes;\r\n for (var id in nodes) {\r\n if (Object.prototype.hasOwnProperty.call(nodes, id)) {\r\n jointName = nodes[id].jointName;\r\n if (defined(jointName)) {\r\n jointNameToId[jointName] = id;\r\n }\r\n }\r\n }\r\n\r\n // Convert top level objects to arrays\r\n for (var topLevelId in gltf) {\r\n if (Object.prototype.hasOwnProperty.call(gltf, topLevelId) && defined(globalMapping[topLevelId])) {\r\n var objectMapping = {};\r\n var object = gltf[topLevelId];\r\n gltf[topLevelId] = objectToArray(object, objectMapping);\r\n globalMapping[topLevelId] = objectMapping;\r\n }\r\n }\r\n\r\n // Remap joint names to array indexes\r\n for (jointName in jointNameToId) {\r\n if (Object.prototype.hasOwnProperty.call(jointNameToId, jointName)) {\r\n jointNameToId[jointName] = globalMapping.nodes[jointNameToId[jointName]];\r\n }\r\n }\r\n\r\n // Fix references\r\n if (defined(gltf.scene)) {\r\n gltf.scene = globalMapping.scenes[gltf.scene];\r\n }\r\n ForEach.bufferView(gltf, function(bufferView) {\r\n if (defined(bufferView.buffer)) {\r\n bufferView.buffer = globalMapping.buffers[bufferView.buffer];\r\n }\r\n });\r\n ForEach.accessor(gltf, function(accessor) {\r\n if (defined(accessor.bufferView)) {\r\n accessor.bufferView = globalMapping.bufferViews[accessor.bufferView];\r\n }\r\n });\r\n ForEach.shader(gltf, function(shader) {\r\n var extensions = shader.extensions;\r\n if (defined(extensions)) {\r\n var binaryGltf = extensions.KHR_binary_glTF;\r\n if (defined(binaryGltf)) {\r\n shader.bufferView = globalMapping.bufferViews[binaryGltf.bufferView];\r\n delete extensions.KHR_binary_glTF;\r\n }\r\n if (Object.keys(extensions).length === 0) {\r\n delete shader.extensions;\r\n }\r\n }\r\n });\r\n ForEach.program(gltf, function(program) {\r\n if (defined(program.vertexShader)) {\r\n program.vertexShader = globalMapping.shaders[program.vertexShader];\r\n }\r\n if (defined(program.fragmentShader)) {\r\n program.fragmentShader = globalMapping.shaders[program.fragmentShader];\r\n }\r\n });\r\n ForEach.technique(gltf, function(technique) {\r\n if (defined(technique.program)) {\r\n technique.program = globalMapping.programs[technique.program];\r\n }\r\n ForEach.techniqueParameter(technique, function(parameter) {\r\n if (defined(parameter.node)) {\r\n parameter.node = globalMapping.nodes[parameter.node];\r\n }\r\n var value = parameter.value;\r\n if (typeof value === 'string') {\r\n parameter.value = {\r\n index: globalMapping.textures[value]\r\n };\r\n }\r\n });\r\n });\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n if (defined(primitive.indices)) {\r\n primitive.indices = globalMapping.accessors[primitive.indices];\r\n }\r\n ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {\r\n primitive.attributes[semantic] = globalMapping.accessors[accessorId];\r\n });\r\n if (defined(primitive.material)) {\r\n primitive.material = globalMapping.materials[primitive.material];\r\n }\r\n });\r\n });\r\n ForEach.node(gltf, function(node) {\r\n var children = node.children;\r\n if (defined(children)) {\r\n var childrenLength = children.length;\r\n for (i = 0; i < childrenLength; ++i) {\r\n children[i] = globalMapping.nodes[children[i]];\r\n }\r\n }\r\n if (defined(node.meshes)) {\r\n // Split out meshes on nodes\r\n var meshes = node.meshes;\r\n var meshesLength = meshes.length;\r\n if (meshesLength > 0) {\r\n node.mesh = globalMapping.meshes[meshes[0]];\r\n for (i = 1; i < meshesLength; ++i) {\r\n var meshNode = {\r\n mesh: globalMapping.meshes[meshes[i]]\r\n };\r\n var meshNodeId = addToArray(gltf.nodes, meshNode);\r\n if (!defined(children)) {\r\n children = [];\r\n node.children = children;\r\n }\r\n children.push(meshNodeId);\r\n }\r\n }\r\n delete node.meshes;\r\n }\r\n if (defined(node.camera)) {\r\n node.camera = globalMapping.cameras[node.camera];\r\n }\r\n if (defined(node.skin)) {\r\n node.skin = globalMapping.skins[node.skin];\r\n }\r\n if (defined(node.skeletons)) {\r\n // Assign skeletons to skins\r\n var skeletons = node.skeletons;\r\n var skeletonsLength = skeletons.length;\r\n if ((skeletonsLength > 0) && defined(node.skin)) {\r\n var skin = gltf.skins[node.skin];\r\n skin.skeleton = globalMapping.nodes[skeletons[0]];\r\n }\r\n delete node.skeletons;\r\n }\r\n if (defined(node.jointName)) {\r\n delete node.jointName;\r\n }\r\n });\r\n ForEach.skin(gltf, function(skin) {\r\n if (defined(skin.inverseBindMatrices)) {\r\n skin.inverseBindMatrices = globalMapping.accessors[skin.inverseBindMatrices];\r\n }\r\n var jointNames = skin.jointNames;\r\n if (defined(jointNames)) {\r\n var joints = [];\r\n var jointNamesLength = jointNames.length;\r\n for (i = 0; i < jointNamesLength; ++i) {\r\n joints[i] = jointNameToId[jointNames[i]];\r\n }\r\n skin.joints = joints;\r\n delete skin.jointNames;\r\n }\r\n });\r\n ForEach.scene(gltf, function(scene) {\r\n var sceneNodes = scene.nodes;\r\n if (defined(sceneNodes)) {\r\n var sceneNodesLength = sceneNodes.length;\r\n for (i = 0; i < sceneNodesLength; ++i) {\r\n sceneNodes[i] = globalMapping.nodes[sceneNodes[i]];\r\n }\r\n }\r\n });\r\n ForEach.animation(gltf, function(animation) {\r\n var samplerMapping = {};\r\n animation.samplers = objectToArray(animation.samplers, samplerMapping);\r\n ForEach.animationSampler(animation, function(sampler) {\r\n sampler.input = globalMapping.accessors[sampler.input];\r\n sampler.output = globalMapping.accessors[sampler.output];\r\n });\r\n ForEach.animationChannel(animation, function(channel) {\r\n channel.sampler = samplerMapping[channel.sampler];\r\n var target = channel.target;\r\n if (defined(target)) {\r\n target.node = globalMapping.nodes[target.id];\r\n delete target.id;\r\n }\r\n });\r\n });\r\n ForEach.material(gltf, function(material) {\r\n if (defined(material.technique)) {\r\n material.technique = globalMapping.techniques[material.technique];\r\n }\r\n ForEach.materialValue(material, function(value, name) {\r\n if (typeof value === 'string') {\r\n material.values[name] = {\r\n index: globalMapping.textures[value]\r\n };\r\n }\r\n });\r\n var extensions = material.extensions;\r\n if (defined(extensions)) {\r\n var materialsCommon = extensions.KHR_materials_common;\r\n if (defined(materialsCommon)) {\r\n ForEach.materialValue(materialsCommon, function(value, name) {\r\n if (typeof value === 'string') {\r\n materialsCommon.values[name] = {\r\n index: globalMapping.textures[value]\r\n };\r\n }\r\n });\r\n }\r\n }\r\n });\r\n ForEach.image(gltf, function(image) {\r\n var extensions = image.extensions;\r\n if (defined(extensions)) {\r\n var binaryGltf = extensions.KHR_binary_glTF;\r\n if (defined(binaryGltf)) {\r\n image.bufferView = globalMapping.bufferViews[binaryGltf.bufferView];\r\n image.mimeType = binaryGltf.mimeType;\r\n delete extensions.KHR_binary_glTF;\r\n }\r\n if (Object.keys(extensions).length === 0) {\r\n delete image.extensions;\r\n }\r\n }\r\n ForEach.compressedImage(image, function(compressedImage) {\r\n var compressedExtensions = compressedImage.extensions;\r\n if (defined(compressedExtensions)) {\r\n var compressedBinaryGltf = compressedExtensions.KHR_binary_glTF;\r\n if (defined(compressedBinaryGltf)) {\r\n compressedImage.bufferView = globalMapping.bufferViews[compressedBinaryGltf.bufferView];\r\n compressedImage.mimeType = compressedBinaryGltf.mimeType;\r\n delete compressedExtensions.KHR_binary_glTF;\r\n }\r\n if (Object.keys(extensions).length === 0) {\r\n delete compressedImage.extensions;\r\n }\r\n }\r\n });\r\n });\r\n ForEach.texture(gltf, function(texture) {\r\n if (defined(texture.sampler)) {\r\n texture.sampler = globalMapping.samplers[texture.sampler];\r\n }\r\n if (defined(texture.source)) {\r\n texture.source = globalMapping.images[texture.source];\r\n }\r\n });\r\n }\r\n\r\n function removeAnimationSamplerNames(gltf) {\r\n ForEach.animation(gltf, function(animation) {\r\n ForEach.animationSampler(animation, function(sampler) {\r\n delete sampler.name;\r\n });\r\n });\r\n }\r\n\r\n function removeEmptyArrays(gltf) {\r\n for (var topLevelId in gltf) {\r\n if (Object.prototype.hasOwnProperty.call(gltf, topLevelId)) {\r\n var array = gltf[topLevelId];\r\n if (Array.isArray(array) && array.length === 0) {\r\n delete gltf[topLevelId];\r\n }\r\n }\r\n }\r\n ForEach.node(gltf, function(node) {\r\n if (defined(node.children) && node.children.length === 0) {\r\n delete node.children;\r\n }\r\n });\r\n }\r\n\r\n function stripAsset(gltf) {\r\n var asset = gltf.asset;\r\n delete asset.profile;\r\n delete asset.premultipliedAlpha;\r\n }\r\n\r\n var knownExtensions = {\r\n CESIUM_RTC: true,\r\n KHR_materials_common: true,\r\n WEB3D_quantized_attributes: true\r\n };\r\n function requireKnownExtensions(gltf) {\r\n var extensionsUsed = gltf.extensionsUsed;\r\n gltf.extensionsRequired = defaultValue(gltf.extensionsRequired, []);\r\n if (defined(extensionsUsed)) {\r\n var extensionsUsedLength = extensionsUsed.length;\r\n for (var i = 0; i < extensionsUsedLength; ++i) {\r\n var extension = extensionsUsed[i];\r\n if (defined(knownExtensions[extension])) {\r\n gltf.extensionsRequired.push(extension);\r\n }\r\n }\r\n }\r\n }\r\n\r\n function removeBufferType(gltf) {\r\n ForEach.buffer(gltf, function(buffer) {\r\n delete buffer.type;\r\n });\r\n }\r\n\r\n function removeTextureProperties(gltf) {\r\n ForEach.texture(gltf, function(texture) {\r\n delete texture.format;\r\n delete texture.internalFormat;\r\n delete texture.target;\r\n delete texture.type;\r\n });\r\n }\r\n\r\n function requireAttributeSetIndex(gltf) {\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {\r\n if (semantic === 'TEXCOORD') {\r\n primitive.attributes.TEXCOORD_0 = accessorId;\r\n } else if (semantic === 'COLOR') {\r\n primitive.attributes.COLOR_0 = accessorId;\r\n }\r\n });\r\n delete primitive.attributes.TEXCOORD;\r\n delete primitive.attributes.COLOR;\r\n });\r\n });\r\n ForEach.technique(gltf, function(technique) {\r\n ForEach.techniqueParameter(technique, function(parameter) {\r\n var semantic = parameter.semantic;\r\n if (defined(semantic)) {\r\n if (semantic === 'TEXCOORD') {\r\n parameter.semantic = 'TEXCOORD_0';\r\n } else if (semantic === 'COLOR') {\r\n parameter.semantic = 'COLOR_0';\r\n }\r\n }\r\n });\r\n });\r\n }\r\n\r\n var knownSemantics = {\r\n POSITION: true,\r\n NORMAL: true,\r\n TANGENT: true\r\n };\r\n var indexedSemantics = {\r\n COLOR: 'COLOR',\r\n JOINT : 'JOINTS',\r\n JOINTS: 'JOINTS',\r\n TEXCOORD: 'TEXCOORD',\r\n WEIGHT: 'WEIGHTS',\r\n WEIGHTS: 'WEIGHTS'\r\n };\r\n function underscoreApplicationSpecificSemantics(gltf) {\r\n var mappedSemantics = {};\r\n ForEach.mesh(gltf, function(mesh) {\r\n ForEach.meshPrimitive(mesh, function(primitive) {\r\n /*eslint-disable no-unused-vars*/\r\n ForEach.meshPrimitiveAttribute(primitive, function(accessorId, semantic) {\r\n if (semantic.charAt(0) !== '_') {\r\n var setIndex = semantic.search(/_[0-9]+/g);\r\n var strippedSemantic = semantic;\r\n var suffix = '_0';\r\n if (setIndex >= 0) {\r\n strippedSemantic = semantic.substring(0, setIndex);\r\n suffix = semantic.substring(setIndex);\r\n }\r\n var newSemantic;\r\n var indexedSemantic = indexedSemantics[strippedSemantic];\r\n if (defined(indexedSemantic)) {\r\n newSemantic = indexedSemantic + suffix;\r\n mappedSemantics[semantic] = newSemantic;\r\n } else if (!defined(knownSemantics[strippedSemantic])) {\r\n newSemantic = '_' + semantic;\r\n mappedSemantics[semantic] = newSemantic;\r\n }\r\n }\r\n });\r\n for (var semantic in mappedSemantics) {\r\n if (Object.prototype.hasOwnProperty.call(mappedSemantics, semantic)) {\r\n var mappedSemantic = mappedSemantics[semantic];\r\n var accessorId = primitive.attributes[semantic];\r\n if (defined(accessorId)) {\r\n delete primitive.attributes[semantic];\r\n primitive.attributes[mappedSemantic] = accessorId;\r\n }\r\n }\r\n }\r\n });\r\n });\r\n ForEach.technique(gltf, function(technique) {\r\n ForEach.techniqueParameter(technique, function(parameter) {\r\n var mappedSemantic = mappedSemantics[parameter.semantic];\r\n if (defined(mappedSemantic)) {\r\n parameter.semantic = mappedSemantic;\r\n }\r\n });\r\n });\r\n }\r\n\r\n function clampCameraParameters(gltf) {\r\n ForEach.camera(gltf, function(camera) {\r\n var perspective = camera.perspective;\r\n if (defined(perspective)) {\r\n var aspectRatio = perspective.aspectRatio;\r\n if (defined(aspectRatio) && aspectRatio === 0.0) {\r\n delete perspective.aspectRatio;\r\n }\r\n var yfov = perspective.yfov;\r\n if (defined(yfov) && yfov === 0.0) {\r\n perspective.yfov = 1.0;\r\n }\r\n }\r\n });\r\n }\r\n\r\n function computeAccessorByteStride(gltf, accessor) {\r\n return (defined(accessor.byteStride) && accessor.byteStride !== 0) ? accessor.byteStride : getAccessorByteStride(gltf, accessor);\r\n }\r\n\r\n function requireByteLength(gltf) {\r\n ForEach.buffer(gltf, function(buffer) {\r\n if (!defined(buffer.byteLength)) {\r\n buffer.byteLength = buffer.extras._pipeline.source.length;\r\n }\r\n });\r\n ForEach.accessor(gltf, function(accessor) {\r\n var bufferViewId = accessor.bufferView;\r\n if (defined(bufferViewId)) {\r\n var bufferView = gltf.bufferViews[bufferViewId];\r\n var accessorByteStride = computeAccessorByteStride(gltf, accessor);\r\n var accessorByteEnd = accessor.byteOffset + accessor.count * accessorByteStride;\r\n bufferView.byteLength = Math.max(defaultValue(bufferView.byteLength, 0), accessorByteEnd);\r\n }\r\n });\r\n }\r\n\r\n function moveByteStrideToBufferView(gltf) {\r\n var i;\r\n var j;\r\n var bufferView;\r\n var bufferViews = gltf.bufferViews;\r\n\r\n var bufferViewHasVertexAttributes = {};\r\n ForEach.accessorContainingVertexAttributeData(gltf, function(accessorId) {\r\n var accessor = gltf.accessors[accessorId];\r\n if (defined(accessor.bufferView)) {\r\n bufferViewHasVertexAttributes[accessor.bufferView] = true;\r\n }\r\n });\r\n\r\n // Map buffer views to a list of accessors\r\n var bufferViewMap = {};\r\n ForEach.accessor(gltf, function(accessor) {\r\n if (defined(accessor.bufferView)) {\r\n bufferViewMap[accessor.bufferView] = defaultValue(bufferViewMap[accessor.bufferView], []);\r\n bufferViewMap[accessor.bufferView].push(accessor);\r\n }\r\n });\r\n\r\n // Split accessors with different byte strides\r\n for (var bufferViewId in bufferViewMap) {\r\n if (Object.prototype.hasOwnProperty.call(bufferViewMap, bufferViewId)) {\r\n bufferView = bufferViews[bufferViewId];\r\n var accessors = bufferViewMap[bufferViewId];\r\n accessors.sort(function(a, b) {\r\n return a.byteOffset - b.byteOffset;\r\n });\r\n var currentByteOffset = 0;\r\n var currentIndex = 0;\r\n var accessorsLength = accessors.length;\r\n for (i = 0; i < accessorsLength; ++i) {\r\n var accessor = accessors[i];\r\n var accessorByteStride = computeAccessorByteStride(gltf, accessor);\r\n var accessorByteOffset = accessor.byteOffset;\r\n var accessorByteLength = accessor.count * accessorByteStride;\r\n delete accessor.byteStride;\r\n\r\n var hasNextAccessor = (i < accessorsLength - 1);\r\n var nextAccessorByteStride = hasNextAccessor ? computeAccessorByteStride(gltf, accessors[i + 1]) : undefined;\r\n if (accessorByteStride !== nextAccessorByteStride) {\r\n var newBufferView = clone(bufferView, true);\r\n if (bufferViewHasVertexAttributes[bufferViewId]) {\r\n newBufferView.byteStride = accessorByteStride;\r\n }\r\n newBufferView.byteOffset += currentByteOffset;\r\n newBufferView.byteLength = accessorByteOffset + accessorByteLength - currentByteOffset;\r\n var newBufferViewId = addToArray(bufferViews, newBufferView);\r\n for (j = currentIndex; j <= i; ++j) {\r\n accessor = accessors[j];\r\n accessor.bufferView = newBufferViewId;\r\n accessor.byteOffset = accessor.byteOffset - currentByteOffset;\r\n }\r\n // Set current byte offset to next accessor's byte offset\r\n currentByteOffset = hasNextAccessor ? accessors[i + 1].byteOffset : undefined;\r\n currentIndex = i + 1;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Remove unused buffer views\r\n removeUnusedElements(gltf, ['accessor', 'bufferView', 'buffer']);\r\n }\r\n\r\n function requirePositionAccessorMinMax(gltf) {\r\n ForEach.accessorWithSemantic(gltf, 'POSITION', function(accessorId) {\r\n var accessor = gltf.accessors[accessorId];\r\n if (!defined(accessor.min) || !defined(accessor.max)) {\r\n var minMax = findAccessorMinMax(gltf, accessor);\r\n accessor.min = minMax.min;\r\n accessor.max = minMax.max;\r\n }\r\n });\r\n }\r\n\r\n function isNodeEmpty(node) {\r\n return (!defined(node.children) || node.children.length === 0) &&\r\n (!defined(node.meshes) || node.meshes.length === 0) &&\r\n !defined(node.camera) && !defined(node.skin) && !defined(node.skeletons) && !defined(node.jointName) &&\r\n (!defined(node.translation) || Cartesian3.fromArray(node.translation).equals(Cartesian3.ZERO)) &&\r\n (!defined(node.scale) || Cartesian3.fromArray(node.scale).equals(new Cartesian3(1.0, 1.0, 1.0))) &&\r\n (!defined(node.rotation) || Cartesian4.fromArray(node.rotation).equals(new Cartesian4(0.0, 0.0, 0.0, 1.0))) &&\r\n (!defined(node.matrix) || Matrix4.fromColumnMajorArray(node.matrix).equals(Matrix4.IDENTITY)) &&\r\n !defined(node.extensions) && !defined(node.extras);\r\n }\r\n\r\n function deleteNode(gltf, nodeId) {\r\n // Remove from list of nodes in scene\r\n ForEach.scene(gltf, function(scene) {\r\n var sceneNodes = scene.nodes;\r\n if (defined(sceneNodes)) {\r\n var sceneNodesLength = sceneNodes.length;\r\n for (var i = sceneNodesLength; i >= 0; --i) {\r\n if (sceneNodes[i] === nodeId) {\r\n sceneNodes.splice(i, 1);\r\n return;\r\n }\r\n }\r\n }\r\n });\r\n\r\n // Remove parent node's reference to this node, and delete the parent if also empty\r\n ForEach.node(gltf, function(parentNode, parentNodeId) {\r\n if (defined(parentNode.children)) {\r\n var index = parentNode.children.indexOf(nodeId);\r\n if (index > -1) {\r\n parentNode.children.splice(index, 1);\r\n\r\n if (isNodeEmpty(parentNode)) {\r\n deleteNode(gltf, parentNodeId);\r\n }\r\n }\r\n }\r\n });\r\n\r\n delete gltf.nodes[nodeId];\r\n }\r\n\r\n function removeEmptyNodes(gltf) {\r\n ForEach.node(gltf, function(node, nodeId) {\r\n if (isNodeEmpty(node)) {\r\n deleteNode(gltf, nodeId);\r\n }\r\n });\r\n\r\n return gltf;\r\n }\r\n\r\n function requireAnimationAccessorMinMax(gltf) {\r\n ForEach.animation(gltf, function(animation) {\r\n ForEach.animationSampler(animation, function(sampler) {\r\n var accessor = gltf.accessors[sampler.input];\r\n if (!defined(accessor.min) || !defined(accessor.max)) {\r\n var minMax = findAccessorMinMax(gltf, accessor);\r\n accessor.min = minMax.min;\r\n accessor.max = minMax.max;\r\n }\r\n });\r\n });\r\n }\r\n\r\n function glTF10to20(gltf) {\r\n gltf.asset = defaultValue(gltf.asset, {});\r\n gltf.asset.version = '2.0';\r\n // material.instanceTechnique properties should be directly on the material. instanceTechnique is a gltf 0.8 property but is seen in some 1.0 models.\r\n updateInstanceTechniques(gltf);\r\n // animation.samplers now refers directly to accessors and animation.parameters should be removed\r\n removeAnimationSamplersIndirection(gltf);\r\n // Remove empty nodes and re-assign referencing indices\r\n removeEmptyNodes(gltf);\r\n // Top-level objects are now arrays referenced by index instead of id\r\n objectsToArrays(gltf);\r\n // Animation.sampler objects cannot have names\r\n removeAnimationSamplerNames(gltf);\r\n // asset.profile no longer exists\r\n stripAsset(gltf);\r\n // Move known extensions from extensionsUsed to extensionsRequired\r\n requireKnownExtensions(gltf);\r\n // bufferView.byteLength and buffer.byteLength are required\r\n requireByteLength(gltf);\r\n // byteStride moved from accessor to bufferView\r\n moveByteStrideToBufferView(gltf);\r\n // accessor.min and accessor.max must be defined for accessors containing POSITION attributes\r\n requirePositionAccessorMinMax(gltf);\r\n // An animation sampler's input accessor must have min and max properties defined\r\n requireAnimationAccessorMinMax(gltf);\r\n // buffer.type is unnecessary and should be removed\r\n removeBufferType(gltf);\r\n // Remove format, internalFormat, target, and type\r\n removeTextureProperties(gltf);\r\n // TEXCOORD and COLOR attributes must be written with a set index (TEXCOORD_#)\r\n requireAttributeSetIndex(gltf);\r\n // Add underscores to application-specific parameters\r\n underscoreApplicationSpecificSemantics(gltf);\r\n // Accessors referenced by JOINTS_0 and WEIGHTS_0 attributes must have correct component types\r\n updateAccessorComponentTypes(gltf);\r\n // Clamp camera parameters\r\n clampCameraParameters(gltf);\r\n // Move legacy technique render states to material properties and add KHR_blend extension blending functions\r\n moveTechniqueRenderStates(gltf);\r\n // Add material techniques to KHR_techniques_webgl extension, removing shaders, programs, and techniques\r\n moveTechniquesToExtension(gltf);\r\n // Remove empty arrays\r\n removeEmptyArrays(gltf);\r\n }\r\n\r\n export default updateVersion;\r\n","import Queue from \"../Core/Queue.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction ModelLoadResources() {\r\n this.initialized = false;\r\n this.resourcesParsed = false;\r\n\r\n this.vertexBuffersToCreate = new Queue();\r\n this.indexBuffersToCreate = new Queue();\r\n this.buffers = {};\r\n this.pendingBufferLoads = 0;\r\n\r\n this.programsToCreate = new Queue();\r\n this.shaders = {};\r\n this.pendingShaderLoads = 0;\r\n\r\n this.texturesToCreate = new Queue();\r\n this.pendingTextureLoads = 0;\r\n\r\n this.texturesToCreateFromBufferView = new Queue();\r\n this.pendingBufferViewToImage = 0;\r\n\r\n this.createSamplers = true;\r\n this.createSkins = true;\r\n this.createRuntimeAnimations = true;\r\n this.createVertexArrays = true;\r\n this.createRenderStates = true;\r\n this.createUniformMaps = true;\r\n this.createRuntimeNodes = true;\r\n\r\n this.createdBufferViews = {};\r\n this.primitivesToDecode = new Queue();\r\n this.activeDecodingTasks = 0;\r\n this.pendingDecodingCache = false;\r\n\r\n this.skinnedNodesIds = [];\r\n}\r\n\r\n/**\r\n * This function differs from the normal subarray function\r\n * because it takes offset and length, rather than begin and end.\r\n * @private\r\n */\r\nfunction getSubarray(array, offset, length) {\r\n return array.subarray(offset, offset + length);\r\n}\r\n\r\nModelLoadResources.prototype.getBuffer = function (bufferView) {\r\n return getSubarray(\r\n this.buffers[bufferView.buffer],\r\n bufferView.byteOffset,\r\n bufferView.byteLength\r\n );\r\n};\r\n\r\nModelLoadResources.prototype.finishedPendingBufferLoads = function () {\r\n return this.pendingBufferLoads === 0;\r\n};\r\n\r\nModelLoadResources.prototype.finishedBuffersCreation = function () {\r\n return (\r\n this.pendingBufferLoads === 0 &&\r\n this.vertexBuffersToCreate.length === 0 &&\r\n this.indexBuffersToCreate.length === 0\r\n );\r\n};\r\n\r\nModelLoadResources.prototype.finishedProgramCreation = function () {\r\n return this.pendingShaderLoads === 0 && this.programsToCreate.length === 0;\r\n};\r\n\r\nModelLoadResources.prototype.finishedTextureCreation = function () {\r\n var finishedPendingLoads = this.pendingTextureLoads === 0;\r\n var finishedResourceCreation =\r\n this.texturesToCreate.length === 0 &&\r\n this.texturesToCreateFromBufferView.length === 0;\r\n\r\n return finishedPendingLoads && finishedResourceCreation;\r\n};\r\n\r\nModelLoadResources.prototype.finishedEverythingButTextureCreation = function () {\r\n var finishedPendingLoads =\r\n this.pendingBufferLoads === 0 && this.pendingShaderLoads === 0;\r\n var finishedResourceCreation =\r\n this.vertexBuffersToCreate.length === 0 &&\r\n this.indexBuffersToCreate.length === 0 &&\r\n this.programsToCreate.length === 0 &&\r\n this.pendingBufferViewToImage === 0;\r\n\r\n return (\r\n this.finishedDecoding() && finishedPendingLoads && finishedResourceCreation\r\n );\r\n};\r\n\r\nModelLoadResources.prototype.finishedDecoding = function () {\r\n return (\r\n this.primitivesToDecode.length === 0 &&\r\n this.activeDecodingTasks === 0 &&\r\n !this.pendingDecodingCache\r\n );\r\n};\r\n\r\nModelLoadResources.prototype.finished = function () {\r\n return (\r\n this.finishedDecoding() &&\r\n this.finishedTextureCreation() &&\r\n this.finishedEverythingButTextureCreation()\r\n );\r\n};\r\nexport default ModelLoadResources;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport clone from \"../Core/clone.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Matrix2 from \"../Core/Matrix2.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Quaternion from \"../Core/Quaternion.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport addToArray from \"../ThirdParty/GltfPipeline/addToArray.js\";\r\nimport ForEach from \"../ThirdParty/GltfPipeline/ForEach.js\";\r\nimport hasExtension from \"../ThirdParty/GltfPipeline/hasExtension.js\";\r\nimport AttributeType from \"./AttributeType.js\";\r\nimport Axis from \"./Axis.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nvar ModelUtility = {};\r\n\r\n/**\r\n * Updates the model's forward axis if the model is not a 2.0 model.\r\n *\r\n * @param {Object} model The model to update.\r\n */\r\nModelUtility.updateForwardAxis = function (model) {\r\n var cachedSourceVersion = model.gltf.extras.sourceVersion;\r\n\r\n if (\r\n (defined(cachedSourceVersion) && cachedSourceVersion !== \"2.0\") ||\r\n ModelUtility.getAssetVersion(model.gltf) !== \"2.0\"\r\n ) {\r\n model._gltfForwardAxis = Axis.X;\r\n }\r\n};\r\n\r\n/**\r\n * Gets the string representing the glTF asset version.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @returns {String} The glTF asset version string.\r\n */\r\nModelUtility.getAssetVersion = function (gltf) {\r\n // In glTF 1.0 it was valid to omit the version number.\r\n if (!defined(gltf.asset) || !defined(gltf.asset.version)) {\r\n return \"1.0\";\r\n }\r\n\r\n return gltf.asset.version;\r\n};\r\n\r\n/**\r\n * Splits primitive materials with values incompatible for generating techniques.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @returns {Object} The glTF asset with modified materials.\r\n */\r\nModelUtility.splitIncompatibleMaterials = function (gltf) {\r\n var accessors = gltf.accessors;\r\n var materials = gltf.materials;\r\n var primitiveInfoByMaterial = {};\r\n ForEach.mesh(gltf, function (mesh) {\r\n ForEach.meshPrimitive(mesh, function (primitive) {\r\n var materialIndex = primitive.material;\r\n var material = materials[materialIndex];\r\n\r\n var jointAccessorId = primitive.attributes.JOINTS_0;\r\n var componentType;\r\n var accessorType;\r\n if (defined(jointAccessorId)) {\r\n var jointAccessor = accessors[jointAccessorId];\r\n componentType = jointAccessor.componentType;\r\n accessorType = jointAccessor.type;\r\n }\r\n var isSkinned = defined(jointAccessorId) && accessorType === \"VEC4\";\r\n var hasVertexColors = defined(primitive.attributes.COLOR_0);\r\n var hasMorphTargets = defined(primitive.targets);\r\n var hasNormals = defined(primitive.attributes.NORMAL);\r\n var hasTangents = defined(primitive.attributes.TANGENT);\r\n var hasTexCoords = defined(primitive.attributes.TEXCOORD_0);\r\n var hasTexCoord1 =\r\n hasTexCoords && defined(primitive.attributes.TEXCOORD_1);\r\n var hasOutline =\r\n defined(primitive.extensions) &&\r\n defined(primitive.extensions.CESIUM_primitive_outline);\r\n\r\n var primitiveInfo = primitiveInfoByMaterial[materialIndex];\r\n if (!defined(primitiveInfo)) {\r\n primitiveInfoByMaterial[materialIndex] = {\r\n skinning: {\r\n skinned: isSkinned,\r\n componentType: componentType,\r\n },\r\n hasVertexColors: hasVertexColors,\r\n hasMorphTargets: hasMorphTargets,\r\n hasNormals: hasNormals,\r\n hasTangents: hasTangents,\r\n hasTexCoords: hasTexCoords,\r\n hasTexCoord1: hasTexCoord1,\r\n hasOutline: hasOutline,\r\n };\r\n } else if (\r\n primitiveInfo.skinning.skinned !== isSkinned ||\r\n primitiveInfo.hasVertexColors !== hasVertexColors ||\r\n primitiveInfo.hasMorphTargets !== hasMorphTargets ||\r\n primitiveInfo.hasNormals !== hasNormals ||\r\n primitiveInfo.hasTangents !== hasTangents ||\r\n primitiveInfo.hasTexCoords !== hasTexCoords ||\r\n primitiveInfo.hasTexCoord1 !== hasTexCoord1 ||\r\n primitiveInfo.hasOutline !== hasOutline\r\n ) {\r\n // This primitive uses the same material as another one that either:\r\n // * Isn't skinned\r\n // * Uses a different type to store joints and weights\r\n // * Doesn't have vertex colors, morph targets, normals, tangents, or texCoords\r\n // * Doesn't have a CESIUM_primitive_outline extension.\r\n var clonedMaterial = clone(material, true);\r\n // Split this off as a separate material\r\n materialIndex = addToArray(materials, clonedMaterial);\r\n primitive.material = materialIndex;\r\n primitiveInfoByMaterial[materialIndex] = {\r\n skinning: {\r\n skinned: isSkinned,\r\n componentType: componentType,\r\n },\r\n hasVertexColors: hasVertexColors,\r\n hasMorphTargets: hasMorphTargets,\r\n hasNormals: hasNormals,\r\n hasTangents: hasTangents,\r\n hasTexCoords: hasTexCoords,\r\n hasTexCoord1: hasTexCoord1,\r\n hasOutline: hasOutline,\r\n };\r\n }\r\n });\r\n });\r\n\r\n return primitiveInfoByMaterial;\r\n};\r\n\r\nModelUtility.getShaderVariable = function (type) {\r\n if (type === \"SCALAR\") {\r\n return \"float\";\r\n }\r\n return type.toLowerCase();\r\n};\r\n\r\nModelUtility.ModelState = {\r\n NEEDS_LOAD: 0,\r\n LOADING: 1,\r\n LOADED: 2, // Renderable, but textures can still be pending when incrementallyLoadTextures is true.\r\n FAILED: 3,\r\n};\r\n\r\nModelUtility.getFailedLoadFunction = function (model, type, path) {\r\n return function (error) {\r\n model._state = ModelUtility.ModelState.FAILED;\r\n var message = \"Failed to load \" + type + \": \" + path;\r\n if (defined(error)) {\r\n message += \"\\n\" + error.message;\r\n }\r\n model._readyPromise.reject(new RuntimeError(message));\r\n };\r\n};\r\n\r\nModelUtility.parseBuffers = function (model, bufferLoad) {\r\n var loadResources = model._loadResources;\r\n ForEach.buffer(model.gltf, function (buffer, bufferViewId) {\r\n if (defined(buffer.extras._pipeline.source)) {\r\n loadResources.buffers[bufferViewId] = buffer.extras._pipeline.source;\r\n } else if (defined(bufferLoad)) {\r\n var bufferResource = model._resource.getDerivedResource({\r\n url: buffer.uri,\r\n });\r\n ++loadResources.pendingBufferLoads;\r\n bufferResource\r\n .fetchArrayBuffer()\r\n .then(bufferLoad(model, bufferViewId))\r\n .otherwise(\r\n ModelUtility.getFailedLoadFunction(\r\n model,\r\n \"buffer\",\r\n bufferResource.url\r\n )\r\n );\r\n }\r\n });\r\n};\r\n\r\nvar aMinScratch = new Cartesian3();\r\nvar aMaxScratch = new Cartesian3();\r\n\r\nModelUtility.computeBoundingSphere = function (model) {\r\n var gltf = model.gltf;\r\n var gltfNodes = gltf.nodes;\r\n var gltfMeshes = gltf.meshes;\r\n var rootNodes = gltf.scenes[gltf.scene].nodes;\r\n var rootNodesLength = rootNodes.length;\r\n\r\n var nodeStack = [];\r\n\r\n var min = new Cartesian3(\r\n Number.MAX_VALUE,\r\n Number.MAX_VALUE,\r\n Number.MAX_VALUE\r\n );\r\n var max = new Cartesian3(\r\n -Number.MAX_VALUE,\r\n -Number.MAX_VALUE,\r\n -Number.MAX_VALUE\r\n );\r\n\r\n for (var i = 0; i < rootNodesLength; ++i) {\r\n var n = gltfNodes[rootNodes[i]];\r\n n._transformToRoot = ModelUtility.getTransform(n);\r\n nodeStack.push(n);\r\n\r\n while (nodeStack.length > 0) {\r\n n = nodeStack.pop();\r\n var transformToRoot = n._transformToRoot;\r\n\r\n var meshId = n.mesh;\r\n if (defined(meshId)) {\r\n var mesh = gltfMeshes[meshId];\r\n var primitives = mesh.primitives;\r\n var primitivesLength = primitives.length;\r\n for (var m = 0; m < primitivesLength; ++m) {\r\n var positionAccessor = primitives[m].attributes.POSITION;\r\n if (defined(positionAccessor)) {\r\n var minMax = ModelUtility.getAccessorMinMax(gltf, positionAccessor);\r\n if (defined(minMax.min) && defined(minMax.max)) {\r\n var aMin = Cartesian3.fromArray(minMax.min, 0, aMinScratch);\r\n var aMax = Cartesian3.fromArray(minMax.max, 0, aMaxScratch);\r\n\r\n Matrix4.multiplyByPoint(transformToRoot, aMin, aMin);\r\n Matrix4.multiplyByPoint(transformToRoot, aMax, aMax);\r\n Cartesian3.minimumByComponent(min, aMin, min);\r\n Cartesian3.maximumByComponent(max, aMax, max);\r\n }\r\n }\r\n }\r\n }\r\n\r\n var children = n.children;\r\n if (defined(children)) {\r\n var childrenLength = children.length;\r\n for (var k = 0; k < childrenLength; ++k) {\r\n var child = gltfNodes[children[k]];\r\n child._transformToRoot = ModelUtility.getTransform(child);\r\n Matrix4.multiplyTransformation(\r\n transformToRoot,\r\n child._transformToRoot,\r\n child._transformToRoot\r\n );\r\n nodeStack.push(child);\r\n }\r\n }\r\n delete n._transformToRoot;\r\n }\r\n }\r\n\r\n var boundingSphere = BoundingSphere.fromCornerPoints(min, max);\r\n if (model._forwardAxis === Axis.Z) {\r\n // glTF 2.0 has a Z-forward convention that must be adapted here to X-forward.\r\n BoundingSphere.transformWithoutScale(\r\n boundingSphere,\r\n Axis.Z_UP_TO_X_UP,\r\n boundingSphere\r\n );\r\n }\r\n if (model._upAxis === Axis.Y) {\r\n BoundingSphere.transformWithoutScale(\r\n boundingSphere,\r\n Axis.Y_UP_TO_Z_UP,\r\n boundingSphere\r\n );\r\n } else if (model._upAxis === Axis.X) {\r\n BoundingSphere.transformWithoutScale(\r\n boundingSphere,\r\n Axis.X_UP_TO_Z_UP,\r\n boundingSphere\r\n );\r\n }\r\n return boundingSphere;\r\n};\r\n\r\nfunction techniqueAttributeForSemantic(technique, semantic) {\r\n return ForEach.techniqueAttribute(technique, function (\r\n attribute,\r\n attributeName\r\n ) {\r\n if (attribute.semantic === semantic) {\r\n return attributeName;\r\n }\r\n });\r\n}\r\n\r\nfunction ensureSemanticExistenceForPrimitive(gltf, primitive) {\r\n var accessors = gltf.accessors;\r\n var materials = gltf.materials;\r\n var techniquesWebgl = gltf.extensions.KHR_techniques_webgl;\r\n\r\n var techniques = techniquesWebgl.techniques;\r\n var programs = techniquesWebgl.programs;\r\n var shaders = techniquesWebgl.shaders;\r\n var targets = primitive.targets;\r\n\r\n var attributes = primitive.attributes;\r\n for (var target in targets) {\r\n if (targets.hasOwnProperty(target)) {\r\n var targetAttributes = targets[target];\r\n for (var attribute in targetAttributes) {\r\n if (attribute !== \"extras\") {\r\n attributes[attribute + \"_\" + target] = targetAttributes[attribute];\r\n }\r\n }\r\n }\r\n }\r\n\r\n var material = materials[primitive.material];\r\n var technique =\r\n techniques[material.extensions.KHR_techniques_webgl.technique];\r\n var program = programs[technique.program];\r\n var vertexShader = shaders[program.vertexShader];\r\n\r\n for (var semantic in attributes) {\r\n if (attributes.hasOwnProperty(semantic)) {\r\n if (!defined(techniqueAttributeForSemantic(technique, semantic))) {\r\n var accessorId = attributes[semantic];\r\n var accessor = accessors[accessorId];\r\n var lowerCase = semantic.toLowerCase();\r\n if (lowerCase.charAt(0) === \"_\") {\r\n lowerCase = lowerCase.slice(1);\r\n }\r\n var attributeName = \"a_\" + lowerCase;\r\n technique.attributes[attributeName] = {\r\n semantic: semantic,\r\n type: accessor.componentType,\r\n };\r\n var pipelineExtras = vertexShader.extras._pipeline;\r\n var shaderText = pipelineExtras.source;\r\n shaderText =\r\n \"attribute \" +\r\n ModelUtility.getShaderVariable(accessor.type) +\r\n \" \" +\r\n attributeName +\r\n \";\\n\" +\r\n shaderText;\r\n pipelineExtras.source = shaderText;\r\n }\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Ensures all attributes present on the primitive are present in the technique and\r\n * vertex shader.\r\n *\r\n * @param {Object} gltf A javascript object containing a glTF asset.\r\n * @returns {Object} The glTF asset, including any additional attributes.\r\n */\r\nModelUtility.ensureSemanticExistence = function (gltf) {\r\n ForEach.mesh(gltf, function (mesh) {\r\n ForEach.meshPrimitive(mesh, function (primitive) {\r\n ensureSemanticExistenceForPrimitive(gltf, primitive);\r\n });\r\n });\r\n\r\n return gltf;\r\n};\r\n\r\n/**\r\n * Creates attribute location for all attributes required by a technique.\r\n *\r\n * @param {Object} technique A glTF KHR_techniques_webgl technique object.\r\n * @param {Object} precreatedAttributes A dictionary object of pre-created attributes for which to also create locations.\r\n * @returns {Object} A dictionary object containing attribute names and their locations.\r\n */\r\nModelUtility.createAttributeLocations = function (\r\n technique,\r\n precreatedAttributes\r\n) {\r\n var attributeLocations = {};\r\n var hasIndex0 = false;\r\n var i = 1;\r\n\r\n ForEach.techniqueAttribute(technique, function (attribute, attributeName) {\r\n // Set the position attribute to the 0th index. In some WebGL implementations the shader\r\n // will not work correctly if the 0th attribute is not active. For example, some glTF models\r\n // list the normal attribute first but derived shaders like the cast-shadows shader do not use\r\n // the normal attribute.\r\n if (/pos/i.test(attributeName) && !hasIndex0) {\r\n attributeLocations[attributeName] = 0;\r\n hasIndex0 = true;\r\n } else {\r\n attributeLocations[attributeName] = i++;\r\n }\r\n });\r\n\r\n if (defined(precreatedAttributes)) {\r\n for (var attributeName in precreatedAttributes) {\r\n if (precreatedAttributes.hasOwnProperty(attributeName)) {\r\n attributeLocations[attributeName] = i++;\r\n }\r\n }\r\n }\r\n\r\n return attributeLocations;\r\n};\r\n\r\nModelUtility.getAccessorMinMax = function (gltf, accessorId) {\r\n var accessor = gltf.accessors[accessorId];\r\n var extensions = accessor.extensions;\r\n var accessorMin = accessor.min;\r\n var accessorMax = accessor.max;\r\n // If this accessor is quantized, we should use the decoded min and max\r\n if (defined(extensions)) {\r\n var quantizedAttributes = extensions.WEB3D_quantized_attributes;\r\n if (defined(quantizedAttributes)) {\r\n accessorMin = quantizedAttributes.decodedMin;\r\n accessorMax = quantizedAttributes.decodedMax;\r\n }\r\n }\r\n return {\r\n min: accessorMin,\r\n max: accessorMax,\r\n };\r\n};\r\n\r\nfunction getTechniqueAttributeOrUniformFunction(\r\n gltf,\r\n technique,\r\n semantic,\r\n ignoreNodes\r\n) {\r\n if (hasExtension(gltf, \"KHR_techniques_webgl\")) {\r\n return function (attributeOrUniform, attributeOrUniformName) {\r\n if (\r\n attributeOrUniform.semantic === semantic &&\r\n (!ignoreNodes || !defined(attributeOrUniform.node))\r\n ) {\r\n return attributeOrUniformName;\r\n }\r\n };\r\n }\r\n\r\n return function (parameterName, attributeOrUniformName) {\r\n var attributeOrUniform = technique.parameters[parameterName];\r\n if (\r\n attributeOrUniform.semantic === semantic &&\r\n (!ignoreNodes || !defined(attributeOrUniform.node))\r\n ) {\r\n return attributeOrUniformName;\r\n }\r\n };\r\n}\r\n\r\nModelUtility.getAttributeOrUniformBySemantic = function (\r\n gltf,\r\n semantic,\r\n programId,\r\n ignoreNodes\r\n) {\r\n return ForEach.technique(gltf, function (technique) {\r\n if (defined(programId) && technique.program !== programId) {\r\n return;\r\n }\r\n\r\n var value = ForEach.techniqueAttribute(\r\n technique,\r\n getTechniqueAttributeOrUniformFunction(\r\n gltf,\r\n technique,\r\n semantic,\r\n ignoreNodes\r\n )\r\n );\r\n\r\n if (defined(value)) {\r\n return value;\r\n }\r\n\r\n return ForEach.techniqueUniform(\r\n technique,\r\n getTechniqueAttributeOrUniformFunction(\r\n gltf,\r\n technique,\r\n semantic,\r\n ignoreNodes\r\n )\r\n );\r\n });\r\n};\r\n\r\nModelUtility.getDiffuseAttributeOrUniform = function (gltf, programId) {\r\n var diffuseUniformName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"COLOR_0\",\r\n programId\r\n );\r\n if (!defined(diffuseUniformName)) {\r\n diffuseUniformName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"_3DTILESDIFFUSE\",\r\n programId\r\n );\r\n }\r\n return diffuseUniformName;\r\n};\r\n\r\nvar nodeTranslationScratch = new Cartesian3();\r\nvar nodeQuaternionScratch = new Quaternion();\r\nvar nodeScaleScratch = new Cartesian3();\r\n\r\nModelUtility.getTransform = function (node, result) {\r\n if (defined(node.matrix)) {\r\n return Matrix4.fromColumnMajorArray(node.matrix, result);\r\n }\r\n\r\n return Matrix4.fromTranslationQuaternionRotationScale(\r\n Cartesian3.fromArray(node.translation, 0, nodeTranslationScratch),\r\n Quaternion.unpack(node.rotation, 0, nodeQuaternionScratch),\r\n Cartesian3.fromArray(node.scale, 0, nodeScaleScratch),\r\n result\r\n );\r\n};\r\n\r\nModelUtility.getUsedExtensions = function (gltf) {\r\n var extensionsUsed = gltf.extensionsUsed;\r\n var cachedExtensionsUsed = {};\r\n\r\n if (defined(extensionsUsed)) {\r\n var extensionsUsedLength = extensionsUsed.length;\r\n for (var i = 0; i < extensionsUsedLength; i++) {\r\n var extension = extensionsUsed[i];\r\n cachedExtensionsUsed[extension] = true;\r\n }\r\n }\r\n return cachedExtensionsUsed;\r\n};\r\n\r\nModelUtility.getRequiredExtensions = function (gltf) {\r\n var extensionsRequired = gltf.extensionsRequired;\r\n var cachedExtensionsRequired = {};\r\n\r\n if (defined(extensionsRequired)) {\r\n var extensionsRequiredLength = extensionsRequired.length;\r\n for (var i = 0; i < extensionsRequiredLength; i++) {\r\n var extension = extensionsRequired[i];\r\n cachedExtensionsRequired[extension] = true;\r\n }\r\n }\r\n\r\n return cachedExtensionsRequired;\r\n};\r\n\r\nModelUtility.supportedExtensions = {\r\n AGI_articulations: true,\r\n CESIUM_RTC: true,\r\n EXT_texture_webp: true,\r\n KHR_blend: true,\r\n KHR_binary_glTF: true,\r\n KHR_draco_mesh_compression: true,\r\n KHR_materials_common: true,\r\n KHR_techniques_webgl: true,\r\n KHR_materials_unlit: true,\r\n KHR_materials_pbrSpecularGlossiness: true,\r\n KHR_texture_transform: true,\r\n WEB3D_quantized_attributes: true,\r\n};\r\n\r\nModelUtility.checkSupportedExtensions = function (\r\n extensionsRequired,\r\n browserSupportsWebp\r\n) {\r\n for (var extension in extensionsRequired) {\r\n if (extensionsRequired.hasOwnProperty(extension)) {\r\n if (!ModelUtility.supportedExtensions[extension]) {\r\n throw new RuntimeError(\"Unsupported glTF Extension: \" + extension);\r\n }\r\n\r\n if (extension === \"EXT_texture_webp\" && browserSupportsWebp === false) {\r\n throw new RuntimeError(\r\n \"Loaded model requires WebP but browser does not support it.\"\r\n );\r\n }\r\n }\r\n }\r\n};\r\n\r\nModelUtility.checkSupportedGlExtensions = function (extensionsUsed, context) {\r\n if (defined(extensionsUsed)) {\r\n var glExtensionsUsedLength = extensionsUsed.length;\r\n for (var i = 0; i < glExtensionsUsedLength; i++) {\r\n var extension = extensionsUsed[i];\r\n if (extension !== \"OES_element_index_uint\") {\r\n throw new RuntimeError(\"Unsupported WebGL Extension: \" + extension);\r\n } else if (!context.elementIndexUint) {\r\n throw new RuntimeError(\r\n \"OES_element_index_uint WebGL extension is not enabled.\"\r\n );\r\n }\r\n }\r\n }\r\n};\r\n\r\nfunction replaceAllButFirstInString(string, find, replace) {\r\n // Limit search to strings that are not a subset of other tokens.\r\n find += \"(?!\\\\w)\";\r\n find = new RegExp(find, \"g\");\r\n\r\n var index = string.search(find);\r\n return string.replace(find, function (match, offset) {\r\n return index === offset ? match : replace;\r\n });\r\n}\r\n\r\nfunction getQuantizedAttributes(gltf, accessorId) {\r\n var accessor = gltf.accessors[accessorId];\r\n var extensions = accessor.extensions;\r\n if (defined(extensions)) {\r\n return extensions.WEB3D_quantized_attributes;\r\n }\r\n return undefined;\r\n}\r\n\r\nfunction getAttributeVariableName(gltf, primitive, attributeSemantic) {\r\n var materialId = primitive.material;\r\n var material = gltf.materials[materialId];\r\n\r\n if (\r\n !hasExtension(gltf, \"KHR_techniques_webgl\") ||\r\n !defined(material.extensions) ||\r\n !defined(material.extensions.KHR_techniques_webgl)\r\n ) {\r\n return;\r\n }\r\n\r\n var techniqueId = material.extensions.KHR_techniques_webgl.technique;\r\n var techniquesWebgl = gltf.extensions.KHR_techniques_webgl;\r\n var technique = techniquesWebgl.techniques[techniqueId];\r\n return ForEach.techniqueAttribute(technique, function (\r\n attribute,\r\n attributeName\r\n ) {\r\n var semantic = attribute.semantic;\r\n if (semantic === attributeSemantic) {\r\n return attributeName;\r\n }\r\n });\r\n}\r\n\r\nModelUtility.modifyShaderForDracoQuantizedAttributes = function (\r\n gltf,\r\n primitive,\r\n shader,\r\n decodedAttributes\r\n) {\r\n var quantizedUniforms = {};\r\n for (var attributeSemantic in decodedAttributes) {\r\n if (decodedAttributes.hasOwnProperty(attributeSemantic)) {\r\n var attribute = decodedAttributes[attributeSemantic];\r\n var quantization = attribute.quantization;\r\n if (!defined(quantization)) {\r\n continue;\r\n }\r\n\r\n var attributeVarName = getAttributeVariableName(\r\n gltf,\r\n primitive,\r\n attributeSemantic\r\n );\r\n\r\n if (attributeSemantic.charAt(0) === \"_\") {\r\n attributeSemantic = attributeSemantic.substring(1);\r\n }\r\n var decodeUniformVarName =\r\n \"gltf_u_dec_\" + attributeSemantic.toLowerCase();\r\n\r\n if (!defined(quantizedUniforms[decodeUniformVarName])) {\r\n var newMain = \"gltf_decoded_\" + attributeSemantic;\r\n var decodedAttributeVarName = attributeVarName.replace(\r\n \"a_\",\r\n \"gltf_a_dec_\"\r\n );\r\n var size = attribute.componentsPerAttribute;\r\n\r\n // replace usages of the original attribute with the decoded version, but not the declaration\r\n shader = replaceAllButFirstInString(\r\n shader,\r\n attributeVarName,\r\n decodedAttributeVarName\r\n );\r\n\r\n // declare decoded attribute\r\n var variableType;\r\n if (quantization.octEncoded) {\r\n variableType = \"vec3\";\r\n } else if (size > 1) {\r\n variableType = \"vec\" + size;\r\n } else {\r\n variableType = \"float\";\r\n }\r\n shader = variableType + \" \" + decodedAttributeVarName + \";\\n\" + shader;\r\n\r\n // The gltf 2.0 COLOR_0 vertex attribute can be VEC4 or VEC3\r\n var vec3Color = size === 3 && attributeSemantic === \"COLOR_0\";\r\n if (vec3Color) {\r\n shader = replaceAllButFirstInString(\r\n shader,\r\n decodedAttributeVarName,\r\n \"vec4(\" + decodedAttributeVarName + \", 1.0)\"\r\n );\r\n }\r\n\r\n // splice decode function into the shader\r\n var decode = \"\";\r\n if (quantization.octEncoded) {\r\n var decodeUniformVarNameRangeConstant =\r\n decodeUniformVarName + \"_rangeConstant\";\r\n shader =\r\n \"uniform float \" +\r\n decodeUniformVarNameRangeConstant +\r\n \";\\n\" +\r\n shader;\r\n decode =\r\n \"\\n\" +\r\n \"void main() {\\n\" +\r\n // Draco oct-encoding decodes to zxy order\r\n \" \" +\r\n decodedAttributeVarName +\r\n \" = czm_octDecode(\" +\r\n attributeVarName +\r\n \".xy, \" +\r\n decodeUniformVarNameRangeConstant +\r\n \").zxy;\\n\" +\r\n \" \" +\r\n newMain +\r\n \"();\\n\" +\r\n \"}\\n\";\r\n } else {\r\n var decodeUniformVarNameNormConstant =\r\n decodeUniformVarName + \"_normConstant\";\r\n var decodeUniformVarNameMin = decodeUniformVarName + \"_min\";\r\n shader =\r\n \"uniform float \" +\r\n decodeUniformVarNameNormConstant +\r\n \";\\n\" +\r\n \"uniform \" +\r\n variableType +\r\n \" \" +\r\n decodeUniformVarNameMin +\r\n \";\\n\" +\r\n shader;\r\n var attributeVarAccess = vec3Color ? \".xyz\" : \"\";\r\n decode =\r\n \"\\n\" +\r\n \"void main() {\\n\" +\r\n \" \" +\r\n decodedAttributeVarName +\r\n \" = \" +\r\n decodeUniformVarNameMin +\r\n \" + \" +\r\n attributeVarName +\r\n attributeVarAccess +\r\n \" * \" +\r\n decodeUniformVarNameNormConstant +\r\n \";\\n\" +\r\n \" \" +\r\n newMain +\r\n \"();\\n\" +\r\n \"}\\n\";\r\n }\r\n\r\n shader = ShaderSource.replaceMain(shader, newMain);\r\n shader += decode;\r\n }\r\n }\r\n }\r\n return {\r\n shader: shader,\r\n };\r\n};\r\n\r\nModelUtility.modifyShaderForQuantizedAttributes = function (\r\n gltf,\r\n primitive,\r\n shader\r\n) {\r\n var quantizedUniforms = {};\r\n var attributes = primitive.attributes;\r\n for (var attributeSemantic in attributes) {\r\n if (attributes.hasOwnProperty(attributeSemantic)) {\r\n var attributeVarName = getAttributeVariableName(\r\n gltf,\r\n primitive,\r\n attributeSemantic\r\n );\r\n var accessorId = primitive.attributes[attributeSemantic];\r\n\r\n if (attributeSemantic.charAt(0) === \"_\") {\r\n attributeSemantic = attributeSemantic.substring(1);\r\n }\r\n var decodeUniformVarName =\r\n \"gltf_u_dec_\" + attributeSemantic.toLowerCase();\r\n\r\n var decodeUniformVarNameScale = decodeUniformVarName + \"_scale\";\r\n var decodeUniformVarNameTranslate = decodeUniformVarName + \"_translate\";\r\n if (\r\n !defined(quantizedUniforms[decodeUniformVarName]) &&\r\n !defined(quantizedUniforms[decodeUniformVarNameScale])\r\n ) {\r\n var quantizedAttributes = getQuantizedAttributes(gltf, accessorId);\r\n if (defined(quantizedAttributes)) {\r\n var decodeMatrix = quantizedAttributes.decodeMatrix;\r\n var newMain = \"gltf_decoded_\" + attributeSemantic;\r\n var decodedAttributeVarName = attributeVarName.replace(\r\n \"a_\",\r\n \"gltf_a_dec_\"\r\n );\r\n var size = Math.floor(Math.sqrt(decodeMatrix.length));\r\n\r\n // replace usages of the original attribute with the decoded version, but not the declaration\r\n shader = replaceAllButFirstInString(\r\n shader,\r\n attributeVarName,\r\n decodedAttributeVarName\r\n );\r\n // declare decoded attribute\r\n var variableType;\r\n if (size > 2) {\r\n variableType = \"vec\" + (size - 1);\r\n } else {\r\n variableType = \"float\";\r\n }\r\n shader =\r\n variableType + \" \" + decodedAttributeVarName + \";\\n\" + shader;\r\n // splice decode function into the shader - attributes are pre-multiplied with the decode matrix\r\n // uniform in the shader (32-bit floating point)\r\n var decode = \"\";\r\n if (size === 5) {\r\n // separate scale and translate since glsl doesn't have mat5\r\n shader =\r\n \"uniform mat4 \" + decodeUniformVarNameScale + \";\\n\" + shader;\r\n shader =\r\n \"uniform vec4 \" + decodeUniformVarNameTranslate + \";\\n\" + shader;\r\n decode =\r\n \"\\n\" +\r\n \"void main() {\\n\" +\r\n \" \" +\r\n decodedAttributeVarName +\r\n \" = \" +\r\n decodeUniformVarNameScale +\r\n \" * \" +\r\n attributeVarName +\r\n \" + \" +\r\n decodeUniformVarNameTranslate +\r\n \";\\n\" +\r\n \" \" +\r\n newMain +\r\n \"();\\n\" +\r\n \"}\\n\";\r\n\r\n quantizedUniforms[decodeUniformVarNameScale] = { mat: 4 };\r\n quantizedUniforms[decodeUniformVarNameTranslate] = { vec: 4 };\r\n } else {\r\n shader =\r\n \"uniform mat\" +\r\n size +\r\n \" \" +\r\n decodeUniformVarName +\r\n \";\\n\" +\r\n shader;\r\n decode =\r\n \"\\n\" +\r\n \"void main() {\\n\" +\r\n \" \" +\r\n decodedAttributeVarName +\r\n \" = \" +\r\n variableType +\r\n \"(\" +\r\n decodeUniformVarName +\r\n \" * vec\" +\r\n size +\r\n \"(\" +\r\n attributeVarName +\r\n \",1.0));\\n\" +\r\n \" \" +\r\n newMain +\r\n \"();\\n\" +\r\n \"}\\n\";\r\n\r\n quantizedUniforms[decodeUniformVarName] = { mat: size };\r\n }\r\n shader = ShaderSource.replaceMain(shader, newMain);\r\n shader += decode;\r\n }\r\n }\r\n }\r\n }\r\n return {\r\n shader: shader,\r\n uniforms: quantizedUniforms,\r\n };\r\n};\r\n\r\nfunction getScalarUniformFunction(value) {\r\n var that = {\r\n value: value,\r\n clone: function (source, result) {\r\n return source;\r\n },\r\n func: function () {\r\n return that.value;\r\n },\r\n };\r\n return that;\r\n}\r\n\r\nfunction getVec2UniformFunction(value) {\r\n var that = {\r\n value: Cartesian2.fromArray(value),\r\n clone: Cartesian2.clone,\r\n func: function () {\r\n return that.value;\r\n },\r\n };\r\n return that;\r\n}\r\n\r\nfunction getVec3UniformFunction(value) {\r\n var that = {\r\n value: Cartesian3.fromArray(value),\r\n clone: Cartesian3.clone,\r\n func: function () {\r\n return that.value;\r\n },\r\n };\r\n return that;\r\n}\r\n\r\nfunction getVec4UniformFunction(value) {\r\n var that = {\r\n value: Cartesian4.fromArray(value),\r\n clone: Cartesian4.clone,\r\n func: function () {\r\n return that.value;\r\n },\r\n };\r\n return that;\r\n}\r\n\r\nfunction getMat2UniformFunction(value) {\r\n var that = {\r\n value: Matrix2.fromColumnMajorArray(value),\r\n clone: Matrix2.clone,\r\n func: function () {\r\n return that.value;\r\n },\r\n };\r\n return that;\r\n}\r\n\r\nfunction getMat3UniformFunction(value) {\r\n var that = {\r\n value: Matrix3.fromColumnMajorArray(value),\r\n clone: Matrix3.clone,\r\n func: function () {\r\n return that.value;\r\n },\r\n };\r\n return that;\r\n}\r\n\r\nfunction getMat4UniformFunction(value) {\r\n var that = {\r\n value: Matrix4.fromColumnMajorArray(value),\r\n clone: Matrix4.clone,\r\n func: function () {\r\n return that.value;\r\n },\r\n };\r\n return that;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction DelayLoadedTextureUniform(value, textures, defaultTexture) {\r\n this._value = undefined;\r\n this._textureId = value.index;\r\n this._textures = textures;\r\n this._defaultTexture = defaultTexture;\r\n}\r\n\r\nObject.defineProperties(DelayLoadedTextureUniform.prototype, {\r\n value: {\r\n get: function () {\r\n // Use the default texture (1x1 white) until the model's texture is loaded\r\n if (!defined(this._value)) {\r\n var texture = this._textures[this._textureId];\r\n if (defined(texture)) {\r\n this._value = texture;\r\n } else {\r\n return this._defaultTexture;\r\n }\r\n }\r\n\r\n return this._value;\r\n },\r\n set: function (value) {\r\n this._value = value;\r\n },\r\n },\r\n});\r\n\r\nDelayLoadedTextureUniform.prototype.clone = function (source) {\r\n return source;\r\n};\r\n\r\nDelayLoadedTextureUniform.prototype.func = undefined;\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction getTextureUniformFunction(value, textures, defaultTexture) {\r\n var uniform = new DelayLoadedTextureUniform(value, textures, defaultTexture);\r\n // Define function here to access closure since 'this' can't be\r\n // used when the Renderer sets uniforms.\r\n uniform.func = function () {\r\n return uniform.value;\r\n };\r\n return uniform;\r\n}\r\n\r\nvar gltfUniformFunctions = {};\r\ngltfUniformFunctions[WebGLConstants.FLOAT] = getScalarUniformFunction;\r\ngltfUniformFunctions[WebGLConstants.FLOAT_VEC2] = getVec2UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.FLOAT_VEC3] = getVec3UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.FLOAT_VEC4] = getVec4UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.INT] = getScalarUniformFunction;\r\ngltfUniformFunctions[WebGLConstants.INT_VEC2] = getVec2UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.INT_VEC3] = getVec3UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.INT_VEC4] = getVec4UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.BOOL] = getScalarUniformFunction;\r\ngltfUniformFunctions[WebGLConstants.BOOL_VEC2] = getVec2UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.BOOL_VEC3] = getVec3UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.BOOL_VEC4] = getVec4UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.FLOAT_MAT2] = getMat2UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.FLOAT_MAT3] = getMat3UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.FLOAT_MAT4] = getMat4UniformFunction;\r\ngltfUniformFunctions[WebGLConstants.SAMPLER_2D] = getTextureUniformFunction;\r\n// GLTF_SPEC: Support SAMPLER_CUBE. https://github.com/KhronosGroup/glTF/issues/40\r\n\r\nModelUtility.createUniformFunction = function (\r\n type,\r\n value,\r\n textures,\r\n defaultTexture\r\n) {\r\n return gltfUniformFunctions[type](value, textures, defaultTexture);\r\n};\r\n\r\nfunction scaleFromMatrix5Array(matrix) {\r\n return [\r\n matrix[0],\r\n matrix[1],\r\n matrix[2],\r\n matrix[3],\r\n matrix[5],\r\n matrix[6],\r\n matrix[7],\r\n matrix[8],\r\n matrix[10],\r\n matrix[11],\r\n matrix[12],\r\n matrix[13],\r\n matrix[15],\r\n matrix[16],\r\n matrix[17],\r\n matrix[18],\r\n ];\r\n}\r\n\r\nfunction translateFromMatrix5Array(matrix) {\r\n return [matrix[20], matrix[21], matrix[22], matrix[23]];\r\n}\r\n\r\nModelUtility.createUniformsForDracoQuantizedAttributes = function (\r\n decodedAttributes\r\n) {\r\n var uniformMap = {};\r\n for (var attribute in decodedAttributes) {\r\n if (decodedAttributes.hasOwnProperty(attribute)) {\r\n var decodedData = decodedAttributes[attribute];\r\n var quantization = decodedData.quantization;\r\n\r\n if (!defined(quantization)) {\r\n continue;\r\n }\r\n\r\n if (attribute.charAt(0) === \"_\") {\r\n attribute = attribute.substring(1);\r\n }\r\n\r\n var uniformVarName = \"gltf_u_dec_\" + attribute.toLowerCase();\r\n\r\n if (quantization.octEncoded) {\r\n var uniformVarNameRangeConstant = uniformVarName + \"_rangeConstant\";\r\n var rangeConstant = (1 << quantization.quantizationBits) - 1.0;\r\n uniformMap[uniformVarNameRangeConstant] = getScalarUniformFunction(\r\n rangeConstant\r\n ).func;\r\n continue;\r\n }\r\n\r\n var uniformVarNameNormConstant = uniformVarName + \"_normConstant\";\r\n var normConstant =\r\n quantization.range / (1 << quantization.quantizationBits);\r\n uniformMap[uniformVarNameNormConstant] = getScalarUniformFunction(\r\n normConstant\r\n ).func;\r\n\r\n var uniformVarNameMin = uniformVarName + \"_min\";\r\n switch (decodedData.componentsPerAttribute) {\r\n case 1:\r\n uniformMap[uniformVarNameMin] = getScalarUniformFunction(\r\n quantization.minValues\r\n ).func;\r\n break;\r\n case 2:\r\n uniformMap[uniformVarNameMin] = getVec2UniformFunction(\r\n quantization.minValues\r\n ).func;\r\n break;\r\n case 3:\r\n uniformMap[uniformVarNameMin] = getVec3UniformFunction(\r\n quantization.minValues\r\n ).func;\r\n break;\r\n case 4:\r\n uniformMap[uniformVarNameMin] = getVec4UniformFunction(\r\n quantization.minValues\r\n ).func;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return uniformMap;\r\n};\r\n\r\nModelUtility.createUniformsForQuantizedAttributes = function (\r\n gltf,\r\n primitive,\r\n quantizedUniforms\r\n) {\r\n var accessors = gltf.accessors;\r\n var setUniforms = {};\r\n var uniformMap = {};\r\n\r\n var attributes = primitive.attributes;\r\n for (var attribute in attributes) {\r\n if (attributes.hasOwnProperty(attribute)) {\r\n var accessorId = attributes[attribute];\r\n var a = accessors[accessorId];\r\n var extensions = a.extensions;\r\n\r\n if (attribute.charAt(0) === \"_\") {\r\n attribute = attribute.substring(1);\r\n }\r\n\r\n if (defined(extensions)) {\r\n var quantizedAttributes = extensions.WEB3D_quantized_attributes;\r\n if (defined(quantizedAttributes)) {\r\n var decodeMatrix = quantizedAttributes.decodeMatrix;\r\n var uniformVariable = \"gltf_u_dec_\" + attribute.toLowerCase();\r\n\r\n switch (a.type) {\r\n case AttributeType.SCALAR:\r\n uniformMap[uniformVariable] = getMat2UniformFunction(\r\n decodeMatrix\r\n ).func;\r\n setUniforms[uniformVariable] = true;\r\n break;\r\n case AttributeType.VEC2:\r\n uniformMap[uniformVariable] = getMat3UniformFunction(\r\n decodeMatrix\r\n ).func;\r\n setUniforms[uniformVariable] = true;\r\n break;\r\n case AttributeType.VEC3:\r\n uniformMap[uniformVariable] = getMat4UniformFunction(\r\n decodeMatrix\r\n ).func;\r\n setUniforms[uniformVariable] = true;\r\n break;\r\n case AttributeType.VEC4:\r\n // VEC4 attributes are split into scale and translate because there is no mat5 in GLSL\r\n var uniformVariableScale = uniformVariable + \"_scale\";\r\n var uniformVariableTranslate = uniformVariable + \"_translate\";\r\n uniformMap[uniformVariableScale] = getMat4UniformFunction(\r\n scaleFromMatrix5Array(decodeMatrix)\r\n ).func;\r\n uniformMap[uniformVariableTranslate] = getVec4UniformFunction(\r\n translateFromMatrix5Array(decodeMatrix)\r\n ).func;\r\n setUniforms[uniformVariableScale] = true;\r\n setUniforms[uniformVariableTranslate] = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If there are any unset quantized uniforms in this program, they should be set to the identity\r\n for (var quantizedUniform in quantizedUniforms) {\r\n if (quantizedUniforms.hasOwnProperty(quantizedUniform)) {\r\n if (!setUniforms[quantizedUniform]) {\r\n var properties = quantizedUniforms[quantizedUniform];\r\n if (defined(properties.mat)) {\r\n if (properties.mat === 2) {\r\n uniformMap[quantizedUniform] = getMat2UniformFunction(\r\n Matrix2.IDENTITY\r\n ).func;\r\n } else if (properties.mat === 3) {\r\n uniformMap[quantizedUniform] = getMat3UniformFunction(\r\n Matrix3.IDENTITY\r\n ).func;\r\n } else if (properties.mat === 4) {\r\n uniformMap[quantizedUniform] = getMat4UniformFunction(\r\n Matrix4.IDENTITY\r\n ).func;\r\n }\r\n }\r\n if (defined(properties.vec)) {\r\n if (properties.vec === 4) {\r\n uniformMap[quantizedUniform] = getVec4UniformFunction([\r\n 0,\r\n 0,\r\n 0,\r\n 0,\r\n ]).func;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return uniformMap;\r\n};\r\n\r\n// This doesn't support LOCAL, which we could add if it is ever used.\r\nvar scratchTranslationRtc = new Cartesian3();\r\nvar gltfSemanticUniforms = {\r\n MODEL: function (uniformState, model) {\r\n return function () {\r\n return uniformState.model;\r\n };\r\n },\r\n VIEW: function (uniformState, model) {\r\n return function () {\r\n return uniformState.view;\r\n };\r\n },\r\n PROJECTION: function (uniformState, model) {\r\n return function () {\r\n return uniformState.projection;\r\n };\r\n },\r\n MODELVIEW: function (uniformState, model) {\r\n return function () {\r\n return uniformState.modelView;\r\n };\r\n },\r\n CESIUM_RTC_MODELVIEW: function (uniformState, model) {\r\n // CESIUM_RTC extension\r\n var mvRtc = new Matrix4();\r\n return function () {\r\n if (defined(model._rtcCenter)) {\r\n Matrix4.getTranslation(uniformState.model, scratchTranslationRtc);\r\n Cartesian3.add(\r\n scratchTranslationRtc,\r\n model._rtcCenter,\r\n scratchTranslationRtc\r\n );\r\n Matrix4.multiplyByPoint(\r\n uniformState.view,\r\n scratchTranslationRtc,\r\n scratchTranslationRtc\r\n );\r\n return Matrix4.setTranslation(\r\n uniformState.modelView,\r\n scratchTranslationRtc,\r\n mvRtc\r\n );\r\n }\r\n return uniformState.modelView;\r\n };\r\n },\r\n MODELVIEWPROJECTION: function (uniformState, model) {\r\n return function () {\r\n return uniformState.modelViewProjection;\r\n };\r\n },\r\n MODELINVERSE: function (uniformState, model) {\r\n return function () {\r\n return uniformState.inverseModel;\r\n };\r\n },\r\n VIEWINVERSE: function (uniformState, model) {\r\n return function () {\r\n return uniformState.inverseView;\r\n };\r\n },\r\n PROJECTIONINVERSE: function (uniformState, model) {\r\n return function () {\r\n return uniformState.inverseProjection;\r\n };\r\n },\r\n MODELVIEWINVERSE: function (uniformState, model) {\r\n return function () {\r\n return uniformState.inverseModelView;\r\n };\r\n },\r\n MODELVIEWPROJECTIONINVERSE: function (uniformState, model) {\r\n return function () {\r\n return uniformState.inverseModelViewProjection;\r\n };\r\n },\r\n MODELINVERSETRANSPOSE: function (uniformState, model) {\r\n return function () {\r\n return uniformState.inverseTransposeModel;\r\n };\r\n },\r\n MODELVIEWINVERSETRANSPOSE: function (uniformState, model) {\r\n return function () {\r\n return uniformState.normal;\r\n };\r\n },\r\n VIEWPORT: function (uniformState, model) {\r\n return function () {\r\n return uniformState.viewportCartesian4;\r\n };\r\n },\r\n // JOINTMATRIX created in createCommand()\r\n};\r\n\r\nModelUtility.getGltfSemanticUniforms = function () {\r\n return gltfSemanticUniforms;\r\n};\r\nexport default ModelUtility;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport webGLConstantToGlslType from \"../Core/webGLConstantToGlslType.js\";\r\nimport addToArray from \"../ThirdParty/GltfPipeline/addToArray.js\";\r\nimport ForEach from \"../ThirdParty/GltfPipeline/ForEach.js\";\r\nimport hasExtension from \"../ThirdParty/GltfPipeline/hasExtension.js\";\r\nimport ModelUtility from \"./ModelUtility.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction processModelMaterialsCommon(gltf, options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n if (!defined(gltf)) {\r\n return;\r\n }\r\n\r\n if (!hasExtension(gltf, \"KHR_materials_common\")) {\r\n return;\r\n }\r\n\r\n if (!hasExtension(gltf, \"KHR_techniques_webgl\")) {\r\n if (!defined(gltf.extensions)) {\r\n gltf.extensions = {};\r\n }\r\n\r\n gltf.extensions.KHR_techniques_webgl = {\r\n programs: [],\r\n shaders: [],\r\n techniques: [],\r\n };\r\n gltf.extensionsUsed.push(\"KHR_techniques_webgl\");\r\n gltf.extensionsRequired.push(\"KHR_techniques_webgl\");\r\n }\r\n\r\n var techniquesWebgl = gltf.extensions.KHR_techniques_webgl;\r\n\r\n lightDefaults(gltf);\r\n\r\n var lightParameters = generateLightParameters(gltf);\r\n\r\n var primitiveByMaterial = ModelUtility.splitIncompatibleMaterials(gltf);\r\n\r\n var techniques = {};\r\n var generatedTechniques = false;\r\n ForEach.material(gltf, function (material, materialIndex) {\r\n if (\r\n defined(material.extensions) &&\r\n defined(material.extensions.KHR_materials_common)\r\n ) {\r\n var khrMaterialsCommon = material.extensions.KHR_materials_common;\r\n var primitiveInfo = primitiveByMaterial[materialIndex];\r\n\r\n var techniqueKey = getTechniqueKey(khrMaterialsCommon, primitiveInfo);\r\n var technique = techniques[techniqueKey];\r\n\r\n if (!defined(technique)) {\r\n technique = generateTechnique(\r\n gltf,\r\n techniquesWebgl,\r\n primitiveInfo,\r\n khrMaterialsCommon,\r\n lightParameters,\r\n options.addBatchIdToGeneratedShaders\r\n );\r\n techniques[techniqueKey] = technique;\r\n generatedTechniques = true;\r\n }\r\n\r\n var materialValues = {};\r\n var values = khrMaterialsCommon.values;\r\n var uniformName;\r\n for (var valueName in values) {\r\n if (\r\n values.hasOwnProperty(valueName) &&\r\n valueName !== \"transparent\" &&\r\n valueName !== \"doubleSided\"\r\n ) {\r\n uniformName = \"u_\" + valueName.toLowerCase();\r\n materialValues[uniformName] = values[valueName];\r\n }\r\n }\r\n\r\n material.extensions.KHR_techniques_webgl = {\r\n technique: technique,\r\n values: materialValues,\r\n };\r\n\r\n material.alphaMode = \"OPAQUE\";\r\n if (khrMaterialsCommon.transparent) {\r\n material.alphaMode = \"BLEND\";\r\n }\r\n\r\n if (khrMaterialsCommon.doubleSided) {\r\n material.doubleSided = true;\r\n }\r\n }\r\n });\r\n\r\n if (!generatedTechniques) {\r\n return gltf;\r\n }\r\n\r\n // If any primitives have semantics that aren't declared in the generated\r\n // shaders, we want to preserve them.\r\n ModelUtility.ensureSemanticExistence(gltf);\r\n\r\n return gltf;\r\n}\r\n\r\nfunction generateLightParameters(gltf) {\r\n var result = {};\r\n\r\n var lights;\r\n if (\r\n defined(gltf.extensions) &&\r\n defined(gltf.extensions.KHR_materials_common)\r\n ) {\r\n lights = gltf.extensions.KHR_materials_common.lights;\r\n }\r\n\r\n if (defined(lights)) {\r\n // Figure out which node references the light\r\n var nodes = gltf.nodes;\r\n for (var nodeName in nodes) {\r\n if (nodes.hasOwnProperty(nodeName)) {\r\n var node = nodes[nodeName];\r\n if (\r\n defined(node.extensions) &&\r\n defined(node.extensions.KHR_materials_common)\r\n ) {\r\n var nodeLightId = node.extensions.KHR_materials_common.light;\r\n if (defined(nodeLightId) && defined(lights[nodeLightId])) {\r\n lights[nodeLightId].node = nodeName;\r\n }\r\n delete node.extensions.KHR_materials_common;\r\n }\r\n }\r\n }\r\n\r\n // Add light parameters to result\r\n var lightCount = 0;\r\n for (var lightName in lights) {\r\n if (lights.hasOwnProperty(lightName)) {\r\n var light = lights[lightName];\r\n var lightType = light.type;\r\n if (lightType !== \"ambient\" && !defined(light.node)) {\r\n delete lights[lightName];\r\n continue;\r\n }\r\n var lightBaseName = \"light\" + lightCount.toString();\r\n light.baseName = lightBaseName;\r\n switch (lightType) {\r\n case \"ambient\":\r\n var ambient = light.ambient;\r\n result[lightBaseName + \"Color\"] = {\r\n type: WebGLConstants.FLOAT_VEC3,\r\n value: ambient.color,\r\n };\r\n break;\r\n case \"directional\":\r\n var directional = light.directional;\r\n result[lightBaseName + \"Color\"] = {\r\n type: WebGLConstants.FLOAT_VEC3,\r\n value: directional.color,\r\n };\r\n if (defined(light.node)) {\r\n result[lightBaseName + \"Transform\"] = {\r\n node: light.node,\r\n semantic: \"MODELVIEW\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n };\r\n }\r\n break;\r\n case \"point\":\r\n var point = light.point;\r\n result[lightBaseName + \"Color\"] = {\r\n type: WebGLConstants.FLOAT_VEC3,\r\n value: point.color,\r\n };\r\n if (defined(light.node)) {\r\n result[lightBaseName + \"Transform\"] = {\r\n node: light.node,\r\n semantic: \"MODELVIEW\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n };\r\n }\r\n result[lightBaseName + \"Attenuation\"] = {\r\n type: WebGLConstants.FLOAT_VEC3,\r\n value: [\r\n point.constantAttenuation,\r\n point.linearAttenuation,\r\n point.quadraticAttenuation,\r\n ],\r\n };\r\n break;\r\n case \"spot\":\r\n var spot = light.spot;\r\n result[lightBaseName + \"Color\"] = {\r\n type: WebGLConstants.FLOAT_VEC3,\r\n value: spot.color,\r\n };\r\n if (defined(light.node)) {\r\n result[lightBaseName + \"Transform\"] = {\r\n node: light.node,\r\n semantic: \"MODELVIEW\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n };\r\n result[lightBaseName + \"InverseTransform\"] = {\r\n node: light.node,\r\n semantic: \"MODELVIEWINVERSE\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n useInFragment: true,\r\n };\r\n }\r\n result[lightBaseName + \"Attenuation\"] = {\r\n type: WebGLConstants.FLOAT_VEC3,\r\n value: [\r\n spot.constantAttenuation,\r\n spot.linearAttenuation,\r\n spot.quadraticAttenuation,\r\n ],\r\n };\r\n\r\n result[lightBaseName + \"FallOff\"] = {\r\n type: WebGLConstants.FLOAT_VEC2,\r\n value: [spot.fallOffAngle, spot.fallOffExponent],\r\n };\r\n break;\r\n }\r\n ++lightCount;\r\n }\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction generateTechnique(\r\n gltf,\r\n techniquesWebgl,\r\n primitiveInfo,\r\n khrMaterialsCommon,\r\n lightParameters,\r\n addBatchIdToGeneratedShaders\r\n) {\r\n if (!defined(khrMaterialsCommon)) {\r\n khrMaterialsCommon = {};\r\n }\r\n\r\n addBatchIdToGeneratedShaders = defaultValue(\r\n addBatchIdToGeneratedShaders,\r\n false\r\n );\r\n\r\n var techniques = techniquesWebgl.techniques;\r\n var shaders = techniquesWebgl.shaders;\r\n var programs = techniquesWebgl.programs;\r\n var lightingModel = khrMaterialsCommon.technique.toUpperCase();\r\n var lights;\r\n if (\r\n defined(gltf.extensions) &&\r\n defined(gltf.extensions.KHR_materials_common)\r\n ) {\r\n lights = gltf.extensions.KHR_materials_common.lights;\r\n }\r\n\r\n var parameterValues = khrMaterialsCommon.values;\r\n var jointCount = defaultValue(khrMaterialsCommon.jointCount, 0);\r\n\r\n var skinningInfo;\r\n var hasSkinning = false;\r\n var hasVertexColors = false;\r\n\r\n if (defined(primitiveInfo)) {\r\n skinningInfo = primitiveInfo.skinning;\r\n hasSkinning = skinningInfo.skinned;\r\n hasVertexColors = primitiveInfo.hasVertexColors;\r\n }\r\n\r\n var vertexShader = \"precision highp float;\\n\";\r\n var fragmentShader = \"precision highp float;\\n\";\r\n\r\n var hasNormals = lightingModel !== \"CONSTANT\";\r\n\r\n // Add techniques\r\n var techniqueUniforms = {\r\n u_modelViewMatrix: {\r\n semantic: hasExtension(gltf, \"CESIUM_RTC\")\r\n ? \"CESIUM_RTC_MODELVIEW\"\r\n : \"MODELVIEW\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n },\r\n u_projectionMatrix: {\r\n semantic: \"PROJECTION\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n },\r\n };\r\n\r\n if (hasNormals) {\r\n techniqueUniforms.u_normalMatrix = {\r\n semantic: \"MODELVIEWINVERSETRANSPOSE\",\r\n type: WebGLConstants.FLOAT_MAT3,\r\n };\r\n }\r\n\r\n if (hasSkinning) {\r\n techniqueUniforms.u_jointMatrix = {\r\n count: jointCount,\r\n semantic: \"JOINTMATRIX\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n };\r\n }\r\n\r\n // Add material values\r\n var uniformName;\r\n var hasTexCoords = false;\r\n for (var name in parameterValues) {\r\n //generate shader parameters for KHR_materials_common attributes\r\n //(including a check, because some boolean flags should not be used as shader parameters)\r\n if (\r\n parameterValues.hasOwnProperty(name) &&\r\n name !== \"transparent\" &&\r\n name !== \"doubleSided\"\r\n ) {\r\n var uniformType = getKHRMaterialsCommonValueType(\r\n name,\r\n parameterValues[name]\r\n );\r\n uniformName = \"u_\" + name.toLowerCase();\r\n if (!hasTexCoords && uniformType === WebGLConstants.SAMPLER_2D) {\r\n hasTexCoords = true;\r\n }\r\n\r\n techniqueUniforms[uniformName] = {\r\n type: uniformType,\r\n };\r\n }\r\n }\r\n\r\n // Give the diffuse uniform a semantic to support color replacement in 3D Tiles\r\n if (defined(techniqueUniforms.u_diffuse)) {\r\n techniqueUniforms.u_diffuse.semantic = \"_3DTILESDIFFUSE\";\r\n }\r\n\r\n // Copy light parameters into technique parameters\r\n if (defined(lightParameters)) {\r\n for (var lightParamName in lightParameters) {\r\n if (lightParameters.hasOwnProperty(lightParamName)) {\r\n uniformName = \"u_\" + lightParamName;\r\n techniqueUniforms[uniformName] = lightParameters[lightParamName];\r\n }\r\n }\r\n }\r\n\r\n // Add uniforms to shaders\r\n for (uniformName in techniqueUniforms) {\r\n if (techniqueUniforms.hasOwnProperty(uniformName)) {\r\n var uniform = techniqueUniforms[uniformName];\r\n var arraySize = defined(uniform.count) ? \"[\" + uniform.count + \"]\" : \"\";\r\n if (\r\n (uniform.type !== WebGLConstants.FLOAT_MAT3 &&\r\n uniform.type !== WebGLConstants.FLOAT_MAT4) ||\r\n uniform.useInFragment\r\n ) {\r\n fragmentShader +=\r\n \"uniform \" +\r\n webGLConstantToGlslType(uniform.type) +\r\n \" \" +\r\n uniformName +\r\n arraySize +\r\n \";\\n\";\r\n delete uniform.useInFragment;\r\n } else {\r\n vertexShader +=\r\n \"uniform \" +\r\n webGLConstantToGlslType(uniform.type) +\r\n \" \" +\r\n uniformName +\r\n arraySize +\r\n \";\\n\";\r\n }\r\n }\r\n }\r\n\r\n // Add attributes with semantics\r\n var vertexShaderMain = \"\";\r\n if (hasSkinning) {\r\n vertexShaderMain +=\r\n \" mat4 skinMatrix =\\n\" +\r\n \" a_weight.x * u_jointMatrix[int(a_joint.x)] +\\n\" +\r\n \" a_weight.y * u_jointMatrix[int(a_joint.y)] +\\n\" +\r\n \" a_weight.z * u_jointMatrix[int(a_joint.z)] +\\n\" +\r\n \" a_weight.w * u_jointMatrix[int(a_joint.w)];\\n\";\r\n }\r\n\r\n // Add position always\r\n var techniqueAttributes = {\r\n a_position: {\r\n semantic: \"POSITION\",\r\n },\r\n };\r\n vertexShader += \"attribute vec3 a_position;\\n\";\r\n vertexShader += \"varying vec3 v_positionEC;\\n\";\r\n if (hasSkinning) {\r\n vertexShaderMain +=\r\n \" vec4 pos = u_modelViewMatrix * skinMatrix * vec4(a_position,1.0);\\n\";\r\n } else {\r\n vertexShaderMain +=\r\n \" vec4 pos = u_modelViewMatrix * vec4(a_position,1.0);\\n\";\r\n }\r\n vertexShaderMain += \" v_positionEC = pos.xyz;\\n\";\r\n vertexShaderMain += \" gl_Position = u_projectionMatrix * pos;\\n\";\r\n fragmentShader += \"varying vec3 v_positionEC;\\n\";\r\n\r\n // Add normal if we don't have constant lighting\r\n if (hasNormals) {\r\n techniqueAttributes.a_normal = {\r\n semantic: \"NORMAL\",\r\n };\r\n vertexShader += \"attribute vec3 a_normal;\\n\";\r\n vertexShader += \"varying vec3 v_normal;\\n\";\r\n if (hasSkinning) {\r\n vertexShaderMain +=\r\n \" v_normal = u_normalMatrix * mat3(skinMatrix) * a_normal;\\n\";\r\n } else {\r\n vertexShaderMain += \" v_normal = u_normalMatrix * a_normal;\\n\";\r\n }\r\n\r\n fragmentShader += \"varying vec3 v_normal;\\n\";\r\n }\r\n\r\n // Add texture coordinates if the material uses them\r\n var v_texcoord;\r\n if (hasTexCoords) {\r\n techniqueAttributes.a_texcoord_0 = {\r\n semantic: \"TEXCOORD_0\",\r\n };\r\n\r\n v_texcoord = \"v_texcoord_0\";\r\n vertexShader += \"attribute vec2 a_texcoord_0;\\n\";\r\n vertexShader += \"varying vec2 \" + v_texcoord + \";\\n\";\r\n vertexShaderMain += \" \" + v_texcoord + \" = a_texcoord_0;\\n\";\r\n\r\n fragmentShader += \"varying vec2 \" + v_texcoord + \";\\n\";\r\n }\r\n\r\n if (hasSkinning) {\r\n techniqueAttributes.a_joint = {\r\n semantic: \"JOINTS_0\",\r\n };\r\n techniqueAttributes.a_weight = {\r\n semantic: \"WEIGHTS_0\",\r\n };\r\n\r\n vertexShader += \"attribute vec4 a_joint;\\n\";\r\n vertexShader += \"attribute vec4 a_weight;\\n\";\r\n }\r\n\r\n if (hasVertexColors) {\r\n techniqueAttributes.a_vertexColor = {\r\n semantic: \"COLOR_0\",\r\n };\r\n vertexShader += \"attribute vec4 a_vertexColor;\\n\";\r\n vertexShader += \"varying vec4 v_vertexColor;\\n\";\r\n vertexShaderMain += \" v_vertexColor = a_vertexColor;\\n\";\r\n fragmentShader += \"varying vec4 v_vertexColor;\\n\";\r\n }\r\n\r\n if (addBatchIdToGeneratedShaders) {\r\n techniqueAttributes.a_batchId = {\r\n semantic: \"_BATCHID\",\r\n };\r\n vertexShader += \"attribute float a_batchId;\\n\";\r\n }\r\n\r\n var hasSpecular =\r\n hasNormals &&\r\n (lightingModel === \"BLINN\" || lightingModel === \"PHONG\") &&\r\n defined(techniqueUniforms.u_specular) &&\r\n defined(techniqueUniforms.u_shininess) &&\r\n techniqueUniforms.u_shininess > 0.0;\r\n\r\n // Generate lighting code blocks\r\n var hasNonAmbientLights = false;\r\n var hasAmbientLights = false;\r\n var fragmentLightingBlock = \"\";\r\n for (var lightName in lights) {\r\n if (lights.hasOwnProperty(lightName)) {\r\n var light = lights[lightName];\r\n var lightType = light.type.toLowerCase();\r\n var lightBaseName = light.baseName;\r\n fragmentLightingBlock += \" {\\n\";\r\n var lightColorName = \"u_\" + lightBaseName + \"Color\";\r\n var varyingDirectionName;\r\n var varyingPositionName;\r\n if (lightType === \"ambient\") {\r\n hasAmbientLights = true;\r\n fragmentLightingBlock +=\r\n \" ambientLight += \" + lightColorName + \";\\n\";\r\n } else if (hasNormals) {\r\n hasNonAmbientLights = true;\r\n varyingDirectionName = \"v_\" + lightBaseName + \"Direction\";\r\n varyingPositionName = \"v_\" + lightBaseName + \"Position\";\r\n\r\n if (lightType !== \"point\") {\r\n vertexShader += \"varying vec3 \" + varyingDirectionName + \";\\n\";\r\n fragmentShader += \"varying vec3 \" + varyingDirectionName + \";\\n\";\r\n\r\n vertexShaderMain +=\r\n \" \" +\r\n varyingDirectionName +\r\n \" = mat3(u_\" +\r\n lightBaseName +\r\n \"Transform) * vec3(0.,0.,1.);\\n\";\r\n if (lightType === \"directional\") {\r\n fragmentLightingBlock +=\r\n \" vec3 l = normalize(\" + varyingDirectionName + \");\\n\";\r\n }\r\n }\r\n\r\n if (lightType !== \"directional\") {\r\n vertexShader += \"varying vec3 \" + varyingPositionName + \";\\n\";\r\n fragmentShader += \"varying vec3 \" + varyingPositionName + \";\\n\";\r\n\r\n vertexShaderMain +=\r\n \" \" +\r\n varyingPositionName +\r\n \" = u_\" +\r\n lightBaseName +\r\n \"Transform[3].xyz;\\n\";\r\n fragmentLightingBlock +=\r\n \" vec3 VP = \" + varyingPositionName + \" - v_positionEC;\\n\";\r\n fragmentLightingBlock += \" vec3 l = normalize(VP);\\n\";\r\n fragmentLightingBlock += \" float range = length(VP);\\n\";\r\n fragmentLightingBlock +=\r\n \" float attenuation = 1.0 / (u_\" +\r\n lightBaseName +\r\n \"Attenuation.x + \";\r\n fragmentLightingBlock +=\r\n \"(u_\" + lightBaseName + \"Attenuation.y * range) + \";\r\n fragmentLightingBlock +=\r\n \"(u_\" + lightBaseName + \"Attenuation.z * range * range));\\n\";\r\n } else {\r\n fragmentLightingBlock += \" float attenuation = 1.0;\\n\";\r\n }\r\n\r\n if (lightType === \"spot\") {\r\n fragmentLightingBlock +=\r\n \" float spotDot = dot(l, normalize(\" +\r\n varyingDirectionName +\r\n \"));\\n\";\r\n fragmentLightingBlock +=\r\n \" if (spotDot < cos(u_\" + lightBaseName + \"FallOff.x * 0.5))\\n\";\r\n fragmentLightingBlock += \" {\\n\";\r\n fragmentLightingBlock += \" attenuation = 0.0;\\n\";\r\n fragmentLightingBlock += \" }\\n\";\r\n fragmentLightingBlock += \" else\\n\";\r\n fragmentLightingBlock += \" {\\n\";\r\n fragmentLightingBlock +=\r\n \" attenuation *= max(0.0, pow(spotDot, u_\" +\r\n lightBaseName +\r\n \"FallOff.y));\\n\";\r\n fragmentLightingBlock += \" }\\n\";\r\n }\r\n\r\n fragmentLightingBlock +=\r\n \" diffuseLight += \" +\r\n lightColorName +\r\n \"* max(dot(normal,l), 0.) * attenuation;\\n\";\r\n\r\n if (hasSpecular) {\r\n if (lightingModel === \"BLINN\") {\r\n fragmentLightingBlock += \" vec3 h = normalize(l + viewDir);\\n\";\r\n fragmentLightingBlock +=\r\n \" float specularIntensity = max(0., pow(max(dot(normal, h), 0.), u_shininess)) * attenuation;\\n\";\r\n } else {\r\n // PHONG\r\n fragmentLightingBlock +=\r\n \" vec3 reflectDir = reflect(-l, normal);\\n\";\r\n fragmentLightingBlock +=\r\n \" float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess)) * attenuation;\\n\";\r\n }\r\n fragmentLightingBlock +=\r\n \" specularLight += \" +\r\n lightColorName +\r\n \" * specularIntensity;\\n\";\r\n }\r\n }\r\n fragmentLightingBlock += \" }\\n\";\r\n }\r\n }\r\n\r\n if (!hasAmbientLights) {\r\n // Add an ambient light if we don't have one\r\n fragmentLightingBlock += \" ambientLight += vec3(0.2, 0.2, 0.2);\\n\";\r\n }\r\n\r\n if (!hasNonAmbientLights && lightingModel !== \"CONSTANT\") {\r\n fragmentShader += \"#ifdef USE_CUSTOM_LIGHT_COLOR \\n\";\r\n fragmentShader += \"uniform vec3 gltf_lightColor; \\n\";\r\n fragmentShader += \"#endif \\n\";\r\n\r\n fragmentLightingBlock += \"#ifndef USE_CUSTOM_LIGHT_COLOR \\n\";\r\n fragmentLightingBlock += \" vec3 lightColor = czm_lightColor;\\n\";\r\n fragmentLightingBlock += \"#else \\n\";\r\n fragmentLightingBlock += \" vec3 lightColor = gltf_lightColor;\\n\";\r\n fragmentLightingBlock += \"#endif \\n\";\r\n\r\n fragmentLightingBlock += \" vec3 l = normalize(czm_lightDirectionEC);\\n\";\r\n var minimumLighting = \"0.2\"; // Use strings instead of values as 0.0 -> 0 when stringified\r\n fragmentLightingBlock +=\r\n \" diffuseLight += lightColor * max(dot(normal,l), \" +\r\n minimumLighting +\r\n \");\\n\";\r\n\r\n if (hasSpecular) {\r\n if (lightingModel === \"BLINN\") {\r\n fragmentLightingBlock += \" vec3 h = normalize(l + viewDir);\\n\";\r\n fragmentLightingBlock +=\r\n \" float specularIntensity = max(0., pow(max(dot(normal, h), 0.), u_shininess));\\n\";\r\n } else {\r\n // PHONG\r\n fragmentLightingBlock += \" vec3 reflectDir = reflect(-l, normal);\\n\";\r\n fragmentLightingBlock +=\r\n \" float specularIntensity = max(0., pow(max(dot(reflectDir, viewDir), 0.), u_shininess));\\n\";\r\n }\r\n\r\n fragmentLightingBlock +=\r\n \" specularLight += lightColor * specularIntensity;\\n\";\r\n }\r\n }\r\n\r\n vertexShader += \"void main(void) {\\n\";\r\n vertexShader += vertexShaderMain;\r\n vertexShader += \"}\\n\";\r\n\r\n fragmentShader += \"void main(void) {\\n\";\r\n var colorCreationBlock = \" vec3 color = vec3(0.0, 0.0, 0.0);\\n\";\r\n if (hasNormals) {\r\n fragmentShader += \" vec3 normal = normalize(v_normal);\\n\";\r\n if (khrMaterialsCommon.doubleSided) {\r\n fragmentShader += \" if (czm_backFacing())\\n\";\r\n fragmentShader += \" {\\n\";\r\n fragmentShader += \" normal = -normal;\\n\";\r\n fragmentShader += \" }\\n\";\r\n }\r\n }\r\n\r\n var finalColorComputation;\r\n if (lightingModel !== \"CONSTANT\") {\r\n if (defined(techniqueUniforms.u_diffuse)) {\r\n if (techniqueUniforms.u_diffuse.type === WebGLConstants.SAMPLER_2D) {\r\n fragmentShader +=\r\n \" vec4 diffuse = texture2D(u_diffuse, \" + v_texcoord + \");\\n\";\r\n } else {\r\n fragmentShader += \" vec4 diffuse = u_diffuse;\\n\";\r\n }\r\n fragmentShader += \" vec3 diffuseLight = vec3(0.0, 0.0, 0.0);\\n\";\r\n colorCreationBlock += \" color += diffuse.rgb * diffuseLight;\\n\";\r\n }\r\n\r\n if (hasSpecular) {\r\n if (techniqueUniforms.u_specular.type === WebGLConstants.SAMPLER_2D) {\r\n fragmentShader +=\r\n \" vec3 specular = texture2D(u_specular, \" + v_texcoord + \").rgb;\\n\";\r\n } else {\r\n fragmentShader += \" vec3 specular = u_specular.rgb;\\n\";\r\n }\r\n fragmentShader += \" vec3 specularLight = vec3(0.0, 0.0, 0.0);\\n\";\r\n colorCreationBlock += \" color += specular * specularLight;\\n\";\r\n }\r\n\r\n if (defined(techniqueUniforms.u_transparency)) {\r\n finalColorComputation =\r\n \" gl_FragColor = vec4(color * diffuse.a * u_transparency, diffuse.a * u_transparency);\\n\";\r\n } else {\r\n finalColorComputation =\r\n \" gl_FragColor = vec4(color * diffuse.a, diffuse.a);\\n\";\r\n }\r\n } else if (defined(techniqueUniforms.u_transparency)) {\r\n finalColorComputation =\r\n \" gl_FragColor = vec4(color * u_transparency, u_transparency);\\n\";\r\n } else {\r\n finalColorComputation = \" gl_FragColor = vec4(color, 1.0);\\n\";\r\n }\r\n\r\n if (hasVertexColors) {\r\n colorCreationBlock += \" color *= v_vertexColor.rgb;\\n\";\r\n }\r\n\r\n if (defined(techniqueUniforms.u_emission)) {\r\n if (techniqueUniforms.u_emission.type === WebGLConstants.SAMPLER_2D) {\r\n fragmentShader +=\r\n \" vec3 emission = texture2D(u_emission, \" + v_texcoord + \").rgb;\\n\";\r\n } else {\r\n fragmentShader += \" vec3 emission = u_emission.rgb;\\n\";\r\n }\r\n colorCreationBlock += \" color += emission;\\n\";\r\n }\r\n\r\n if (defined(techniqueUniforms.u_ambient) || lightingModel !== \"CONSTANT\") {\r\n if (defined(techniqueUniforms.u_ambient)) {\r\n if (techniqueUniforms.u_ambient.type === WebGLConstants.SAMPLER_2D) {\r\n fragmentShader +=\r\n \" vec3 ambient = texture2D(u_ambient, \" + v_texcoord + \").rgb;\\n\";\r\n } else {\r\n fragmentShader += \" vec3 ambient = u_ambient.rgb;\\n\";\r\n }\r\n } else {\r\n fragmentShader += \" vec3 ambient = diffuse.rgb;\\n\";\r\n }\r\n colorCreationBlock += \" color += ambient * ambientLight;\\n\";\r\n }\r\n fragmentShader += \" vec3 viewDir = -normalize(v_positionEC);\\n\";\r\n fragmentShader += \" vec3 ambientLight = vec3(0.0, 0.0, 0.0);\\n\";\r\n\r\n // Add in light computations\r\n fragmentShader += fragmentLightingBlock;\r\n\r\n fragmentShader += colorCreationBlock;\r\n fragmentShader += finalColorComputation;\r\n fragmentShader += \"}\\n\";\r\n\r\n // Add shaders\r\n var vertexShaderId = addToArray(shaders, {\r\n type: WebGLConstants.VERTEX_SHADER,\r\n extras: {\r\n _pipeline: {\r\n source: vertexShader,\r\n extension: \".glsl\",\r\n },\r\n },\r\n });\r\n\r\n var fragmentShaderId = addToArray(shaders, {\r\n type: WebGLConstants.FRAGMENT_SHADER,\r\n extras: {\r\n _pipeline: {\r\n source: fragmentShader,\r\n extension: \".glsl\",\r\n },\r\n },\r\n });\r\n\r\n // Add program\r\n var programId = addToArray(programs, {\r\n fragmentShader: fragmentShaderId,\r\n vertexShader: vertexShaderId,\r\n });\r\n\r\n var techniqueId = addToArray(techniques, {\r\n attributes: techniqueAttributes,\r\n program: programId,\r\n uniforms: techniqueUniforms,\r\n });\r\n\r\n return techniqueId;\r\n}\r\n\r\nfunction getKHRMaterialsCommonValueType(paramName, paramValue) {\r\n var value;\r\n\r\n // Backwards compatibility for COLLADA2GLTF v1.0-draft when it encoding\r\n // materials using KHR_materials_common with explicit type/value members\r\n if (defined(paramValue.value)) {\r\n value = paramValue.value;\r\n } else if (defined(paramValue.index)) {\r\n value = [paramValue.index];\r\n } else {\r\n value = paramValue;\r\n }\r\n\r\n switch (paramName) {\r\n case \"ambient\":\r\n return value.length === 1\r\n ? WebGLConstants.SAMPLER_2D\r\n : WebGLConstants.FLOAT_VEC4;\r\n case \"diffuse\":\r\n return value.length === 1\r\n ? WebGLConstants.SAMPLER_2D\r\n : WebGLConstants.FLOAT_VEC4;\r\n case \"emission\":\r\n return value.length === 1\r\n ? WebGLConstants.SAMPLER_2D\r\n : WebGLConstants.FLOAT_VEC4;\r\n case \"specular\":\r\n return value.length === 1\r\n ? WebGLConstants.SAMPLER_2D\r\n : WebGLConstants.FLOAT_VEC4;\r\n case \"shininess\":\r\n return WebGLConstants.FLOAT;\r\n case \"transparency\":\r\n return WebGLConstants.FLOAT;\r\n\r\n // these two are usually not used directly within shaders,\r\n // they are just added here for completeness\r\n case \"transparent\":\r\n return WebGLConstants.BOOL;\r\n case \"doubleSided\":\r\n return WebGLConstants.BOOL;\r\n }\r\n}\r\n\r\nfunction getTechniqueKey(khrMaterialsCommon, primitiveInfo) {\r\n var techniqueKey = \"\";\r\n techniqueKey += \"technique:\" + khrMaterialsCommon.technique + \";\";\r\n\r\n var values = khrMaterialsCommon.values;\r\n var keys = Object.keys(values).sort();\r\n var keysCount = keys.length;\r\n for (var i = 0; i < keysCount; ++i) {\r\n var name = keys[i];\r\n if (values.hasOwnProperty(name)) {\r\n techniqueKey +=\r\n name + \":\" + getKHRMaterialsCommonValueType(name, values[name]);\r\n techniqueKey += \";\";\r\n }\r\n }\r\n\r\n var jointCount = defaultValue(khrMaterialsCommon.jointCount, 0);\r\n techniqueKey += jointCount.toString() + \";\";\r\n if (defined(primitiveInfo)) {\r\n var skinningInfo = primitiveInfo.skinning;\r\n if (jointCount > 0) {\r\n techniqueKey += skinningInfo.type + \";\";\r\n }\r\n techniqueKey += primitiveInfo.hasVertexColors;\r\n }\r\n\r\n return techniqueKey;\r\n}\r\n\r\nfunction lightDefaults(gltf) {\r\n var khrMaterialsCommon = gltf.extensions.KHR_materials_common;\r\n if (!defined(khrMaterialsCommon) || !defined(khrMaterialsCommon.lights)) {\r\n return;\r\n }\r\n\r\n var lights = khrMaterialsCommon.lights;\r\n\r\n var lightsLength = lights.length;\r\n for (var lightId = 0; lightId < lightsLength; lightId++) {\r\n var light = lights[lightId];\r\n if (light.type === \"ambient\") {\r\n if (!defined(light.ambient)) {\r\n light.ambient = {};\r\n }\r\n var ambientLight = light.ambient;\r\n\r\n if (!defined(ambientLight.color)) {\r\n ambientLight.color = [1.0, 1.0, 1.0];\r\n }\r\n } else if (light.type === \"directional\") {\r\n if (!defined(light.directional)) {\r\n light.directional = {};\r\n }\r\n var directionalLight = light.directional;\r\n\r\n if (!defined(directionalLight.color)) {\r\n directionalLight.color = [1.0, 1.0, 1.0];\r\n }\r\n } else if (light.type === \"point\") {\r\n if (!defined(light.point)) {\r\n light.point = {};\r\n }\r\n var pointLight = light.point;\r\n\r\n if (!defined(pointLight.color)) {\r\n pointLight.color = [1.0, 1.0, 1.0];\r\n }\r\n\r\n pointLight.constantAttenuation = defaultValue(\r\n pointLight.constantAttenuation,\r\n 1.0\r\n );\r\n pointLight.linearAttenuation = defaultValue(\r\n pointLight.linearAttenuation,\r\n 0.0\r\n );\r\n pointLight.quadraticAttenuation = defaultValue(\r\n pointLight.quadraticAttenuation,\r\n 0.0\r\n );\r\n } else if (light.type === \"spot\") {\r\n if (!defined(light.spot)) {\r\n light.spot = {};\r\n }\r\n var spotLight = light.spot;\r\n\r\n if (!defined(spotLight.color)) {\r\n spotLight.color = [1.0, 1.0, 1.0];\r\n }\r\n\r\n spotLight.constantAttenuation = defaultValue(\r\n spotLight.constantAttenuation,\r\n 1.0\r\n );\r\n spotLight.fallOffAngle = defaultValue(spotLight.fallOffAngle, 3.14159265);\r\n spotLight.fallOffExponent = defaultValue(spotLight.fallOffExponent, 0.0);\r\n spotLight.linearAttenuation = defaultValue(\r\n spotLight.linearAttenuation,\r\n 0.0\r\n );\r\n spotLight.quadraticAttenuation = defaultValue(\r\n spotLight.quadraticAttenuation,\r\n 0.0\r\n );\r\n }\r\n }\r\n}\r\nexport default processModelMaterialsCommon;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport webGLConstantToGlslType from \"../Core/webGLConstantToGlslType.js\";\r\nimport addToArray from \"../ThirdParty/GltfPipeline/addToArray.js\";\r\nimport ForEach from \"../ThirdParty/GltfPipeline/ForEach.js\";\r\nimport hasExtension from \"../ThirdParty/GltfPipeline/hasExtension.js\";\r\nimport ModelUtility from \"./ModelUtility.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction processPbrMaterials(gltf, options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n // No need to create new techniques if they already exist,\r\n // the shader should handle these values\r\n if (hasExtension(gltf, \"KHR_techniques_webgl\")) {\r\n return gltf;\r\n }\r\n\r\n // All materials in glTF are PBR by default,\r\n // so we should apply PBR unless no materials are found.\r\n if (!defined(gltf.materials) || gltf.materials.length === 0) {\r\n return gltf;\r\n }\r\n\r\n if (!defined(gltf.extensions)) {\r\n gltf.extensions = {};\r\n }\r\n\r\n if (!defined(gltf.extensionsUsed)) {\r\n gltf.extensionsUsed = [];\r\n }\r\n\r\n if (!defined(gltf.extensionsRequired)) {\r\n gltf.extensionsRequired = [];\r\n }\r\n\r\n gltf.extensions.KHR_techniques_webgl = {\r\n programs: [],\r\n shaders: [],\r\n techniques: [],\r\n };\r\n\r\n gltf.extensionsUsed.push(\"KHR_techniques_webgl\");\r\n gltf.extensionsRequired.push(\"KHR_techniques_webgl\");\r\n\r\n var primitiveByMaterial = ModelUtility.splitIncompatibleMaterials(gltf);\r\n\r\n ForEach.material(gltf, function (material, materialIndex) {\r\n var generatedMaterialValues = {};\r\n var technique = generateTechnique(\r\n gltf,\r\n material,\r\n materialIndex,\r\n generatedMaterialValues,\r\n primitiveByMaterial,\r\n options\r\n );\r\n\r\n if (!defined(material.extensions)) {\r\n material.extensions = {};\r\n }\r\n\r\n material.extensions.KHR_techniques_webgl = {\r\n values: generatedMaterialValues,\r\n technique: technique,\r\n };\r\n });\r\n\r\n // If any primitives have semantics that aren't declared in the generated\r\n // shaders, we want to preserve them.\r\n ModelUtility.ensureSemanticExistence(gltf);\r\n\r\n return gltf;\r\n}\r\n\r\nfunction isSpecularGlossinessMaterial(material) {\r\n return (\r\n defined(material.extensions) &&\r\n defined(material.extensions.KHR_materials_pbrSpecularGlossiness)\r\n );\r\n}\r\n\r\nfunction addTextureCoordinates(\r\n gltf,\r\n textureName,\r\n generatedMaterialValues,\r\n defaultTexCoord,\r\n result\r\n) {\r\n var texCoord;\r\n var texInfo = generatedMaterialValues[textureName];\r\n if (defined(texInfo) && defined(texInfo.texCoord) && texInfo.texCoord === 1) {\r\n defaultTexCoord = defaultTexCoord.replace(\"0\", \"1\");\r\n }\r\n if (defined(generatedMaterialValues[textureName + \"Offset\"])) {\r\n texCoord = textureName + \"Coord\";\r\n result.fragmentShaderMain +=\r\n \" vec2 \" +\r\n texCoord +\r\n \" = computeTexCoord(\" +\r\n defaultTexCoord +\r\n \", \" +\r\n textureName +\r\n \"Offset, \" +\r\n textureName +\r\n \"Rotation, \" +\r\n textureName +\r\n \"Scale);\\n\";\r\n } else {\r\n texCoord = defaultTexCoord;\r\n }\r\n return texCoord;\r\n}\r\n\r\nvar DEFAULT_TEXTURE_OFFSET = [0.0, 0.0];\r\nvar DEFAULT_TEXTURE_ROTATION = [0.0];\r\nvar DEFAULT_TEXTURE_SCALE = [1.0, 1.0];\r\n\r\nfunction handleKHRTextureTransform(\r\n parameterName,\r\n value,\r\n generatedMaterialValues\r\n) {\r\n if (\r\n parameterName.indexOf(\"Texture\") === -1 ||\r\n !defined(value.extensions) ||\r\n !defined(value.extensions.KHR_texture_transform)\r\n ) {\r\n return;\r\n }\r\n\r\n var uniformName = \"u_\" + parameterName;\r\n var extension = value.extensions.KHR_texture_transform;\r\n generatedMaterialValues[uniformName + \"Offset\"] = defaultValue(\r\n extension.offset,\r\n DEFAULT_TEXTURE_OFFSET\r\n );\r\n generatedMaterialValues[uniformName + \"Rotation\"] = defaultValue(\r\n extension.rotation,\r\n DEFAULT_TEXTURE_ROTATION\r\n );\r\n generatedMaterialValues[uniformName + \"Scale\"] = defaultValue(\r\n extension.scale,\r\n DEFAULT_TEXTURE_SCALE\r\n );\r\n\r\n if (defined(value.texCoord) && defined(extension.texCoord)) {\r\n generatedMaterialValues[uniformName].texCoord = extension.texCoord;\r\n }\r\n}\r\n\r\nfunction generateTechnique(\r\n gltf,\r\n material,\r\n materialIndex,\r\n generatedMaterialValues,\r\n primitiveByMaterial,\r\n options\r\n) {\r\n var addBatchIdToGeneratedShaders = defaultValue(\r\n options.addBatchIdToGeneratedShaders,\r\n false\r\n );\r\n\r\n var techniquesWebgl = gltf.extensions.KHR_techniques_webgl;\r\n var techniques = techniquesWebgl.techniques;\r\n var shaders = techniquesWebgl.shaders;\r\n var programs = techniquesWebgl.programs;\r\n\r\n var useSpecGloss = isSpecularGlossinessMaterial(material);\r\n\r\n var uniformName;\r\n var parameterName;\r\n var value;\r\n var pbrMetallicRoughness = material.pbrMetallicRoughness;\r\n if (defined(pbrMetallicRoughness) && !useSpecGloss) {\r\n for (parameterName in pbrMetallicRoughness) {\r\n if (pbrMetallicRoughness.hasOwnProperty(parameterName)) {\r\n value = pbrMetallicRoughness[parameterName];\r\n uniformName = \"u_\" + parameterName;\r\n generatedMaterialValues[uniformName] = value;\r\n handleKHRTextureTransform(\r\n parameterName,\r\n value,\r\n generatedMaterialValues\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (useSpecGloss) {\r\n var pbrSpecularGlossiness =\r\n material.extensions.KHR_materials_pbrSpecularGlossiness;\r\n for (parameterName in pbrSpecularGlossiness) {\r\n if (pbrSpecularGlossiness.hasOwnProperty(parameterName)) {\r\n value = pbrSpecularGlossiness[parameterName];\r\n uniformName = \"u_\" + parameterName;\r\n generatedMaterialValues[uniformName] = value;\r\n handleKHRTextureTransform(\r\n parameterName,\r\n value,\r\n generatedMaterialValues\r\n );\r\n }\r\n }\r\n }\r\n\r\n for (var additional in material) {\r\n if (\r\n material.hasOwnProperty(additional) &&\r\n (additional.indexOf(\"Texture\") >= 0 || additional.indexOf(\"Factor\") >= 0)\r\n ) {\r\n value = material[additional];\r\n uniformName = \"u_\" + additional;\r\n generatedMaterialValues[uniformName] = value;\r\n handleKHRTextureTransform(additional, value, generatedMaterialValues);\r\n }\r\n }\r\n\r\n var vertexShader = \"precision highp float;\\n\";\r\n var fragmentShader = \"precision highp float;\\n\";\r\n\r\n var skin;\r\n if (defined(gltf.skins)) {\r\n skin = gltf.skins[0];\r\n }\r\n var joints = defined(skin) ? skin.joints : [];\r\n var jointCount = joints.length;\r\n\r\n var primitiveInfo = primitiveByMaterial[materialIndex];\r\n\r\n var skinningInfo;\r\n var hasSkinning = false;\r\n var hasVertexColors = false;\r\n var hasMorphTargets = false;\r\n var hasNormals = false;\r\n var hasTangents = false;\r\n var hasTexCoords = false;\r\n var hasTexCoord1 = false;\r\n var hasOutline = false;\r\n var isUnlit = false;\r\n\r\n if (defined(primitiveInfo)) {\r\n skinningInfo = primitiveInfo.skinning;\r\n hasSkinning = skinningInfo.skinned && joints.length > 0;\r\n hasVertexColors = primitiveInfo.hasVertexColors;\r\n hasMorphTargets = primitiveInfo.hasMorphTargets;\r\n hasNormals = primitiveInfo.hasNormals;\r\n hasTangents = primitiveInfo.hasTangents;\r\n hasTexCoords = primitiveInfo.hasTexCoords;\r\n hasTexCoord1 = primitiveInfo.hasTexCoord1;\r\n hasOutline = primitiveInfo.hasOutline;\r\n }\r\n\r\n var morphTargets;\r\n if (hasMorphTargets) {\r\n ForEach.mesh(gltf, function (mesh) {\r\n ForEach.meshPrimitive(mesh, function (primitive) {\r\n if (primitive.material === materialIndex) {\r\n var targets = primitive.targets;\r\n if (defined(targets)) {\r\n morphTargets = targets;\r\n }\r\n }\r\n });\r\n });\r\n }\r\n\r\n // Add techniques\r\n var techniqueUniforms = {\r\n // Add matrices\r\n u_modelViewMatrix: {\r\n semantic: hasExtension(gltf, \"CESIUM_RTC\")\r\n ? \"CESIUM_RTC_MODELVIEW\"\r\n : \"MODELVIEW\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n },\r\n u_projectionMatrix: {\r\n semantic: \"PROJECTION\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n },\r\n };\r\n\r\n if (\r\n defined(material.extensions) &&\r\n defined(material.extensions.KHR_materials_unlit)\r\n ) {\r\n isUnlit = true;\r\n }\r\n\r\n if (hasNormals) {\r\n techniqueUniforms.u_normalMatrix = {\r\n semantic: \"MODELVIEWINVERSETRANSPOSE\",\r\n type: WebGLConstants.FLOAT_MAT3,\r\n };\r\n }\r\n\r\n if (hasSkinning) {\r\n techniqueUniforms.u_jointMatrix = {\r\n count: jointCount,\r\n semantic: \"JOINTMATRIX\",\r\n type: WebGLConstants.FLOAT_MAT4,\r\n };\r\n }\r\n\r\n if (hasMorphTargets) {\r\n techniqueUniforms.u_morphWeights = {\r\n count: morphTargets.length,\r\n semantic: \"MORPHWEIGHTS\",\r\n type: WebGLConstants.FLOAT,\r\n };\r\n }\r\n\r\n var alphaMode = material.alphaMode;\r\n if (defined(alphaMode) && alphaMode === \"MASK\") {\r\n techniqueUniforms.u_alphaCutoff = {\r\n semantic: \"ALPHACUTOFF\",\r\n type: WebGLConstants.FLOAT,\r\n };\r\n }\r\n\r\n // Add material values\r\n for (uniformName in generatedMaterialValues) {\r\n if (generatedMaterialValues.hasOwnProperty(uniformName)) {\r\n techniqueUniforms[uniformName] = {\r\n type: getPBRValueType(uniformName),\r\n };\r\n }\r\n }\r\n\r\n var baseColorUniform = defaultValue(\r\n techniqueUniforms.u_baseColorTexture,\r\n techniqueUniforms.u_baseColorFactor\r\n );\r\n if (defined(baseColorUniform)) {\r\n baseColorUniform.semantic = \"_3DTILESDIFFUSE\";\r\n }\r\n\r\n // Add uniforms to shaders\r\n for (uniformName in techniqueUniforms) {\r\n if (techniqueUniforms.hasOwnProperty(uniformName)) {\r\n var uniform = techniqueUniforms[uniformName];\r\n var arraySize = defined(uniform.count) ? \"[\" + uniform.count + \"]\" : \"\";\r\n if (\r\n (uniform.type !== WebGLConstants.FLOAT_MAT3 &&\r\n uniform.type !== WebGLConstants.FLOAT_MAT4 &&\r\n uniformName !== \"u_morphWeights\") ||\r\n uniform.useInFragment\r\n ) {\r\n fragmentShader +=\r\n \"uniform \" +\r\n webGLConstantToGlslType(uniform.type) +\r\n \" \" +\r\n uniformName +\r\n arraySize +\r\n \";\\n\";\r\n delete uniform.useInFragment;\r\n } else {\r\n vertexShader +=\r\n \"uniform \" +\r\n webGLConstantToGlslType(uniform.type) +\r\n \" \" +\r\n uniformName +\r\n arraySize +\r\n \";\\n\";\r\n }\r\n }\r\n }\r\n\r\n if (hasOutline) {\r\n fragmentShader += \"uniform sampler2D u_outlineTexture;\\n\";\r\n }\r\n\r\n // Add attributes with semantics\r\n var vertexShaderMain = \"\";\r\n if (hasSkinning) {\r\n vertexShaderMain +=\r\n \" mat4 skinMatrix =\\n\" +\r\n \" a_weight.x * u_jointMatrix[int(a_joint.x)] +\\n\" +\r\n \" a_weight.y * u_jointMatrix[int(a_joint.y)] +\\n\" +\r\n \" a_weight.z * u_jointMatrix[int(a_joint.z)] +\\n\" +\r\n \" a_weight.w * u_jointMatrix[int(a_joint.w)];\\n\";\r\n }\r\n\r\n // Add position always\r\n var techniqueAttributes = {\r\n a_position: {\r\n semantic: \"POSITION\",\r\n },\r\n };\r\n\r\n if (hasOutline) {\r\n techniqueAttributes.a_outlineCoordinates = {\r\n semantic: \"_OUTLINE_COORDINATES\",\r\n };\r\n }\r\n\r\n vertexShader += \"attribute vec3 a_position;\\n\";\r\n if (hasNormals) {\r\n vertexShader += \"varying vec3 v_positionEC;\\n\";\r\n }\r\n if (hasOutline) {\r\n vertexShader += \"attribute vec3 a_outlineCoordinates;\\n\";\r\n vertexShader += \"varying vec3 v_outlineCoordinates;\\n\";\r\n }\r\n\r\n // Morph Target Weighting\r\n vertexShaderMain += \" vec3 weightedPosition = a_position;\\n\";\r\n if (hasNormals) {\r\n vertexShaderMain += \" vec3 weightedNormal = a_normal;\\n\";\r\n }\r\n if (hasTangents) {\r\n vertexShaderMain += \" vec4 weightedTangent = a_tangent;\\n\";\r\n }\r\n if (hasMorphTargets) {\r\n for (var k = 0; k < morphTargets.length; k++) {\r\n var targetAttributes = morphTargets[k];\r\n for (var targetAttribute in targetAttributes) {\r\n if (\r\n targetAttributes.hasOwnProperty(targetAttribute) &&\r\n targetAttribute !== \"extras\"\r\n ) {\r\n var attributeName = \"a_\" + targetAttribute + \"_\" + k;\r\n techniqueAttributes[attributeName] = {\r\n semantic: targetAttribute + \"_\" + k,\r\n };\r\n vertexShader += \"attribute vec3 \" + attributeName + \";\\n\";\r\n if (targetAttribute === \"POSITION\") {\r\n vertexShaderMain +=\r\n \" weightedPosition += u_morphWeights[\" +\r\n k +\r\n \"] * \" +\r\n attributeName +\r\n \";\\n\";\r\n } else if (targetAttribute === \"NORMAL\") {\r\n vertexShaderMain +=\r\n \" weightedNormal += u_morphWeights[\" +\r\n k +\r\n \"] * \" +\r\n attributeName +\r\n \";\\n\";\r\n } else if (hasTangents && targetAttribute === \"TANGENT\") {\r\n vertexShaderMain +=\r\n \" weightedTangent.xyz += u_morphWeights[\" +\r\n k +\r\n \"] * \" +\r\n attributeName +\r\n \";\\n\";\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Final position computation\r\n if (hasSkinning) {\r\n vertexShaderMain +=\r\n \" vec4 position = skinMatrix * vec4(weightedPosition, 1.0);\\n\";\r\n } else {\r\n vertexShaderMain += \" vec4 position = vec4(weightedPosition, 1.0);\\n\";\r\n }\r\n vertexShaderMain += \" position = u_modelViewMatrix * position;\\n\";\r\n if (hasNormals) {\r\n vertexShaderMain += \" v_positionEC = position.xyz;\\n\";\r\n }\r\n vertexShaderMain += \" gl_Position = u_projectionMatrix * position;\\n\";\r\n\r\n if (hasOutline) {\r\n vertexShaderMain += \" v_outlineCoordinates = a_outlineCoordinates;\\n\";\r\n }\r\n\r\n // Final normal computation\r\n if (hasNormals) {\r\n techniqueAttributes.a_normal = {\r\n semantic: \"NORMAL\",\r\n };\r\n vertexShader += \"attribute vec3 a_normal;\\n\";\r\n if (!isUnlit) {\r\n vertexShader += \"varying vec3 v_normal;\\n\";\r\n if (hasSkinning) {\r\n vertexShaderMain +=\r\n \" v_normal = u_normalMatrix * mat3(skinMatrix) * weightedNormal;\\n\";\r\n } else {\r\n vertexShaderMain += \" v_normal = u_normalMatrix * weightedNormal;\\n\";\r\n }\r\n fragmentShader += \"varying vec3 v_normal;\\n\";\r\n }\r\n fragmentShader += \"varying vec3 v_positionEC;\\n\";\r\n }\r\n\r\n // Read tangents if available\r\n if (hasTangents) {\r\n techniqueAttributes.a_tangent = {\r\n semantic: \"TANGENT\",\r\n };\r\n vertexShader += \"attribute vec4 a_tangent;\\n\";\r\n vertexShader += \"varying vec4 v_tangent;\\n\";\r\n vertexShaderMain +=\r\n \" v_tangent.xyz = u_normalMatrix * weightedTangent.xyz;\\n\";\r\n vertexShaderMain += \" v_tangent.w = weightedTangent.w;\\n\";\r\n\r\n fragmentShader += \"varying vec4 v_tangent;\\n\";\r\n }\r\n\r\n if (hasOutline) {\r\n fragmentShader += \"varying vec3 v_outlineCoordinates;\\n\";\r\n }\r\n\r\n var fragmentShaderMain = \"\";\r\n\r\n // Add texture coordinates if the material uses them\r\n var v_texCoord;\r\n var normalTexCoord;\r\n var baseColorTexCoord;\r\n var specularGlossinessTexCoord;\r\n var diffuseTexCoord;\r\n var metallicRoughnessTexCoord;\r\n var occlusionTexCoord;\r\n var emissiveTexCoord;\r\n\r\n if (hasTexCoords) {\r\n techniqueAttributes.a_texcoord_0 = {\r\n semantic: \"TEXCOORD_0\",\r\n };\r\n\r\n v_texCoord = \"v_texcoord_0\";\r\n vertexShader += \"attribute vec2 a_texcoord_0;\\n\";\r\n vertexShader += \"varying vec2 \" + v_texCoord + \";\\n\";\r\n vertexShaderMain += \" \" + v_texCoord + \" = a_texcoord_0;\\n\";\r\n\r\n fragmentShader += \"varying vec2 \" + v_texCoord + \";\\n\";\r\n\r\n if (hasTexCoord1) {\r\n techniqueAttributes.a_texcoord_1 = {\r\n semantic: \"TEXCOORD_1\",\r\n };\r\n\r\n var v_texCoord1 = v_texCoord.replace(\"0\", \"1\");\r\n vertexShader += \"attribute vec2 a_texcoord_1;\\n\";\r\n vertexShader += \"varying vec2 \" + v_texCoord1 + \";\\n\";\r\n vertexShaderMain += \" \" + v_texCoord1 + \" = a_texcoord_1;\\n\";\r\n\r\n fragmentShader += \"varying vec2 \" + v_texCoord1 + \";\\n\";\r\n }\r\n\r\n var result = {\r\n fragmentShaderMain: fragmentShaderMain,\r\n };\r\n normalTexCoord = addTextureCoordinates(\r\n gltf,\r\n \"u_normalTexture\",\r\n generatedMaterialValues,\r\n v_texCoord,\r\n result\r\n );\r\n baseColorTexCoord = addTextureCoordinates(\r\n gltf,\r\n \"u_baseColorTexture\",\r\n generatedMaterialValues,\r\n v_texCoord,\r\n result\r\n );\r\n specularGlossinessTexCoord = addTextureCoordinates(\r\n gltf,\r\n \"u_specularGlossinessTexture\",\r\n generatedMaterialValues,\r\n v_texCoord,\r\n result\r\n );\r\n diffuseTexCoord = addTextureCoordinates(\r\n gltf,\r\n \"u_diffuseTexture\",\r\n generatedMaterialValues,\r\n v_texCoord,\r\n result\r\n );\r\n metallicRoughnessTexCoord = addTextureCoordinates(\r\n gltf,\r\n \"u_metallicRoughnessTexture\",\r\n generatedMaterialValues,\r\n v_texCoord,\r\n result\r\n );\r\n occlusionTexCoord = addTextureCoordinates(\r\n gltf,\r\n \"u_occlusionTexture\",\r\n generatedMaterialValues,\r\n v_texCoord,\r\n result\r\n );\r\n emissiveTexCoord = addTextureCoordinates(\r\n gltf,\r\n \"u_emissiveTexture\",\r\n generatedMaterialValues,\r\n v_texCoord,\r\n result\r\n );\r\n\r\n fragmentShaderMain = result.fragmentShaderMain;\r\n }\r\n\r\n // Add skinning information if available\r\n if (hasSkinning) {\r\n techniqueAttributes.a_joint = {\r\n semantic: \"JOINTS_0\",\r\n };\r\n techniqueAttributes.a_weight = {\r\n semantic: \"WEIGHTS_0\",\r\n };\r\n\r\n vertexShader += \"attribute vec4 a_joint;\\n\";\r\n vertexShader += \"attribute vec4 a_weight;\\n\";\r\n }\r\n\r\n if (hasVertexColors) {\r\n techniqueAttributes.a_vertexColor = {\r\n semantic: \"COLOR_0\",\r\n };\r\n vertexShader += \"attribute vec4 a_vertexColor;\\n\";\r\n vertexShader += \"varying vec4 v_vertexColor;\\n\";\r\n vertexShaderMain += \" v_vertexColor = a_vertexColor;\\n\";\r\n fragmentShader += \"varying vec4 v_vertexColor;\\n\";\r\n }\r\n\r\n if (addBatchIdToGeneratedShaders) {\r\n techniqueAttributes.a_batchId = {\r\n semantic: \"_BATCHID\",\r\n };\r\n vertexShader += \"attribute float a_batchId;\\n\";\r\n }\r\n\r\n vertexShader += \"void main(void) \\n{\\n\";\r\n vertexShader += vertexShaderMain;\r\n vertexShader += \"}\\n\";\r\n\r\n // Fragment shader lighting\r\n if (hasNormals && !isUnlit) {\r\n fragmentShader += \"const float M_PI = 3.141592653589793;\\n\";\r\n\r\n fragmentShader +=\r\n \"vec3 lambertianDiffuse(vec3 diffuseColor) \\n\" +\r\n \"{\\n\" +\r\n \" return diffuseColor / M_PI;\\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"vec3 fresnelSchlick2(vec3 f0, vec3 f90, float VdotH) \\n\" +\r\n \"{\\n\" +\r\n \" return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);\\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"vec3 fresnelSchlick(float metalness, float VdotH) \\n\" +\r\n \"{\\n\" +\r\n \" return metalness + (vec3(1.0) - metalness) * pow(1.0 - VdotH, 5.0);\\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"float smithVisibilityG1(float NdotV, float roughness) \\n\" +\r\n \"{\\n\" +\r\n \" float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;\\n\" +\r\n \" return NdotV / (NdotV * (1.0 - k) + k);\\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"float smithVisibilityGGX(float roughness, float NdotL, float NdotV) \\n\" +\r\n \"{\\n\" +\r\n \" return smithVisibilityG1(NdotL, roughness) * smithVisibilityG1(NdotV, roughness);\\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"float GGX(float roughness, float NdotH) \\n\" +\r\n \"{\\n\" +\r\n \" float roughnessSquared = roughness * roughness;\\n\" +\r\n \" float f = (NdotH * roughnessSquared - NdotH) * NdotH + 1.0;\\n\" +\r\n \" return roughnessSquared / (M_PI * f * f);\\n\" +\r\n \"}\\n\\n\";\r\n }\r\n\r\n fragmentShader +=\r\n \"vec3 SRGBtoLINEAR3(vec3 srgbIn) \\n\" +\r\n \"{\\n\" +\r\n \" return pow(srgbIn, vec3(2.2));\\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"vec4 SRGBtoLINEAR4(vec4 srgbIn) \\n\" +\r\n \"{\\n\" +\r\n \" vec3 linearOut = pow(srgbIn.rgb, vec3(2.2));\\n\" +\r\n \" return vec4(linearOut, srgbIn.a);\\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"vec3 applyTonemapping(vec3 linearIn) \\n\" +\r\n \"{\\n\" +\r\n \"#ifndef HDR \\n\" +\r\n \" return czm_acesTonemapping(linearIn);\\n\" +\r\n \"#else \\n\" +\r\n \" return linearIn;\\n\" +\r\n \"#endif \\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"vec3 LINEARtoSRGB(vec3 linearIn) \\n\" +\r\n \"{\\n\" +\r\n \"#ifndef HDR \\n\" +\r\n \" return pow(linearIn, vec3(1.0/2.2));\\n\" +\r\n \"#else \\n\" +\r\n \" return linearIn;\\n\" +\r\n \"#endif \\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader +=\r\n \"vec2 computeTexCoord(vec2 texCoords, vec2 offset, float rotation, vec2 scale) \\n\" +\r\n \"{\\n\" +\r\n \" rotation = -rotation; \\n\" +\r\n \" mat3 transform = mat3(\\n\" +\r\n \" cos(rotation) * scale.x, sin(rotation) * scale.x, 0.0, \\n\" +\r\n \" -sin(rotation) * scale.y, cos(rotation) * scale.y, 0.0, \\n\" +\r\n \" offset.x, offset.y, 1.0); \\n\" +\r\n \" vec2 transformedTexCoords = (transform * vec3(fract(texCoords), 1.0)).xy; \\n\" +\r\n \" return transformedTexCoords; \\n\" +\r\n \"}\\n\\n\";\r\n\r\n fragmentShader += \"#ifdef USE_IBL_LIGHTING \\n\";\r\n fragmentShader += \"uniform vec2 gltf_iblFactor; \\n\";\r\n fragmentShader += \"#endif \\n\";\r\n fragmentShader += \"#ifdef USE_CUSTOM_LIGHT_COLOR \\n\";\r\n fragmentShader += \"uniform vec3 gltf_lightColor; \\n\";\r\n fragmentShader += \"#endif \\n\";\r\n\r\n fragmentShader += \"void main(void) \\n{\\n\";\r\n fragmentShader += fragmentShaderMain;\r\n\r\n // Add normal mapping to fragment shader\r\n if (hasNormals && !isUnlit) {\r\n fragmentShader += \" vec3 ng = normalize(v_normal);\\n\";\r\n fragmentShader +=\r\n \" vec3 positionWC = vec3(czm_inverseView * vec4(v_positionEC, 1.0));\\n\";\r\n if (defined(generatedMaterialValues.u_normalTexture)) {\r\n if (hasTangents) {\r\n // Read tangents from varying\r\n fragmentShader += \" vec3 t = normalize(v_tangent.xyz);\\n\";\r\n fragmentShader +=\r\n \" vec3 b = normalize(cross(ng, t) * v_tangent.w);\\n\";\r\n fragmentShader += \" mat3 tbn = mat3(t, b, ng);\\n\";\r\n fragmentShader +=\r\n \" vec3 n = texture2D(u_normalTexture, \" +\r\n normalTexCoord +\r\n \").rgb;\\n\";\r\n fragmentShader += \" n = normalize(tbn * (2.0 * n - 1.0));\\n\";\r\n } else {\r\n // Add standard derivatives extension\r\n fragmentShader =\r\n \"#ifdef GL_OES_standard_derivatives\\n\" +\r\n \"#extension GL_OES_standard_derivatives : enable\\n\" +\r\n \"#endif\\n\" +\r\n fragmentShader;\r\n // Compute tangents\r\n fragmentShader += \"#ifdef GL_OES_standard_derivatives\\n\";\r\n fragmentShader += \" vec3 pos_dx = dFdx(v_positionEC);\\n\";\r\n fragmentShader += \" vec3 pos_dy = dFdy(v_positionEC);\\n\";\r\n fragmentShader +=\r\n \" vec3 tex_dx = dFdx(vec3(\" + normalTexCoord + \",0.0));\\n\";\r\n fragmentShader +=\r\n \" vec3 tex_dy = dFdy(vec3(\" + normalTexCoord + \",0.0));\\n\";\r\n fragmentShader +=\r\n \" vec3 t = (tex_dy.t * pos_dx - tex_dx.t * pos_dy) / (tex_dx.s * tex_dy.t - tex_dy.s * tex_dx.t);\\n\";\r\n fragmentShader += \" t = normalize(t - ng * dot(ng, t));\\n\";\r\n fragmentShader += \" vec3 b = normalize(cross(ng, t));\\n\";\r\n fragmentShader += \" mat3 tbn = mat3(t, b, ng);\\n\";\r\n fragmentShader +=\r\n \" vec3 n = texture2D(u_normalTexture, \" +\r\n normalTexCoord +\r\n \").rgb;\\n\";\r\n fragmentShader += \" n = normalize(tbn * (2.0 * n - 1.0));\\n\";\r\n fragmentShader += \"#else\\n\";\r\n fragmentShader += \" vec3 n = ng;\\n\";\r\n fragmentShader += \"#endif\\n\";\r\n }\r\n } else {\r\n fragmentShader += \" vec3 n = ng;\\n\";\r\n }\r\n if (material.doubleSided) {\r\n fragmentShader += \" if (czm_backFacing())\\n\";\r\n fragmentShader += \" {\\n\";\r\n fragmentShader += \" n = -n;\\n\";\r\n fragmentShader += \" }\\n\";\r\n }\r\n }\r\n\r\n // Add base color to fragment shader\r\n if (defined(generatedMaterialValues.u_baseColorTexture)) {\r\n fragmentShader +=\r\n \" vec4 baseColorWithAlpha = SRGBtoLINEAR4(texture2D(u_baseColorTexture, \" +\r\n baseColorTexCoord +\r\n \"));\\n\";\r\n if (defined(generatedMaterialValues.u_baseColorFactor)) {\r\n fragmentShader += \" baseColorWithAlpha *= u_baseColorFactor;\\n\";\r\n }\r\n } else if (defined(generatedMaterialValues.u_baseColorFactor)) {\r\n fragmentShader += \" vec4 baseColorWithAlpha = u_baseColorFactor;\\n\";\r\n } else {\r\n fragmentShader += \" vec4 baseColorWithAlpha = vec4(1.0);\\n\";\r\n }\r\n\r\n if (hasVertexColors) {\r\n fragmentShader += \" baseColorWithAlpha *= v_vertexColor;\\n\";\r\n }\r\n\r\n fragmentShader += \" vec3 baseColor = baseColorWithAlpha.rgb;\\n\";\r\n\r\n if (hasNormals && !isUnlit) {\r\n if (useSpecGloss) {\r\n if (defined(generatedMaterialValues.u_specularGlossinessTexture)) {\r\n fragmentShader +=\r\n \" vec4 specularGlossiness = SRGBtoLINEAR4(texture2D(u_specularGlossinessTexture, \" +\r\n specularGlossinessTexCoord +\r\n \"));\\n\";\r\n fragmentShader += \" vec3 specular = specularGlossiness.rgb;\\n\";\r\n fragmentShader += \" float glossiness = specularGlossiness.a;\\n\";\r\n if (defined(generatedMaterialValues.u_specularFactor)) {\r\n fragmentShader += \" specular *= u_specularFactor;\\n\";\r\n }\r\n if (defined(generatedMaterialValues.u_glossinessFactor)) {\r\n fragmentShader += \" glossiness *= u_glossinessFactor;\\n\";\r\n }\r\n } else {\r\n if (defined(generatedMaterialValues.u_specularFactor)) {\r\n fragmentShader +=\r\n \" vec3 specular = clamp(u_specularFactor, vec3(0.0), vec3(1.0));\\n\";\r\n } else {\r\n fragmentShader += \" vec3 specular = vec3(1.0);\\n\";\r\n }\r\n if (defined(generatedMaterialValues.u_glossinessFactor)) {\r\n fragmentShader +=\r\n \" float glossiness = clamp(u_glossinessFactor, 0.0, 1.0);\\n\";\r\n } else {\r\n fragmentShader += \" float glossiness = 1.0;\\n\";\r\n }\r\n }\r\n if (defined(generatedMaterialValues.u_diffuseTexture)) {\r\n fragmentShader +=\r\n \" vec4 diffuse = SRGBtoLINEAR4(texture2D(u_diffuseTexture, \" +\r\n diffuseTexCoord +\r\n \"));\\n\";\r\n if (defined(generatedMaterialValues.u_diffuseFactor)) {\r\n fragmentShader += \" diffuse *= u_diffuseFactor;\\n\";\r\n }\r\n } else if (defined(generatedMaterialValues.u_diffuseFactor)) {\r\n fragmentShader +=\r\n \" vec4 diffuse = clamp(u_diffuseFactor, vec4(0.0), vec4(1.0));\\n\";\r\n } else {\r\n fragmentShader += \" vec4 diffuse = vec4(1.0);\\n\";\r\n }\r\n } else if (defined(generatedMaterialValues.u_metallicRoughnessTexture)) {\r\n fragmentShader +=\r\n \" vec3 metallicRoughness = texture2D(u_metallicRoughnessTexture, \" +\r\n metallicRoughnessTexCoord +\r\n \").rgb;\\n\";\r\n fragmentShader +=\r\n \" float metalness = clamp(metallicRoughness.b, 0.0, 1.0);\\n\";\r\n fragmentShader +=\r\n \" float roughness = clamp(metallicRoughness.g, 0.04, 1.0);\\n\";\r\n if (defined(generatedMaterialValues.u_metallicFactor)) {\r\n fragmentShader += \" metalness *= u_metallicFactor;\\n\";\r\n }\r\n if (defined(generatedMaterialValues.u_roughnessFactor)) {\r\n fragmentShader += \" roughness *= u_roughnessFactor;\\n\";\r\n }\r\n } else {\r\n if (defined(generatedMaterialValues.u_metallicFactor)) {\r\n fragmentShader +=\r\n \" float metalness = clamp(u_metallicFactor, 0.0, 1.0);\\n\";\r\n } else {\r\n fragmentShader += \" float metalness = 1.0;\\n\";\r\n }\r\n if (defined(generatedMaterialValues.u_roughnessFactor)) {\r\n fragmentShader +=\r\n \" float roughness = clamp(u_roughnessFactor, 0.04, 1.0);\\n\";\r\n } else {\r\n fragmentShader += \" float roughness = 1.0;\\n\";\r\n }\r\n }\r\n\r\n fragmentShader += \" vec3 v = -normalize(v_positionEC);\\n\";\r\n\r\n // Generate fragment shader's lighting block\r\n fragmentShader += \"#ifndef USE_CUSTOM_LIGHT_COLOR \\n\";\r\n fragmentShader += \" vec3 lightColorHdr = czm_lightColorHdr;\\n\";\r\n fragmentShader += \"#else \\n\";\r\n fragmentShader += \" vec3 lightColorHdr = gltf_lightColor;\\n\";\r\n fragmentShader += \"#endif \\n\";\r\n fragmentShader += \" vec3 l = normalize(czm_lightDirectionEC);\\n\";\r\n fragmentShader += \" vec3 h = normalize(v + l);\\n\";\r\n fragmentShader += \" float NdotL = clamp(dot(n, l), 0.001, 1.0);\\n\";\r\n fragmentShader += \" float NdotV = abs(dot(n, v)) + 0.001;\\n\";\r\n fragmentShader += \" float NdotH = clamp(dot(n, h), 0.0, 1.0);\\n\";\r\n fragmentShader += \" float LdotH = clamp(dot(l, h), 0.0, 1.0);\\n\";\r\n fragmentShader += \" float VdotH = clamp(dot(v, h), 0.0, 1.0);\\n\";\r\n fragmentShader += \" vec3 f0 = vec3(0.04);\\n\";\r\n // Whether the material uses metallic-roughness or specular-glossiness changes how the BRDF inputs are computed.\r\n // It does not change the implementation of the BRDF itself.\r\n if (useSpecGloss) {\r\n fragmentShader += \" float roughness = 1.0 - glossiness;\\n\";\r\n fragmentShader +=\r\n \" vec3 diffuseColor = diffuse.rgb * (1.0 - max(max(specular.r, specular.g), specular.b));\\n\";\r\n fragmentShader += \" vec3 specularColor = specular;\\n\";\r\n } else {\r\n fragmentShader +=\r\n \" vec3 diffuseColor = baseColor * (1.0 - metalness) * (1.0 - f0);\\n\";\r\n fragmentShader +=\r\n \" vec3 specularColor = mix(f0, baseColor, metalness);\\n\";\r\n }\r\n\r\n fragmentShader += \" float alpha = roughness * roughness;\\n\";\r\n fragmentShader +=\r\n \" float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);\\n\";\r\n fragmentShader +=\r\n \" vec3 r90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0));\\n\";\r\n fragmentShader += \" vec3 r0 = specularColor.rgb;\\n\";\r\n\r\n fragmentShader += \" vec3 F = fresnelSchlick2(r0, r90, VdotH);\\n\";\r\n fragmentShader +=\r\n \" float G = smithVisibilityGGX(alpha, NdotL, NdotV);\\n\";\r\n fragmentShader += \" float D = GGX(alpha, NdotH);\\n\";\r\n\r\n fragmentShader +=\r\n \" vec3 diffuseContribution = (1.0 - F) * lambertianDiffuse(diffuseColor);\\n\";\r\n fragmentShader +=\r\n \" vec3 specularContribution = F * G * D / (4.0 * NdotL * NdotV);\\n\";\r\n fragmentShader +=\r\n \" vec3 color = NdotL * lightColorHdr * (diffuseContribution + specularContribution);\\n\";\r\n\r\n // Use the procedural IBL if there are no environment maps\r\n fragmentShader +=\r\n \"#if defined(USE_IBL_LIGHTING) && !defined(DIFFUSE_IBL) && !defined(SPECULAR_IBL) \\n\";\r\n\r\n fragmentShader +=\r\n \" vec3 r = normalize(czm_inverseViewRotation * normalize(reflect(v, n)));\\n\";\r\n // Figure out if the reflection vector hits the ellipsoid\r\n fragmentShader += \" float vertexRadius = length(positionWC);\\n\";\r\n fragmentShader +=\r\n \" float horizonDotNadir = 1.0 - min(1.0, czm_ellipsoidRadii.x / vertexRadius);\\n\";\r\n fragmentShader +=\r\n \" float reflectionDotNadir = dot(r, normalize(positionWC));\\n\";\r\n // Flipping the X vector is a cheap way to get the inverse of czm_temeToPseudoFixed, since that's a rotation about Z.\r\n fragmentShader += \" r.x = -r.x;\\n\";\r\n fragmentShader += \" r = -normalize(czm_temeToPseudoFixed * r);\\n\";\r\n fragmentShader += \" r.x = -r.x;\\n\";\r\n\r\n fragmentShader += \" float inverseRoughness = 1.04 - roughness;\\n\";\r\n fragmentShader += \" inverseRoughness *= inverseRoughness;\\n\";\r\n fragmentShader +=\r\n \" vec3 sceneSkyBox = textureCube(czm_environmentMap, r).rgb * inverseRoughness;\\n\";\r\n\r\n fragmentShader += \" float atmosphereHeight = 0.05;\\n\";\r\n fragmentShader +=\r\n \" float blendRegionSize = 0.1 * ((1.0 - inverseRoughness) * 8.0 + 1.1 - horizonDotNadir);\\n\";\r\n fragmentShader += \" float blendRegionOffset = roughness * -1.0;\\n\";\r\n fragmentShader +=\r\n \" float farAboveHorizon = clamp(horizonDotNadir - blendRegionSize * 0.5 + blendRegionOffset, 1.0e-10 - blendRegionSize, 0.99999);\\n\";\r\n fragmentShader +=\r\n \" float aroundHorizon = clamp(horizonDotNadir + blendRegionSize * 0.5, 1.0e-10 - blendRegionSize, 0.99999);\\n\";\r\n fragmentShader +=\r\n \" float farBelowHorizon = clamp(horizonDotNadir + blendRegionSize * 1.5, 1.0e-10 - blendRegionSize, 0.99999);\\n\";\r\n fragmentShader +=\r\n \" float smoothstepHeight = smoothstep(0.0, atmosphereHeight, horizonDotNadir);\\n\";\r\n\r\n fragmentShader +=\r\n \" vec3 belowHorizonColor = mix(vec3(0.1, 0.15, 0.25), vec3(0.4, 0.7, 0.9), smoothstepHeight);\\n\";\r\n fragmentShader += \" vec3 nadirColor = belowHorizonColor * 0.5;\\n\";\r\n fragmentShader +=\r\n \" vec3 aboveHorizonColor = mix(vec3(0.9, 1.0, 1.2), belowHorizonColor, roughness * 0.5);\\n\";\r\n fragmentShader +=\r\n \" vec3 blueSkyColor = mix(vec3(0.18, 0.26, 0.48), aboveHorizonColor, reflectionDotNadir * inverseRoughness * 0.5 + 0.75);\\n\";\r\n fragmentShader +=\r\n \" vec3 zenithColor = mix(blueSkyColor, sceneSkyBox, smoothstepHeight);\\n\";\r\n\r\n fragmentShader += \" vec3 blueSkyDiffuseColor = vec3(0.7, 0.85, 0.9);\\n\";\r\n fragmentShader +=\r\n \" float diffuseIrradianceFromEarth = (1.0 - horizonDotNadir) * (reflectionDotNadir * 0.25 + 0.75) * smoothstepHeight;\\n\";\r\n fragmentShader +=\r\n \" float diffuseIrradianceFromSky = (1.0 - smoothstepHeight) * (1.0 - (reflectionDotNadir * 0.25 + 0.25));\\n\";\r\n fragmentShader +=\r\n \" vec3 diffuseIrradiance = blueSkyDiffuseColor * clamp(diffuseIrradianceFromEarth + diffuseIrradianceFromSky, 0.0, 1.0);\\n\";\r\n\r\n fragmentShader +=\r\n \" float notDistantRough = (1.0 - horizonDotNadir * roughness * 0.8);\\n\";\r\n fragmentShader +=\r\n \" vec3 specularIrradiance = mix(zenithColor, aboveHorizonColor, smoothstep(farAboveHorizon, aroundHorizon, reflectionDotNadir) * notDistantRough);\\n\";\r\n fragmentShader +=\r\n \" specularIrradiance = mix(specularIrradiance, belowHorizonColor, smoothstep(aroundHorizon, farBelowHorizon, reflectionDotNadir) * inverseRoughness);\\n\";\r\n fragmentShader +=\r\n \" specularIrradiance = mix(specularIrradiance, nadirColor, smoothstep(farBelowHorizon, 1.0, reflectionDotNadir) * inverseRoughness);\\n\";\r\n\r\n // Luminance model from page 40 of http://silviojemma.com/public/papers/lighting/spherical-harmonic-lighting.pdf\r\n fragmentShader += \"#ifdef USE_SUN_LUMINANCE \\n\";\r\n // Angle between sun and zenith\r\n fragmentShader +=\r\n \" float LdotZenith = clamp(dot(normalize(czm_inverseViewRotation * l), normalize(positionWC * -1.0)), 0.001, 1.0);\\n\";\r\n fragmentShader += \" float S = acos(LdotZenith);\\n\";\r\n // Angle between zenith and current pixel\r\n fragmentShader +=\r\n \" float NdotZenith = clamp(dot(normalize(czm_inverseViewRotation * n), normalize(positionWC * -1.0)), 0.001, 1.0);\\n\";\r\n // Angle between sun and current pixel\r\n fragmentShader += \" float gamma = acos(NdotL);\\n\";\r\n fragmentShader +=\r\n \" float numerator = ((0.91 + 10.0 * exp(-3.0 * gamma) + 0.45 * pow(NdotL, 2.0)) * (1.0 - exp(-0.32 / NdotZenith)));\\n\";\r\n fragmentShader +=\r\n \" float denominator = (0.91 + 10.0 * exp(-3.0 * S) + 0.45 * pow(LdotZenith,2.0)) * (1.0 - exp(-0.32));\\n\";\r\n fragmentShader +=\r\n \" float luminance = gltf_luminanceAtZenith * (numerator / denominator);\\n\";\r\n fragmentShader += \"#endif \\n\";\r\n\r\n fragmentShader +=\r\n \" vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, roughness)).rg;\\n\";\r\n fragmentShader +=\r\n \" vec3 IBLColor = (diffuseIrradiance * diffuseColor * gltf_iblFactor.x) + (specularIrradiance * SRGBtoLINEAR3(specularColor * brdfLut.x + brdfLut.y) * gltf_iblFactor.y);\\n\";\r\n\r\n fragmentShader +=\r\n \" float maximumComponent = max(max(lightColorHdr.x, lightColorHdr.y), lightColorHdr.z);\\n\";\r\n fragmentShader +=\r\n \" vec3 lightColor = lightColorHdr / max(maximumComponent, 1.0);\\n\";\r\n fragmentShader += \" IBLColor *= lightColor;\\n\";\r\n\r\n fragmentShader += \"#ifdef USE_SUN_LUMINANCE \\n\";\r\n fragmentShader += \" color += IBLColor * luminance;\\n\";\r\n fragmentShader += \"#else \\n\";\r\n fragmentShader += \" color += IBLColor; \\n\";\r\n fragmentShader += \"#endif \\n\";\r\n\r\n // Environment maps were provided, use them for IBL\r\n fragmentShader += \"#elif defined(DIFFUSE_IBL) || defined(SPECULAR_IBL) \\n\";\r\n fragmentShader +=\r\n \" const mat3 yUpToZUp = mat3(-1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, 1.0, 0.0); \\n\";\r\n fragmentShader +=\r\n \" vec3 cubeDir = normalize(yUpToZUp * gltf_iblReferenceFrameMatrix * normalize(reflect(-v, n))); \\n\";\r\n\r\n fragmentShader += \"#ifdef DIFFUSE_IBL \\n\";\r\n fragmentShader += \"#ifdef CUSTOM_SPHERICAL_HARMONICS \\n\";\r\n fragmentShader +=\r\n \" vec3 diffuseIrradiance = czm_sphericalHarmonics(cubeDir, gltf_sphericalHarmonicCoefficients); \\n\";\r\n fragmentShader += \"#else \\n\";\r\n fragmentShader +=\r\n \" vec3 diffuseIrradiance = czm_sphericalHarmonics(cubeDir, czm_sphericalHarmonicCoefficients); \\n\";\r\n fragmentShader += \"#endif \\n\";\r\n fragmentShader += \"#else \\n\";\r\n fragmentShader += \" vec3 diffuseIrradiance = vec3(0.0); \\n\";\r\n fragmentShader += \"#endif \\n\";\r\n\r\n fragmentShader += \"#ifdef SPECULAR_IBL \\n\";\r\n fragmentShader +=\r\n \" vec2 brdfLut = texture2D(czm_brdfLut, vec2(NdotV, roughness)).rg;\\n\";\r\n fragmentShader += \"#ifdef CUSTOM_SPECULAR_IBL \\n\";\r\n fragmentShader +=\r\n \" vec3 specularIBL = czm_sampleOctahedralProjection(gltf_specularMap, gltf_specularMapSize, cubeDir, roughness * gltf_maxSpecularLOD, gltf_maxSpecularLOD);\\n\";\r\n fragmentShader += \"#else \\n\";\r\n fragmentShader +=\r\n \" vec3 specularIBL = czm_sampleOctahedralProjection(czm_specularEnvironmentMaps, czm_specularEnvironmentMapSize, cubeDir, roughness * czm_specularEnvironmentMapsMaximumLOD, czm_specularEnvironmentMapsMaximumLOD);\\n\";\r\n fragmentShader += \"#endif \\n\";\r\n fragmentShader += \" specularIBL *= F * brdfLut.x + brdfLut.y;\\n\";\r\n fragmentShader += \"#else \\n\";\r\n fragmentShader += \" vec3 specularIBL = vec3(0.0); \\n\";\r\n fragmentShader += \"#endif \\n\";\r\n\r\n fragmentShader +=\r\n \" color += diffuseIrradiance * diffuseColor + specularColor * specularIBL;\\n\";\r\n\r\n fragmentShader += \"#endif \\n\";\r\n } else {\r\n fragmentShader += \" vec3 color = baseColor;\\n\";\r\n }\r\n\r\n // Ignore occlusion and emissive when unlit\r\n if (!isUnlit) {\r\n if (defined(generatedMaterialValues.u_occlusionTexture)) {\r\n fragmentShader +=\r\n \" color *= texture2D(u_occlusionTexture, \" +\r\n occlusionTexCoord +\r\n \").r;\\n\";\r\n }\r\n if (defined(generatedMaterialValues.u_emissiveTexture)) {\r\n fragmentShader +=\r\n \" vec3 emissive = SRGBtoLINEAR3(texture2D(u_emissiveTexture, \" +\r\n emissiveTexCoord +\r\n \").rgb);\\n\";\r\n if (defined(generatedMaterialValues.u_emissiveFactor)) {\r\n fragmentShader += \" emissive *= u_emissiveFactor;\\n\";\r\n }\r\n fragmentShader += \" color += emissive;\\n\";\r\n } else if (defined(generatedMaterialValues.u_emissiveFactor)) {\r\n fragmentShader += \" color += u_emissiveFactor;\\n\";\r\n }\r\n }\r\n\r\n if (!isUnlit) {\r\n fragmentShader += \" color = applyTonemapping(color);\\n\";\r\n }\r\n\r\n fragmentShader += \" color = LINEARtoSRGB(color);\\n\";\r\n\r\n if (hasOutline) {\r\n fragmentShader += \" float outlineness = max(\\n\";\r\n fragmentShader +=\r\n \" texture2D(u_outlineTexture, vec2(v_outlineCoordinates.x, 0.5)).r,\\n\";\r\n fragmentShader += \" max(\\n\";\r\n fragmentShader +=\r\n \" texture2D(u_outlineTexture, vec2(v_outlineCoordinates.y, 0.5)).r,\\n\";\r\n fragmentShader +=\r\n \" texture2D(u_outlineTexture, vec2(v_outlineCoordinates.z, 0.5)).r));\\n\";\r\n fragmentShader +=\r\n \" color = mix(color, vec3(0.0, 0.0, 0.0), outlineness);\\n\";\r\n }\r\n\r\n if (defined(alphaMode)) {\r\n if (alphaMode === \"MASK\") {\r\n fragmentShader += \" if (baseColorWithAlpha.a < u_alphaCutoff) {\\n\";\r\n fragmentShader += \" discard;\\n\";\r\n fragmentShader += \" }\\n\";\r\n fragmentShader += \" gl_FragColor = vec4(color, 1.0);\\n\";\r\n } else if (alphaMode === \"BLEND\") {\r\n fragmentShader +=\r\n \" gl_FragColor = vec4(color, baseColorWithAlpha.a);\\n\";\r\n } else {\r\n fragmentShader += \" gl_FragColor = vec4(color, 1.0);\\n\";\r\n }\r\n } else {\r\n fragmentShader += \" gl_FragColor = vec4(color, 1.0);\\n\";\r\n }\r\n\r\n fragmentShader += \"}\\n\";\r\n\r\n // Add shaders\r\n var vertexShaderId = addToArray(shaders, {\r\n type: WebGLConstants.VERTEX_SHADER,\r\n extras: {\r\n _pipeline: {\r\n source: vertexShader,\r\n extension: \".glsl\",\r\n },\r\n },\r\n });\r\n\r\n var fragmentShaderId = addToArray(shaders, {\r\n type: WebGLConstants.FRAGMENT_SHADER,\r\n extras: {\r\n _pipeline: {\r\n source: fragmentShader,\r\n extension: \".glsl\",\r\n },\r\n },\r\n });\r\n\r\n // Add program\r\n var programId = addToArray(programs, {\r\n fragmentShader: fragmentShaderId,\r\n vertexShader: vertexShaderId,\r\n });\r\n\r\n var techniqueId = addToArray(techniques, {\r\n attributes: techniqueAttributes,\r\n program: programId,\r\n uniforms: techniqueUniforms,\r\n });\r\n\r\n return techniqueId;\r\n}\r\n\r\nfunction getPBRValueType(paramName) {\r\n if (paramName.indexOf(\"Offset\") !== -1) {\r\n return WebGLConstants.FLOAT_VEC2;\r\n } else if (paramName.indexOf(\"Rotation\") !== -1) {\r\n return WebGLConstants.FLOAT;\r\n } else if (paramName.indexOf(\"Scale\") !== -1) {\r\n return WebGLConstants.FLOAT_VEC2;\r\n } else if (paramName.indexOf(\"Texture\") !== -1) {\r\n return WebGLConstants.SAMPLER_2D;\r\n }\r\n\r\n switch (paramName) {\r\n case \"u_baseColorFactor\":\r\n return WebGLConstants.FLOAT_VEC4;\r\n case \"u_metallicFactor\":\r\n return WebGLConstants.FLOAT;\r\n case \"u_roughnessFactor\":\r\n return WebGLConstants.FLOAT;\r\n case \"u_emissiveFactor\":\r\n return WebGLConstants.FLOAT_VEC3;\r\n // Specular Glossiness Types\r\n case \"u_diffuseFactor\":\r\n return WebGLConstants.FLOAT_VEC4;\r\n case \"u_specularFactor\":\r\n return WebGLConstants.FLOAT_VEC3;\r\n case \"u_glossinessFactor\":\r\n return WebGLConstants.FLOAT;\r\n }\r\n}\r\nexport default processPbrMaterials;\r\n","/**\r\n * Describes a renderable batch of geometry.\r\n *\r\n * @alias Vector3DTileBatch\r\n * @constructor\r\n *\r\n * @param {Object} options An object with the following properties:\r\n * @param {Number} options.offset The offset of the batch into the indices buffer.\r\n * @param {Number} options.count The number of indices in the batch.\r\n * @param {Color} options.color The color of the geometry in the batch.\r\n * @param {Number[]} options.batchIds An array where each element is the batch id of the geometry in the batch.\r\n *\r\n * @private\r\n */\r\nfunction Vector3DTileBatch(options) {\r\n /**\r\n * The offset of the batch into the indices buffer.\r\n * @type {Number}\r\n */\r\n this.offset = options.offset;\r\n /**\r\n * The number of indices in the batch.\r\n * @type {Number}\r\n */\r\n this.count = options.count;\r\n /**\r\n * The color of the geometry in the batch.\r\n * @type {Color}\r\n */\r\n this.color = options.color;\r\n /**\r\n * An array where each element is the batch id of the geometry in the batch.\r\n * @type {Number[]}\r\n */\r\n this.batchIds = options.batchIds;\r\n}\r\nexport default Vector3DTileBatch;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position;\\n\\\nattribute float a_batchId;\\n\\\nuniform mat4 u_modifiedModelViewProjection;\\n\\\nvoid main()\\n\\\n{\\n\\\ngl_Position = czm_depthClamp(u_modifiedModelViewProjection * vec4(position, 1.0));\\n\\\n}\\n\\\n\";\n","// JavaScript Expression Parser (JSEP) 0.3.1\r\n// JSEP may be freely distributed under the MIT License\r\n// http://jsep.from.so/\r\n\r\nvar tmp = {};\r\n\r\n/*global module: true, exports: true, console: true */\r\n(function (root) {\r\n\t'use strict';\r\n\t// Node Types\r\n\t// ----------\r\n\r\n\t// This is the full set of types that any JSEP node can be.\r\n\t// Store them here to save space when minified\r\n\tvar COMPOUND = 'Compound',\r\n\t\tIDENTIFIER = 'Identifier',\r\n\t\tMEMBER_EXP = 'MemberExpression',\r\n\t\tLITERAL = 'Literal',\r\n\t\tTHIS_EXP = 'ThisExpression',\r\n\t\tCALL_EXP = 'CallExpression',\r\n\t\tUNARY_EXP = 'UnaryExpression',\r\n\t\tBINARY_EXP = 'BinaryExpression',\r\n\t\tLOGICAL_EXP = 'LogicalExpression',\r\n\t\tCONDITIONAL_EXP = 'ConditionalExpression',\r\n\t\tARRAY_EXP = 'ArrayExpression',\r\n\r\n\t\tPERIOD_CODE = 46, // '.'\r\n\t\tCOMMA_CODE = 44, // ','\r\n\t\tSQUOTE_CODE = 39, // single quote\r\n\t\tDQUOTE_CODE = 34, // double quotes\r\n\t\tOPAREN_CODE = 40, // (\r\n\t\tCPAREN_CODE = 41, // )\r\n\t\tOBRACK_CODE = 91, // [\r\n\t\tCBRACK_CODE = 93, // ]\r\n\t\tQUMARK_CODE = 63, // ?\r\n\t\tSEMCOL_CODE = 59, // ;\r\n\t\tCOLON_CODE = 58, // :\r\n\r\n\t\tthrowError = function(message, index) {\r\n\t\t\tvar error = new Error(message + ' at character ' + index);\r\n\t\t\terror.index = index;\r\n\t\t\terror.description = message;\r\n\t\t\tthrow error;\r\n\t\t},\r\n\r\n\t// Operations\r\n\t// ----------\r\n\r\n\t// Set `t` to `true` to save space (when minified, not gzipped)\r\n\t\tt = true,\r\n\t// Use a quickly-accessible map to store all of the unary operators\r\n\t// Values are set to `true` (it really doesn't matter)\r\n\t\tunary_ops = {'-': t, '!': t, '~': t, '+': t},\r\n\t// Also use a map for the binary operations but set their values to their\r\n\t// binary precedence for quick reference:\r\n\t// see [Order of operations](http://en.wikipedia.org/wiki/Order_of_operations#Programming_language)\r\n\t\tbinary_ops = {\r\n\t\t\t'||': 1, '&&': 2, '|': 3, '^': 4, '&': 5,\r\n\t\t\t'==': 6, '!=': 6, '===': 6, '!==': 6,\r\n\t\t\t'<': 7, '>': 7, '<=': 7, '>=': 7,\r\n\t\t\t'<<':8, '>>': 8, '>>>': 8,\r\n\t\t\t'+': 9, '-': 9,\r\n\t\t\t'*': 10, '/': 10, '%': 10\r\n\t\t},\r\n\t// Get return the longest key length of any object\r\n\t\tgetMaxKeyLen = function(obj) {\r\n\t\t\tvar max_len = 0, len;\r\n\t\t\tfor(var key in obj) {\r\n\t\t\t\tif((len = key.length) > max_len && obj.hasOwnProperty(key)) {\r\n\t\t\t\t\tmax_len = len;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\treturn max_len;\r\n\t\t},\r\n\t\tmax_unop_len = getMaxKeyLen(unary_ops),\r\n\t\tmax_binop_len = getMaxKeyLen(binary_ops),\r\n\t// Literals\r\n\t// ----------\r\n\t// Store the values to return for the various literals we may encounter\r\n\t\tliterals = {\r\n\t\t\t'true': true,\r\n\t\t\t'false': false,\r\n\t\t\t'null': null\r\n\t\t},\r\n\t// Except for `this`, which is special. This could be changed to something like `'self'` as well\r\n\t\tthis_str = 'this',\r\n\t// Returns the precedence of a binary operator or `0` if it isn't a binary operator\r\n\t\tbinaryPrecedence = function(op_val) {\r\n\t\t\treturn binary_ops[op_val] || 0;\r\n\t\t},\r\n\t// Utility function (gets called from multiple places)\r\n\t// Also note that `a && b` and `a || b` are *logical* expressions, not binary expressions\r\n\t\tcreateBinaryExpression = function (operator, left, right) {\r\n\t\t\tvar type = (operator === '||' || operator === '&&') ? LOGICAL_EXP : BINARY_EXP;\r\n\t\t\treturn {\r\n\t\t\t\ttype: type,\r\n\t\t\t\toperator: operator,\r\n\t\t\t\tleft: left,\r\n\t\t\t\tright: right\r\n\t\t\t};\r\n\t\t},\r\n\t\t// `ch` is a character code in the next three functions\r\n\t\tisDecimalDigit = function(ch) {\r\n\t\t\treturn (ch >= 48 && ch <= 57); // 0...9\r\n\t\t},\r\n\t\tisIdentifierStart = function(ch) {\r\n\t\t\treturn (ch === 36) || (ch === 95) || // `$` and `_`\r\n\t\t\t\t\t(ch >= 65 && ch <= 90) || // A...Z\r\n\t\t\t\t\t(ch >= 97 && ch <= 122) || // a...z\r\n (ch >= 128 && !binary_ops[String.fromCharCode(ch)]); // any non-ASCII that is not an operator\r\n\t\t},\r\n\t\tisIdentifierPart = function(ch) {\r\n\t\t\treturn (ch === 36) || (ch === 95) || // `$` and `_`\r\n\t\t\t\t\t(ch >= 65 && ch <= 90) || // A...Z\r\n\t\t\t\t\t(ch >= 97 && ch <= 122) || // a...z\r\n\t\t\t\t\t(ch >= 48 && ch <= 57) || // 0...9\r\n (ch >= 128 && !binary_ops[String.fromCharCode(ch)]); // any non-ASCII that is not an operator\r\n\t\t},\r\n\r\n\t\t// Parsing\r\n\t\t// -------\r\n\t\t// `expr` is a string with the passed in expression\r\n\t\tjsep = function(expr) {\r\n\t\t\t// `index` stores the character number we are currently at while `length` is a constant\r\n\t\t\t// All of the gobbles below will modify `index` as we move along\r\n\t\t\tvar index = 0,\r\n\t\t\t\tcharAtFunc = expr.charAt,\r\n\t\t\t\tcharCodeAtFunc = expr.charCodeAt,\r\n\t\t\t\texprI = function(i) { return charAtFunc.call(expr, i); },\r\n\t\t\t\texprICode = function(i) { return charCodeAtFunc.call(expr, i); },\r\n\t\t\t\tlength = expr.length,\r\n\r\n\t\t\t\t// Push `index` up to the next non-space character\r\n\t\t\t\tgobbleSpaces = function() {\r\n\t\t\t\t\tvar ch = exprICode(index);\r\n\t\t\t\t\t// space or tab\r\n\t\t\t\t\twhile(ch === 32 || ch === 9) {\r\n\t\t\t\t\t\tch = exprICode(++index);\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// The main parsing function. Much of this code is dedicated to ternary expressions\r\n\t\t\t\tgobbleExpression = function() {\r\n\t\t\t\t\tvar test = gobbleBinaryExpression(),\r\n\t\t\t\t\t\tconsequent, alternate;\r\n\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\tif(exprICode(index) === QUMARK_CODE) {\r\n\t\t\t\t\t\t// Ternary expression: test ? consequent : alternate\r\n\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t\tconsequent = gobbleExpression();\r\n\t\t\t\t\t\tif(!consequent) {\r\n\t\t\t\t\t\t\tthrowError('Expected expression', index);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\t\tif(exprICode(index) === COLON_CODE) {\r\n\t\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t\t\talternate = gobbleExpression();\r\n\t\t\t\t\t\t\tif(!alternate) {\r\n\t\t\t\t\t\t\t\tthrowError('Expected expression', index);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\t\ttype: CONDITIONAL_EXP,\r\n\t\t\t\t\t\t\t\ttest: test,\r\n\t\t\t\t\t\t\t\tconsequent: consequent,\r\n\t\t\t\t\t\t\t\talternate: alternate\r\n\t\t\t\t\t\t\t};\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tthrowError('Expected :', index);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\treturn test;\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// Search for the operation portion of the string (e.g. `+`, `===`)\r\n\t\t\t\t// Start by taking the longest possible binary operations (3 characters: `===`, `!==`, `>>>`)\r\n\t\t\t\t// and move down from 3 to 2 to 1 character until a matching binary operation is found\r\n\t\t\t\t// then, return that binary operation\r\n\t\t\t\tgobbleBinaryOp = function() {\r\n\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\tvar biop, to_check = expr.substr(index, max_binop_len), tc_len = to_check.length;\r\n\t\t\t\t\twhile(tc_len > 0) {\r\n\t\t\t\t\t\tif(binary_ops.hasOwnProperty(to_check)) {\r\n\t\t\t\t\t\t\tindex += tc_len;\r\n\t\t\t\t\t\t\treturn to_check;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tto_check = to_check.substr(0, --tc_len);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn false;\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// This function is responsible for gobbling an individual expression,\r\n\t\t\t\t// e.g. `1`, `1+2`, `a+(b*2)-Math.sqrt(2)`\r\n\t\t\t\tgobbleBinaryExpression = function() {\r\n\t\t\t\t\tvar ch_i, node, biop, prec, stack, biop_info, left, right, i;\r\n\r\n\t\t\t\t\t// First, try to get the leftmost thing\r\n\t\t\t\t\t// Then, check to see if there's a binary operator operating on that leftmost thing\r\n\t\t\t\t\tleft = gobbleToken();\r\n\t\t\t\t\tbiop = gobbleBinaryOp();\r\n\r\n\t\t\t\t\t// If there wasn't a binary operator, just return the leftmost node\r\n\t\t\t\t\tif(!biop) {\r\n\t\t\t\t\t\treturn left;\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\t// Otherwise, we need to start a stack to properly place the binary operations in their\r\n\t\t\t\t\t// precedence structure\r\n\t\t\t\t\tbiop_info = { value: biop, prec: binaryPrecedence(biop)};\r\n\r\n\t\t\t\t\tright = gobbleToken();\r\n\t\t\t\t\tif(!right) {\r\n\t\t\t\t\t\tthrowError(\"Expected expression after \" + biop, index);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tstack = [left, biop_info, right];\r\n\r\n\t\t\t\t\t// Properly deal with precedence using [recursive descent](http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm)\r\n\t\t\t\t\twhile((biop = gobbleBinaryOp())) {\r\n\t\t\t\t\t\tprec = binaryPrecedence(biop);\r\n\r\n\t\t\t\t\t\tif(prec === 0) {\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tbiop_info = { value: biop, prec: prec };\r\n\r\n\t\t\t\t\t\t// Reduce: make a binary expression from the three topmost entries.\r\n\t\t\t\t\t\twhile ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) {\r\n\t\t\t\t\t\t\tright = stack.pop();\r\n\t\t\t\t\t\t\tbiop = stack.pop().value;\r\n\t\t\t\t\t\t\tleft = stack.pop();\r\n\t\t\t\t\t\t\tnode = createBinaryExpression(biop, left, right);\r\n\t\t\t\t\t\t\tstack.push(node);\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\tnode = gobbleToken();\r\n\t\t\t\t\t\tif(!node) {\r\n\t\t\t\t\t\t\tthrowError(\"Expected expression after \" + biop, index);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tstack.push(biop_info, node);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\ti = stack.length - 1;\r\n\t\t\t\t\tnode = stack[i];\r\n\t\t\t\t\twhile(i > 1) {\r\n\t\t\t\t\t\tnode = createBinaryExpression(stack[i - 1].value, stack[i - 2], node);\r\n\t\t\t\t\t\ti -= 2;\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn node;\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// An individual part of a binary expression:\r\n\t\t\t\t// e.g. `foo.bar(baz)`, `1`, `\"abc\"`, `(a % 2)` (because it's in parenthesis)\r\n\t\t\t\tgobbleToken = function() {\r\n\t\t\t\t\tvar ch, to_check, tc_len;\r\n\r\n\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\tch = exprICode(index);\r\n\r\n\t\t\t\t\tif(isDecimalDigit(ch) || ch === PERIOD_CODE) {\r\n\t\t\t\t\t\t// Char code 46 is a dot `.` which can start off a numeric literal\r\n\t\t\t\t\t\treturn gobbleNumericLiteral();\r\n\t\t\t\t\t} else if(ch === SQUOTE_CODE || ch === DQUOTE_CODE) {\r\n\t\t\t\t\t\t// Single or double quotes\r\n\t\t\t\t\t\treturn gobbleStringLiteral();\r\n\t\t\t\t\t} else if(isIdentifierStart(ch) || ch === OPAREN_CODE) { // open parenthesis\r\n\t\t\t\t\t\t// `foo`, `bar.baz`\r\n\t\t\t\t\t\treturn gobbleVariable();\r\n\t\t\t\t\t} else if (ch === OBRACK_CODE) {\r\n\t\t\t\t\t\treturn gobbleArray();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tto_check = expr.substr(index, max_unop_len);\r\n\t\t\t\t\t\ttc_len = to_check.length;\r\n\t\t\t\t\t\twhile(tc_len > 0) {\r\n\t\t\t\t\t\t\tif(unary_ops.hasOwnProperty(to_check)) {\r\n\t\t\t\t\t\t\t\tindex += tc_len;\r\n\t\t\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\t\t\ttype: UNARY_EXP,\r\n\t\t\t\t\t\t\t\t\toperator: to_check,\r\n\t\t\t\t\t\t\t\t\targument: gobbleToken(),\r\n\t\t\t\t\t\t\t\t\tprefix: true\r\n\t\t\t\t\t\t\t\t};\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tto_check = to_check.substr(0, --tc_len);\r\n\t\t\t\t\t\t}\r\n\r\n\t\t\t\t\t\treturn false;\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\t\t\t\t// Parse simple numeric literals: `12`, `3.4`, `.5`. Do this by using a string to\r\n\t\t\t\t// keep track of everything in the numeric literal and then calling `parseFloat` on that string\r\n\t\t\t\tgobbleNumericLiteral = function() {\r\n\t\t\t\t\tvar number = '', ch, chCode;\r\n\t\t\t\t\twhile(isDecimalDigit(exprICode(index))) {\r\n\t\t\t\t\t\tnumber += exprI(index++);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(exprICode(index) === PERIOD_CODE) { // can start with a decimal marker\r\n\t\t\t\t\t\tnumber += exprI(index++);\r\n\r\n\t\t\t\t\t\twhile(isDecimalDigit(exprICode(index))) {\r\n\t\t\t\t\t\t\tnumber += exprI(index++);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tch = exprI(index);\r\n\t\t\t\t\tif(ch === 'e' || ch === 'E') { // exponent marker\r\n\t\t\t\t\t\tnumber += exprI(index++);\r\n\t\t\t\t\t\tch = exprI(index);\r\n\t\t\t\t\t\tif(ch === '+' || ch === '-') { // exponent sign\r\n\t\t\t\t\t\t\tnumber += exprI(index++);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\twhile(isDecimalDigit(exprICode(index))) { //exponent itself\r\n\t\t\t\t\t\t\tnumber += exprI(index++);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tif(!isDecimalDigit(exprICode(index-1)) ) {\r\n\t\t\t\t\t\t\tthrowError('Expected exponent (' + number + exprI(index) + ')', index);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\r\n\t\t\t\t\tchCode = exprICode(index);\r\n\t\t\t\t\t// Check to make sure this isn't a variable name that start with a number (123abc)\r\n\t\t\t\t\tif(isIdentifierStart(chCode)) {\r\n\t\t\t\t\t\tthrowError('Variable names cannot start with a number (' +\r\n\t\t\t\t\t\t\t\t\tnumber + exprI(index) + ')', index);\r\n\t\t\t\t\t} else if(chCode === PERIOD_CODE) {\r\n\t\t\t\t\t\tthrowError('Unexpected period', index);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn {\r\n\t\t\t\t\t\ttype: LITERAL,\r\n\t\t\t\t\t\tvalue: parseFloat(number),\r\n\t\t\t\t\t\traw: number\r\n\t\t\t\t\t};\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// Parses a string literal, staring with single or double quotes with basic support for escape codes\r\n\t\t\t\t// e.g. `\"hello world\"`, `'this is\\nJSEP'`\r\n\t\t\t\tgobbleStringLiteral = function() {\r\n\t\t\t\t\tvar str = '', quote = exprI(index++), closed = false, ch;\r\n\r\n\t\t\t\t\twhile(index < length) {\r\n\t\t\t\t\t\tch = exprI(index++);\r\n\t\t\t\t\t\tif(ch === quote) {\r\n\t\t\t\t\t\t\tclosed = true;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t} else if(ch === '\\\\') {\r\n\t\t\t\t\t\t\t// Check for all of the common escape codes\r\n\t\t\t\t\t\t\tch = exprI(index++);\r\n\t\t\t\t\t\t\tswitch(ch) {\r\n\t\t\t\t\t\t\t\tcase 'n': str += '\\n'; break;\r\n\t\t\t\t\t\t\t\tcase 'r': str += '\\r'; break;\r\n\t\t\t\t\t\t\t\tcase 't': str += '\\t'; break;\r\n\t\t\t\t\t\t\t\tcase 'b': str += '\\b'; break;\r\n\t\t\t\t\t\t\t\tcase 'f': str += '\\f'; break;\r\n\t\t\t\t\t\t\t\tcase 'v': str += '\\x0B'; break;\r\n\t\t\t\t\t\t\t\tdefault : str += '\\\\' + ch;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tstr += ch;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\tif(!closed) {\r\n\t\t\t\t\t\tthrowError('Unclosed quote after \"'+str+'\"', index);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\treturn {\r\n\t\t\t\t\t\ttype: LITERAL,\r\n\t\t\t\t\t\tvalue: str,\r\n\t\t\t\t\t\traw: quote + str + quote\r\n\t\t\t\t\t};\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// Gobbles only identifiers\r\n\t\t\t\t// e.g.: `foo`, `_value`, `$x1`\r\n\t\t\t\t// Also, this function checks if that identifier is a literal:\r\n\t\t\t\t// (e.g. `true`, `false`, `null`) or `this`\r\n\t\t\t\tgobbleIdentifier = function() {\r\n\t\t\t\t\tvar ch = exprICode(index), start = index, identifier;\r\n\r\n\t\t\t\t\tif(isIdentifierStart(ch)) {\r\n\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrowError('Unexpected ' + exprI(index), index);\r\n\t\t\t\t\t}\r\n\r\n\t\t\t\t\twhile(index < length) {\r\n\t\t\t\t\t\tch = exprICode(index);\r\n\t\t\t\t\t\tif(isIdentifierPart(ch)) {\r\n\t\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tidentifier = expr.slice(start, index);\r\n\r\n\t\t\t\t\tif(literals.hasOwnProperty(identifier)) {\r\n\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\ttype: LITERAL,\r\n\t\t\t\t\t\t\tvalue: literals[identifier],\r\n\t\t\t\t\t\t\traw: identifier\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t} else if(identifier === this_str) {\r\n\t\t\t\t\t\treturn { type: THIS_EXP };\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\treturn {\r\n\t\t\t\t\t\t\ttype: IDENTIFIER,\r\n\t\t\t\t\t\t\tname: identifier\r\n\t\t\t\t\t\t};\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// Gobbles a list of arguments within the context of a function call\r\n\t\t\t\t// or array literal. This function also assumes that the opening character\r\n\t\t\t\t// `(` or `[` has already been gobbled, and gobbles expressions and commas\r\n\t\t\t\t// until the terminator character `)` or `]` is encountered.\r\n\t\t\t\t// e.g. `foo(bar, baz)`, `my_func()`, or `[bar, baz]`\r\n\t\t\t\tgobbleArguments = function(termination) {\r\n\t\t\t\t\tvar ch_i, args = [], node, closed = false;\r\n\t\t\t\t\twhile(index < length) {\r\n\t\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\t\tch_i = exprICode(index);\r\n\t\t\t\t\t\tif(ch_i === termination) { // done parsing\r\n\t\t\t\t\t\t\tclosed = true;\r\n\t\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t\t\tbreak;\r\n\t\t\t\t\t\t} else if (ch_i === COMMA_CODE) { // between expressions\r\n\t\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\tnode = gobbleExpression();\r\n\t\t\t\t\t\t\tif(!node || node.type === COMPOUND) {\r\n\t\t\t\t\t\t\t\tthrowError('Expected comma', index);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\targs.push(node);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (!closed) {\r\n\t\t\t\t\t\tthrowError('Expected ' + String.fromCharCode(termination), index);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn args;\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// Gobble a non-literal variable name. This variable name may include properties\r\n\t\t\t\t// e.g. `foo`, `bar.baz`, `foo['bar'].baz`\r\n\t\t\t\t// It also gobbles function calls:\r\n\t\t\t\t// e.g. `Math.acos(obj.angle)`\r\n\t\t\t\tgobbleVariable = function() {\r\n\t\t\t\t\tvar ch_i, node;\r\n\t\t\t\t\tch_i = exprICode(index);\r\n\r\n\t\t\t\t\tif(ch_i === OPAREN_CODE) {\r\n\t\t\t\t\t\tnode = gobbleGroup();\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tnode = gobbleIdentifier();\r\n\t\t\t\t\t}\r\n\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\tch_i = exprICode(index);\r\n\t\t\t\t\twhile(ch_i === PERIOD_CODE || ch_i === OBRACK_CODE || ch_i === OPAREN_CODE) {\r\n\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t\tif(ch_i === PERIOD_CODE) {\r\n\t\t\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\t\t\tnode = {\r\n\t\t\t\t\t\t\t\ttype: MEMBER_EXP,\r\n\t\t\t\t\t\t\t\tcomputed: false,\r\n\t\t\t\t\t\t\t\tobject: node,\r\n\t\t\t\t\t\t\t\tproperty: gobbleIdentifier()\r\n\t\t\t\t\t\t\t};\r\n\t\t\t\t\t\t} else if(ch_i === OBRACK_CODE) {\r\n\t\t\t\t\t\t\tnode = {\r\n\t\t\t\t\t\t\t\ttype: MEMBER_EXP,\r\n\t\t\t\t\t\t\t\tcomputed: true,\r\n\t\t\t\t\t\t\t\tobject: node,\r\n\t\t\t\t\t\t\t\tproperty: gobbleExpression()\r\n\t\t\t\t\t\t\t};\r\n\t\t\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\t\t\tch_i = exprICode(index);\r\n\t\t\t\t\t\t\tif(ch_i !== CBRACK_CODE) {\r\n\t\t\t\t\t\t\t\tthrowError('Unclosed [', index);\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t\t} else if(ch_i === OPAREN_CODE) {\r\n\t\t\t\t\t\t\t// A function call is being made; gobble all the arguments\r\n\t\t\t\t\t\t\tnode = {\r\n\t\t\t\t\t\t\t\ttype: CALL_EXP,\r\n\t\t\t\t\t\t\t\t'arguments': gobbleArguments(CPAREN_CODE),\r\n\t\t\t\t\t\t\t\tcallee: node\r\n\t\t\t\t\t\t\t};\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\t\tch_i = exprICode(index);\r\n\t\t\t\t\t}\r\n\t\t\t\t\treturn node;\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// Responsible for parsing a group of things within parentheses `()`\r\n\t\t\t\t// This function assumes that it needs to gobble the opening parenthesis\r\n\t\t\t\t// and then tries to gobble everything within that parenthesis, assuming\r\n\t\t\t\t// that the next thing it should see is the close parenthesis. If not,\r\n\t\t\t\t// then the expression probably doesn't have a `)`\r\n\t\t\t\tgobbleGroup = function() {\r\n\t\t\t\t\tindex++;\r\n\t\t\t\t\tvar node = gobbleExpression();\r\n\t\t\t\t\tgobbleSpaces();\r\n\t\t\t\t\tif(exprICode(index) === CPAREN_CODE) {\r\n\t\t\t\t\t\tindex++;\r\n\t\t\t\t\t\treturn node;\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\tthrowError('Unclosed (', index);\r\n\t\t\t\t\t}\r\n\t\t\t\t},\r\n\r\n\t\t\t\t// Responsible for parsing Array literals `[1, 2, 3]`\r\n\t\t\t\t// This function assumes that it needs to gobble the opening bracket\r\n\t\t\t\t// and then tries to gobble the expressions as arguments.\r\n\t\t\t\tgobbleArray = function() {\r\n\t\t\t\t\tindex++;\r\n\t\t\t\t\treturn {\r\n\t\t\t\t\t\ttype: ARRAY_EXP,\r\n\t\t\t\t\t\telements: gobbleArguments(CBRACK_CODE)\r\n\t\t\t\t\t};\r\n\t\t\t\t},\r\n\r\n\t\t\t\tnodes = [], ch_i, node;\r\n\r\n\t\t\twhile(index < length) {\r\n\t\t\t\tch_i = exprICode(index);\r\n\r\n\t\t\t\t// Expressions can be separated by semicolons, commas, or just inferred without any\r\n\t\t\t\t// separators\r\n\t\t\t\tif(ch_i === SEMCOL_CODE || ch_i === COMMA_CODE) {\r\n\t\t\t\t\tindex++; // ignore separators\r\n\t\t\t\t} else {\r\n\t\t\t\t\t// Try to gobble each expression individually\r\n\t\t\t\t\tif((node = gobbleExpression())) {\r\n\t\t\t\t\t\tnodes.push(node);\r\n\t\t\t\t\t// If we weren't able to find a binary expression and are out of room, then\r\n\t\t\t\t\t// the expression passed in probably has too much\r\n\t\t\t\t\t} else if(index < length) {\r\n\t\t\t\t\t\tthrowError('Unexpected \"' + exprI(index) + '\"', index);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\t// If there's only one expression just try returning the expression\r\n\t\t\tif(nodes.length === 1) {\r\n\t\t\t\treturn nodes[0];\r\n\t\t\t} else {\r\n\t\t\t\treturn {\r\n\t\t\t\t\ttype: COMPOUND,\r\n\t\t\t\t\tbody: nodes\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t// To be filled in by the template\r\n\tjsep.version = '0.3.1';\r\n\tjsep.toString = function() { return 'JavaScript Expression Parser (JSEP) v' + jsep.version; };\r\n\r\n\t/**\r\n\t * @method jsep.addUnaryOp\r\n\t * @param {string} op_name The name of the unary op to add\r\n\t * @return jsep\r\n\t */\r\n\tjsep.addUnaryOp = function(op_name) {\r\n\t\tmax_unop_len = Math.max(op_name.length, max_unop_len);\r\n\t\tunary_ops[op_name] = t; return this;\r\n\t};\r\n\r\n\t/**\r\n\t * @method jsep.addBinaryOp\r\n\t * @param {string} op_name The name of the binary op to add\r\n\t * @param {number} precedence The precedence of the binary op (can be a float)\r\n\t * @return jsep\r\n\t */\r\n\tjsep.addBinaryOp = function(op_name, precedence) {\r\n\t\tmax_binop_len = Math.max(op_name.length, max_binop_len);\r\n\t\tbinary_ops[op_name] = precedence;\r\n\t\treturn this;\r\n\t};\r\n\r\n\t/**\r\n\t * @method jsep.addLiteral\r\n\t * @param {string} literal_name The name of the literal to add\r\n\t * @param {*} literal_value The value of the literal\r\n\t * @return jsep\r\n\t */\r\n\tjsep.addLiteral = function(literal_name, literal_value) {\r\n\t\tliterals[literal_name] = literal_value;\r\n\t\treturn this;\r\n\t};\r\n\r\n\t/**\r\n\t * @method jsep.removeUnaryOp\r\n\t * @param {string} op_name The name of the unary op to remove\r\n\t * @return jsep\r\n\t */\r\n\tjsep.removeUnaryOp = function(op_name) {\r\n\t\tdelete unary_ops[op_name];\r\n\t\tif(op_name.length === max_unop_len) {\r\n\t\t\tmax_unop_len = getMaxKeyLen(unary_ops);\r\n\t\t}\r\n\t\treturn this;\r\n\t};\r\n\r\n\t/**\r\n\t * @method jsep.removeAllUnaryOps\r\n\t * @return jsep\r\n\t */\r\n\tjsep.removeAllUnaryOps = function() {\r\n\t\tunary_ops = {};\r\n\t\tmax_unop_len = 0;\r\n\r\n\t\treturn this;\r\n\t};\r\n\r\n\t/**\r\n\t * @method jsep.removeBinaryOp\r\n\t * @param {string} op_name The name of the binary op to remove\r\n\t * @return jsep\r\n\t */\r\n\tjsep.removeBinaryOp = function(op_name) {\r\n\t\tdelete binary_ops[op_name];\r\n\t\tif(op_name.length === max_binop_len) {\r\n\t\t\tmax_binop_len = getMaxKeyLen(binary_ops);\r\n\t\t}\r\n\t\treturn this;\r\n\t};\r\n\r\n\t/**\r\n\t * @method jsep.removeAllBinaryOps\r\n\t * @return jsep\r\n\t */\r\n\tjsep.removeAllBinaryOps = function() {\r\n\t\tbinary_ops = {};\r\n\t\tmax_binop_len = 0;\r\n\r\n\t\treturn this;\r\n\t};\r\n\r\n\t/**\r\n\t * @method jsep.removeLiteral\r\n\t * @param {string} literal_name The name of the literal to remove\r\n\t * @return jsep\r\n\t */\r\n\tjsep.removeLiteral = function(literal_name) {\r\n\t\tdelete literals[literal_name];\r\n\t\treturn this;\r\n\t};\r\n\r\n\t/**\r\n\t * @method jsep.removeAllLiterals\r\n\t * @return jsep\r\n\t */\r\n\tjsep.removeAllLiterals = function() {\r\n\t\tliterals = {};\r\n\r\n\t\treturn this;\r\n\t};\r\n\r\n root.jsep = jsep;\r\n}(tmp));\r\n\r\nexport default tmp.jsep;\r\n","/**\r\n * @private\r\n */\r\nvar ExpressionNodeType = {\r\n VARIABLE: 0,\r\n UNARY: 1,\r\n BINARY: 2,\r\n TERNARY: 3,\r\n CONDITIONAL: 4,\r\n MEMBER: 5,\r\n FUNCTION_CALL: 6,\r\n ARRAY: 7,\r\n REGEX: 8,\r\n VARIABLE_IN_STRING: 9,\r\n LITERAL_NULL: 10,\r\n LITERAL_BOOLEAN: 11,\r\n LITERAL_NUMBER: 12,\r\n LITERAL_STRING: 13,\r\n LITERAL_COLOR: 14,\r\n LITERAL_VECTOR: 15,\r\n LITERAL_REGEX: 16,\r\n LITERAL_UNDEFINED: 17,\r\n BUILTIN_VARIABLE: 18,\r\n};\r\nexport default Object.freeze(ExpressionNodeType);\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport jsep from \"../ThirdParty/jsep.js\";\r\nimport ExpressionNodeType from \"./ExpressionNodeType.js\";\r\n\r\n/**\r\n * An expression for a style applied to a {@link Cesium3DTileset}.\r\n *

\r\n * Evaluates an expression defined using the\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/Styling|3D Tiles Styling language}.\r\n *

\r\n *

\r\n * Implements the {@link StyleExpression} interface.\r\n *

\r\n *\r\n * @alias Expression\r\n * @constructor\r\n *\r\n * @param {String} [expression] The expression defined using the 3D Tiles Styling language.\r\n * @param {Object} [defines] Defines in the style.\r\n *\r\n * @example\r\n * var expression = new Cesium.Expression('(regExp(\"^Chest\").test(${County})) && (${YearBuilt} >= 1970)');\r\n * expression.evaluate(feature); // returns true or false depending on the feature's properties\r\n *\r\n * @example\r\n * var expression = new Cesium.Expression('(${Temperature} > 90) ? color(\"red\") : color(\"white\")');\r\n * expression.evaluateColor(feature, result); // returns a Cesium.Color object\r\n */\r\nfunction Expression(expression, defines) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"expression\", expression);\r\n //>>includeEnd('debug');\r\n\r\n this._expression = expression;\r\n expression = replaceDefines(expression, defines);\r\n expression = replaceVariables(removeBackslashes(expression));\r\n\r\n // customize jsep operators\r\n jsep.addBinaryOp(\"=~\", 0);\r\n jsep.addBinaryOp(\"!~\", 0);\r\n\r\n var ast;\r\n try {\r\n ast = jsep(expression);\r\n } catch (e) {\r\n throw new RuntimeError(e);\r\n }\r\n\r\n this._runtimeAst = createRuntimeAst(this, ast);\r\n}\r\n\r\nObject.defineProperties(Expression.prototype, {\r\n /**\r\n * Gets the expression defined in the 3D Tiles Styling language.\r\n *\r\n * @memberof Expression.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n *\r\n * @default undefined\r\n */\r\n expression: {\r\n get: function () {\r\n return this._expression;\r\n },\r\n },\r\n});\r\n\r\n// Scratch storage manager while evaluating deep expressions.\r\n// For example, an expression like dot(vec4(${red}), vec4(${green}) * vec4(${blue}) requires 3 scratch Cartesian4's\r\nvar scratchStorage = {\r\n arrayIndex: 0,\r\n arrayArray: [[]],\r\n cartesian2Index: 0,\r\n cartesian3Index: 0,\r\n cartesian4Index: 0,\r\n cartesian2Array: [new Cartesian2()],\r\n cartesian3Array: [new Cartesian3()],\r\n cartesian4Array: [new Cartesian4()],\r\n reset: function () {\r\n this.arrayIndex = 0;\r\n this.cartesian2Index = 0;\r\n this.cartesian3Index = 0;\r\n this.cartesian4Index = 0;\r\n },\r\n getArray: function () {\r\n if (this.arrayIndex >= this.arrayArray.length) {\r\n this.arrayArray.push([]);\r\n }\r\n var array = this.arrayArray[this.arrayIndex++];\r\n array.length = 0;\r\n return array;\r\n },\r\n getCartesian2: function () {\r\n if (this.cartesian2Index >= this.cartesian2Array.length) {\r\n this.cartesian2Array.push(new Cartesian2());\r\n }\r\n return this.cartesian2Array[this.cartesian2Index++];\r\n },\r\n getCartesian3: function () {\r\n if (this.cartesian3Index >= this.cartesian3Array.length) {\r\n this.cartesian3Array.push(new Cartesian3());\r\n }\r\n return this.cartesian3Array[this.cartesian3Index++];\r\n },\r\n getCartesian4: function () {\r\n if (this.cartesian4Index >= this.cartesian4Array.length) {\r\n this.cartesian4Array.push(new Cartesian4());\r\n }\r\n return this.cartesian4Array[this.cartesian4Index++];\r\n },\r\n};\r\n\r\n/**\r\n * Evaluates the result of an expression, optionally using the provided feature's properties. If the result of\r\n * the expression in the\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/Styling|3D Tiles Styling language}\r\n * is of type Boolean, Number, or String, the corresponding JavaScript\r\n * primitive type will be returned. If the result is a RegExp, a Javascript RegExp\r\n * object will be returned. If the result is a Cartesian2, Cartesian3, or Cartesian4,\r\n * a {@link Cartesian2}, {@link Cartesian3}, or {@link Cartesian4} object will be returned. If the result argument is\r\n * a {@link Color}, the {@link Cartesian4} value is converted to a {@link Color} and then returned.\r\n *\r\n * @param {Cesium3DTileFeature} feature The feature whose properties may be used as variables in the expression.\r\n * @param {Object} [result] The object onto which to store the result.\r\n * @returns {Boolean|Number|String|RegExp|Cartesian2|Cartesian3|Cartesian4|Color} The result of evaluating the expression.\r\n */\r\nExpression.prototype.evaluate = function (feature, result) {\r\n scratchStorage.reset();\r\n var value = this._runtimeAst.evaluate(feature);\r\n if (result instanceof Color && value instanceof Cartesian4) {\r\n return Color.fromCartesian4(value, result);\r\n }\r\n if (\r\n value instanceof Cartesian2 ||\r\n value instanceof Cartesian3 ||\r\n value instanceof Cartesian4\r\n ) {\r\n return value.clone(result);\r\n }\r\n return value;\r\n};\r\n\r\n/**\r\n * Evaluates the result of a Color expression, optionally using the provided feature's properties.\r\n *

\r\n * This is equivalent to {@link Expression#evaluate} but always returns a {@link Color} object.\r\n *

\r\n *\r\n * @param {Cesium3DTileFeature} feature The feature whose properties may be used as variables in the expression.\r\n * @param {Color} [result] The object in which to store the result\r\n * @returns {Color} The modified result parameter or a new Color instance if one was not provided.\r\n */\r\nExpression.prototype.evaluateColor = function (feature, result) {\r\n scratchStorage.reset();\r\n var color = this._runtimeAst.evaluate(feature);\r\n return Color.fromCartesian4(color, result);\r\n};\r\n\r\n/**\r\n * Gets the shader function for this expression.\r\n * Returns undefined if the shader function can't be generated from this expression.\r\n *\r\n * @param {String} functionName Name to give to the generated function.\r\n * @param {String} propertyNameMap Maps property variable names to shader attribute names.\r\n * @param {Object} shaderState Stores information about the generated shader function, including whether it is translucent.\r\n * @param {String} returnType The return type of the generated function.\r\n *\r\n * @returns {String} The shader function.\r\n *\r\n * @private\r\n */\r\nExpression.prototype.getShaderFunction = function (\r\n functionName,\r\n propertyNameMap,\r\n shaderState,\r\n returnType\r\n) {\r\n var shaderExpression = this.getShaderExpression(propertyNameMap, shaderState);\r\n\r\n shaderExpression =\r\n returnType +\r\n \" \" +\r\n functionName +\r\n \"() \\n\" +\r\n \"{ \\n\" +\r\n \" return \" +\r\n shaderExpression +\r\n \"; \\n\" +\r\n \"} \\n\";\r\n\r\n return shaderExpression;\r\n};\r\n\r\n/**\r\n * Gets the shader expression for this expression.\r\n * Returns undefined if the shader expression can't be generated from this expression.\r\n *\r\n * @param {String} propertyNameMap Maps property variable names to shader attribute names.\r\n * @param {Object} shaderState Stores information about the generated shader function, including whether it is translucent.\r\n *\r\n * @returns {String} The shader expression.\r\n *\r\n * @private\r\n */\r\nExpression.prototype.getShaderExpression = function (\r\n propertyNameMap,\r\n shaderState\r\n) {\r\n return this._runtimeAst.getShaderExpression(propertyNameMap, shaderState);\r\n};\r\n\r\nvar unaryOperators = [\"!\", \"-\", \"+\"];\r\nvar binaryOperators = [\r\n \"+\",\r\n \"-\",\r\n \"*\",\r\n \"/\",\r\n \"%\",\r\n \"===\",\r\n \"!==\",\r\n \">\",\r\n \">=\",\r\n \"<\",\r\n \"<=\",\r\n \"&&\",\r\n \"||\",\r\n \"!~\",\r\n \"=~\",\r\n];\r\n\r\nvar variableRegex = /\\${(.*?)}/g; // Matches ${variable_name}\r\nvar backslashRegex = /\\\\/g;\r\nvar backslashReplacement = \"@#%\";\r\nvar replacementRegex = /@#%/g;\r\n\r\nvar scratchColor = new Color();\r\n\r\nvar unaryFunctions = {\r\n abs: getEvaluateUnaryComponentwise(Math.abs),\r\n sqrt: getEvaluateUnaryComponentwise(Math.sqrt),\r\n cos: getEvaluateUnaryComponentwise(Math.cos),\r\n sin: getEvaluateUnaryComponentwise(Math.sin),\r\n tan: getEvaluateUnaryComponentwise(Math.tan),\r\n acos: getEvaluateUnaryComponentwise(Math.acos),\r\n asin: getEvaluateUnaryComponentwise(Math.asin),\r\n atan: getEvaluateUnaryComponentwise(Math.atan),\r\n radians: getEvaluateUnaryComponentwise(CesiumMath.toRadians),\r\n degrees: getEvaluateUnaryComponentwise(CesiumMath.toDegrees),\r\n sign: getEvaluateUnaryComponentwise(CesiumMath.sign),\r\n floor: getEvaluateUnaryComponentwise(Math.floor),\r\n ceil: getEvaluateUnaryComponentwise(Math.ceil),\r\n round: getEvaluateUnaryComponentwise(Math.round),\r\n exp: getEvaluateUnaryComponentwise(Math.exp),\r\n exp2: getEvaluateUnaryComponentwise(exp2),\r\n log: getEvaluateUnaryComponentwise(Math.log),\r\n log2: getEvaluateUnaryComponentwise(log2),\r\n fract: getEvaluateUnaryComponentwise(fract),\r\n length: length,\r\n normalize: normalize,\r\n};\r\n\r\nvar binaryFunctions = {\r\n atan2: getEvaluateBinaryComponentwise(Math.atan2, false),\r\n pow: getEvaluateBinaryComponentwise(Math.pow, false),\r\n min: getEvaluateBinaryComponentwise(Math.min, true),\r\n max: getEvaluateBinaryComponentwise(Math.max, true),\r\n distance: distance,\r\n dot: dot,\r\n cross: cross,\r\n};\r\n\r\nvar ternaryFunctions = {\r\n clamp: getEvaluateTernaryComponentwise(CesiumMath.clamp, true),\r\n mix: getEvaluateTernaryComponentwise(CesiumMath.lerp, true),\r\n};\r\n\r\nfunction fract(number) {\r\n return number - Math.floor(number);\r\n}\r\n\r\nfunction exp2(exponent) {\r\n return Math.pow(2.0, exponent);\r\n}\r\n\r\nfunction log2(number) {\r\n return CesiumMath.log2(number);\r\n}\r\n\r\nfunction getEvaluateUnaryComponentwise(operation) {\r\n return function (call, left) {\r\n if (typeof left === \"number\") {\r\n return operation(left);\r\n } else if (left instanceof Cartesian2) {\r\n return Cartesian2.fromElements(\r\n operation(left.x),\r\n operation(left.y),\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (left instanceof Cartesian3) {\r\n return Cartesian3.fromElements(\r\n operation(left.x),\r\n operation(left.y),\r\n operation(left.z),\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (left instanceof Cartesian4) {\r\n return Cartesian4.fromElements(\r\n operation(left.x),\r\n operation(left.y),\r\n operation(left.z),\r\n operation(left.w),\r\n scratchStorage.getCartesian4()\r\n );\r\n }\r\n throw new RuntimeError(\r\n 'Function \"' +\r\n call +\r\n '\" requires a vector or number argument. Argument is ' +\r\n left +\r\n \".\"\r\n );\r\n };\r\n}\r\n\r\nfunction getEvaluateBinaryComponentwise(operation, allowScalar) {\r\n return function (call, left, right) {\r\n if (allowScalar && typeof right === \"number\") {\r\n if (typeof left === \"number\") {\r\n return operation(left, right);\r\n } else if (left instanceof Cartesian2) {\r\n return Cartesian2.fromElements(\r\n operation(left.x, right),\r\n operation(left.y, right),\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (left instanceof Cartesian3) {\r\n return Cartesian3.fromElements(\r\n operation(left.x, right),\r\n operation(left.y, right),\r\n operation(left.z, right),\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (left instanceof Cartesian4) {\r\n return Cartesian4.fromElements(\r\n operation(left.x, right),\r\n operation(left.y, right),\r\n operation(left.z, right),\r\n operation(left.w, right),\r\n scratchStorage.getCartesian4()\r\n );\r\n }\r\n }\r\n\r\n if (typeof left === \"number\" && typeof right === \"number\") {\r\n return operation(left, right);\r\n } else if (left instanceof Cartesian2 && right instanceof Cartesian2) {\r\n return Cartesian2.fromElements(\r\n operation(left.x, right.x),\r\n operation(left.y, right.y),\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (left instanceof Cartesian3 && right instanceof Cartesian3) {\r\n return Cartesian3.fromElements(\r\n operation(left.x, right.x),\r\n operation(left.y, right.y),\r\n operation(left.z, right.z),\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (left instanceof Cartesian4 && right instanceof Cartesian4) {\r\n return Cartesian4.fromElements(\r\n operation(left.x, right.x),\r\n operation(left.y, right.y),\r\n operation(left.z, right.z),\r\n operation(left.w, right.w),\r\n scratchStorage.getCartesian4()\r\n );\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Function \"' +\r\n call +\r\n '\" requires vector or number arguments of matching types. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n };\r\n}\r\n\r\nfunction getEvaluateTernaryComponentwise(operation, allowScalar) {\r\n return function (call, left, right, test) {\r\n if (allowScalar && typeof test === \"number\") {\r\n if (typeof left === \"number\" && typeof right === \"number\") {\r\n return operation(left, right, test);\r\n } else if (left instanceof Cartesian2 && right instanceof Cartesian2) {\r\n return Cartesian2.fromElements(\r\n operation(left.x, right.x, test),\r\n operation(left.y, right.y, test),\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (left instanceof Cartesian3 && right instanceof Cartesian3) {\r\n return Cartesian3.fromElements(\r\n operation(left.x, right.x, test),\r\n operation(left.y, right.y, test),\r\n operation(left.z, right.z, test),\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (left instanceof Cartesian4 && right instanceof Cartesian4) {\r\n return Cartesian4.fromElements(\r\n operation(left.x, right.x, test),\r\n operation(left.y, right.y, test),\r\n operation(left.z, right.z, test),\r\n operation(left.w, right.w, test),\r\n scratchStorage.getCartesian4()\r\n );\r\n }\r\n }\r\n\r\n if (\r\n typeof left === \"number\" &&\r\n typeof right === \"number\" &&\r\n typeof test === \"number\"\r\n ) {\r\n return operation(left, right, test);\r\n } else if (\r\n left instanceof Cartesian2 &&\r\n right instanceof Cartesian2 &&\r\n test instanceof Cartesian2\r\n ) {\r\n return Cartesian2.fromElements(\r\n operation(left.x, right.x, test.x),\r\n operation(left.y, right.y, test.y),\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (\r\n left instanceof Cartesian3 &&\r\n right instanceof Cartesian3 &&\r\n test instanceof Cartesian3\r\n ) {\r\n return Cartesian3.fromElements(\r\n operation(left.x, right.x, test.x),\r\n operation(left.y, right.y, test.y),\r\n operation(left.z, right.z, test.z),\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (\r\n left instanceof Cartesian4 &&\r\n right instanceof Cartesian4 &&\r\n test instanceof Cartesian4\r\n ) {\r\n return Cartesian4.fromElements(\r\n operation(left.x, right.x, test.x),\r\n operation(left.y, right.y, test.y),\r\n operation(left.z, right.z, test.z),\r\n operation(left.w, right.w, test.w),\r\n scratchStorage.getCartesian4()\r\n );\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Function \"' +\r\n call +\r\n '\" requires vector or number arguments of matching types. Arguments are ' +\r\n left +\r\n \", \" +\r\n right +\r\n \", and \" +\r\n test +\r\n \".\"\r\n );\r\n };\r\n}\r\n\r\nfunction length(call, left) {\r\n if (typeof left === \"number\") {\r\n return Math.abs(left);\r\n } else if (left instanceof Cartesian2) {\r\n return Cartesian2.magnitude(left);\r\n } else if (left instanceof Cartesian3) {\r\n return Cartesian3.magnitude(left);\r\n } else if (left instanceof Cartesian4) {\r\n return Cartesian4.magnitude(left);\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Function \"' +\r\n call +\r\n '\" requires a vector or number argument. Argument is ' +\r\n left +\r\n \".\"\r\n );\r\n}\r\n\r\nfunction normalize(call, left) {\r\n if (typeof left === \"number\") {\r\n return 1.0;\r\n } else if (left instanceof Cartesian2) {\r\n return Cartesian2.normalize(left, scratchStorage.getCartesian2());\r\n } else if (left instanceof Cartesian3) {\r\n return Cartesian3.normalize(left, scratchStorage.getCartesian3());\r\n } else if (left instanceof Cartesian4) {\r\n return Cartesian4.normalize(left, scratchStorage.getCartesian4());\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Function \"' +\r\n call +\r\n '\" requires a vector or number argument. Argument is ' +\r\n left +\r\n \".\"\r\n );\r\n}\r\n\r\nfunction distance(call, left, right) {\r\n if (typeof left === \"number\" && typeof right === \"number\") {\r\n return Math.abs(left - right);\r\n } else if (left instanceof Cartesian2 && right instanceof Cartesian2) {\r\n return Cartesian2.distance(left, right);\r\n } else if (left instanceof Cartesian3 && right instanceof Cartesian3) {\r\n return Cartesian3.distance(left, right);\r\n } else if (left instanceof Cartesian4 && right instanceof Cartesian4) {\r\n return Cartesian4.distance(left, right);\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Function \"' +\r\n call +\r\n '\" requires vector or number arguments of matching types. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n}\r\n\r\nfunction dot(call, left, right) {\r\n if (typeof left === \"number\" && typeof right === \"number\") {\r\n return left * right;\r\n } else if (left instanceof Cartesian2 && right instanceof Cartesian2) {\r\n return Cartesian2.dot(left, right);\r\n } else if (left instanceof Cartesian3 && right instanceof Cartesian3) {\r\n return Cartesian3.dot(left, right);\r\n } else if (left instanceof Cartesian4 && right instanceof Cartesian4) {\r\n return Cartesian4.dot(left, right);\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Function \"' +\r\n call +\r\n '\" requires vector or number arguments of matching types. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n}\r\n\r\nfunction cross(call, left, right) {\r\n if (left instanceof Cartesian3 && right instanceof Cartesian3) {\r\n return Cartesian3.cross(left, right, scratchStorage.getCartesian3());\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Function \"' +\r\n call +\r\n '\" requires vec3 arguments. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n}\r\n\r\nfunction Node(type, value, left, right, test) {\r\n this._type = type;\r\n this._value = value;\r\n this._left = left;\r\n this._right = right;\r\n this._test = test;\r\n this.evaluate = undefined;\r\n\r\n setEvaluateFunction(this);\r\n}\r\n\r\nfunction replaceDefines(expression, defines) {\r\n if (!defined(defines)) {\r\n return expression;\r\n }\r\n for (var key in defines) {\r\n if (defines.hasOwnProperty(key)) {\r\n var definePlaceholder = new RegExp(\"\\\\$\\\\{\" + key + \"\\\\}\", \"g\");\r\n var defineReplace = \"(\" + defines[key] + \")\";\r\n if (defined(defineReplace)) {\r\n expression = expression.replace(definePlaceholder, defineReplace);\r\n }\r\n }\r\n }\r\n return expression;\r\n}\r\n\r\nfunction removeBackslashes(expression) {\r\n return expression.replace(backslashRegex, backslashReplacement);\r\n}\r\n\r\nfunction replaceBackslashes(expression) {\r\n return expression.replace(replacementRegex, \"\\\\\");\r\n}\r\n\r\nfunction replaceVariables(expression) {\r\n var exp = expression;\r\n var result = \"\";\r\n var i = exp.indexOf(\"${\");\r\n while (i >= 0) {\r\n // Check if string is inside quotes\r\n var openSingleQuote = exp.indexOf(\"'\");\r\n var openDoubleQuote = exp.indexOf('\"');\r\n var closeQuote;\r\n if (openSingleQuote >= 0 && openSingleQuote < i) {\r\n closeQuote = exp.indexOf(\"'\", openSingleQuote + 1);\r\n result += exp.substr(0, closeQuote + 1);\r\n exp = exp.substr(closeQuote + 1);\r\n i = exp.indexOf(\"${\");\r\n } else if (openDoubleQuote >= 0 && openDoubleQuote < i) {\r\n closeQuote = exp.indexOf('\"', openDoubleQuote + 1);\r\n result += exp.substr(0, closeQuote + 1);\r\n exp = exp.substr(closeQuote + 1);\r\n i = exp.indexOf(\"${\");\r\n } else {\r\n result += exp.substr(0, i);\r\n var j = exp.indexOf(\"}\");\r\n if (j < 0) {\r\n throw new RuntimeError(\"Unmatched {.\");\r\n }\r\n result += \"czm_\" + exp.substr(i + 2, j - (i + 2));\r\n exp = exp.substr(j + 1);\r\n i = exp.indexOf(\"${\");\r\n }\r\n }\r\n result += exp;\r\n return result;\r\n}\r\n\r\nfunction parseLiteral(ast) {\r\n var type = typeof ast.value;\r\n if (ast.value === null) {\r\n return new Node(ExpressionNodeType.LITERAL_NULL, null);\r\n } else if (type === \"boolean\") {\r\n return new Node(ExpressionNodeType.LITERAL_BOOLEAN, ast.value);\r\n } else if (type === \"number\") {\r\n return new Node(ExpressionNodeType.LITERAL_NUMBER, ast.value);\r\n } else if (type === \"string\") {\r\n if (ast.value.indexOf(\"${\") >= 0) {\r\n return new Node(ExpressionNodeType.VARIABLE_IN_STRING, ast.value);\r\n }\r\n return new Node(\r\n ExpressionNodeType.LITERAL_STRING,\r\n replaceBackslashes(ast.value)\r\n );\r\n }\r\n}\r\n\r\nfunction parseCall(expression, ast) {\r\n var args = ast.arguments;\r\n var argsLength = args.length;\r\n var call;\r\n var val, left, right;\r\n\r\n // Member function calls\r\n if (ast.callee.type === \"MemberExpression\") {\r\n call = ast.callee.property.name;\r\n var object = ast.callee.object;\r\n if (call === \"test\" || call === \"exec\") {\r\n // Make sure this is called on a valid type\r\n if (object.callee.name !== \"regExp\") {\r\n throw new RuntimeError(call + \" is not a function.\");\r\n }\r\n if (argsLength === 0) {\r\n if (call === \"test\") {\r\n return new Node(ExpressionNodeType.LITERAL_BOOLEAN, false);\r\n }\r\n return new Node(ExpressionNodeType.LITERAL_NULL, null);\r\n }\r\n left = createRuntimeAst(expression, object);\r\n right = createRuntimeAst(expression, args[0]);\r\n return new Node(ExpressionNodeType.FUNCTION_CALL, call, left, right);\r\n } else if (call === \"toString\") {\r\n val = createRuntimeAst(expression, object);\r\n return new Node(ExpressionNodeType.FUNCTION_CALL, call, val);\r\n }\r\n\r\n throw new RuntimeError('Unexpected function call \"' + call + '\".');\r\n }\r\n\r\n // Non-member function calls\r\n call = ast.callee.name;\r\n if (call === \"color\") {\r\n if (argsLength === 0) {\r\n return new Node(ExpressionNodeType.LITERAL_COLOR, call);\r\n }\r\n val = createRuntimeAst(expression, args[0]);\r\n if (defined(args[1])) {\r\n var alpha = createRuntimeAst(expression, args[1]);\r\n return new Node(ExpressionNodeType.LITERAL_COLOR, call, [val, alpha]);\r\n }\r\n return new Node(ExpressionNodeType.LITERAL_COLOR, call, [val]);\r\n } else if (call === \"rgb\" || call === \"hsl\") {\r\n if (argsLength < 3) {\r\n throw new RuntimeError(call + \" requires three arguments.\");\r\n }\r\n val = [\r\n createRuntimeAst(expression, args[0]),\r\n createRuntimeAst(expression, args[1]),\r\n createRuntimeAst(expression, args[2]),\r\n ];\r\n return new Node(ExpressionNodeType.LITERAL_COLOR, call, val);\r\n } else if (call === \"rgba\" || call === \"hsla\") {\r\n if (argsLength < 4) {\r\n throw new RuntimeError(call + \" requires four arguments.\");\r\n }\r\n val = [\r\n createRuntimeAst(expression, args[0]),\r\n createRuntimeAst(expression, args[1]),\r\n createRuntimeAst(expression, args[2]),\r\n createRuntimeAst(expression, args[3]),\r\n ];\r\n return new Node(ExpressionNodeType.LITERAL_COLOR, call, val);\r\n } else if (call === \"vec2\" || call === \"vec3\" || call === \"vec4\") {\r\n // Check for invalid constructors at evaluation time\r\n val = new Array(argsLength);\r\n for (var i = 0; i < argsLength; ++i) {\r\n val[i] = createRuntimeAst(expression, args[i]);\r\n }\r\n return new Node(ExpressionNodeType.LITERAL_VECTOR, call, val);\r\n } else if (call === \"isNaN\" || call === \"isFinite\") {\r\n if (argsLength === 0) {\r\n if (call === \"isNaN\") {\r\n return new Node(ExpressionNodeType.LITERAL_BOOLEAN, true);\r\n }\r\n return new Node(ExpressionNodeType.LITERAL_BOOLEAN, false);\r\n }\r\n val = createRuntimeAst(expression, args[0]);\r\n return new Node(ExpressionNodeType.UNARY, call, val);\r\n } else if (call === \"isExactClass\" || call === \"isClass\") {\r\n if (argsLength < 1 || argsLength > 1) {\r\n throw new RuntimeError(call + \" requires exactly one argument.\");\r\n }\r\n val = createRuntimeAst(expression, args[0]);\r\n return new Node(ExpressionNodeType.UNARY, call, val);\r\n } else if (call === \"getExactClassName\") {\r\n if (argsLength > 0) {\r\n throw new RuntimeError(call + \" does not take any argument.\");\r\n }\r\n return new Node(ExpressionNodeType.UNARY, call);\r\n } else if (defined(unaryFunctions[call])) {\r\n if (argsLength !== 1) {\r\n throw new RuntimeError(call + \" requires exactly one argument.\");\r\n }\r\n val = createRuntimeAst(expression, args[0]);\r\n return new Node(ExpressionNodeType.UNARY, call, val);\r\n } else if (defined(binaryFunctions[call])) {\r\n if (argsLength !== 2) {\r\n throw new RuntimeError(call + \" requires exactly two arguments.\");\r\n }\r\n left = createRuntimeAst(expression, args[0]);\r\n right = createRuntimeAst(expression, args[1]);\r\n return new Node(ExpressionNodeType.BINARY, call, left, right);\r\n } else if (defined(ternaryFunctions[call])) {\r\n if (argsLength !== 3) {\r\n throw new RuntimeError(call + \" requires exactly three arguments.\");\r\n }\r\n left = createRuntimeAst(expression, args[0]);\r\n right = createRuntimeAst(expression, args[1]);\r\n var test = createRuntimeAst(expression, args[2]);\r\n return new Node(ExpressionNodeType.TERNARY, call, left, right, test);\r\n } else if (call === \"Boolean\") {\r\n if (argsLength === 0) {\r\n return new Node(ExpressionNodeType.LITERAL_BOOLEAN, false);\r\n }\r\n val = createRuntimeAst(expression, args[0]);\r\n return new Node(ExpressionNodeType.UNARY, call, val);\r\n } else if (call === \"Number\") {\r\n if (argsLength === 0) {\r\n return new Node(ExpressionNodeType.LITERAL_NUMBER, 0);\r\n }\r\n val = createRuntimeAst(expression, args[0]);\r\n return new Node(ExpressionNodeType.UNARY, call, val);\r\n } else if (call === \"String\") {\r\n if (argsLength === 0) {\r\n return new Node(ExpressionNodeType.LITERAL_STRING, \"\");\r\n }\r\n val = createRuntimeAst(expression, args[0]);\r\n return new Node(ExpressionNodeType.UNARY, call, val);\r\n } else if (call === \"regExp\") {\r\n return parseRegex(expression, ast);\r\n }\r\n\r\n throw new RuntimeError('Unexpected function call \"' + call + '\".');\r\n}\r\n\r\nfunction parseRegex(expression, ast) {\r\n var args = ast.arguments;\r\n // no arguments, return default regex\r\n if (args.length === 0) {\r\n return new Node(ExpressionNodeType.LITERAL_REGEX, new RegExp());\r\n }\r\n\r\n var pattern = createRuntimeAst(expression, args[0]);\r\n var exp;\r\n\r\n // optional flag argument supplied\r\n if (args.length > 1) {\r\n var flags = createRuntimeAst(expression, args[1]);\r\n if (isLiteralType(pattern) && isLiteralType(flags)) {\r\n try {\r\n exp = new RegExp(\r\n replaceBackslashes(String(pattern._value)),\r\n flags._value\r\n );\r\n } catch (e) {\r\n throw new RuntimeError(e);\r\n }\r\n return new Node(ExpressionNodeType.LITERAL_REGEX, exp);\r\n }\r\n return new Node(ExpressionNodeType.REGEX, pattern, flags);\r\n }\r\n\r\n // only pattern argument supplied\r\n if (isLiteralType(pattern)) {\r\n try {\r\n exp = new RegExp(replaceBackslashes(String(pattern._value)));\r\n } catch (e) {\r\n throw new RuntimeError(e);\r\n }\r\n return new Node(ExpressionNodeType.LITERAL_REGEX, exp);\r\n }\r\n return new Node(ExpressionNodeType.REGEX, pattern);\r\n}\r\n\r\nfunction parseKeywordsAndVariables(ast) {\r\n if (isVariable(ast.name)) {\r\n var name = getPropertyName(ast.name);\r\n if (name.substr(0, 8) === \"tiles3d_\") {\r\n return new Node(ExpressionNodeType.BUILTIN_VARIABLE, name);\r\n }\r\n return new Node(ExpressionNodeType.VARIABLE, name);\r\n } else if (ast.name === \"NaN\") {\r\n return new Node(ExpressionNodeType.LITERAL_NUMBER, NaN);\r\n } else if (ast.name === \"Infinity\") {\r\n return new Node(ExpressionNodeType.LITERAL_NUMBER, Infinity);\r\n } else if (ast.name === \"undefined\") {\r\n return new Node(ExpressionNodeType.LITERAL_UNDEFINED, undefined);\r\n }\r\n\r\n throw new RuntimeError(ast.name + \" is not defined.\");\r\n}\r\n\r\nfunction parseMathConstant(ast) {\r\n var name = ast.property.name;\r\n if (name === \"PI\") {\r\n return new Node(ExpressionNodeType.LITERAL_NUMBER, Math.PI);\r\n } else if (name === \"E\") {\r\n return new Node(ExpressionNodeType.LITERAL_NUMBER, Math.E);\r\n }\r\n}\r\n\r\nfunction parseNumberConstant(ast) {\r\n var name = ast.property.name;\r\n if (name === \"POSITIVE_INFINITY\") {\r\n return new Node(\r\n ExpressionNodeType.LITERAL_NUMBER,\r\n Number.POSITIVE_INFINITY\r\n );\r\n }\r\n}\r\n\r\nfunction parseMemberExpression(expression, ast) {\r\n if (ast.object.name === \"Math\") {\r\n return parseMathConstant(ast);\r\n } else if (ast.object.name === \"Number\") {\r\n return parseNumberConstant(ast);\r\n }\r\n\r\n var val;\r\n var obj = createRuntimeAst(expression, ast.object);\r\n if (ast.computed) {\r\n val = createRuntimeAst(expression, ast.property);\r\n return new Node(ExpressionNodeType.MEMBER, \"brackets\", obj, val);\r\n }\r\n\r\n val = new Node(ExpressionNodeType.LITERAL_STRING, ast.property.name);\r\n return new Node(ExpressionNodeType.MEMBER, \"dot\", obj, val);\r\n}\r\n\r\nfunction isLiteralType(node) {\r\n return node._type >= ExpressionNodeType.LITERAL_NULL;\r\n}\r\n\r\nfunction isVariable(name) {\r\n return name.substr(0, 4) === \"czm_\";\r\n}\r\n\r\nfunction getPropertyName(variable) {\r\n return variable.substr(4);\r\n}\r\n\r\nfunction createRuntimeAst(expression, ast) {\r\n var node;\r\n var op;\r\n var left;\r\n var right;\r\n\r\n if (ast.type === \"Literal\") {\r\n node = parseLiteral(ast);\r\n } else if (ast.type === \"CallExpression\") {\r\n node = parseCall(expression, ast);\r\n } else if (ast.type === \"Identifier\") {\r\n node = parseKeywordsAndVariables(ast);\r\n } else if (ast.type === \"UnaryExpression\") {\r\n op = ast.operator;\r\n var child = createRuntimeAst(expression, ast.argument);\r\n if (unaryOperators.indexOf(op) > -1) {\r\n node = new Node(ExpressionNodeType.UNARY, op, child);\r\n } else {\r\n throw new RuntimeError('Unexpected operator \"' + op + '\".');\r\n }\r\n } else if (ast.type === \"BinaryExpression\") {\r\n op = ast.operator;\r\n left = createRuntimeAst(expression, ast.left);\r\n right = createRuntimeAst(expression, ast.right);\r\n if (binaryOperators.indexOf(op) > -1) {\r\n node = new Node(ExpressionNodeType.BINARY, op, left, right);\r\n } else {\r\n throw new RuntimeError('Unexpected operator \"' + op + '\".');\r\n }\r\n } else if (ast.type === \"LogicalExpression\") {\r\n op = ast.operator;\r\n left = createRuntimeAst(expression, ast.left);\r\n right = createRuntimeAst(expression, ast.right);\r\n if (binaryOperators.indexOf(op) > -1) {\r\n node = new Node(ExpressionNodeType.BINARY, op, left, right);\r\n }\r\n } else if (ast.type === \"ConditionalExpression\") {\r\n var test = createRuntimeAst(expression, ast.test);\r\n left = createRuntimeAst(expression, ast.consequent);\r\n right = createRuntimeAst(expression, ast.alternate);\r\n node = new Node(ExpressionNodeType.CONDITIONAL, \"?\", left, right, test);\r\n } else if (ast.type === \"MemberExpression\") {\r\n node = parseMemberExpression(expression, ast);\r\n } else if (ast.type === \"ArrayExpression\") {\r\n var val = [];\r\n for (var i = 0; i < ast.elements.length; i++) {\r\n val[i] = createRuntimeAst(expression, ast.elements[i]);\r\n }\r\n node = new Node(ExpressionNodeType.ARRAY, val);\r\n } else if (ast.type === \"Compound\") {\r\n // empty expression or multiple expressions\r\n throw new RuntimeError(\"Provide exactly one expression.\");\r\n } else {\r\n throw new RuntimeError(\"Cannot parse expression.\");\r\n }\r\n\r\n return node;\r\n}\r\n\r\nfunction setEvaluateFunction(node) {\r\n if (node._type === ExpressionNodeType.CONDITIONAL) {\r\n node.evaluate = node._evaluateConditional;\r\n } else if (node._type === ExpressionNodeType.FUNCTION_CALL) {\r\n if (node._value === \"test\") {\r\n node.evaluate = node._evaluateRegExpTest;\r\n } else if (node._value === \"exec\") {\r\n node.evaluate = node._evaluateRegExpExec;\r\n } else if (node._value === \"toString\") {\r\n node.evaluate = node._evaluateToString;\r\n }\r\n } else if (node._type === ExpressionNodeType.UNARY) {\r\n if (node._value === \"!\") {\r\n node.evaluate = node._evaluateNot;\r\n } else if (node._value === \"-\") {\r\n node.evaluate = node._evaluateNegative;\r\n } else if (node._value === \"+\") {\r\n node.evaluate = node._evaluatePositive;\r\n } else if (node._value === \"isNaN\") {\r\n node.evaluate = node._evaluateNaN;\r\n } else if (node._value === \"isFinite\") {\r\n node.evaluate = node._evaluateIsFinite;\r\n } else if (node._value === \"isExactClass\") {\r\n node.evaluate = node._evaluateIsExactClass;\r\n } else if (node._value === \"isClass\") {\r\n node.evaluate = node._evaluateIsClass;\r\n } else if (node._value === \"getExactClassName\") {\r\n node.evaluate = node._evaluateGetExactClassName;\r\n } else if (node._value === \"Boolean\") {\r\n node.evaluate = node._evaluateBooleanConversion;\r\n } else if (node._value === \"Number\") {\r\n node.evaluate = node._evaluateNumberConversion;\r\n } else if (node._value === \"String\") {\r\n node.evaluate = node._evaluateStringConversion;\r\n } else if (defined(unaryFunctions[node._value])) {\r\n node.evaluate = getEvaluateUnaryFunction(node._value);\r\n }\r\n } else if (node._type === ExpressionNodeType.BINARY) {\r\n if (node._value === \"+\") {\r\n node.evaluate = node._evaluatePlus;\r\n } else if (node._value === \"-\") {\r\n node.evaluate = node._evaluateMinus;\r\n } else if (node._value === \"*\") {\r\n node.evaluate = node._evaluateTimes;\r\n } else if (node._value === \"/\") {\r\n node.evaluate = node._evaluateDivide;\r\n } else if (node._value === \"%\") {\r\n node.evaluate = node._evaluateMod;\r\n } else if (node._value === \"===\") {\r\n node.evaluate = node._evaluateEqualsStrict;\r\n } else if (node._value === \"!==\") {\r\n node.evaluate = node._evaluateNotEqualsStrict;\r\n } else if (node._value === \"<\") {\r\n node.evaluate = node._evaluateLessThan;\r\n } else if (node._value === \"<=\") {\r\n node.evaluate = node._evaluateLessThanOrEquals;\r\n } else if (node._value === \">\") {\r\n node.evaluate = node._evaluateGreaterThan;\r\n } else if (node._value === \">=\") {\r\n node.evaluate = node._evaluateGreaterThanOrEquals;\r\n } else if (node._value === \"&&\") {\r\n node.evaluate = node._evaluateAnd;\r\n } else if (node._value === \"||\") {\r\n node.evaluate = node._evaluateOr;\r\n } else if (node._value === \"=~\") {\r\n node.evaluate = node._evaluateRegExpMatch;\r\n } else if (node._value === \"!~\") {\r\n node.evaluate = node._evaluateRegExpNotMatch;\r\n } else if (defined(binaryFunctions[node._value])) {\r\n node.evaluate = getEvaluateBinaryFunction(node._value);\r\n }\r\n } else if (node._type === ExpressionNodeType.TERNARY) {\r\n node.evaluate = getEvaluateTernaryFunction(node._value);\r\n } else if (node._type === ExpressionNodeType.MEMBER) {\r\n if (node._value === \"brackets\") {\r\n node.evaluate = node._evaluateMemberBrackets;\r\n } else {\r\n node.evaluate = node._evaluateMemberDot;\r\n }\r\n } else if (node._type === ExpressionNodeType.ARRAY) {\r\n node.evaluate = node._evaluateArray;\r\n } else if (node._type === ExpressionNodeType.VARIABLE) {\r\n node.evaluate = node._evaluateVariable;\r\n } else if (node._type === ExpressionNodeType.VARIABLE_IN_STRING) {\r\n node.evaluate = node._evaluateVariableString;\r\n } else if (node._type === ExpressionNodeType.LITERAL_COLOR) {\r\n node.evaluate = node._evaluateLiteralColor;\r\n } else if (node._type === ExpressionNodeType.LITERAL_VECTOR) {\r\n node.evaluate = node._evaluateLiteralVector;\r\n } else if (node._type === ExpressionNodeType.LITERAL_STRING) {\r\n node.evaluate = node._evaluateLiteralString;\r\n } else if (node._type === ExpressionNodeType.REGEX) {\r\n node.evaluate = node._evaluateRegExp;\r\n } else if (node._type === ExpressionNodeType.BUILTIN_VARIABLE) {\r\n if (node._value === \"tiles3d_tileset_time\") {\r\n node.evaluate = evaluateTilesetTime;\r\n }\r\n } else {\r\n node.evaluate = node._evaluateLiteral;\r\n }\r\n}\r\n\r\nfunction evaluateTilesetTime(feature) {\r\n if (!defined(feature)) {\r\n return 0.0;\r\n }\r\n return feature.content.tileset.timeSinceLoad;\r\n}\r\n\r\nfunction getEvaluateUnaryFunction(call) {\r\n var evaluate = unaryFunctions[call];\r\n return function (feature) {\r\n var left = this._left.evaluate(feature);\r\n return evaluate(call, left);\r\n };\r\n}\r\n\r\nfunction getEvaluateBinaryFunction(call) {\r\n var evaluate = binaryFunctions[call];\r\n return function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n return evaluate(call, left, right);\r\n };\r\n}\r\n\r\nfunction getEvaluateTernaryFunction(call) {\r\n var evaluate = ternaryFunctions[call];\r\n return function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n var test = this._test.evaluate(feature);\r\n return evaluate(call, left, right, test);\r\n };\r\n}\r\n\r\nfunction getFeatureProperty(feature, name) {\r\n // Returns undefined if the feature is not defined or the property name is not defined for that feature\r\n if (defined(feature)) {\r\n return feature.getProperty(name);\r\n }\r\n}\r\n\r\nNode.prototype._evaluateLiteral = function () {\r\n return this._value;\r\n};\r\n\r\nNode.prototype._evaluateLiteralColor = function (feature) {\r\n var color = scratchColor;\r\n var args = this._left;\r\n if (this._value === \"color\") {\r\n if (!defined(args)) {\r\n Color.fromBytes(255, 255, 255, 255, color);\r\n } else if (args.length > 1) {\r\n Color.fromCssColorString(args[0].evaluate(feature), color);\r\n color.alpha = args[1].evaluate(feature);\r\n } else {\r\n Color.fromCssColorString(args[0].evaluate(feature), color);\r\n }\r\n } else if (this._value === \"rgb\") {\r\n Color.fromBytes(\r\n args[0].evaluate(feature),\r\n args[1].evaluate(feature),\r\n args[2].evaluate(feature),\r\n 255,\r\n color\r\n );\r\n } else if (this._value === \"rgba\") {\r\n // convert between css alpha (0 to 1) and cesium alpha (0 to 255)\r\n var a = args[3].evaluate(feature) * 255;\r\n Color.fromBytes(\r\n args[0].evaluate(feature),\r\n args[1].evaluate(feature),\r\n args[2].evaluate(feature),\r\n a,\r\n color\r\n );\r\n } else if (this._value === \"hsl\") {\r\n Color.fromHsl(\r\n args[0].evaluate(feature),\r\n args[1].evaluate(feature),\r\n args[2].evaluate(feature),\r\n 1.0,\r\n color\r\n );\r\n } else if (this._value === \"hsla\") {\r\n Color.fromHsl(\r\n args[0].evaluate(feature),\r\n args[1].evaluate(feature),\r\n args[2].evaluate(feature),\r\n args[3].evaluate(feature),\r\n color\r\n );\r\n }\r\n return Cartesian4.fromColor(color, scratchStorage.getCartesian4());\r\n};\r\n\r\nNode.prototype._evaluateLiteralVector = function (feature) {\r\n // Gather the components that make up the vector, which includes components from interior vectors.\r\n // For example vec3(1, 2, 3) or vec3(vec2(1, 2), 3) are both valid.\r\n //\r\n // If the number of components does not equal the vector's size, then a RuntimeError is thrown - with two exceptions:\r\n // 1. A vector may be constructed from a larger vector and drop the extra components.\r\n // 2. A vector may be constructed from a single component - vec3(1) will become vec3(1, 1, 1).\r\n //\r\n // Examples of invalid constructors include:\r\n // vec4(1, 2) // not enough components\r\n // vec3(vec2(1, 2)) // not enough components\r\n // vec3(1, 2, 3, 4) // too many components\r\n // vec2(vec4(1), 1) // too many components\r\n\r\n var components = scratchStorage.getArray();\r\n var call = this._value;\r\n var args = this._left;\r\n var argsLength = args.length;\r\n for (var i = 0; i < argsLength; ++i) {\r\n var value = args[i].evaluate(feature);\r\n if (typeof value === \"number\") {\r\n components.push(value);\r\n } else if (value instanceof Cartesian2) {\r\n components.push(value.x, value.y);\r\n } else if (value instanceof Cartesian3) {\r\n components.push(value.x, value.y, value.z);\r\n } else if (value instanceof Cartesian4) {\r\n components.push(value.x, value.y, value.z, value.w);\r\n } else {\r\n throw new RuntimeError(\r\n call +\r\n \" argument must be a vector or number. Argument is \" +\r\n value +\r\n \".\"\r\n );\r\n }\r\n }\r\n\r\n var componentsLength = components.length;\r\n var vectorLength = parseInt(call.charAt(3));\r\n\r\n if (componentsLength === 0) {\r\n throw new RuntimeError(\r\n \"Invalid \" + call + \" constructor. No valid arguments.\"\r\n );\r\n } else if (componentsLength < vectorLength && componentsLength > 1) {\r\n throw new RuntimeError(\r\n \"Invalid \" + call + \" constructor. Not enough arguments.\"\r\n );\r\n } else if (componentsLength > vectorLength && argsLength > 1) {\r\n throw new RuntimeError(\r\n \"Invalid \" + call + \" constructor. Too many arguments.\"\r\n );\r\n }\r\n\r\n if (componentsLength === 1) {\r\n // Add the same component 3 more times\r\n var component = components[0];\r\n components.push(component, component, component);\r\n }\r\n\r\n if (call === \"vec2\") {\r\n return Cartesian2.fromArray(components, 0, scratchStorage.getCartesian2());\r\n } else if (call === \"vec3\") {\r\n return Cartesian3.fromArray(components, 0, scratchStorage.getCartesian3());\r\n } else if (call === \"vec4\") {\r\n return Cartesian4.fromArray(components, 0, scratchStorage.getCartesian4());\r\n }\r\n};\r\n\r\nNode.prototype._evaluateLiteralString = function () {\r\n return this._value;\r\n};\r\n\r\nNode.prototype._evaluateVariableString = function (feature) {\r\n var result = this._value;\r\n var match = variableRegex.exec(result);\r\n while (match !== null) {\r\n var placeholder = match[0];\r\n var variableName = match[1];\r\n var property = getFeatureProperty(feature, variableName);\r\n if (!defined(property)) {\r\n property = \"\";\r\n }\r\n result = result.replace(placeholder, property);\r\n match = variableRegex.exec(result);\r\n }\r\n return result;\r\n};\r\n\r\nNode.prototype._evaluateVariable = function (feature) {\r\n // evaluates to undefined if the property name is not defined for that feature\r\n return getFeatureProperty(feature, this._value);\r\n};\r\n\r\nfunction checkFeature(ast) {\r\n return ast._value === \"feature\";\r\n}\r\n\r\n// PERFORMANCE_IDEA: Determine if parent property needs to be computed before runtime\r\nNode.prototype._evaluateMemberDot = function (feature) {\r\n if (checkFeature(this._left)) {\r\n return getFeatureProperty(feature, this._right.evaluate(feature));\r\n }\r\n var property = this._left.evaluate(feature);\r\n if (!defined(property)) {\r\n return undefined;\r\n }\r\n\r\n var member = this._right.evaluate(feature);\r\n if (\r\n property instanceof Cartesian2 ||\r\n property instanceof Cartesian3 ||\r\n property instanceof Cartesian4\r\n ) {\r\n // Vector components may be accessed with .r, .g, .b, .a and implicitly with .x, .y, .z, .w\r\n if (member === \"r\") {\r\n return property.x;\r\n } else if (member === \"g\") {\r\n return property.y;\r\n } else if (member === \"b\") {\r\n return property.z;\r\n } else if (member === \"a\") {\r\n return property.w;\r\n }\r\n }\r\n return property[member];\r\n};\r\n\r\nNode.prototype._evaluateMemberBrackets = function (feature) {\r\n if (checkFeature(this._left)) {\r\n return getFeatureProperty(feature, this._right.evaluate(feature));\r\n }\r\n var property = this._left.evaluate(feature);\r\n if (!defined(property)) {\r\n return undefined;\r\n }\r\n\r\n var member = this._right.evaluate(feature);\r\n if (\r\n property instanceof Cartesian2 ||\r\n property instanceof Cartesian3 ||\r\n property instanceof Cartesian4\r\n ) {\r\n // Vector components may be accessed with [0][1][2][3], ['r']['g']['b']['a'] and implicitly with ['x']['y']['z']['w']\r\n // For Cartesian2 and Cartesian3 out-of-range components will just return undefined\r\n if (member === 0 || member === \"r\") {\r\n return property.x;\r\n } else if (member === 1 || member === \"g\") {\r\n return property.y;\r\n } else if (member === 2 || member === \"b\") {\r\n return property.z;\r\n } else if (member === 3 || member === \"a\") {\r\n return property.w;\r\n }\r\n }\r\n return property[member];\r\n};\r\n\r\nNode.prototype._evaluateArray = function (feature) {\r\n var array = [];\r\n for (var i = 0; i < this._value.length; i++) {\r\n array[i] = this._value[i].evaluate(feature);\r\n }\r\n return array;\r\n};\r\n\r\n// PERFORMANCE_IDEA: Have \"fast path\" functions that deal only with specific types\r\n// that we can assign if we know the types before runtime\r\n\r\nNode.prototype._evaluateNot = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n if (typeof left !== \"boolean\") {\r\n throw new RuntimeError(\r\n 'Operator \"!\" requires a boolean argument. Argument is ' + left + \".\"\r\n );\r\n }\r\n return !left;\r\n};\r\n\r\nNode.prototype._evaluateNegative = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n if (left instanceof Cartesian2) {\r\n return Cartesian2.negate(left, scratchStorage.getCartesian2());\r\n } else if (left instanceof Cartesian3) {\r\n return Cartesian3.negate(left, scratchStorage.getCartesian3());\r\n } else if (left instanceof Cartesian4) {\r\n return Cartesian4.negate(left, scratchStorage.getCartesian4());\r\n } else if (typeof left === \"number\") {\r\n return -left;\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Operator \"-\" requires a vector or number argument. Argument is ' +\r\n left +\r\n \".\"\r\n );\r\n};\r\n\r\nNode.prototype._evaluatePositive = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n\r\n if (\r\n !(\r\n left instanceof Cartesian2 ||\r\n left instanceof Cartesian3 ||\r\n left instanceof Cartesian4 ||\r\n typeof left === \"number\"\r\n )\r\n ) {\r\n throw new RuntimeError(\r\n 'Operator \"+\" requires a vector or number argument. Argument is ' +\r\n left +\r\n \".\"\r\n );\r\n }\r\n\r\n return left;\r\n};\r\n\r\nNode.prototype._evaluateLessThan = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n\r\n if (typeof left !== \"number\" || typeof right !== \"number\") {\r\n throw new RuntimeError(\r\n 'Operator \"<\" requires number arguments. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n }\r\n\r\n return left < right;\r\n};\r\n\r\nNode.prototype._evaluateLessThanOrEquals = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n\r\n if (typeof left !== \"number\" || typeof right !== \"number\") {\r\n throw new RuntimeError(\r\n 'Operator \"<=\" requires number arguments. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n }\r\n\r\n return left <= right;\r\n};\r\n\r\nNode.prototype._evaluateGreaterThan = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n\r\n if (typeof left !== \"number\" || typeof right !== \"number\") {\r\n throw new RuntimeError(\r\n 'Operator \">\" requires number arguments. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n }\r\n\r\n return left > right;\r\n};\r\n\r\nNode.prototype._evaluateGreaterThanOrEquals = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n\r\n if (typeof left !== \"number\" || typeof right !== \"number\") {\r\n throw new RuntimeError(\r\n 'Operator \">=\" requires number arguments. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n }\r\n\r\n return left >= right;\r\n};\r\n\r\nNode.prototype._evaluateOr = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n if (typeof left !== \"boolean\") {\r\n throw new RuntimeError(\r\n 'Operator \"||\" requires boolean arguments. First argument is ' +\r\n left +\r\n \".\"\r\n );\r\n }\r\n\r\n // short circuit the expression\r\n if (left) {\r\n return true;\r\n }\r\n\r\n var right = this._right.evaluate(feature);\r\n if (typeof right !== \"boolean\") {\r\n throw new RuntimeError(\r\n 'Operator \"||\" requires boolean arguments. Second argument is ' +\r\n right +\r\n \".\"\r\n );\r\n }\r\n\r\n return left || right;\r\n};\r\n\r\nNode.prototype._evaluateAnd = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n if (typeof left !== \"boolean\") {\r\n throw new RuntimeError(\r\n 'Operator \"&&\" requires boolean arguments. First argument is ' +\r\n left +\r\n \".\"\r\n );\r\n }\r\n\r\n // short circuit the expression\r\n if (!left) {\r\n return false;\r\n }\r\n\r\n var right = this._right.evaluate(feature);\r\n if (typeof right !== \"boolean\") {\r\n throw new RuntimeError(\r\n 'Operator \"&&\" requires boolean arguments. Second argument is ' +\r\n right +\r\n \".\"\r\n );\r\n }\r\n\r\n return left && right;\r\n};\r\n\r\nNode.prototype._evaluatePlus = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n if (right instanceof Cartesian2 && left instanceof Cartesian2) {\r\n return Cartesian2.add(left, right, scratchStorage.getCartesian2());\r\n } else if (right instanceof Cartesian3 && left instanceof Cartesian3) {\r\n return Cartesian3.add(left, right, scratchStorage.getCartesian3());\r\n } else if (right instanceof Cartesian4 && left instanceof Cartesian4) {\r\n return Cartesian4.add(left, right, scratchStorage.getCartesian4());\r\n } else if (typeof left === \"string\" || typeof right === \"string\") {\r\n // If only one argument is a string the other argument calls its toString function.\r\n return left + right;\r\n } else if (typeof left === \"number\" && typeof right === \"number\") {\r\n return left + right;\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Operator \"+\" requires vector or number arguments of matching types, or at least one string argument. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n};\r\n\r\nNode.prototype._evaluateMinus = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n if (right instanceof Cartesian2 && left instanceof Cartesian2) {\r\n return Cartesian2.subtract(left, right, scratchStorage.getCartesian2());\r\n } else if (right instanceof Cartesian3 && left instanceof Cartesian3) {\r\n return Cartesian3.subtract(left, right, scratchStorage.getCartesian3());\r\n } else if (right instanceof Cartesian4 && left instanceof Cartesian4) {\r\n return Cartesian4.subtract(left, right, scratchStorage.getCartesian4());\r\n } else if (typeof left === \"number\" && typeof right === \"number\") {\r\n return left - right;\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Operator \"-\" requires vector or number arguments of matching types. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n};\r\n\r\nNode.prototype._evaluateTimes = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n if (right instanceof Cartesian2 && left instanceof Cartesian2) {\r\n return Cartesian2.multiplyComponents(\r\n left,\r\n right,\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (right instanceof Cartesian2 && typeof left === \"number\") {\r\n return Cartesian2.multiplyByScalar(\r\n right,\r\n left,\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (left instanceof Cartesian2 && typeof right === \"number\") {\r\n return Cartesian2.multiplyByScalar(\r\n left,\r\n right,\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (right instanceof Cartesian3 && left instanceof Cartesian3) {\r\n return Cartesian3.multiplyComponents(\r\n left,\r\n right,\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (right instanceof Cartesian3 && typeof left === \"number\") {\r\n return Cartesian3.multiplyByScalar(\r\n right,\r\n left,\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (left instanceof Cartesian3 && typeof right === \"number\") {\r\n return Cartesian3.multiplyByScalar(\r\n left,\r\n right,\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (right instanceof Cartesian4 && left instanceof Cartesian4) {\r\n return Cartesian4.multiplyComponents(\r\n left,\r\n right,\r\n scratchStorage.getCartesian4()\r\n );\r\n } else if (right instanceof Cartesian4 && typeof left === \"number\") {\r\n return Cartesian4.multiplyByScalar(\r\n right,\r\n left,\r\n scratchStorage.getCartesian4()\r\n );\r\n } else if (left instanceof Cartesian4 && typeof right === \"number\") {\r\n return Cartesian4.multiplyByScalar(\r\n left,\r\n right,\r\n scratchStorage.getCartesian4()\r\n );\r\n } else if (typeof left === \"number\" && typeof right === \"number\") {\r\n return left * right;\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Operator \"*\" requires vector or number arguments. If both arguments are vectors they must be matching types. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n};\r\n\r\nNode.prototype._evaluateDivide = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n if (right instanceof Cartesian2 && left instanceof Cartesian2) {\r\n return Cartesian2.divideComponents(\r\n left,\r\n right,\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (left instanceof Cartesian2 && typeof right === \"number\") {\r\n return Cartesian2.divideByScalar(\r\n left,\r\n right,\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (right instanceof Cartesian3 && left instanceof Cartesian3) {\r\n return Cartesian3.divideComponents(\r\n left,\r\n right,\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (left instanceof Cartesian3 && typeof right === \"number\") {\r\n return Cartesian3.divideByScalar(\r\n left,\r\n right,\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (right instanceof Cartesian4 && left instanceof Cartesian4) {\r\n return Cartesian4.divideComponents(\r\n left,\r\n right,\r\n scratchStorage.getCartesian4()\r\n );\r\n } else if (left instanceof Cartesian4 && typeof right === \"number\") {\r\n return Cartesian4.divideByScalar(\r\n left,\r\n right,\r\n scratchStorage.getCartesian4()\r\n );\r\n } else if (typeof left === \"number\" && typeof right === \"number\") {\r\n return left / right;\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Operator \"/\" requires vector or number arguments of matching types, or a number as the second argument. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n};\r\n\r\nNode.prototype._evaluateMod = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n if (right instanceof Cartesian2 && left instanceof Cartesian2) {\r\n return Cartesian2.fromElements(\r\n left.x % right.x,\r\n left.y % right.y,\r\n scratchStorage.getCartesian2()\r\n );\r\n } else if (right instanceof Cartesian3 && left instanceof Cartesian3) {\r\n return Cartesian3.fromElements(\r\n left.x % right.x,\r\n left.y % right.y,\r\n left.z % right.z,\r\n scratchStorage.getCartesian3()\r\n );\r\n } else if (right instanceof Cartesian4 && left instanceof Cartesian4) {\r\n return Cartesian4.fromElements(\r\n left.x % right.x,\r\n left.y % right.y,\r\n left.z % right.z,\r\n left.w % right.w,\r\n scratchStorage.getCartesian4()\r\n );\r\n } else if (typeof left === \"number\" && typeof right === \"number\") {\r\n return left % right;\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Operator \"%\" requires vector or number arguments of matching types. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n};\r\n\r\nNode.prototype._evaluateEqualsStrict = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n if (\r\n (right instanceof Cartesian2 && left instanceof Cartesian2) ||\r\n (right instanceof Cartesian3 && left instanceof Cartesian3) ||\r\n (right instanceof Cartesian4 && left instanceof Cartesian4)\r\n ) {\r\n return left.equals(right);\r\n }\r\n return left === right;\r\n};\r\n\r\nNode.prototype._evaluateNotEqualsStrict = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n if (\r\n (right instanceof Cartesian2 && left instanceof Cartesian2) ||\r\n (right instanceof Cartesian3 && left instanceof Cartesian3) ||\r\n (right instanceof Cartesian4 && left instanceof Cartesian4)\r\n ) {\r\n return !left.equals(right);\r\n }\r\n return left !== right;\r\n};\r\n\r\nNode.prototype._evaluateConditional = function (feature) {\r\n var test = this._test.evaluate(feature);\r\n\r\n if (typeof test !== \"boolean\") {\r\n throw new RuntimeError(\r\n \"Conditional argument of conditional expression must be a boolean. Argument is \" +\r\n test +\r\n \".\"\r\n );\r\n }\r\n\r\n if (test) {\r\n return this._left.evaluate(feature);\r\n }\r\n return this._right.evaluate(feature);\r\n};\r\n\r\nNode.prototype._evaluateNaN = function (feature) {\r\n return isNaN(this._left.evaluate(feature));\r\n};\r\n\r\nNode.prototype._evaluateIsFinite = function (feature) {\r\n return isFinite(this._left.evaluate(feature));\r\n};\r\n\r\nNode.prototype._evaluateIsExactClass = function (feature) {\r\n if (defined(feature)) {\r\n return feature.isExactClass(this._left.evaluate(feature));\r\n }\r\n return false;\r\n};\r\n\r\nNode.prototype._evaluateIsClass = function (feature) {\r\n if (defined(feature)) {\r\n return feature.isClass(this._left.evaluate(feature));\r\n }\r\n return false;\r\n};\r\n\r\nNode.prototype._evaluateGetExactClassName = function (feature) {\r\n if (defined(feature)) {\r\n return feature.getExactClassName();\r\n }\r\n};\r\n\r\nNode.prototype._evaluateBooleanConversion = function (feature) {\r\n return Boolean(this._left.evaluate(feature));\r\n};\r\n\r\nNode.prototype._evaluateNumberConversion = function (feature) {\r\n return Number(this._left.evaluate(feature));\r\n};\r\n\r\nNode.prototype._evaluateStringConversion = function (feature) {\r\n return String(this._left.evaluate(feature));\r\n};\r\n\r\nNode.prototype._evaluateRegExp = function (feature) {\r\n var pattern = this._value.evaluate(feature);\r\n var flags = \"\";\r\n\r\n if (defined(this._left)) {\r\n flags = this._left.evaluate(feature);\r\n }\r\n\r\n var exp;\r\n try {\r\n exp = new RegExp(pattern, flags);\r\n } catch (e) {\r\n throw new RuntimeError(e);\r\n }\r\n return exp;\r\n};\r\n\r\nNode.prototype._evaluateRegExpTest = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n\r\n if (!(left instanceof RegExp && typeof right === \"string\")) {\r\n throw new RuntimeError(\r\n \"RegExp.test requires the first argument to be a RegExp and the second argument to be a string. Arguments are \" +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n }\r\n\r\n return left.test(right);\r\n};\r\n\r\nNode.prototype._evaluateRegExpMatch = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n\r\n if (left instanceof RegExp && typeof right === \"string\") {\r\n return left.test(right);\r\n } else if (right instanceof RegExp && typeof left === \"string\") {\r\n return right.test(left);\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Operator \"=~\" requires one RegExp argument and one string argument. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n};\r\n\r\nNode.prototype._evaluateRegExpNotMatch = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n\r\n if (left instanceof RegExp && typeof right === \"string\") {\r\n return !left.test(right);\r\n } else if (right instanceof RegExp && typeof left === \"string\") {\r\n return !right.test(left);\r\n }\r\n\r\n throw new RuntimeError(\r\n 'Operator \"!~\" requires one RegExp argument and one string argument. Arguments are ' +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n};\r\n\r\nNode.prototype._evaluateRegExpExec = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n var right = this._right.evaluate(feature);\r\n\r\n if (!(left instanceof RegExp && typeof right === \"string\")) {\r\n throw new RuntimeError(\r\n \"RegExp.exec requires the first argument to be a RegExp and the second argument to be a string. Arguments are \" +\r\n left +\r\n \" and \" +\r\n right +\r\n \".\"\r\n );\r\n }\r\n\r\n var exec = left.exec(right);\r\n if (!defined(exec)) {\r\n return null;\r\n }\r\n return exec[1];\r\n};\r\n\r\nNode.prototype._evaluateToString = function (feature) {\r\n var left = this._left.evaluate(feature);\r\n if (\r\n left instanceof RegExp ||\r\n left instanceof Cartesian2 ||\r\n left instanceof Cartesian3 ||\r\n left instanceof Cartesian4\r\n ) {\r\n return String(left);\r\n }\r\n\r\n throw new RuntimeError('Unexpected function call \"' + this._value + '\".');\r\n};\r\n\r\nfunction convertHSLToRGB(ast) {\r\n // Check if the color contains any nested expressions to see if the color can be converted here.\r\n // E.g. \"hsl(0.9, 0.6, 0.7)\" is able to convert directly to rgb, \"hsl(0.9, 0.6, ${Height})\" is not.\r\n var channels = ast._left;\r\n var length = channels.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (channels[i]._type !== ExpressionNodeType.LITERAL_NUMBER) {\r\n return undefined;\r\n }\r\n }\r\n var h = channels[0]._value;\r\n var s = channels[1]._value;\r\n var l = channels[2]._value;\r\n var a = length === 4 ? channels[3]._value : 1.0;\r\n return Color.fromHsl(h, s, l, a, scratchColor);\r\n}\r\n\r\nfunction convertRGBToColor(ast) {\r\n // Check if the color contains any nested expressions to see if the color can be converted here.\r\n // E.g. \"rgb(255, 255, 255)\" is able to convert directly to Color, \"rgb(255, 255, ${Height})\" is not.\r\n var channels = ast._left;\r\n var length = channels.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (channels[i]._type !== ExpressionNodeType.LITERAL_NUMBER) {\r\n return undefined;\r\n }\r\n }\r\n var color = scratchColor;\r\n color.red = channels[0]._value / 255.0;\r\n color.green = channels[1]._value / 255.0;\r\n color.blue = channels[2]._value / 255.0;\r\n color.alpha = length === 4 ? channels[3]._value : 1.0;\r\n return color;\r\n}\r\n\r\nfunction numberToString(number) {\r\n if (number % 1 === 0) {\r\n // Add a .0 to whole numbers\r\n return number.toFixed(1);\r\n }\r\n\r\n return number.toString();\r\n}\r\n\r\nfunction colorToVec3(color) {\r\n var r = numberToString(color.red);\r\n var g = numberToString(color.green);\r\n var b = numberToString(color.blue);\r\n return \"vec3(\" + r + \", \" + g + \", \" + b + \")\";\r\n}\r\n\r\nfunction colorToVec4(color) {\r\n var r = numberToString(color.red);\r\n var g = numberToString(color.green);\r\n var b = numberToString(color.blue);\r\n var a = numberToString(color.alpha);\r\n return \"vec4(\" + r + \", \" + g + \", \" + b + \", \" + a + \")\";\r\n}\r\n\r\nfunction getExpressionArray(array, propertyNameMap, shaderState, parent) {\r\n var length = array.length;\r\n var expressions = new Array(length);\r\n for (var i = 0; i < length; ++i) {\r\n expressions[i] = array[i].getShaderExpression(\r\n propertyNameMap,\r\n shaderState,\r\n parent\r\n );\r\n }\r\n return expressions;\r\n}\r\n\r\nfunction getVariableName(variableName, propertyNameMap) {\r\n if (!defined(propertyNameMap[variableName])) {\r\n throw new RuntimeError(\r\n 'Style references a property \"' +\r\n variableName +\r\n '\" that does not exist or is not styleable.'\r\n );\r\n }\r\n\r\n return propertyNameMap[variableName];\r\n}\r\n\r\nvar nullSentinel = \"czm_infinity\"; // null just needs to be some sentinel value that will cause \"[expression] === null\" to be false in nearly all cases. GLSL doesn't have a NaN constant so use czm_infinity.\r\n\r\nNode.prototype.getShaderExpression = function (\r\n propertyNameMap,\r\n shaderState,\r\n parent\r\n) {\r\n var color;\r\n var left;\r\n var right;\r\n var test;\r\n\r\n var type = this._type;\r\n var value = this._value;\r\n\r\n if (defined(this._left)) {\r\n if (Array.isArray(this._left)) {\r\n // Left can be an array if the type is LITERAL_COLOR or LITERAL_VECTOR\r\n left = getExpressionArray(this._left, propertyNameMap, shaderState, this);\r\n } else {\r\n left = this._left.getShaderExpression(propertyNameMap, shaderState, this);\r\n }\r\n }\r\n\r\n if (defined(this._right)) {\r\n right = this._right.getShaderExpression(propertyNameMap, shaderState, this);\r\n }\r\n\r\n if (defined(this._test)) {\r\n test = this._test.getShaderExpression(propertyNameMap, shaderState, this);\r\n }\r\n\r\n if (Array.isArray(this._value)) {\r\n // For ARRAY type\r\n value = getExpressionArray(this._value, propertyNameMap, shaderState, this);\r\n }\r\n\r\n switch (type) {\r\n case ExpressionNodeType.VARIABLE:\r\n if (checkFeature(this)) {\r\n return undefined;\r\n }\r\n return getVariableName(value, propertyNameMap);\r\n case ExpressionNodeType.UNARY:\r\n // Supported types: +, -, !, Boolean, Number\r\n if (value === \"Boolean\") {\r\n return \"bool(\" + left + \")\";\r\n } else if (value === \"Number\") {\r\n return \"float(\" + left + \")\";\r\n } else if (value === \"round\") {\r\n return \"floor(\" + left + \" + 0.5)\";\r\n } else if (defined(unaryFunctions[value])) {\r\n return value + \"(\" + left + \")\";\r\n } else if (value === \"isNaN\") {\r\n // In GLSL 2.0 use isnan instead\r\n return \"(\" + left + \" != \" + left + \")\";\r\n } else if (value === \"isFinite\") {\r\n // In GLSL 2.0 use isinf instead. GLSL doesn't have an infinity constant so use czm_infinity which is an arbitrarily big enough number.\r\n return \"(abs(\" + left + \") < czm_infinity)\";\r\n } else if (\r\n value === \"String\" ||\r\n value === \"isExactClass\" ||\r\n value === \"isClass\" ||\r\n value === \"getExactClassName\"\r\n ) {\r\n throw new RuntimeError(\r\n 'Error generating style shader: \"' + value + '\" is not supported.'\r\n );\r\n }\r\n return value + left;\r\n case ExpressionNodeType.BINARY:\r\n // Supported types: ||, &&, ===, !==, <, >, <=, >=, +, -, *, /, %\r\n if (value === \"%\") {\r\n return \"mod(\" + left + \", \" + right + \")\";\r\n } else if (value === \"===\") {\r\n return \"(\" + left + \" == \" + right + \")\";\r\n } else if (value === \"!==\") {\r\n return \"(\" + left + \" != \" + right + \")\";\r\n } else if (value === \"atan2\") {\r\n return \"atan(\" + left + \", \" + right + \")\";\r\n } else if (defined(binaryFunctions[value])) {\r\n return value + \"(\" + left + \", \" + right + \")\";\r\n }\r\n return \"(\" + left + \" \" + value + \" \" + right + \")\";\r\n case ExpressionNodeType.TERNARY:\r\n if (defined(ternaryFunctions[value])) {\r\n return value + \"(\" + left + \", \" + right + \", \" + test + \")\";\r\n }\r\n break;\r\n case ExpressionNodeType.CONDITIONAL:\r\n return \"(\" + test + \" ? \" + left + \" : \" + right + \")\";\r\n case ExpressionNodeType.MEMBER:\r\n if (checkFeature(this._left)) {\r\n return getVariableName(right, propertyNameMap);\r\n }\r\n // This is intended for accessing the components of vector properties. String members aren't supported.\r\n // Check for 0.0 rather than 0 because all numbers are previously converted to decimals.\r\n if (right === \"r\" || right === \"x\" || right === \"0.0\") {\r\n return left + \"[0]\";\r\n } else if (right === \"g\" || right === \"y\" || right === \"1.0\") {\r\n return left + \"[1]\";\r\n } else if (right === \"b\" || right === \"z\" || right === \"2.0\") {\r\n return left + \"[2]\";\r\n } else if (right === \"a\" || right === \"w\" || right === \"3.0\") {\r\n return left + \"[3]\";\r\n }\r\n return left + \"[int(\" + right + \")]\";\r\n case ExpressionNodeType.FUNCTION_CALL:\r\n throw new RuntimeError(\r\n 'Error generating style shader: \"' + value + '\" is not supported.'\r\n );\r\n case ExpressionNodeType.ARRAY:\r\n if (value.length === 4) {\r\n return (\r\n \"vec4(\" +\r\n value[0] +\r\n \", \" +\r\n value[1] +\r\n \", \" +\r\n value[2] +\r\n \", \" +\r\n value[3] +\r\n \")\"\r\n );\r\n } else if (value.length === 3) {\r\n return \"vec3(\" + value[0] + \", \" + value[1] + \", \" + value[2] + \")\";\r\n } else if (value.length === 2) {\r\n return \"vec2(\" + value[0] + \", \" + value[1] + \")\";\r\n }\r\n throw new RuntimeError(\r\n \"Error generating style shader: Invalid array length. Array length should be 2, 3, or 4.\"\r\n );\r\n case ExpressionNodeType.REGEX:\r\n throw new RuntimeError(\r\n \"Error generating style shader: Regular expressions are not supported.\"\r\n );\r\n case ExpressionNodeType.VARIABLE_IN_STRING:\r\n throw new RuntimeError(\r\n \"Error generating style shader: Converting a variable to a string is not supported.\"\r\n );\r\n case ExpressionNodeType.LITERAL_NULL:\r\n return nullSentinel;\r\n case ExpressionNodeType.LITERAL_BOOLEAN:\r\n return value ? \"true\" : \"false\";\r\n case ExpressionNodeType.LITERAL_NUMBER:\r\n return numberToString(value);\r\n case ExpressionNodeType.LITERAL_STRING:\r\n if (defined(parent) && parent._type === ExpressionNodeType.MEMBER) {\r\n if (\r\n value === \"r\" ||\r\n value === \"g\" ||\r\n value === \"b\" ||\r\n value === \"a\" ||\r\n value === \"x\" ||\r\n value === \"y\" ||\r\n value === \"z\" ||\r\n value === \"w\" ||\r\n checkFeature(parent._left)\r\n ) {\r\n return value;\r\n }\r\n }\r\n // Check for css color strings\r\n color = Color.fromCssColorString(value, scratchColor);\r\n if (defined(color)) {\r\n return colorToVec3(color);\r\n }\r\n throw new RuntimeError(\r\n \"Error generating style shader: String literals are not supported.\"\r\n );\r\n case ExpressionNodeType.LITERAL_COLOR:\r\n var args = left;\r\n if (value === \"color\") {\r\n if (!defined(args)) {\r\n return \"vec4(1.0)\";\r\n } else if (args.length > 1) {\r\n var rgb = args[0];\r\n var alpha = args[1];\r\n if (alpha !== \"1.0\") {\r\n shaderState.translucent = true;\r\n }\r\n return \"vec4(\" + rgb + \", \" + alpha + \")\";\r\n }\r\n return \"vec4(\" + args[0] + \", 1.0)\";\r\n } else if (value === \"rgb\") {\r\n color = convertRGBToColor(this);\r\n if (defined(color)) {\r\n return colorToVec4(color);\r\n }\r\n return (\r\n \"vec4(\" +\r\n args[0] +\r\n \" / 255.0, \" +\r\n args[1] +\r\n \" / 255.0, \" +\r\n args[2] +\r\n \" / 255.0, 1.0)\"\r\n );\r\n } else if (value === \"rgba\") {\r\n if (args[3] !== \"1.0\") {\r\n shaderState.translucent = true;\r\n }\r\n color = convertRGBToColor(this);\r\n if (defined(color)) {\r\n return colorToVec4(color);\r\n }\r\n return (\r\n \"vec4(\" +\r\n args[0] +\r\n \" / 255.0, \" +\r\n args[1] +\r\n \" / 255.0, \" +\r\n args[2] +\r\n \" / 255.0, \" +\r\n args[3] +\r\n \")\"\r\n );\r\n } else if (value === \"hsl\") {\r\n color = convertHSLToRGB(this);\r\n if (defined(color)) {\r\n return colorToVec4(color);\r\n }\r\n return (\r\n \"vec4(czm_HSLToRGB(vec3(\" +\r\n args[0] +\r\n \", \" +\r\n args[1] +\r\n \", \" +\r\n args[2] +\r\n \")), 1.0)\"\r\n );\r\n } else if (value === \"hsla\") {\r\n color = convertHSLToRGB(this);\r\n if (defined(color)) {\r\n if (color.alpha !== 1.0) {\r\n shaderState.translucent = true;\r\n }\r\n return colorToVec4(color);\r\n }\r\n if (args[3] !== \"1.0\") {\r\n shaderState.translucent = true;\r\n }\r\n return (\r\n \"vec4(czm_HSLToRGB(vec3(\" +\r\n args[0] +\r\n \", \" +\r\n args[1] +\r\n \", \" +\r\n args[2] +\r\n \")), \" +\r\n args[3] +\r\n \")\"\r\n );\r\n }\r\n break;\r\n case ExpressionNodeType.LITERAL_VECTOR:\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(left)) {\r\n throw new DeveloperError(\r\n \"left should always be defined for type ExpressionNodeType.LITERAL_VECTOR\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n var length = left.length;\r\n var vectorExpression = value + \"(\";\r\n for (var i = 0; i < length; ++i) {\r\n vectorExpression += left[i];\r\n if (i < length - 1) {\r\n vectorExpression += \", \";\r\n }\r\n }\r\n vectorExpression += \")\";\r\n return vectorExpression;\r\n case ExpressionNodeType.LITERAL_REGEX:\r\n throw new RuntimeError(\r\n \"Error generating style shader: Regular expressions are not supported.\"\r\n );\r\n case ExpressionNodeType.LITERAL_UNDEFINED:\r\n return nullSentinel;\r\n case ExpressionNodeType.BUILTIN_VARIABLE:\r\n if (value === \"tiles3d_tileset_time\") {\r\n return \"u_time\";\r\n }\r\n }\r\n};\r\nexport default Expression;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport PrimitiveType from \"../Core/PrimitiveType.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport VertexArray from \"../Renderer/VertexArray.js\";\r\nimport ShadowVolumeFS from \"../Shaders/ShadowVolumeFS.js\";\r\nimport VectorTileVS from \"../Shaders/VectorTileVS.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport Cesium3DTileFeature from \"./Cesium3DTileFeature.js\";\r\nimport ClassificationType from \"./ClassificationType.js\";\r\nimport DepthFunction from \"./DepthFunction.js\";\r\nimport Expression from \"./Expression.js\";\r\nimport StencilConstants from \"./StencilConstants.js\";\r\nimport StencilFunction from \"./StencilFunction.js\";\r\nimport StencilOperation from \"./StencilOperation.js\";\r\nimport Vector3DTileBatch from \"./Vector3DTileBatch.js\";\r\n\r\n/**\r\n * Creates a batch of classification meshes.\r\n *\r\n * @alias Vector3DTilePrimitive\r\n * @constructor\r\n *\r\n * @param {Object} options An object with following properties:\r\n * @param {Float32Array} options.positions The positions of the meshes.\r\n * @param {Uint16Array|Uint32Array} options.indices The indices of the triangulated meshes. The indices must be contiguous so that\r\n * the indices for mesh n are in [i, i + indexCounts[n]] where i = sum{indexCounts[0], indexCounts[n - 1]}.\r\n * @param {Uint32Array} options.indexCounts The number of indices for each mesh.\r\n * @param {Uint32Array} options.indexOffsets The offset into the index buffer for each mesh.\r\n * @param {Vector3DTileBatch[]} options.batchedIndices The index offset and count for each batch with the same color.\r\n * @param {Cartesian3} [options.center=Cartesian3.ZERO] The RTC center.\r\n * @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched meshes.\r\n * @param {Uint16Array} options.batchIds The batch ids for each mesh.\r\n * @param {Uint16Array} options.vertexBatchIds The batch id for each vertex.\r\n * @param {BoundingSphere} options.boundingVolume The bounding volume for the entire batch of meshes.\r\n * @param {BoundingSphere[]} options.boundingVolumes The bounding volume for each mesh.\r\n * @param {ClassificationType} [options.classificationType] What this tile will classify.\r\n *\r\n * @private\r\n */\r\nfunction Vector3DTilePrimitive(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._batchTable = options.batchTable;\r\n this._batchIds = options.batchIds;\r\n\r\n // These arrays are released after VAO creation.\r\n this._positions = options.positions;\r\n this._vertexBatchIds = options.vertexBatchIds;\r\n\r\n // These arrays are kept for re-batching indices based on colors.\r\n // If WebGL 2 is supported, indices will be released and re-batching uses buffer-to-buffer copies.\r\n this._indices = options.indices;\r\n this._indexCounts = options.indexCounts;\r\n this._indexOffsets = options.indexOffsets;\r\n this._batchedIndices = options.batchedIndices;\r\n\r\n this._boundingVolume = options.boundingVolume;\r\n this._boundingVolumes = options.boundingVolumes;\r\n\r\n this._center = defaultValue(options.center, Cartesian3.ZERO);\r\n\r\n this._va = undefined;\r\n this._sp = undefined;\r\n this._spStencil = undefined;\r\n this._spPick = undefined;\r\n this._uniformMap = undefined;\r\n\r\n // Only used with WebGL 2 to ping-pong ibos after copy.\r\n this._vaSwap = undefined;\r\n\r\n this._rsStencilDepthPass = undefined;\r\n this._rsStencilDepthPass3DTiles = undefined;\r\n this._rsColorPass = undefined;\r\n this._rsPickPass = undefined;\r\n this._rsWireframe = undefined;\r\n\r\n this._commands = [];\r\n this._commandsIgnoreShow = [];\r\n this._pickCommands = [];\r\n\r\n this._constantColor = Color.clone(Color.WHITE);\r\n this._highlightColor = this._constantColor;\r\n\r\n this._batchDirty = true;\r\n this._pickCommandsDirty = true;\r\n this._framesSinceLastRebatch = 0;\r\n\r\n this._updatingAllCommands = false;\r\n\r\n this._trianglesLength = this._indices.length / 3;\r\n this._geometryByteLength =\r\n this._indices.byteLength +\r\n this._positions.byteLength +\r\n this._vertexBatchIds.byteLength;\r\n\r\n /**\r\n * Draw the wireframe of the classification meshes.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugWireframe = false;\r\n this._debugWireframe = this.debugWireframe;\r\n this._wireframeDirty = false;\r\n\r\n /**\r\n * Forces a re-batch instead of waiting after a number of frames have been rendered. For testing only.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.forceRebatch = false;\r\n\r\n /**\r\n * What this tile will classify.\r\n * @type {ClassificationType}\r\n * @default ClassificationType.BOTH\r\n */\r\n this.classificationType = defaultValue(\r\n options.classificationType,\r\n ClassificationType.BOTH\r\n );\r\n\r\n // Hidden options\r\n this._vertexShaderSource = options._vertexShaderSource;\r\n this._fragmentShaderSource = options._fragmentShaderSource;\r\n this._attributeLocations = options._attributeLocations;\r\n this._uniformMap = options._uniformMap;\r\n this._pickId = options._pickId;\r\n this._modelMatrix = options._modelMatrix;\r\n this._boundingSphere = options._boundingSphere;\r\n\r\n this._batchIdLookUp = {};\r\n\r\n var length = this._batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = this._batchIds[i];\r\n this._batchIdLookUp[batchId] = i;\r\n }\r\n}\r\n\r\nObject.defineProperties(Vector3DTilePrimitive.prototype, {\r\n /**\r\n * Gets the number of triangles.\r\n *\r\n * @memberof Vector3DTilePrimitive.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n trianglesLength: {\r\n get: function () {\r\n return this._trianglesLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the geometry memory in bytes.\r\n *\r\n * @memberof Vector3DTilePrimitive.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n geometryByteLength: {\r\n get: function () {\r\n return this._geometryByteLength;\r\n },\r\n },\r\n});\r\n\r\nvar defaultAttributeLocations = {\r\n position: 0,\r\n a_batchId: 1,\r\n};\r\n\r\nfunction createVertexArray(primitive, context) {\r\n if (defined(primitive._va)) {\r\n return;\r\n }\r\n\r\n var positionBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: primitive._positions,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var idBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: primitive._vertexBatchIds,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: primitive._indices,\r\n usage: BufferUsage.DYNAMIC_DRAW,\r\n indexDatatype:\r\n primitive._indices.BYTES_PER_ELEMENT === 2\r\n ? IndexDatatype.UNSIGNED_SHORT\r\n : IndexDatatype.UNSIGNED_INT,\r\n });\r\n\r\n var vertexAttributes = [\r\n {\r\n index: 0,\r\n vertexBuffer: positionBuffer,\r\n componentDatatype: ComponentDatatype.fromTypedArray(primitive._positions),\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n index: 1,\r\n vertexBuffer: idBuffer,\r\n componentDatatype: ComponentDatatype.fromTypedArray(\r\n primitive._vertexBatchIds\r\n ),\r\n componentsPerAttribute: 1,\r\n },\r\n ];\r\n\r\n primitive._va = new VertexArray({\r\n context: context,\r\n attributes: vertexAttributes,\r\n indexBuffer: indexBuffer,\r\n });\r\n\r\n if (context.webgl2) {\r\n primitive._vaSwap = new VertexArray({\r\n context: context,\r\n attributes: vertexAttributes,\r\n indexBuffer: Buffer.createIndexBuffer({\r\n context: context,\r\n sizeInBytes: indexBuffer.sizeInBytes,\r\n usage: BufferUsage.DYNAMIC_DRAW,\r\n indexDatatype: indexBuffer.indexDatatype,\r\n }),\r\n });\r\n }\r\n\r\n primitive._batchedPositions = undefined;\r\n primitive._transferrableBatchIds = undefined;\r\n primitive._vertexBatchIds = undefined;\r\n primitive._verticesPromise = undefined;\r\n}\r\n\r\nfunction createShaders(primitive, context) {\r\n if (defined(primitive._sp)) {\r\n return;\r\n }\r\n\r\n var batchTable = primitive._batchTable;\r\n var attributeLocations = defaultValue(\r\n primitive._attributeLocations,\r\n defaultAttributeLocations\r\n );\r\n\r\n var pickId = primitive._pickId;\r\n var vertexShaderSource = primitive._vertexShaderSource;\r\n var fragmentShaderSource = primitive._fragmentShaderSource;\r\n if (defined(vertexShaderSource)) {\r\n primitive._sp = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vertexShaderSource,\r\n fragmentShaderSource: fragmentShaderSource,\r\n attributeLocations: attributeLocations,\r\n });\r\n primitive._spStencil = primitive._sp;\r\n\r\n fragmentShaderSource = ShaderSource.replaceMain(\r\n fragmentShaderSource,\r\n \"czm_non_pick_main\"\r\n );\r\n fragmentShaderSource =\r\n fragmentShaderSource +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" czm_non_pick_main(); \\n\" +\r\n \" gl_FragColor = \" +\r\n pickId +\r\n \"; \\n\" +\r\n \"} \\n\";\r\n primitive._spPick = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vertexShaderSource,\r\n fragmentShaderSource: fragmentShaderSource,\r\n attributeLocations: attributeLocations,\r\n });\r\n return;\r\n }\r\n\r\n var vsSource = batchTable.getVertexShaderCallback(\r\n false,\r\n \"a_batchId\",\r\n undefined\r\n )(VectorTileVS);\r\n var fsSource = batchTable.getFragmentShaderCallback(\r\n false,\r\n undefined,\r\n true\r\n )(ShadowVolumeFS);\r\n\r\n pickId = batchTable.getPickId();\r\n\r\n var vs = new ShaderSource({\r\n sources: [vsSource],\r\n });\r\n var fs = new ShaderSource({\r\n defines: [\"VECTOR_TILE\"],\r\n sources: [fsSource],\r\n });\r\n\r\n primitive._sp = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n vs = new ShaderSource({\r\n sources: [VectorTileVS],\r\n });\r\n fs = new ShaderSource({\r\n defines: [\"VECTOR_TILE\"],\r\n sources: [ShadowVolumeFS],\r\n });\r\n\r\n primitive._spStencil = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n fsSource = ShaderSource.replaceMain(fsSource, \"czm_non_pick_main\");\r\n fsSource =\r\n fsSource +\r\n \"\\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" czm_non_pick_main(); \\n\" +\r\n \" gl_FragColor = \" +\r\n pickId +\r\n \"; \\n\" +\r\n \"} \\n\";\r\n\r\n var pickVS = new ShaderSource({\r\n sources: [vsSource],\r\n });\r\n var pickFS = new ShaderSource({\r\n defines: [\"VECTOR_TILE\"],\r\n sources: [fsSource],\r\n });\r\n primitive._spPick = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: pickVS,\r\n fragmentShaderSource: pickFS,\r\n attributeLocations: attributeLocations,\r\n });\r\n}\r\n\r\nfunction getStencilDepthRenderState(mask3DTiles) {\r\n var stencilFunction = mask3DTiles\r\n ? StencilFunction.EQUAL\r\n : StencilFunction.ALWAYS;\r\n return {\r\n colorMask: {\r\n red: false,\r\n green: false,\r\n blue: false,\r\n alpha: false,\r\n },\r\n stencilTest: {\r\n enabled: true,\r\n frontFunction: stencilFunction,\r\n frontOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.DECREMENT_WRAP,\r\n zPass: StencilOperation.KEEP,\r\n },\r\n backFunction: stencilFunction,\r\n backOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.INCREMENT_WRAP,\r\n zPass: StencilOperation.KEEP,\r\n },\r\n reference: StencilConstants.CESIUM_3D_TILE_MASK,\r\n mask: StencilConstants.CESIUM_3D_TILE_MASK,\r\n },\r\n stencilMask: StencilConstants.CLASSIFICATION_MASK,\r\n depthTest: {\r\n enabled: true,\r\n func: DepthFunction.LESS_OR_EQUAL,\r\n },\r\n depthMask: false,\r\n };\r\n}\r\n\r\nvar colorRenderState = {\r\n stencilTest: {\r\n enabled: true,\r\n frontFunction: StencilFunction.NOT_EQUAL,\r\n frontOperation: {\r\n fail: StencilOperation.ZERO,\r\n zFail: StencilOperation.ZERO,\r\n zPass: StencilOperation.ZERO,\r\n },\r\n backFunction: StencilFunction.NOT_EQUAL,\r\n backOperation: {\r\n fail: StencilOperation.ZERO,\r\n zFail: StencilOperation.ZERO,\r\n zPass: StencilOperation.ZERO,\r\n },\r\n reference: 0,\r\n mask: StencilConstants.CLASSIFICATION_MASK,\r\n },\r\n stencilMask: StencilConstants.CLASSIFICATION_MASK,\r\n depthTest: {\r\n enabled: false,\r\n },\r\n depthMask: false,\r\n blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,\r\n};\r\n\r\nvar pickRenderState = {\r\n stencilTest: {\r\n enabled: true,\r\n frontFunction: StencilFunction.NOT_EQUAL,\r\n frontOperation: {\r\n fail: StencilOperation.ZERO,\r\n zFail: StencilOperation.ZERO,\r\n zPass: StencilOperation.ZERO,\r\n },\r\n backFunction: StencilFunction.NOT_EQUAL,\r\n backOperation: {\r\n fail: StencilOperation.ZERO,\r\n zFail: StencilOperation.ZERO,\r\n zPass: StencilOperation.ZERO,\r\n },\r\n reference: 0,\r\n mask: StencilConstants.CLASSIFICATION_MASK,\r\n },\r\n stencilMask: StencilConstants.CLASSIFICATION_MASK,\r\n depthTest: {\r\n enabled: false,\r\n },\r\n depthMask: false,\r\n};\r\n\r\nfunction createRenderStates(primitive) {\r\n if (defined(primitive._rsStencilDepthPass)) {\r\n return;\r\n }\r\n\r\n primitive._rsStencilDepthPass = RenderState.fromCache(\r\n getStencilDepthRenderState(false)\r\n );\r\n primitive._rsStencilDepthPass3DTiles = RenderState.fromCache(\r\n getStencilDepthRenderState(true)\r\n );\r\n primitive._rsColorPass = RenderState.fromCache(colorRenderState);\r\n primitive._rsPickPass = RenderState.fromCache(pickRenderState);\r\n}\r\n\r\nvar modifiedModelViewScratch = new Matrix4();\r\nvar rtcScratch = new Cartesian3();\r\n\r\nfunction createUniformMap(primitive, context) {\r\n if (defined(primitive._uniformMap)) {\r\n return;\r\n }\r\n\r\n var uniformMap = {\r\n u_modifiedModelViewProjection: function () {\r\n var viewMatrix = context.uniformState.view;\r\n var projectionMatrix = context.uniformState.projection;\r\n Matrix4.clone(viewMatrix, modifiedModelViewScratch);\r\n Matrix4.multiplyByPoint(\r\n modifiedModelViewScratch,\r\n primitive._center,\r\n rtcScratch\r\n );\r\n Matrix4.setTranslation(\r\n modifiedModelViewScratch,\r\n rtcScratch,\r\n modifiedModelViewScratch\r\n );\r\n Matrix4.multiply(\r\n projectionMatrix,\r\n modifiedModelViewScratch,\r\n modifiedModelViewScratch\r\n );\r\n return modifiedModelViewScratch;\r\n },\r\n u_highlightColor: function () {\r\n return primitive._highlightColor;\r\n },\r\n };\r\n\r\n primitive._uniformMap = primitive._batchTable.getUniformMapCallback()(\r\n uniformMap\r\n );\r\n}\r\n\r\nfunction copyIndicesCPU(\r\n indices,\r\n newIndices,\r\n currentOffset,\r\n offsets,\r\n counts,\r\n batchIds,\r\n batchIdLookUp\r\n) {\r\n var sizeInBytes = indices.constructor.BYTES_PER_ELEMENT;\r\n\r\n var batchedIdsLength = batchIds.length;\r\n for (var j = 0; j < batchedIdsLength; ++j) {\r\n var batchedId = batchIds[j];\r\n var index = batchIdLookUp[batchedId];\r\n var offset = offsets[index];\r\n var count = counts[index];\r\n\r\n var subarray = new indices.constructor(\r\n indices.buffer,\r\n sizeInBytes * offset,\r\n count\r\n );\r\n newIndices.set(subarray, currentOffset);\r\n\r\n offsets[index] = currentOffset;\r\n currentOffset += count;\r\n }\r\n\r\n return currentOffset;\r\n}\r\n\r\nfunction rebatchCPU(primitive, batchedIndices) {\r\n var indices = primitive._indices;\r\n var indexOffsets = primitive._indexOffsets;\r\n var indexCounts = primitive._indexCounts;\r\n var batchIdLookUp = primitive._batchIdLookUp;\r\n\r\n var newIndices = new indices.constructor(indices.length);\r\n\r\n var current = batchedIndices.pop();\r\n var newBatchedIndices = [current];\r\n\r\n var currentOffset = copyIndicesCPU(\r\n indices,\r\n newIndices,\r\n 0,\r\n indexOffsets,\r\n indexCounts,\r\n current.batchIds,\r\n batchIdLookUp\r\n );\r\n\r\n current.offset = 0;\r\n current.count = currentOffset;\r\n\r\n while (batchedIndices.length > 0) {\r\n var next = batchedIndices.pop();\r\n if (Color.equals(next.color, current.color)) {\r\n currentOffset = copyIndicesCPU(\r\n indices,\r\n newIndices,\r\n currentOffset,\r\n indexOffsets,\r\n indexCounts,\r\n next.batchIds,\r\n batchIdLookUp\r\n );\r\n current.batchIds = current.batchIds.concat(next.batchIds);\r\n current.count = currentOffset - current.offset;\r\n } else {\r\n var offset = currentOffset;\r\n currentOffset = copyIndicesCPU(\r\n indices,\r\n newIndices,\r\n currentOffset,\r\n indexOffsets,\r\n indexCounts,\r\n next.batchIds,\r\n batchIdLookUp\r\n );\r\n\r\n next.offset = offset;\r\n next.count = currentOffset - offset;\r\n newBatchedIndices.push(next);\r\n current = next;\r\n }\r\n }\r\n\r\n primitive._va.indexBuffer.copyFromArrayView(newIndices);\r\n\r\n primitive._indices = newIndices;\r\n primitive._batchedIndices = newBatchedIndices;\r\n}\r\n\r\nfunction copyIndicesGPU(\r\n readBuffer,\r\n writeBuffer,\r\n currentOffset,\r\n offsets,\r\n counts,\r\n batchIds,\r\n batchIdLookUp\r\n) {\r\n var sizeInBytes = readBuffer.bytesPerIndex;\r\n\r\n var batchedIdsLength = batchIds.length;\r\n for (var j = 0; j < batchedIdsLength; ++j) {\r\n var batchedId = batchIds[j];\r\n var index = batchIdLookUp[batchedId];\r\n var offset = offsets[index];\r\n var count = counts[index];\r\n\r\n writeBuffer.copyFromBuffer(\r\n readBuffer,\r\n offset * sizeInBytes,\r\n currentOffset * sizeInBytes,\r\n count * sizeInBytes\r\n );\r\n\r\n offsets[index] = currentOffset;\r\n currentOffset += count;\r\n }\r\n\r\n return currentOffset;\r\n}\r\n\r\nfunction rebatchGPU(primitive, batchedIndices) {\r\n var indexOffsets = primitive._indexOffsets;\r\n var indexCounts = primitive._indexCounts;\r\n var batchIdLookUp = primitive._batchIdLookUp;\r\n\r\n var current = batchedIndices.pop();\r\n var newBatchedIndices = [current];\r\n\r\n var readBuffer = primitive._va.indexBuffer;\r\n var writeBuffer = primitive._vaSwap.indexBuffer;\r\n\r\n var currentOffset = copyIndicesGPU(\r\n readBuffer,\r\n writeBuffer,\r\n 0,\r\n indexOffsets,\r\n indexCounts,\r\n current.batchIds,\r\n batchIdLookUp\r\n );\r\n\r\n current.offset = 0;\r\n current.count = currentOffset;\r\n\r\n while (batchedIndices.length > 0) {\r\n var next = batchedIndices.pop();\r\n if (Color.equals(next.color, current.color)) {\r\n currentOffset = copyIndicesGPU(\r\n readBuffer,\r\n writeBuffer,\r\n currentOffset,\r\n indexOffsets,\r\n indexCounts,\r\n next.batchIds,\r\n batchIdLookUp\r\n );\r\n current.batchIds = current.batchIds.concat(next.batchIds);\r\n current.count = currentOffset - current.offset;\r\n } else {\r\n var offset = currentOffset;\r\n currentOffset = copyIndicesGPU(\r\n readBuffer,\r\n writeBuffer,\r\n currentOffset,\r\n indexOffsets,\r\n indexCounts,\r\n next.batchIds,\r\n batchIdLookUp\r\n );\r\n next.offset = offset;\r\n next.count = currentOffset - offset;\r\n newBatchedIndices.push(next);\r\n current = next;\r\n }\r\n }\r\n\r\n var temp = primitive._va;\r\n primitive._va = primitive._vaSwap;\r\n primitive._vaSwap = temp;\r\n\r\n primitive._batchedIndices = newBatchedIndices;\r\n}\r\n\r\nfunction compareColors(a, b) {\r\n return b.color.toRgba() - a.color.toRgba();\r\n}\r\n\r\n// PERFORMANCE_IDEA: For WebGL 2, we can use copyBufferSubData for buffer-to-buffer copies.\r\n// PERFORMANCE_IDEA: Not supported, but we could use glMultiDrawElements here.\r\nfunction rebatchCommands(primitive, context) {\r\n if (!primitive._batchDirty) {\r\n return false;\r\n }\r\n\r\n var batchedIndices = primitive._batchedIndices;\r\n var length = batchedIndices.length;\r\n\r\n var needToRebatch = false;\r\n var colorCounts = {};\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var color = batchedIndices[i].color;\r\n var rgba = color.toRgba();\r\n if (defined(colorCounts[rgba])) {\r\n needToRebatch = true;\r\n break;\r\n } else {\r\n colorCounts[rgba] = true;\r\n }\r\n }\r\n\r\n if (!needToRebatch) {\r\n primitive._batchDirty = false;\r\n return false;\r\n }\r\n\r\n if (\r\n needToRebatch &&\r\n !primitive.forceRebatch &&\r\n primitive._framesSinceLastRebatch < 120\r\n ) {\r\n ++primitive._framesSinceLastRebatch;\r\n return;\r\n }\r\n\r\n batchedIndices.sort(compareColors);\r\n\r\n if (context.webgl2) {\r\n rebatchGPU(primitive, batchedIndices);\r\n } else {\r\n rebatchCPU(primitive, batchedIndices);\r\n }\r\n\r\n primitive._framesSinceLastRebatch = 0;\r\n primitive._batchDirty = false;\r\n primitive._pickCommandsDirty = true;\r\n primitive._wireframeDirty = true;\r\n return true;\r\n}\r\n\r\nfunction createColorCommands(primitive, context) {\r\n var needsRebatch = rebatchCommands(primitive, context);\r\n\r\n var commands = primitive._commands;\r\n var batchedIndices = primitive._batchedIndices;\r\n var length = batchedIndices.length;\r\n var commandsLength = length * 2;\r\n\r\n if (\r\n defined(commands) &&\r\n !needsRebatch &&\r\n commands.length === commandsLength\r\n ) {\r\n return;\r\n }\r\n\r\n commands.length = commandsLength;\r\n\r\n var vertexArray = primitive._va;\r\n var sp = primitive._sp;\r\n var modelMatrix = defaultValue(primitive._modelMatrix, Matrix4.IDENTITY);\r\n var uniformMap = primitive._uniformMap;\r\n var bv = primitive._boundingVolume;\r\n\r\n for (var j = 0; j < length; ++j) {\r\n var offset = batchedIndices[j].offset;\r\n var count = batchedIndices[j].count;\r\n\r\n var stencilDepthCommand = commands[j * 2];\r\n if (!defined(stencilDepthCommand)) {\r\n stencilDepthCommand = commands[j * 2] = new DrawCommand({\r\n owner: primitive,\r\n });\r\n }\r\n\r\n stencilDepthCommand.vertexArray = vertexArray;\r\n stencilDepthCommand.modelMatrix = modelMatrix;\r\n stencilDepthCommand.offset = offset;\r\n stencilDepthCommand.count = count;\r\n stencilDepthCommand.renderState = primitive._rsStencilDepthPass;\r\n stencilDepthCommand.shaderProgram = sp;\r\n stencilDepthCommand.uniformMap = uniformMap;\r\n stencilDepthCommand.boundingVolume = bv;\r\n stencilDepthCommand.cull = false;\r\n stencilDepthCommand.pass = Pass.TERRAIN_CLASSIFICATION;\r\n\r\n var stencilDepthDerivedCommand = DrawCommand.shallowClone(\r\n stencilDepthCommand,\r\n stencilDepthCommand.derivedCommands.tileset\r\n );\r\n stencilDepthDerivedCommand.renderState =\r\n primitive._rsStencilDepthPass3DTiles;\r\n stencilDepthDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n stencilDepthCommand.derivedCommands.tileset = stencilDepthDerivedCommand;\r\n\r\n var colorCommand = commands[j * 2 + 1];\r\n if (!defined(colorCommand)) {\r\n colorCommand = commands[j * 2 + 1] = new DrawCommand({\r\n owner: primitive,\r\n });\r\n }\r\n\r\n colorCommand.vertexArray = vertexArray;\r\n colorCommand.modelMatrix = modelMatrix;\r\n colorCommand.offset = offset;\r\n colorCommand.count = count;\r\n colorCommand.renderState = primitive._rsColorPass;\r\n colorCommand.shaderProgram = sp;\r\n colorCommand.uniformMap = uniformMap;\r\n colorCommand.boundingVolume = bv;\r\n colorCommand.cull = false;\r\n colorCommand.pass = Pass.TERRAIN_CLASSIFICATION;\r\n\r\n var colorDerivedCommand = DrawCommand.shallowClone(\r\n colorCommand,\r\n colorCommand.derivedCommands.tileset\r\n );\r\n colorDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n colorCommand.derivedCommands.tileset = colorDerivedCommand;\r\n }\r\n\r\n primitive._commandsDirty = true;\r\n}\r\n\r\nfunction createColorCommandsIgnoreShow(primitive, frameState) {\r\n if (\r\n primitive.classificationType === ClassificationType.TERRAIN ||\r\n !frameState.invertClassification ||\r\n (defined(primitive._commandsIgnoreShow) && !primitive._commandsDirty)\r\n ) {\r\n return;\r\n }\r\n\r\n var commands = primitive._commands;\r\n var commandsIgnoreShow = primitive._commandsIgnoreShow;\r\n var spStencil = primitive._spStencil;\r\n\r\n var commandsLength = commands.length;\r\n var length = (commandsIgnoreShow.length = commandsLength / 2);\r\n\r\n var commandIndex = 0;\r\n for (var j = 0; j < length; ++j) {\r\n var commandIgnoreShow = (commandsIgnoreShow[j] = DrawCommand.shallowClone(\r\n commands[commandIndex],\r\n commandsIgnoreShow[j]\r\n ));\r\n commandIgnoreShow.shaderProgram = spStencil;\r\n commandIgnoreShow.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW;\r\n\r\n commandIndex += 2;\r\n }\r\n\r\n primitive._commandsDirty = false;\r\n}\r\n\r\nfunction createPickCommands(primitive) {\r\n if (!primitive._pickCommandsDirty) {\r\n return;\r\n }\r\n\r\n var length = primitive._indexOffsets.length;\r\n var pickCommands = primitive._pickCommands;\r\n pickCommands.length = length * 2;\r\n\r\n var vertexArray = primitive._va;\r\n var spStencil = primitive._spStencil;\r\n var spPick = primitive._spPick;\r\n var modelMatrix = defaultValue(primitive._modelMatrix, Matrix4.IDENTITY);\r\n var uniformMap = primitive._uniformMap;\r\n\r\n for (var j = 0; j < length; ++j) {\r\n var offset = primitive._indexOffsets[j];\r\n var count = primitive._indexCounts[j];\r\n var bv = defined(primitive._boundingVolumes)\r\n ? primitive._boundingVolumes[j]\r\n : primitive.boundingVolume;\r\n\r\n var stencilDepthCommand = pickCommands[j * 2];\r\n if (!defined(stencilDepthCommand)) {\r\n stencilDepthCommand = pickCommands[j * 2] = new DrawCommand({\r\n owner: primitive,\r\n pickOnly: true,\r\n });\r\n }\r\n\r\n stencilDepthCommand.vertexArray = vertexArray;\r\n stencilDepthCommand.modelMatrix = modelMatrix;\r\n stencilDepthCommand.offset = offset;\r\n stencilDepthCommand.count = count;\r\n stencilDepthCommand.renderState = primitive._rsStencilDepthPass;\r\n stencilDepthCommand.shaderProgram = spStencil;\r\n stencilDepthCommand.uniformMap = uniformMap;\r\n stencilDepthCommand.boundingVolume = bv;\r\n stencilDepthCommand.pass = Pass.TERRAIN_CLASSIFICATION;\r\n\r\n var stencilDepthDerivedCommand = DrawCommand.shallowClone(\r\n stencilDepthCommand,\r\n stencilDepthCommand.derivedCommands.tileset\r\n );\r\n stencilDepthDerivedCommand.renderState =\r\n primitive._rsStencilDepthPass3DTiles;\r\n stencilDepthDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n stencilDepthCommand.derivedCommands.tileset = stencilDepthDerivedCommand;\r\n\r\n var colorCommand = pickCommands[j * 2 + 1];\r\n if (!defined(colorCommand)) {\r\n colorCommand = pickCommands[j * 2 + 1] = new DrawCommand({\r\n owner: primitive,\r\n pickOnly: true,\r\n });\r\n }\r\n\r\n colorCommand.vertexArray = vertexArray;\r\n colorCommand.modelMatrix = modelMatrix;\r\n colorCommand.offset = offset;\r\n colorCommand.count = count;\r\n colorCommand.renderState = primitive._rsPickPass;\r\n colorCommand.shaderProgram = spPick;\r\n colorCommand.uniformMap = uniformMap;\r\n colorCommand.boundingVolume = bv;\r\n colorCommand.pass = Pass.TERRAIN_CLASSIFICATION;\r\n\r\n var colorDerivedCommand = DrawCommand.shallowClone(\r\n colorCommand,\r\n colorCommand.derivedCommands.tileset\r\n );\r\n colorDerivedCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n colorCommand.derivedCommands.tileset = colorDerivedCommand;\r\n }\r\n\r\n primitive._pickCommandsDirty = false;\r\n}\r\n\r\n/**\r\n * Creates features for each mesh and places it at the batch id index of features.\r\n *\r\n * @param {Vector3DTileContent} content The vector tile content.\r\n * @param {Cesium3DTileFeature[]} features An array of features where the polygon features will be placed.\r\n */\r\nVector3DTilePrimitive.prototype.createFeatures = function (content, features) {\r\n var batchIds = this._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n features[batchId] = new Cesium3DTileFeature(content, batchId);\r\n }\r\n};\r\n\r\n/**\r\n * Colors the entire tile when enabled is true. The resulting color will be (mesh batch table color * color).\r\n *\r\n * @param {Boolean} enabled Whether to enable debug coloring.\r\n * @param {Color} color The debug color.\r\n */\r\nVector3DTilePrimitive.prototype.applyDebugSettings = function (enabled, color) {\r\n this._highlightColor = enabled ? color : this._constantColor;\r\n};\r\n\r\nfunction clearStyle(polygons, features) {\r\n polygons._updatingAllCommands = true;\r\n\r\n var batchIds = polygons._batchIds;\r\n var length = batchIds.length;\r\n var i;\r\n\r\n for (i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n var feature = features[batchId];\r\n\r\n feature.show = true;\r\n feature.color = Color.WHITE;\r\n }\r\n\r\n var batchedIndices = polygons._batchedIndices;\r\n length = batchedIndices.length;\r\n\r\n for (i = 0; i < length; ++i) {\r\n batchedIndices[i].color = Color.clone(Color.WHITE);\r\n }\r\n\r\n polygons._updatingAllCommands = false;\r\n polygons._batchDirty = true;\r\n}\r\n\r\nvar scratchColor = new Color();\r\n\r\nvar DEFAULT_COLOR_VALUE = Color.WHITE;\r\nvar DEFAULT_SHOW_VALUE = true;\r\n\r\nvar complexExpressionReg = /\\$/;\r\n\r\n/**\r\n * Apply a style to the content.\r\n *\r\n * @param {Cesium3DTileStyle} style The style.\r\n * @param {Cesium3DTileFeature[]} features The array of features.\r\n */\r\nVector3DTilePrimitive.prototype.applyStyle = function (style, features) {\r\n if (!defined(style)) {\r\n clearStyle(this, features);\r\n return;\r\n }\r\n\r\n var colorExpression = style.color;\r\n var isSimpleStyle =\r\n colorExpression instanceof Expression &&\r\n !complexExpressionReg.test(colorExpression.expression);\r\n this._updatingAllCommands = isSimpleStyle;\r\n\r\n var batchIds = this._batchIds;\r\n var length = batchIds.length;\r\n var i;\r\n\r\n for (i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n var feature = features[batchId];\r\n\r\n feature.color = defined(style.color)\r\n ? style.color.evaluateColor(feature, scratchColor)\r\n : DEFAULT_COLOR_VALUE;\r\n feature.show = defined(style.show)\r\n ? style.show.evaluate(feature)\r\n : DEFAULT_SHOW_VALUE;\r\n }\r\n\r\n if (isSimpleStyle) {\r\n var batchedIndices = this._batchedIndices;\r\n length = batchedIndices.length;\r\n\r\n for (i = 0; i < length; ++i) {\r\n batchedIndices[i].color = Color.clone(Color.WHITE);\r\n }\r\n\r\n this._updatingAllCommands = false;\r\n this._batchDirty = true;\r\n }\r\n};\r\n\r\n/**\r\n * Call when updating the color of a mesh with batchId changes color. The meshes will need to be re-batched\r\n * on the next update.\r\n *\r\n * @param {Number} batchId The batch id of the meshes whose color has changed.\r\n * @param {Color} color The new polygon color.\r\n */\r\nVector3DTilePrimitive.prototype.updateCommands = function (batchId, color) {\r\n if (this._updatingAllCommands) {\r\n return;\r\n }\r\n\r\n var batchIdLookUp = this._batchIdLookUp;\r\n var index = batchIdLookUp[batchId];\r\n if (!defined(index)) {\r\n return;\r\n }\r\n\r\n var indexOffsets = this._indexOffsets;\r\n var indexCounts = this._indexCounts;\r\n\r\n var offset = indexOffsets[index];\r\n var count = indexCounts[index];\r\n\r\n var batchedIndices = this._batchedIndices;\r\n var length = batchedIndices.length;\r\n\r\n var i;\r\n for (i = 0; i < length; ++i) {\r\n var batchedOffset = batchedIndices[i].offset;\r\n var batchedCount = batchedIndices[i].count;\r\n\r\n if (offset >= batchedOffset && offset < batchedOffset + batchedCount) {\r\n break;\r\n }\r\n }\r\n\r\n batchedIndices.push(\r\n new Vector3DTileBatch({\r\n color: Color.clone(color),\r\n offset: offset,\r\n count: count,\r\n batchIds: [batchId],\r\n })\r\n );\r\n\r\n var startIds = [];\r\n var endIds = [];\r\n\r\n var batchIds = batchedIndices[i].batchIds;\r\n var batchIdsLength = batchIds.length;\r\n\r\n for (var j = 0; j < batchIdsLength; ++j) {\r\n var id = batchIds[j];\r\n if (id === batchId) {\r\n continue;\r\n }\r\n\r\n var offsetIndex = batchIdLookUp[id];\r\n if (indexOffsets[offsetIndex] < offset) {\r\n startIds.push(id);\r\n } else {\r\n endIds.push(id);\r\n }\r\n }\r\n\r\n if (endIds.length !== 0) {\r\n batchedIndices.push(\r\n new Vector3DTileBatch({\r\n color: Color.clone(batchedIndices[i].color),\r\n offset: offset + count,\r\n count:\r\n batchedIndices[i].offset + batchedIndices[i].count - (offset + count),\r\n batchIds: endIds,\r\n })\r\n );\r\n }\r\n\r\n if (startIds.length !== 0) {\r\n batchedIndices[i].count = offset - batchedIndices[i].offset;\r\n batchedIndices[i].batchIds = startIds;\r\n } else {\r\n batchedIndices.splice(i, 1);\r\n }\r\n\r\n this._batchDirty = true;\r\n};\r\n\r\nfunction queueCommands(primitive, frameState, commands, commandsIgnoreShow) {\r\n var classificationType = primitive.classificationType;\r\n var queueTerrainCommands =\r\n classificationType !== ClassificationType.CESIUM_3D_TILE;\r\n var queue3DTilesCommands = classificationType !== ClassificationType.TERRAIN;\r\n\r\n var commandList = frameState.commandList;\r\n var commandLength = commands.length;\r\n var command;\r\n var i;\r\n for (i = 0; i < commandLength; ++i) {\r\n if (queueTerrainCommands) {\r\n command = commands[i];\r\n command.pass = Pass.TERRAIN_CLASSIFICATION;\r\n commandList.push(command);\r\n }\r\n if (queue3DTilesCommands) {\r\n command = commands[i].derivedCommands.tileset;\r\n command.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n commandList.push(command);\r\n }\r\n }\r\n\r\n if (!frameState.invertClassification || !defined(commandsIgnoreShow)) {\r\n return;\r\n }\r\n\r\n commandLength = commandsIgnoreShow.length;\r\n for (i = 0; i < commandLength; ++i) {\r\n commandList.push(commandsIgnoreShow[i]);\r\n }\r\n}\r\n\r\nfunction queueWireframeCommands(frameState, commands) {\r\n var commandList = frameState.commandList;\r\n var commandLength = commands.length;\r\n for (var i = 0; i < commandLength; i += 2) {\r\n var command = commands[i + 1];\r\n command.pass = Pass.OPAQUE;\r\n commandList.push(command);\r\n }\r\n}\r\n\r\nfunction updateWireframe(primitive) {\r\n var earlyExit = primitive.debugWireframe === primitive._debugWireframe;\r\n earlyExit =\r\n earlyExit && !(primitive.debugWireframe && primitive._wireframeDirty);\r\n if (earlyExit) {\r\n return;\r\n }\r\n\r\n if (!defined(primitive._rsWireframe)) {\r\n primitive._rsWireframe = RenderState.fromCache({});\r\n }\r\n\r\n var rs;\r\n var type;\r\n\r\n if (primitive.debugWireframe) {\r\n rs = primitive._rsWireframe;\r\n type = PrimitiveType.LINES;\r\n } else {\r\n rs = primitive._rsColorPass;\r\n type = PrimitiveType.TRIANGLES;\r\n }\r\n\r\n var commands = primitive._commands;\r\n var commandLength = commands.length;\r\n for (var i = 0; i < commandLength; i += 2) {\r\n var command = commands[i + 1];\r\n command.renderState = rs;\r\n command.primitiveType = type;\r\n }\r\n\r\n primitive._debugWireframe = primitive.debugWireframe;\r\n primitive._wireframeDirty = false;\r\n}\r\n\r\n/**\r\n * Updates the batches and queues the commands for rendering.\r\n *\r\n * @param {FrameState} frameState The current frame state.\r\n */\r\nVector3DTilePrimitive.prototype.update = function (frameState) {\r\n var context = frameState.context;\r\n\r\n createVertexArray(this, context);\r\n createShaders(this, context);\r\n createRenderStates(this);\r\n createUniformMap(this, context);\r\n\r\n var passes = frameState.passes;\r\n if (passes.render) {\r\n createColorCommands(this, context);\r\n createColorCommandsIgnoreShow(this, frameState);\r\n updateWireframe(this);\r\n\r\n if (this._debugWireframe) {\r\n queueWireframeCommands(frameState, this._commands);\r\n } else {\r\n queueCommands(this, frameState, this._commands, this._commandsIgnoreShow);\r\n }\r\n }\r\n\r\n if (passes.pick) {\r\n createPickCommands(this);\r\n queueCommands(this, frameState, this._pickCommands);\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n */\r\nVector3DTilePrimitive.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nVector3DTilePrimitive.prototype.destroy = function () {\r\n this._va = this._va && this._va.destroy();\r\n this._sp = this._sp && this._sp.destroy();\r\n this._spPick = this._spPick && this._spPick.destroy();\r\n this._vaSwap = this._vaSwap && this._vaSwap.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Vector3DTilePrimitive;\r\n","import arraySlice from \"../Core/arraySlice.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport PrimitiveType from \"../Core/PrimitiveType.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport addDefaults from \"../ThirdParty/GltfPipeline/addDefaults.js\";\r\nimport ForEach from \"../ThirdParty/GltfPipeline/ForEach.js\";\r\nimport getAccessorByteStride from \"../ThirdParty/GltfPipeline/getAccessorByteStride.js\";\r\nimport numberOfComponentsForType from \"../ThirdParty/GltfPipeline/numberOfComponentsForType.js\";\r\nimport parseGlb from \"../ThirdParty/GltfPipeline/parseGlb.js\";\r\nimport updateVersion from \"../ThirdParty/GltfPipeline/updateVersion.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Axis from \"./Axis.js\";\r\nimport ModelLoadResources from \"./ModelLoadResources.js\";\r\nimport ModelUtility from \"./ModelUtility.js\";\r\nimport processModelMaterialsCommon from \"./processModelMaterialsCommon.js\";\r\nimport processPbrMaterials from \"./processPbrMaterials.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport Vector3DTileBatch from \"./Vector3DTileBatch.js\";\r\nimport Vector3DTilePrimitive from \"./Vector3DTilePrimitive.js\";\r\n\r\nvar boundingSphereCartesian3Scratch = new Cartesian3();\r\n\r\nvar ModelState = ModelUtility.ModelState;\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * A 3D model for classifying other 3D assets based on glTF, the runtime 3D asset format.\r\n * This is a special case when a model of a 3D tileset becomes a classifier when setting {@link Cesium3DTileset#classificationType}.\r\n *\r\n * @alias ClassificationModel\r\n * @constructor\r\n *\r\n * @private\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {ArrayBuffer|Uint8Array} options.gltf A binary glTF buffer.\r\n * @param {Boolean} [options.show=true] Determines if the model primitive will be shown.\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms the model from model to world coordinates.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each draw command in the model.\r\n * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe.\r\n * @param {ClassificationType} [options.classificationType] What this model will classify.\r\n *\r\n * @exception {RuntimeError} Only binary glTF is supported.\r\n * @exception {RuntimeError} Buffer data must be embedded in the binary glTF.\r\n * @exception {RuntimeError} Only one node is supported for classification and it must have a mesh.\r\n * @exception {RuntimeError} Only one mesh is supported when using b3dm for classification.\r\n * @exception {RuntimeError} Only one primitive per mesh is supported when using b3dm for classification.\r\n * @exception {RuntimeError} The mesh must have a position attribute.\r\n * @exception {RuntimeError} The mesh must have a batch id attribute.\r\n */\r\nfunction ClassificationModel(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var gltf = options.gltf;\r\n if (gltf instanceof ArrayBuffer) {\r\n gltf = new Uint8Array(gltf);\r\n }\r\n\r\n if (gltf instanceof Uint8Array) {\r\n // Parse and update binary glTF\r\n gltf = parseGlb(gltf);\r\n updateVersion(gltf);\r\n addDefaults(gltf);\r\n processModelMaterialsCommon(gltf);\r\n processPbrMaterials(gltf);\r\n } else {\r\n throw new RuntimeError(\"Only binary glTF is supported as a classifier.\");\r\n }\r\n\r\n ForEach.buffer(gltf, function (buffer) {\r\n if (!defined(buffer.extras._pipeline.source)) {\r\n throw new RuntimeError(\r\n \"Buffer data must be embedded in the binary gltf.\"\r\n );\r\n }\r\n });\r\n\r\n var gltfNodes = gltf.nodes;\r\n var gltfMeshes = gltf.meshes;\r\n\r\n var gltfNode = gltfNodes[0];\r\n var meshId = gltfNode.mesh;\r\n if (gltfNodes.length !== 1 || !defined(meshId)) {\r\n throw new RuntimeError(\r\n \"Only one node is supported for classification and it must have a mesh.\"\r\n );\r\n }\r\n\r\n if (gltfMeshes.length !== 1) {\r\n throw new RuntimeError(\r\n \"Only one mesh is supported when using b3dm for classification.\"\r\n );\r\n }\r\n\r\n var gltfPrimitives = gltfMeshes[0].primitives;\r\n if (gltfPrimitives.length !== 1) {\r\n throw new RuntimeError(\r\n \"Only one primitive per mesh is supported when using b3dm for classification.\"\r\n );\r\n }\r\n\r\n var gltfPositionAttribute = gltfPrimitives[0].attributes.POSITION;\r\n if (!defined(gltfPositionAttribute)) {\r\n throw new RuntimeError(\"The mesh must have a position attribute.\");\r\n }\r\n\r\n var gltfBatchIdAttribute = gltfPrimitives[0].attributes._BATCHID;\r\n if (!defined(gltfBatchIdAttribute)) {\r\n throw new RuntimeError(\"The mesh must have a batch id attribute.\");\r\n }\r\n\r\n this._gltf = gltf;\r\n\r\n /**\r\n * Determines if the model primitive will be shown.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * The 4x4 transformation matrix that transforms the model from model to world coordinates.\r\n * When this is the identity matrix, the model is drawn in world coordinates, i.e., Earth's WGS84 coordinates.\r\n * Local reference frames can be used by providing a different transformation matrix, like that returned\r\n * by {@link Transforms.eastNorthUpToFixedFrame}.\r\n *\r\n * @type {Matrix4}\r\n *\r\n * @default {@link Matrix4.IDENTITY}\r\n *\r\n * @example\r\n * var origin = Cesium.Cartesian3.fromDegrees(-95.0, 40.0, 200000.0);\r\n * m.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n this._modelMatrix = Matrix4.clone(this.modelMatrix);\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the model. A glTF primitive corresponds\r\n * to one draw command. A glTF mesh has an array of primitives, often of length one.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n this._debugShowBoundingVolume = false;\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the model in wireframe.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugWireframe = defaultValue(options.debugWireframe, false);\r\n this._debugWireframe = false;\r\n\r\n this._classificationType = options.classificationType;\r\n\r\n // Undocumented options\r\n this._vertexShaderLoaded = options.vertexShaderLoaded;\r\n this._classificationShaderLoaded = options.classificationShaderLoaded;\r\n this._uniformMapLoaded = options.uniformMapLoaded;\r\n this._pickIdLoaded = options.pickIdLoaded;\r\n this._ignoreCommands = defaultValue(options.ignoreCommands, false);\r\n this._upAxis = defaultValue(options.upAxis, Axis.Y);\r\n this._batchTable = options.batchTable;\r\n\r\n this._computedModelMatrix = new Matrix4(); // Derived from modelMatrix and axis\r\n this._initialRadius = undefined; // Radius without model's scale property, model-matrix scale, animations, or skins\r\n this._boundingSphere = undefined;\r\n this._scaledBoundingSphere = new BoundingSphere();\r\n this._state = ModelState.NEEDS_LOAD;\r\n this._loadResources = undefined;\r\n\r\n this._mode = undefined;\r\n this._dirty = false; // true when the model was transformed this frame\r\n\r\n this._nodeMatrix = new Matrix4();\r\n this._primitive = undefined;\r\n\r\n this._extensionsUsed = undefined; // Cached used glTF extensions\r\n this._extensionsRequired = undefined; // Cached required glTF extensions\r\n this._quantizedUniforms = undefined; // Quantized uniforms for WEB3D_quantized_attributes\r\n\r\n this._buffers = {};\r\n this._vertexArray = undefined;\r\n this._shaderProgram = undefined;\r\n this._uniformMap = undefined;\r\n\r\n this._geometryByteLength = 0;\r\n this._trianglesLength = 0;\r\n\r\n // CESIUM_RTC extension\r\n this._rtcCenter = undefined; // reference to either 3D or 2D\r\n this._rtcCenterEye = undefined; // in eye coordinates\r\n this._rtcCenter3D = undefined; // in world coordinates\r\n this._rtcCenter2D = undefined; // in projected world coordinates\r\n}\r\n\r\nObject.defineProperties(ClassificationModel.prototype, {\r\n /**\r\n * The object for the glTF JSON, including properties with default values omitted\r\n * from the JSON provided to this model.\r\n *\r\n * @memberof ClassificationModel.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n *\r\n * @default undefined\r\n */\r\n gltf: {\r\n get: function () {\r\n return this._gltf;\r\n },\r\n },\r\n\r\n /**\r\n * The model's bounding sphere in its local coordinate system.\r\n *\r\n * @memberof ClassificationModel.prototype\r\n *\r\n * @type {BoundingSphere}\r\n * @readonly\r\n *\r\n * @default undefined\r\n *\r\n * @exception {DeveloperError} The model is not loaded. Use ClassificationModel.readyPromise or wait for ClassificationModel.ready to be true.\r\n *\r\n * @example\r\n * // Center in WGS84 coordinates\r\n * var center = Cesium.Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, new Cesium.Cartesian3());\r\n */\r\n boundingSphere: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (this._state !== ModelState.LOADED) {\r\n throw new DeveloperError(\r\n \"The model is not loaded. Use ClassificationModel.readyPromise or wait for ClassificationModel.ready to be true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var modelMatrix = this.modelMatrix;\r\n var nonUniformScale = Matrix4.getScale(\r\n modelMatrix,\r\n boundingSphereCartesian3Scratch\r\n );\r\n\r\n var scaledBoundingSphere = this._scaledBoundingSphere;\r\n scaledBoundingSphere.center = Cartesian3.multiplyComponents(\r\n this._boundingSphere.center,\r\n nonUniformScale,\r\n scaledBoundingSphere.center\r\n );\r\n scaledBoundingSphere.radius =\r\n Cartesian3.maximumComponent(nonUniformScale) * this._initialRadius;\r\n\r\n if (defined(this._rtcCenter)) {\r\n Cartesian3.add(\r\n this._rtcCenter,\r\n scaledBoundingSphere.center,\r\n scaledBoundingSphere.center\r\n );\r\n }\r\n\r\n return scaledBoundingSphere;\r\n },\r\n },\r\n\r\n /**\r\n * When true, this model is ready to render, i.e., the external binary, image,\r\n * and shader files were downloaded and the WebGL resources were created. This is set to\r\n * true right before {@link ClassificationModel#readyPromise} is resolved.\r\n *\r\n * @memberof ClassificationModel.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the promise that will be resolved when this model is ready to render, i.e., when the external binary, image,\r\n * and shader files were downloaded and the WebGL resources were created.\r\n *

\r\n * This promise is resolved at the end of the frame before the first frame the model is rendered in.\r\n *

\r\n *\r\n * @memberof ClassificationModel.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n *\r\n * @see ClassificationModel#ready\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n /**\r\n * Returns true if the model was transformed this frame\r\n *\r\n * @memberof ClassificationModel.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n dirty: {\r\n get: function () {\r\n return this._dirty;\r\n },\r\n },\r\n\r\n /**\r\n * Returns an object with all of the glTF extensions used.\r\n *\r\n * @memberof ClassificationModel.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n extensionsUsed: {\r\n get: function () {\r\n if (!defined(this._extensionsUsed)) {\r\n this._extensionsUsed = ModelUtility.getUsedExtensions(this.gltf);\r\n }\r\n return this._extensionsUsed;\r\n },\r\n },\r\n\r\n /**\r\n * Returns an object with all of the glTF extensions required.\r\n *\r\n * @memberof ClassificationModel.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n extensionsRequired: {\r\n get: function () {\r\n if (!defined(this._extensionsRequired)) {\r\n this._extensionsRequired = ModelUtility.getRequiredExtensions(\r\n this.gltf\r\n );\r\n }\r\n return this._extensionsRequired;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's up-axis.\r\n * By default models are y-up according to the glTF spec, however geo-referenced models will typically be z-up.\r\n *\r\n * @memberof ClassificationModel.prototype\r\n *\r\n * @type {Number}\r\n * @default Axis.Y\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n upAxis: {\r\n get: function () {\r\n return this._upAxis;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's triangle count.\r\n *\r\n * @private\r\n */\r\n trianglesLength: {\r\n get: function () {\r\n return this._trianglesLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's geometry memory in bytes. This includes all vertex and index buffers.\r\n *\r\n * @private\r\n */\r\n geometryByteLength: {\r\n get: function () {\r\n return this._geometryByteLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's texture memory in bytes.\r\n *\r\n * @private\r\n */\r\n texturesByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's classification type.\r\n * @memberof ClassificationModel.prototype\r\n * @type {ClassificationType}\r\n */\r\n classificationType: {\r\n get: function () {\r\n return this._classificationType;\r\n },\r\n },\r\n});\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction addBuffersToLoadResources(model) {\r\n var gltf = model.gltf;\r\n var loadResources = model._loadResources;\r\n ForEach.buffer(gltf, function (buffer, id) {\r\n loadResources.buffers[id] = buffer.extras._pipeline.source;\r\n });\r\n}\r\n\r\nfunction parseBufferViews(model) {\r\n var bufferViews = model.gltf.bufferViews;\r\n\r\n var vertexBuffersToCreate = model._loadResources.vertexBuffersToCreate;\r\n\r\n // Only ARRAY_BUFFER here. ELEMENT_ARRAY_BUFFER created below.\r\n ForEach.bufferView(model.gltf, function (bufferView, id) {\r\n if (bufferView.target === WebGLConstants.ARRAY_BUFFER) {\r\n vertexBuffersToCreate.enqueue(id);\r\n }\r\n });\r\n\r\n var indexBuffersToCreate = model._loadResources.indexBuffersToCreate;\r\n var indexBufferIds = {};\r\n\r\n // The Cesium Renderer requires knowing the datatype for an index buffer\r\n // at creation type, which is not part of the glTF bufferview so loop\r\n // through glTF accessors to create the bufferview's index buffer.\r\n ForEach.accessor(model.gltf, function (accessor) {\r\n var bufferViewId = accessor.bufferView;\r\n var bufferView = bufferViews[bufferViewId];\r\n\r\n if (\r\n bufferView.target === WebGLConstants.ELEMENT_ARRAY_BUFFER &&\r\n !defined(indexBufferIds[bufferViewId])\r\n ) {\r\n indexBufferIds[bufferViewId] = true;\r\n indexBuffersToCreate.enqueue({\r\n id: bufferViewId,\r\n componentType: accessor.componentType,\r\n });\r\n }\r\n });\r\n}\r\n\r\nfunction createVertexBuffer(bufferViewId, model) {\r\n var loadResources = model._loadResources;\r\n var bufferViews = model.gltf.bufferViews;\r\n var bufferView = bufferViews[bufferViewId];\r\n var vertexBuffer = loadResources.getBuffer(bufferView);\r\n model._buffers[bufferViewId] = vertexBuffer;\r\n model._geometryByteLength += vertexBuffer.byteLength;\r\n}\r\n\r\nfunction createIndexBuffer(bufferViewId, componentType, model) {\r\n var loadResources = model._loadResources;\r\n var bufferViews = model.gltf.bufferViews;\r\n var bufferView = bufferViews[bufferViewId];\r\n var indexBuffer = {\r\n typedArray: loadResources.getBuffer(bufferView),\r\n indexDatatype: componentType,\r\n };\r\n model._buffers[bufferViewId] = indexBuffer;\r\n model._geometryByteLength += indexBuffer.typedArray.byteLength;\r\n}\r\n\r\nfunction createBuffers(model) {\r\n var loadResources = model._loadResources;\r\n\r\n if (loadResources.pendingBufferLoads !== 0) {\r\n return;\r\n }\r\n\r\n var vertexBuffersToCreate = loadResources.vertexBuffersToCreate;\r\n var indexBuffersToCreate = loadResources.indexBuffersToCreate;\r\n\r\n while (vertexBuffersToCreate.length > 0) {\r\n createVertexBuffer(vertexBuffersToCreate.dequeue(), model);\r\n }\r\n\r\n while (indexBuffersToCreate.length > 0) {\r\n var i = indexBuffersToCreate.dequeue();\r\n createIndexBuffer(i.id, i.componentType, model);\r\n }\r\n}\r\n\r\nfunction modifyShaderForQuantizedAttributes(shader, model) {\r\n var primitive = model.gltf.meshes[0].primitives[0];\r\n var result = ModelUtility.modifyShaderForQuantizedAttributes(\r\n model.gltf,\r\n primitive,\r\n shader\r\n );\r\n model._quantizedUniforms = result.uniforms;\r\n return result.shader;\r\n}\r\n\r\nfunction modifyShader(shader, callback) {\r\n if (defined(callback)) {\r\n shader = callback(shader);\r\n }\r\n return shader;\r\n}\r\n\r\nfunction createProgram(model) {\r\n var gltf = model.gltf;\r\n\r\n var positionName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"POSITION\"\r\n );\r\n var batchIdName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"_BATCHID\"\r\n );\r\n\r\n var attributeLocations = {};\r\n attributeLocations[positionName] = 0;\r\n attributeLocations[batchIdName] = 1;\r\n\r\n var modelViewProjectionName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"MODELVIEWPROJECTION\"\r\n );\r\n\r\n var uniformDecl;\r\n var toClip;\r\n\r\n if (!defined(modelViewProjectionName)) {\r\n var projectionName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"PROJECTION\"\r\n );\r\n var modelViewName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"MODELVIEW\"\r\n );\r\n if (!defined(modelViewName)) {\r\n modelViewName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"CESIUM_RTC_MODELVIEW\"\r\n );\r\n }\r\n\r\n uniformDecl =\r\n \"uniform mat4 \" +\r\n modelViewName +\r\n \";\\n\" +\r\n \"uniform mat4 \" +\r\n projectionName +\r\n \";\\n\";\r\n toClip =\r\n projectionName +\r\n \" * \" +\r\n modelViewName +\r\n \" * vec4(\" +\r\n positionName +\r\n \", 1.0)\";\r\n } else {\r\n uniformDecl = \"uniform mat4 \" + modelViewProjectionName + \";\\n\";\r\n toClip = modelViewProjectionName + \" * vec4(\" + positionName + \", 1.0)\";\r\n }\r\n\r\n var computePosition = \" vec4 positionInClipCoords = \" + toClip + \";\\n\";\r\n\r\n var vs =\r\n \"attribute vec3 \" +\r\n positionName +\r\n \";\\n\" +\r\n \"attribute float \" +\r\n batchIdName +\r\n \";\\n\" +\r\n uniformDecl +\r\n \"void main() {\\n\" +\r\n computePosition +\r\n \" gl_Position = czm_depthClamp(positionInClipCoords);\\n\" +\r\n \"}\\n\";\r\n var fs =\r\n \"#ifdef GL_EXT_frag_depth\\n\" +\r\n \"#extension GL_EXT_frag_depth : enable\\n\" +\r\n \"#endif\\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" gl_FragColor = vec4(1.0); \\n\" +\r\n \" czm_writeDepthClamp();\\n\" +\r\n \"}\\n\";\r\n\r\n if (model.extensionsUsed.WEB3D_quantized_attributes) {\r\n vs = modifyShaderForQuantizedAttributes(vs, model);\r\n }\r\n\r\n var drawVS = modifyShader(vs, model._vertexShaderLoaded);\r\n var drawFS = modifyShader(fs, model._classificationShaderLoaded);\r\n\r\n model._shaderProgram = {\r\n vertexShaderSource: drawVS,\r\n fragmentShaderSource: drawFS,\r\n attributeLocations: attributeLocations,\r\n };\r\n}\r\n\r\nfunction getAttributeLocations() {\r\n return {\r\n POSITION: 0,\r\n _BATCHID: 1,\r\n };\r\n}\r\n\r\nfunction createVertexArray(model) {\r\n var loadResources = model._loadResources;\r\n if (!loadResources.finishedBuffersCreation() || defined(model._vertexArray)) {\r\n return;\r\n }\r\n\r\n var rendererBuffers = model._buffers;\r\n var gltf = model.gltf;\r\n var accessors = gltf.accessors;\r\n var meshes = gltf.meshes;\r\n var primitives = meshes[0].primitives;\r\n\r\n var primitive = primitives[0];\r\n var attributeLocations = getAttributeLocations();\r\n var attributes = {};\r\n ForEach.meshPrimitiveAttribute(primitive, function (\r\n accessorId,\r\n attributeName\r\n ) {\r\n // Skip if the attribute is not used by the material, e.g., because the asset\r\n // was exported with an attribute that wasn't used and the asset wasn't optimized.\r\n var attributeLocation = attributeLocations[attributeName];\r\n if (defined(attributeLocation)) {\r\n var a = accessors[accessorId];\r\n attributes[attributeName] = {\r\n index: attributeLocation,\r\n vertexBuffer: rendererBuffers[a.bufferView],\r\n componentsPerAttribute: numberOfComponentsForType(a.type),\r\n componentDatatype: a.componentType,\r\n offsetInBytes: a.byteOffset,\r\n strideInBytes: getAccessorByteStride(gltf, a),\r\n };\r\n }\r\n });\r\n\r\n var indexBuffer;\r\n if (defined(primitive.indices)) {\r\n var accessor = accessors[primitive.indices];\r\n indexBuffer = rendererBuffers[accessor.bufferView];\r\n }\r\n model._vertexArray = {\r\n attributes: attributes,\r\n indexBuffer: indexBuffer,\r\n };\r\n}\r\n\r\nvar gltfSemanticUniforms = {\r\n PROJECTION: function (uniformState, model) {\r\n return ModelUtility.getGltfSemanticUniforms().PROJECTION(\r\n uniformState,\r\n model\r\n );\r\n },\r\n MODELVIEW: function (uniformState, model) {\r\n return ModelUtility.getGltfSemanticUniforms().MODELVIEW(\r\n uniformState,\r\n model\r\n );\r\n },\r\n CESIUM_RTC_MODELVIEW: function (uniformState, model) {\r\n return ModelUtility.getGltfSemanticUniforms().CESIUM_RTC_MODELVIEW(\r\n uniformState,\r\n model\r\n );\r\n },\r\n MODELVIEWPROJECTION: function (uniformState, model) {\r\n return ModelUtility.getGltfSemanticUniforms().MODELVIEWPROJECTION(\r\n uniformState,\r\n model\r\n );\r\n },\r\n};\r\n\r\nfunction createUniformMap(model, context) {\r\n if (defined(model._uniformMap)) {\r\n return;\r\n }\r\n\r\n var uniformMap = {};\r\n ForEach.technique(model.gltf, function (technique) {\r\n ForEach.techniqueUniform(technique, function (uniform, uniformName) {\r\n if (\r\n !defined(uniform.semantic) ||\r\n !defined(gltfSemanticUniforms[uniform.semantic])\r\n ) {\r\n return;\r\n }\r\n\r\n uniformMap[uniformName] = gltfSemanticUniforms[uniform.semantic](\r\n context.uniformState,\r\n model\r\n );\r\n });\r\n });\r\n\r\n model._uniformMap = uniformMap;\r\n}\r\n\r\nfunction createUniformsForQuantizedAttributes(model, primitive) {\r\n return ModelUtility.createUniformsForQuantizedAttributes(\r\n model.gltf,\r\n primitive,\r\n model._quantizedUniforms\r\n );\r\n}\r\n\r\nfunction triangleCountFromPrimitiveIndices(primitive, indicesCount) {\r\n switch (primitive.mode) {\r\n case PrimitiveType.TRIANGLES:\r\n return indicesCount / 3;\r\n case PrimitiveType.TRIANGLE_STRIP:\r\n case PrimitiveType.TRIANGLE_FAN:\r\n return Math.max(indicesCount - 2, 0);\r\n default:\r\n return 0;\r\n }\r\n}\r\n\r\nfunction createPrimitive(model) {\r\n var batchTable = model._batchTable;\r\n\r\n var uniformMap = model._uniformMap;\r\n var vertexArray = model._vertexArray;\r\n\r\n var gltf = model.gltf;\r\n var accessors = gltf.accessors;\r\n var gltfMeshes = gltf.meshes;\r\n var primitive = gltfMeshes[0].primitives[0];\r\n var ix = accessors[primitive.indices];\r\n\r\n var positionAccessor = primitive.attributes.POSITION;\r\n var minMax = ModelUtility.getAccessorMinMax(gltf, positionAccessor);\r\n var boundingSphere = BoundingSphere.fromCornerPoints(\r\n Cartesian3.fromArray(minMax.min),\r\n Cartesian3.fromArray(minMax.max)\r\n );\r\n\r\n var offset;\r\n var count;\r\n if (defined(ix)) {\r\n count = ix.count;\r\n offset = ix.byteOffset / IndexDatatype.getSizeInBytes(ix.componentType); // glTF has offset in bytes. Cesium has offsets in indices\r\n } else {\r\n var positions = accessors[primitive.attributes.POSITION];\r\n count = positions.count;\r\n offset = 0;\r\n }\r\n\r\n // Update model triangle count using number of indices\r\n model._trianglesLength += triangleCountFromPrimitiveIndices(primitive, count);\r\n\r\n // Allow callback to modify the uniformMap\r\n if (defined(model._uniformMapLoaded)) {\r\n uniformMap = model._uniformMapLoaded(uniformMap);\r\n }\r\n\r\n // Add uniforms for decoding quantized attributes if used\r\n if (model.extensionsUsed.WEB3D_quantized_attributes) {\r\n var quantizedUniformMap = createUniformsForQuantizedAttributes(\r\n model,\r\n primitive\r\n );\r\n uniformMap = combine(uniformMap, quantizedUniformMap);\r\n }\r\n\r\n var attribute = vertexArray.attributes.POSITION;\r\n var componentDatatype = attribute.componentDatatype;\r\n var typedArray = attribute.vertexBuffer;\r\n var byteOffset = typedArray.byteOffset;\r\n var bufferLength =\r\n typedArray.byteLength / ComponentDatatype.getSizeInBytes(componentDatatype);\r\n var positionsBuffer = ComponentDatatype.createArrayBufferView(\r\n componentDatatype,\r\n typedArray.buffer,\r\n byteOffset,\r\n bufferLength\r\n );\r\n\r\n attribute = vertexArray.attributes._BATCHID;\r\n componentDatatype = attribute.componentDatatype;\r\n typedArray = attribute.vertexBuffer;\r\n byteOffset = typedArray.byteOffset;\r\n bufferLength =\r\n typedArray.byteLength / ComponentDatatype.getSizeInBytes(componentDatatype);\r\n var vertexBatchIds = ComponentDatatype.createArrayBufferView(\r\n componentDatatype,\r\n typedArray.buffer,\r\n byteOffset,\r\n bufferLength\r\n );\r\n\r\n var buffer = vertexArray.indexBuffer.typedArray;\r\n var indices;\r\n if (vertexArray.indexBuffer.indexDatatype === IndexDatatype.UNSIGNED_SHORT) {\r\n indices = new Uint16Array(\r\n buffer.buffer,\r\n buffer.byteOffset,\r\n buffer.byteLength / Uint16Array.BYTES_PER_ELEMENT\r\n );\r\n } else {\r\n indices = new Uint32Array(\r\n buffer.buffer,\r\n buffer.byteOffset,\r\n buffer.byteLength / Uint32Array.BYTES_PER_ELEMENT\r\n );\r\n }\r\n\r\n positionsBuffer = arraySlice(positionsBuffer);\r\n vertexBatchIds = arraySlice(vertexBatchIds);\r\n indices = arraySlice(indices, offset, offset + count);\r\n\r\n var batchIds = [];\r\n var indexCounts = [];\r\n var indexOffsets = [];\r\n var batchedIndices = [];\r\n\r\n var currentId = vertexBatchIds[indices[0]];\r\n batchIds.push(currentId);\r\n indexOffsets.push(0);\r\n\r\n var batchId;\r\n var indexOffset;\r\n var indexCount;\r\n var indicesLength = indices.length;\r\n for (var j = 1; j < indicesLength; ++j) {\r\n batchId = vertexBatchIds[indices[j]];\r\n if (batchId !== currentId) {\r\n indexOffset = indexOffsets[indexOffsets.length - 1];\r\n indexCount = j - indexOffset;\r\n\r\n batchIds.push(batchId);\r\n indexCounts.push(indexCount);\r\n indexOffsets.push(j);\r\n\r\n batchedIndices.push(\r\n new Vector3DTileBatch({\r\n offset: indexOffset,\r\n count: indexCount,\r\n batchIds: [currentId],\r\n color: Color.WHITE,\r\n })\r\n );\r\n\r\n currentId = batchId;\r\n }\r\n }\r\n\r\n indexOffset = indexOffsets[indexOffsets.length - 1];\r\n indexCount = indicesLength - indexOffset;\r\n\r\n indexCounts.push(indexCount);\r\n batchedIndices.push(\r\n new Vector3DTileBatch({\r\n offset: indexOffset,\r\n count: indexCount,\r\n batchIds: [currentId],\r\n color: Color.WHITE,\r\n })\r\n );\r\n\r\n var shader = model._shaderProgram;\r\n var vertexShaderSource = shader.vertexShaderSource;\r\n var fragmentShaderSource = shader.fragmentShaderSource;\r\n var attributeLocations = shader.attributeLocations;\r\n var pickId = defined(model._pickIdLoaded) ? model._pickIdLoaded() : undefined;\r\n\r\n model._primitive = new Vector3DTilePrimitive({\r\n classificationType: model._classificationType,\r\n positions: positionsBuffer,\r\n indices: indices,\r\n indexOffsets: indexOffsets,\r\n indexCounts: indexCounts,\r\n batchIds: batchIds,\r\n vertexBatchIds: vertexBatchIds,\r\n batchedIndices: batchedIndices,\r\n batchTable: batchTable,\r\n boundingVolume: new BoundingSphere(), // updated in update()\r\n _vertexShaderSource: vertexShaderSource,\r\n _fragmentShaderSource: fragmentShaderSource,\r\n _attributeLocations: attributeLocations,\r\n _uniformMap: uniformMap,\r\n _pickId: pickId,\r\n _modelMatrix: new Matrix4(), // updated in update()\r\n _boundingSphere: boundingSphere, // used to update boundingVolume\r\n });\r\n\r\n // Release CPU resources\r\n model._buffers = undefined;\r\n model._vertexArray = undefined;\r\n model._shaderProgram = undefined;\r\n model._uniformMap = undefined;\r\n}\r\n\r\nfunction createRuntimeNodes(model) {\r\n var loadResources = model._loadResources;\r\n if (!loadResources.finished()) {\r\n return;\r\n }\r\n\r\n if (defined(model._primitive)) {\r\n return;\r\n }\r\n\r\n var gltf = model.gltf;\r\n var nodes = gltf.nodes;\r\n var gltfNode = nodes[0];\r\n model._nodeMatrix = ModelUtility.getTransform(gltfNode, model._nodeMatrix);\r\n\r\n createPrimitive(model);\r\n}\r\n\r\nfunction createResources(model, frameState) {\r\n var context = frameState.context;\r\n\r\n ModelUtility.checkSupportedGlExtensions(model.gltf.glExtensionsUsed, context);\r\n createBuffers(model); // using glTF bufferViews\r\n createProgram(model);\r\n createVertexArray(model); // using glTF meshes\r\n createUniformMap(model, context); // using glTF materials/techniques\r\n createRuntimeNodes(model); // using glTF scene\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar scratchComputedTranslation = new Cartesian4();\r\nvar scratchComputedMatrixIn2D = new Matrix4();\r\n\r\nfunction updateNodeModelMatrix(\r\n model,\r\n modelTransformChanged,\r\n justLoaded,\r\n projection\r\n) {\r\n var computedModelMatrix = model._computedModelMatrix;\r\n\r\n if (model._mode !== SceneMode.SCENE3D && !model._ignoreCommands) {\r\n var translation = Matrix4.getColumn(\r\n computedModelMatrix,\r\n 3,\r\n scratchComputedTranslation\r\n );\r\n if (!Cartesian4.equals(translation, Cartesian4.UNIT_W)) {\r\n computedModelMatrix = Transforms.basisTo2D(\r\n projection,\r\n computedModelMatrix,\r\n scratchComputedMatrixIn2D\r\n );\r\n model._rtcCenter = model._rtcCenter3D;\r\n } else {\r\n var center = model.boundingSphere.center;\r\n var to2D = Transforms.wgs84To2DModelMatrix(\r\n projection,\r\n center,\r\n scratchComputedMatrixIn2D\r\n );\r\n computedModelMatrix = Matrix4.multiply(\r\n to2D,\r\n computedModelMatrix,\r\n scratchComputedMatrixIn2D\r\n );\r\n\r\n if (defined(model._rtcCenter)) {\r\n Matrix4.setTranslation(\r\n computedModelMatrix,\r\n Cartesian4.UNIT_W,\r\n computedModelMatrix\r\n );\r\n model._rtcCenter = model._rtcCenter2D;\r\n }\r\n }\r\n }\r\n\r\n var primitive = model._primitive;\r\n\r\n if (modelTransformChanged || justLoaded) {\r\n Matrix4.multiplyTransformation(\r\n computedModelMatrix,\r\n model._nodeMatrix,\r\n primitive._modelMatrix\r\n );\r\n BoundingSphere.transform(\r\n primitive._boundingSphere,\r\n primitive._modelMatrix,\r\n primitive._boundingVolume\r\n );\r\n\r\n if (defined(model._rtcCenter)) {\r\n Cartesian3.add(\r\n model._rtcCenter,\r\n primitive._boundingVolume.center,\r\n primitive._boundingVolume.center\r\n );\r\n }\r\n }\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nClassificationModel.prototype.updateCommands = function (batchId, color) {\r\n this._primitive.updateCommands(batchId, color);\r\n};\r\n\r\nClassificationModel.prototype.update = function (frameState) {\r\n if (frameState.mode === SceneMode.MORPHING) {\r\n return;\r\n }\r\n\r\n if (!FeatureDetection.supportsWebP.initialized) {\r\n FeatureDetection.supportsWebP.initialize();\r\n return;\r\n }\r\n var supportsWebP = FeatureDetection.supportsWebP();\r\n\r\n if (this._state === ModelState.NEEDS_LOAD && defined(this.gltf)) {\r\n this._state = ModelState.LOADING;\r\n if (this._state !== ModelState.FAILED) {\r\n var extensions = this.gltf.extensions;\r\n if (defined(extensions) && defined(extensions.CESIUM_RTC)) {\r\n var center = Cartesian3.fromArray(extensions.CESIUM_RTC.center);\r\n if (!Cartesian3.equals(center, Cartesian3.ZERO)) {\r\n this._rtcCenter3D = center;\r\n\r\n var projection = frameState.mapProjection;\r\n var ellipsoid = projection.ellipsoid;\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n this._rtcCenter3D\r\n );\r\n var projectedCart = projection.project(cartographic);\r\n Cartesian3.fromElements(\r\n projectedCart.z,\r\n projectedCart.x,\r\n projectedCart.y,\r\n projectedCart\r\n );\r\n this._rtcCenter2D = projectedCart;\r\n\r\n this._rtcCenterEye = new Cartesian3();\r\n this._rtcCenter = this._rtcCenter3D;\r\n }\r\n }\r\n\r\n this._loadResources = new ModelLoadResources();\r\n ModelUtility.parseBuffers(this);\r\n }\r\n }\r\n\r\n var loadResources = this._loadResources;\r\n var justLoaded = false;\r\n\r\n if (this._state === ModelState.LOADING) {\r\n // Transition from LOADING -> LOADED once resources are downloaded and created.\r\n // Textures may continue to stream in while in the LOADED state.\r\n if (loadResources.pendingBufferLoads === 0) {\r\n ModelUtility.checkSupportedExtensions(\r\n this.extensionsRequired,\r\n supportsWebP\r\n );\r\n\r\n addBuffersToLoadResources(this);\r\n parseBufferViews(this);\r\n\r\n this._boundingSphere = ModelUtility.computeBoundingSphere(this);\r\n this._initialRadius = this._boundingSphere.radius;\r\n createResources(this, frameState);\r\n }\r\n if (loadResources.finished()) {\r\n this._state = ModelState.LOADED;\r\n justLoaded = true;\r\n }\r\n }\r\n\r\n if (defined(loadResources) && this._state === ModelState.LOADED) {\r\n if (!justLoaded) {\r\n createResources(this, frameState);\r\n }\r\n\r\n if (loadResources.finished()) {\r\n this._loadResources = undefined; // Clear CPU memory since WebGL resources were created.\r\n }\r\n }\r\n\r\n var show = this.show;\r\n\r\n if ((show && this._state === ModelState.LOADED) || justLoaded) {\r\n this._dirty = false;\r\n var modelMatrix = this.modelMatrix;\r\n\r\n var modeChanged = frameState.mode !== this._mode;\r\n this._mode = frameState.mode;\r\n\r\n // ClassificationModel's model matrix needs to be updated\r\n var modelTransformChanged =\r\n !Matrix4.equals(this._modelMatrix, modelMatrix) || modeChanged;\r\n\r\n if (modelTransformChanged || justLoaded) {\r\n Matrix4.clone(modelMatrix, this._modelMatrix);\r\n\r\n var computedModelMatrix = this._computedModelMatrix;\r\n Matrix4.clone(modelMatrix, computedModelMatrix);\r\n if (this._upAxis === Axis.Y) {\r\n Matrix4.multiplyTransformation(\r\n computedModelMatrix,\r\n Axis.Y_UP_TO_Z_UP,\r\n computedModelMatrix\r\n );\r\n } else if (this._upAxis === Axis.X) {\r\n Matrix4.multiplyTransformation(\r\n computedModelMatrix,\r\n Axis.X_UP_TO_Z_UP,\r\n computedModelMatrix\r\n );\r\n }\r\n }\r\n\r\n // Update modelMatrix throughout the graph as needed\r\n if (modelTransformChanged || justLoaded) {\r\n updateNodeModelMatrix(\r\n this,\r\n modelTransformChanged,\r\n justLoaded,\r\n frameState.mapProjection\r\n );\r\n this._dirty = true;\r\n }\r\n }\r\n\r\n if (justLoaded) {\r\n // Called after modelMatrix update.\r\n var model = this;\r\n frameState.afterRender.push(function () {\r\n model._ready = true;\r\n model._readyPromise.resolve(model);\r\n });\r\n return;\r\n }\r\n\r\n if (show && !this._ignoreCommands) {\r\n this._primitive.debugShowBoundingVolume = this.debugShowBoundingVolume;\r\n this._primitive.debugWireframe = this.debugWireframe;\r\n this._primitive.update(frameState);\r\n }\r\n};\r\n\r\nClassificationModel.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nClassificationModel.prototype.destroy = function () {\r\n this._primitive = this._primitive && this._primitive.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default ClassificationModel;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defined from \"../Core/defined.js\";\r\n\r\n/**\r\n * A Plane in Hessian Normal form to be used with {@link ClippingPlaneCollection}.\r\n * Compatible with mathematics functions in {@link Plane}\r\n *\r\n * @alias ClippingPlane\r\n * @constructor\r\n *\r\n * @param {Cartesian3} normal The plane's normal (normalized).\r\n * @param {Number} distance The shortest distance from the origin to the plane. The sign of\r\n * distance determines which side of the plane the origin\r\n * is on. If distance is positive, the origin is in the half-space\r\n * in the direction of the normal; if negative, the origin is in the half-space\r\n * opposite to the normal; if zero, the plane passes through the origin.\r\n */\r\nfunction ClippingPlane(normal, distance) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"normal\", normal);\r\n Check.typeOf.number(\"distance\", distance);\r\n //>>includeEnd('debug');\r\n\r\n this._distance = distance;\r\n this._normal = new UpdateChangedCartesian3(normal, this);\r\n this.onChangeCallback = undefined;\r\n this.index = -1; // to be set by ClippingPlaneCollection\r\n}\r\n\r\nObject.defineProperties(ClippingPlane.prototype, {\r\n /**\r\n * The shortest distance from the origin to the plane. The sign of\r\n * distance determines which side of the plane the origin\r\n * is on. If distance is positive, the origin is in the half-space\r\n * in the direction of the normal; if negative, the origin is in the half-space\r\n * opposite to the normal; if zero, the plane passes through the origin.\r\n *\r\n * @type {Number}\r\n * @memberof ClippingPlane.prototype\r\n */\r\n distance: {\r\n get: function () {\r\n return this._distance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"value\", value);\r\n //>>includeEnd('debug');\r\n if (defined(this.onChangeCallback) && value !== this._distance) {\r\n this.onChangeCallback(this.index);\r\n }\r\n this._distance = value;\r\n },\r\n },\r\n /**\r\n * The plane's normal.\r\n *\r\n * @type {Cartesian3}\r\n * @memberof ClippingPlane.prototype\r\n */\r\n normal: {\r\n get: function () {\r\n return this._normal;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"value\", value);\r\n //>>includeEnd('debug');\r\n if (\r\n defined(this.onChangeCallback) &&\r\n !Cartesian3.equals(this._normal._cartesian3, value)\r\n ) {\r\n this.onChangeCallback(this.index);\r\n }\r\n // Set without firing callback again\r\n Cartesian3.clone(value, this._normal._cartesian3);\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Create a ClippingPlane from a Plane object.\r\n *\r\n * @param {Plane} plane The plane containing parameters to copy\r\n * @param {ClippingPlane} [result] The object on which to store the result\r\n * @returns {ClippingPlane} The ClippingPlane generated from the plane's parameters.\r\n */\r\nClippingPlane.fromPlane = function (plane, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"plane\", plane);\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new ClippingPlane(plane.normal, plane.distance);\r\n } else {\r\n result.normal = plane.normal;\r\n result.distance = plane.distance;\r\n }\r\n return result;\r\n};\r\n\r\n/**\r\n * Clones the ClippingPlane without setting its ownership.\r\n * @param {ClippingPlane} clippingPlane The ClippingPlane to be cloned\r\n * @param {ClippingPlane} [result] The object on which to store the cloned parameters.\r\n * @returns {ClippingPlane} a clone of the input ClippingPlane\r\n */\r\nClippingPlane.clone = function (clippingPlane, result) {\r\n if (!defined(result)) {\r\n return new ClippingPlane(clippingPlane.normal, clippingPlane.distance);\r\n }\r\n result.normal = clippingPlane.normal;\r\n result.distance = clippingPlane.distance;\r\n return result;\r\n};\r\n\r\n/**\r\n * Wrapper on Cartesian3 that allows detection of Plane changes from \"members of members,\" for example:\r\n *\r\n * var clippingPlane = new ClippingPlane(...);\r\n * clippingPlane.normal.z = -1.0;\r\n *\r\n * @private\r\n */\r\nfunction UpdateChangedCartesian3(normal, clippingPlane) {\r\n this._clippingPlane = clippingPlane;\r\n this._cartesian3 = Cartesian3.clone(normal);\r\n}\r\n\r\nObject.defineProperties(UpdateChangedCartesian3.prototype, {\r\n x: {\r\n get: function () {\r\n return this._cartesian3.x;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"value\", value);\r\n //>>includeEnd('debug');\r\n if (\r\n defined(this._clippingPlane.onChangeCallback) &&\r\n value !== this._cartesian3.x\r\n ) {\r\n this._clippingPlane.onChangeCallback(this._clippingPlane.index);\r\n }\r\n this._cartesian3.x = value;\r\n },\r\n },\r\n y: {\r\n get: function () {\r\n return this._cartesian3.y;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"value\", value);\r\n //>>includeEnd('debug');\r\n if (\r\n defined(this._clippingPlane.onChangeCallback) &&\r\n value !== this._cartesian3.y\r\n ) {\r\n this._clippingPlane.onChangeCallback(this._clippingPlane.index);\r\n }\r\n this._cartesian3.y = value;\r\n },\r\n },\r\n z: {\r\n get: function () {\r\n return this._cartesian3.z;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"value\", value);\r\n //>>includeEnd('debug');\r\n if (\r\n defined(this._clippingPlane.onChangeCallback) &&\r\n value !== this._cartesian3.z\r\n ) {\r\n this._clippingPlane.onChangeCallback(this._clippingPlane.index);\r\n }\r\n this._cartesian3.z = value;\r\n },\r\n },\r\n});\r\nexport default ClippingPlane;\r\n","import AttributeCompression from \"../Core/AttributeCompression.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport Intersect from \"../Core/Intersect.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport Plane from \"../Core/Plane.js\";\r\nimport ContextLimits from \"../Renderer/ContextLimits.js\";\r\nimport PixelDatatype from \"../Renderer/PixelDatatype.js\";\r\nimport Sampler from \"../Renderer/Sampler.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport ClippingPlane from \"./ClippingPlane.js\";\r\n\r\n/**\r\n * Specifies a set of clipping planes. Clipping planes selectively disable rendering in a region on the\r\n * outside of the specified list of {@link ClippingPlane} objects for a single gltf model, 3D Tileset, or the globe.\r\n *

\r\n * In general the clipping planes' coordinates are relative to the object they're attached to, so a plane with distance set to 0 will clip\r\n * through the center of the object.\r\n *

\r\n *

\r\n * For 3D Tiles, the root tile's transform is used to position the clipping planes. If a transform is not defined, the root tile's {@link Cesium3DTile#boundingSphere} is used instead.\r\n *

\r\n *\r\n * @alias ClippingPlaneCollection\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {ClippingPlane[]} [options.planes=[]] An array of {@link ClippingPlane} objects used to selectively disable rendering on the outside of each plane.\r\n * @param {Boolean} [options.enabled=true] Determines whether the clipping planes are active.\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix specifying an additional transform relative to the clipping planes original coordinate system.\r\n * @param {Boolean} [options.unionClippingRegions=false] If true, a region will be clipped if it is on the outside of any plane in the collection. Otherwise, a region will only be clipped if it is on the outside of every plane.\r\n * @param {Color} [options.edgeColor=Color.WHITE] The color applied to highlight the edge along which an object is clipped.\r\n * @param {Number} [options.edgeWidth=0.0] The width, in pixels, of the highlight applied to the edge along which an object is clipped.\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/?src=3D%20Tiles%20Clipping%20Planes.html|Clipping 3D Tiles and glTF models.}\r\n * @demo {@link https://sandcastle.cesium.com/?src=Terrain%20Clipping%20Planes.html|Clipping the Globe.}\r\n *\r\n * @example\r\n * // This clipping plane's distance is positive, which means its normal\r\n * // is facing the origin. This will clip everything that is behind\r\n * // the plane, which is anything with y coordinate < -5.\r\n * var clippingPlanes = new Cesium.ClippingPlaneCollection({\r\n * planes : [\r\n * new Cesium.ClippingPlane(new Cesium.Cartesian3(0.0, 1.0, 0.0), 5.0)\r\n * ],\r\n * });\r\n * // Create an entity and attach the ClippingPlaneCollection to the model.\r\n * var entity = viewer.entities.add({\r\n * position : Cesium.Cartesian3.fromDegrees(-123.0744619, 44.0503706, 10000),\r\n * model : {\r\n * uri : 'model.gltf',\r\n * minimumPixelSize : 128,\r\n * maximumScale : 20000,\r\n * clippingPlanes : clippingPlanes\r\n * }\r\n * });\r\n * viewer.zoomTo(entity);\r\n */\r\nfunction ClippingPlaneCollection(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._planes = [];\r\n\r\n // Do partial texture updates if just one plane is dirty.\r\n // If many planes are dirty, refresh the entire texture.\r\n this._dirtyIndex = -1;\r\n this._multipleDirtyPlanes = false;\r\n\r\n this._enabled = defaultValue(options.enabled, true);\r\n\r\n /**\r\n * The 4x4 transformation matrix specifying an additional transform relative to the clipping planes\r\n * original coordinate system.\r\n *\r\n * @type {Matrix4}\r\n * @default Matrix4.IDENTITY\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n\r\n /**\r\n * The color applied to highlight the edge along which an object is clipped.\r\n *\r\n * @type {Color}\r\n * @default Color.WHITE\r\n */\r\n this.edgeColor = Color.clone(defaultValue(options.edgeColor, Color.WHITE));\r\n\r\n /**\r\n * The width, in pixels, of the highlight applied to the edge along which an object is clipped.\r\n *\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n this.edgeWidth = defaultValue(options.edgeWidth, 0.0);\r\n\r\n /**\r\n * An event triggered when a new clipping plane is added to the collection. Event handlers\r\n * are passed the new plane and the index at which it was added.\r\n * @type {Event}\r\n * @default Event()\r\n */\r\n this.planeAdded = new Event();\r\n\r\n /**\r\n * An event triggered when a new clipping plane is removed from the collection. Event handlers\r\n * are passed the new plane and the index from which it was removed.\r\n * @type {Event}\r\n * @default Event()\r\n */\r\n this.planeRemoved = new Event();\r\n\r\n // If this ClippingPlaneCollection has an owner, only its owner should update or destroy it.\r\n // This is because in a Cesium3DTileset multiple models may reference the tileset's ClippingPlaneCollection.\r\n this._owner = undefined;\r\n\r\n var unionClippingRegions = defaultValue(options.unionClippingRegions, false);\r\n this._unionClippingRegions = unionClippingRegions;\r\n this._testIntersection = unionClippingRegions\r\n ? unionIntersectFunction\r\n : defaultIntersectFunction;\r\n\r\n this._uint8View = undefined;\r\n this._float32View = undefined;\r\n\r\n this._clippingPlanesTexture = undefined;\r\n\r\n // Add each ClippingPlane object.\r\n var planes = options.planes;\r\n if (defined(planes)) {\r\n var planesLength = planes.length;\r\n for (var i = 0; i < planesLength; ++i) {\r\n this.add(planes[i]);\r\n }\r\n }\r\n}\r\n\r\nfunction unionIntersectFunction(value) {\r\n return value === Intersect.OUTSIDE;\r\n}\r\n\r\nfunction defaultIntersectFunction(value) {\r\n return value === Intersect.INSIDE;\r\n}\r\n\r\nObject.defineProperties(ClippingPlaneCollection.prototype, {\r\n /**\r\n * Returns the number of planes in this collection. This is commonly used with\r\n * {@link ClippingPlaneCollection#get} to iterate over all the planes\r\n * in the collection.\r\n *\r\n * @memberof ClippingPlaneCollection.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._planes.length;\r\n },\r\n },\r\n\r\n /**\r\n * If true, a region will be clipped if it is on the outside of any plane in the\r\n * collection. Otherwise, a region will only be clipped if it is on the\r\n * outside of every plane.\r\n *\r\n * @memberof ClippingPlaneCollection.prototype\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n unionClippingRegions: {\r\n get: function () {\r\n return this._unionClippingRegions;\r\n },\r\n set: function (value) {\r\n if (this._unionClippingRegions === value) {\r\n return;\r\n }\r\n this._unionClippingRegions = value;\r\n this._testIntersection = value\r\n ? unionIntersectFunction\r\n : defaultIntersectFunction;\r\n },\r\n },\r\n\r\n /**\r\n * If true, clipping will be enabled.\r\n *\r\n * @memberof ClippingPlaneCollection.prototype\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n enabled: {\r\n get: function () {\r\n return this._enabled;\r\n },\r\n set: function (value) {\r\n if (this._enabled === value) {\r\n return;\r\n }\r\n this._enabled = value;\r\n },\r\n },\r\n\r\n /**\r\n * Returns a texture containing packed, untransformed clipping planes.\r\n *\r\n * @memberof ClippingPlaneCollection.prototype\r\n * @type {Texture}\r\n * @readonly\r\n * @private\r\n */\r\n texture: {\r\n get: function () {\r\n return this._clippingPlanesTexture;\r\n },\r\n },\r\n\r\n /**\r\n * A reference to the ClippingPlaneCollection's owner, if any.\r\n *\r\n * @memberof ClippingPlaneCollection.prototype\r\n * @readonly\r\n * @private\r\n */\r\n owner: {\r\n get: function () {\r\n return this._owner;\r\n },\r\n },\r\n\r\n /**\r\n * Returns a Number encapsulating the state for this ClippingPlaneCollection.\r\n *\r\n * Clipping mode is encoded in the sign of the number, which is just the plane count.\r\n * Used for checking if shader regeneration is necessary.\r\n *\r\n * @memberof ClippingPlaneCollection.prototype\r\n * @returns {Number} A Number that describes the ClippingPlaneCollection's state.\r\n * @readonly\r\n * @private\r\n */\r\n clippingPlanesState: {\r\n get: function () {\r\n return this._unionClippingRegions\r\n ? this._planes.length\r\n : -this._planes.length;\r\n },\r\n },\r\n});\r\n\r\nfunction setIndexDirty(collection, index) {\r\n // If there's already a different _dirtyIndex set, more than one plane has changed since update.\r\n // Entire texture must be reloaded\r\n collection._multipleDirtyPlanes =\r\n collection._multipleDirtyPlanes ||\r\n (collection._dirtyIndex !== -1 && collection._dirtyIndex !== index);\r\n collection._dirtyIndex = index;\r\n}\r\n\r\n/**\r\n * Adds the specified {@link ClippingPlane} to the collection to be used to selectively disable rendering\r\n * on the outside of each plane. Use {@link ClippingPlaneCollection#unionClippingRegions} to modify\r\n * how modify the clipping behavior of multiple planes.\r\n *\r\n * @param {ClippingPlane} plane The ClippingPlane to add to the collection.\r\n *\r\n * @see ClippingPlaneCollection#unionClippingRegions\r\n * @see ClippingPlaneCollection#remove\r\n * @see ClippingPlaneCollection#removeAll\r\n */\r\nClippingPlaneCollection.prototype.add = function (plane) {\r\n var newPlaneIndex = this._planes.length;\r\n\r\n var that = this;\r\n plane.onChangeCallback = function (index) {\r\n setIndexDirty(that, index);\r\n };\r\n plane.index = newPlaneIndex;\r\n\r\n setIndexDirty(this, newPlaneIndex);\r\n this._planes.push(plane);\r\n this.planeAdded.raiseEvent(plane, newPlaneIndex);\r\n};\r\n\r\n/**\r\n * Returns the plane in the collection at the specified index. Indices are zero-based\r\n * and increase as planes are added. Removing a plane shifts all planes after\r\n * it to the left, changing their indices. This function is commonly used with\r\n * {@link ClippingPlaneCollection#length} to iterate over all the planes\r\n * in the collection.\r\n *\r\n * @param {Number} index The zero-based index of the plane.\r\n * @returns {ClippingPlane} The ClippingPlane at the specified index.\r\n *\r\n * @see ClippingPlaneCollection#length\r\n */\r\nClippingPlaneCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"index\", index);\r\n //>>includeEnd('debug');\r\n\r\n return this._planes[index];\r\n};\r\n\r\nfunction indexOf(planes, plane) {\r\n var length = planes.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (Plane.equals(planes[i], plane)) {\r\n return i;\r\n }\r\n }\r\n\r\n return -1;\r\n}\r\n\r\n/**\r\n * Checks whether this collection contains a ClippingPlane equal to the given ClippingPlane.\r\n *\r\n * @param {ClippingPlane} [clippingPlane] The ClippingPlane to check for.\r\n * @returns {Boolean} true if this collection contains the ClippingPlane, false otherwise.\r\n *\r\n * @see ClippingPlaneCollection#get\r\n */\r\nClippingPlaneCollection.prototype.contains = function (clippingPlane) {\r\n return indexOf(this._planes, clippingPlane) !== -1;\r\n};\r\n\r\n/**\r\n * Removes the first occurrence of the given ClippingPlane from the collection.\r\n *\r\n * @param {ClippingPlane} clippingPlane\r\n * @returns {Boolean} true if the plane was removed; false if the plane was not found in the collection.\r\n *\r\n * @see ClippingPlaneCollection#add\r\n * @see ClippingPlaneCollection#contains\r\n * @see ClippingPlaneCollection#removeAll\r\n */\r\nClippingPlaneCollection.prototype.remove = function (clippingPlane) {\r\n var planes = this._planes;\r\n var index = indexOf(planes, clippingPlane);\r\n\r\n if (index === -1) {\r\n return false;\r\n }\r\n\r\n // Unlink this ClippingPlaneCollection from the ClippingPlane\r\n if (clippingPlane instanceof ClippingPlane) {\r\n clippingPlane.onChangeCallback = undefined;\r\n clippingPlane.index = -1;\r\n }\r\n\r\n // Shift and update indices\r\n var length = planes.length - 1;\r\n for (var i = index; i < length; ++i) {\r\n var planeToKeep = planes[i + 1];\r\n planes[i] = planeToKeep;\r\n if (planeToKeep instanceof ClippingPlane) {\r\n planeToKeep.index = i;\r\n }\r\n }\r\n\r\n // Indicate planes texture is dirty\r\n this._multipleDirtyPlanes = true;\r\n planes.length = length;\r\n\r\n this.planeRemoved.raiseEvent(clippingPlane, index);\r\n\r\n return true;\r\n};\r\n\r\n/**\r\n * Removes all planes from the collection.\r\n *\r\n * @see ClippingPlaneCollection#add\r\n * @see ClippingPlaneCollection#remove\r\n */\r\nClippingPlaneCollection.prototype.removeAll = function () {\r\n // Dereference this ClippingPlaneCollection from all ClippingPlanes\r\n var planes = this._planes;\r\n var planesCount = planes.length;\r\n for (var i = 0; i < planesCount; ++i) {\r\n var plane = planes[i];\r\n if (plane instanceof ClippingPlane) {\r\n plane.onChangeCallback = undefined;\r\n plane.index = -1;\r\n }\r\n this.planeRemoved.raiseEvent(plane, i);\r\n }\r\n this._multipleDirtyPlanes = true;\r\n this._planes = [];\r\n};\r\n\r\nvar distanceEncodeScratch = new Cartesian4();\r\nvar oct32EncodeScratch = new Cartesian4();\r\nfunction packPlanesAsUint8(clippingPlaneCollection, startIndex, endIndex) {\r\n var uint8View = clippingPlaneCollection._uint8View;\r\n var planes = clippingPlaneCollection._planes;\r\n var byteIndex = 0;\r\n for (var i = startIndex; i < endIndex; ++i) {\r\n var plane = planes[i];\r\n\r\n var oct32Normal = AttributeCompression.octEncodeToCartesian4(\r\n plane.normal,\r\n oct32EncodeScratch\r\n );\r\n uint8View[byteIndex] = oct32Normal.x;\r\n uint8View[byteIndex + 1] = oct32Normal.y;\r\n uint8View[byteIndex + 2] = oct32Normal.z;\r\n uint8View[byteIndex + 3] = oct32Normal.w;\r\n\r\n var encodedDistance = Cartesian4.packFloat(\r\n plane.distance,\r\n distanceEncodeScratch\r\n );\r\n uint8View[byteIndex + 4] = encodedDistance.x;\r\n uint8View[byteIndex + 5] = encodedDistance.y;\r\n uint8View[byteIndex + 6] = encodedDistance.z;\r\n uint8View[byteIndex + 7] = encodedDistance.w;\r\n\r\n byteIndex += 8;\r\n }\r\n}\r\n\r\n// Pack starting at the beginning of the buffer to allow partial update\r\nfunction packPlanesAsFloats(clippingPlaneCollection, startIndex, endIndex) {\r\n var float32View = clippingPlaneCollection._float32View;\r\n var planes = clippingPlaneCollection._planes;\r\n\r\n var floatIndex = 0;\r\n for (var i = startIndex; i < endIndex; ++i) {\r\n var plane = planes[i];\r\n var normal = plane.normal;\r\n\r\n float32View[floatIndex] = normal.x;\r\n float32View[floatIndex + 1] = normal.y;\r\n float32View[floatIndex + 2] = normal.z;\r\n float32View[floatIndex + 3] = plane.distance;\r\n\r\n floatIndex += 4; // each plane is 4 floats\r\n }\r\n}\r\n\r\nfunction computeTextureResolution(pixelsNeeded, result) {\r\n var maxSize = ContextLimits.maximumTextureSize;\r\n result.x = Math.min(pixelsNeeded, maxSize);\r\n result.y = Math.ceil(pixelsNeeded / result.x);\r\n return result;\r\n}\r\n\r\nvar textureResolutionScratch = new Cartesian2();\r\n/**\r\n * Called when {@link Viewer} or {@link CesiumWidget} render the scene to\r\n * build the resources for clipping planes.\r\n *

\r\n * Do not call this function directly.\r\n *

\r\n */\r\nClippingPlaneCollection.prototype.update = function (frameState) {\r\n var clippingPlanesTexture = this._clippingPlanesTexture;\r\n var context = frameState.context;\r\n var useFloatTexture = ClippingPlaneCollection.useFloatTexture(context);\r\n\r\n // Compute texture requirements for current planes\r\n // In RGBA FLOAT, A plane is 4 floats packed to a RGBA.\r\n // In RGBA UNSIGNED_BYTE, A plane is a float in [0, 1) packed to RGBA and an Oct32 quantized normal,\r\n // so 8 bits or 2 pixels in RGBA.\r\n var pixelsNeeded = useFloatTexture ? this.length : this.length * 2;\r\n\r\n if (defined(clippingPlanesTexture)) {\r\n var currentPixelCount =\r\n clippingPlanesTexture.width * clippingPlanesTexture.height;\r\n // Recreate the texture to double current requirement if it isn't big enough or is 4 times larger than it needs to be.\r\n // Optimization note: this isn't exactly the classic resizeable array algorithm\r\n // * not necessarily checking for resize after each add/remove operation\r\n // * random-access deletes instead of just pops\r\n // * alloc ops likely more expensive than demonstrable via big-O analysis\r\n if (\r\n currentPixelCount < pixelsNeeded ||\r\n pixelsNeeded < 0.25 * currentPixelCount\r\n ) {\r\n clippingPlanesTexture.destroy();\r\n clippingPlanesTexture = undefined;\r\n this._clippingPlanesTexture = undefined;\r\n }\r\n }\r\n\r\n // If there are no clipping planes, there's nothing to update.\r\n if (this.length === 0) {\r\n return;\r\n }\r\n\r\n if (!defined(clippingPlanesTexture)) {\r\n var requiredResolution = computeTextureResolution(\r\n pixelsNeeded,\r\n textureResolutionScratch\r\n );\r\n // Allocate twice as much space as needed to avoid frequent texture reallocation.\r\n // Allocate in the Y direction, since texture may be as wide as context texture support.\r\n requiredResolution.y *= 2;\r\n\r\n if (useFloatTexture) {\r\n clippingPlanesTexture = new Texture({\r\n context: context,\r\n width: requiredResolution.x,\r\n height: requiredResolution.y,\r\n pixelFormat: PixelFormat.RGBA,\r\n pixelDatatype: PixelDatatype.FLOAT,\r\n sampler: Sampler.NEAREST,\r\n flipY: false,\r\n });\r\n this._float32View = new Float32Array(\r\n requiredResolution.x * requiredResolution.y * 4\r\n );\r\n } else {\r\n clippingPlanesTexture = new Texture({\r\n context: context,\r\n width: requiredResolution.x,\r\n height: requiredResolution.y,\r\n pixelFormat: PixelFormat.RGBA,\r\n pixelDatatype: PixelDatatype.UNSIGNED_BYTE,\r\n sampler: Sampler.NEAREST,\r\n flipY: false,\r\n });\r\n this._uint8View = new Uint8Array(\r\n requiredResolution.x * requiredResolution.y * 4\r\n );\r\n }\r\n\r\n this._clippingPlanesTexture = clippingPlanesTexture;\r\n this._multipleDirtyPlanes = true;\r\n }\r\n\r\n var dirtyIndex = this._dirtyIndex;\r\n if (!this._multipleDirtyPlanes && dirtyIndex === -1) {\r\n return;\r\n }\r\n if (!this._multipleDirtyPlanes) {\r\n // partial updates possible\r\n var offsetX = 0;\r\n var offsetY = 0;\r\n if (useFloatTexture) {\r\n offsetY = Math.floor(dirtyIndex / clippingPlanesTexture.width);\r\n offsetX = Math.floor(dirtyIndex - offsetY * clippingPlanesTexture.width);\r\n\r\n packPlanesAsFloats(this, dirtyIndex, dirtyIndex + 1);\r\n clippingPlanesTexture.copyFrom(\r\n {\r\n width: 1,\r\n height: 1,\r\n arrayBufferView: this._float32View,\r\n },\r\n offsetX,\r\n offsetY\r\n );\r\n } else {\r\n offsetY = Math.floor((dirtyIndex * 2) / clippingPlanesTexture.width);\r\n offsetX = Math.floor(\r\n dirtyIndex * 2 - offsetY * clippingPlanesTexture.width\r\n );\r\n packPlanesAsUint8(this, dirtyIndex, dirtyIndex + 1);\r\n clippingPlanesTexture.copyFrom(\r\n {\r\n width: 2,\r\n height: 1,\r\n arrayBufferView: this._uint8View,\r\n },\r\n offsetX,\r\n offsetY\r\n );\r\n }\r\n } else if (useFloatTexture) {\r\n packPlanesAsFloats(this, 0, this._planes.length);\r\n clippingPlanesTexture.copyFrom({\r\n width: clippingPlanesTexture.width,\r\n height: clippingPlanesTexture.height,\r\n arrayBufferView: this._float32View,\r\n });\r\n } else {\r\n packPlanesAsUint8(this, 0, this._planes.length);\r\n clippingPlanesTexture.copyFrom({\r\n width: clippingPlanesTexture.width,\r\n height: clippingPlanesTexture.height,\r\n arrayBufferView: this._uint8View,\r\n });\r\n }\r\n\r\n this._multipleDirtyPlanes = false;\r\n this._dirtyIndex = -1;\r\n};\r\n\r\nvar scratchMatrix = new Matrix4();\r\nvar scratchPlane = new Plane(Cartesian3.UNIT_X, 0.0);\r\n/**\r\n * Determines the type intersection with the planes of this ClippingPlaneCollection instance and the specified {@link TileBoundingVolume}.\r\n * @private\r\n *\r\n * @param {Object} tileBoundingVolume The volume to determine the intersection with the planes.\r\n * @param {Matrix4} [transform] An optional, additional matrix to transform the plane to world coordinates.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire volume is on the side of the planes\r\n * the normal is pointing and should be entirely rendered, {@link Intersect.OUTSIDE}\r\n * if the entire volume is on the opposite side and should be clipped, and\r\n * {@link Intersect.INTERSECTING} if the volume intersects the planes.\r\n */\r\nClippingPlaneCollection.prototype.computeIntersectionWithBoundingVolume = function (\r\n tileBoundingVolume,\r\n transform\r\n) {\r\n var planes = this._planes;\r\n var length = planes.length;\r\n\r\n var modelMatrix = this.modelMatrix;\r\n if (defined(transform)) {\r\n modelMatrix = Matrix4.multiply(transform, modelMatrix, scratchMatrix);\r\n }\r\n\r\n // If the collection is not set to union the clipping regions, the volume must be outside of all planes to be\r\n // considered completely clipped. If the collection is set to union the clipping regions, if the volume can be\r\n // outside any the planes, it is considered completely clipped.\r\n // Lastly, if not completely clipped, if any plane is intersecting, more calculations must be performed.\r\n var intersection = Intersect.INSIDE;\r\n if (!this.unionClippingRegions && length > 0) {\r\n intersection = Intersect.OUTSIDE;\r\n }\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var plane = planes[i];\r\n\r\n Plane.transform(plane, modelMatrix, scratchPlane); // ClippingPlane can be used for Plane math\r\n\r\n var value = tileBoundingVolume.intersectPlane(scratchPlane);\r\n if (value === Intersect.INTERSECTING) {\r\n intersection = value;\r\n } else if (this._testIntersection(value)) {\r\n return value;\r\n }\r\n }\r\n\r\n return intersection;\r\n};\r\n\r\n/**\r\n * Sets the owner for the input ClippingPlaneCollection if there wasn't another owner.\r\n * Destroys the owner's previous ClippingPlaneCollection if setting is successful.\r\n *\r\n * @param {ClippingPlaneCollection} [clippingPlaneCollection] A ClippingPlaneCollection (or undefined) being attached to an object\r\n * @param {Object} owner An Object that should receive the new ClippingPlaneCollection\r\n * @param {String} key The Key for the Object to reference the ClippingPlaneCollection\r\n * @private\r\n */\r\nClippingPlaneCollection.setOwner = function (\r\n clippingPlaneCollection,\r\n owner,\r\n key\r\n) {\r\n // Don't destroy the ClippingPlaneCollection if it is already owned by newOwner\r\n if (clippingPlaneCollection === owner[key]) {\r\n return;\r\n }\r\n // Destroy the existing ClippingPlaneCollection, if any\r\n owner[key] = owner[key] && owner[key].destroy();\r\n if (defined(clippingPlaneCollection)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(clippingPlaneCollection._owner)) {\r\n throw new DeveloperError(\r\n \"ClippingPlaneCollection should only be assigned to one object\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n clippingPlaneCollection._owner = owner;\r\n owner[key] = clippingPlaneCollection;\r\n }\r\n};\r\n\r\n/**\r\n * Function for checking if the context will allow clipping planes with floating point textures.\r\n *\r\n * @param {Context} context The Context that will contain clipped objects and clipping textures.\r\n * @returns {Boolean} true if floating point textures can be used for clipping planes.\r\n * @private\r\n */\r\nClippingPlaneCollection.useFloatTexture = function (context) {\r\n return context.floatingPointTexture;\r\n};\r\n\r\n/**\r\n * Function for getting the clipping plane collection's texture resolution.\r\n * If the ClippingPlaneCollection hasn't been updated, returns the resolution that will be\r\n * allocated based on the current plane count.\r\n *\r\n * @param {ClippingPlaneCollection} clippingPlaneCollection The clipping plane collection\r\n * @param {Context} context The rendering context\r\n * @param {Cartesian2} result A Cartesian2 for the result.\r\n * @returns {Cartesian2} The required resolution.\r\n * @private\r\n */\r\nClippingPlaneCollection.getTextureResolution = function (\r\n clippingPlaneCollection,\r\n context,\r\n result\r\n) {\r\n var texture = clippingPlaneCollection.texture;\r\n if (defined(texture)) {\r\n result.x = texture.width;\r\n result.y = texture.height;\r\n return result;\r\n }\r\n\r\n var pixelsNeeded = ClippingPlaneCollection.useFloatTexture(context)\r\n ? clippingPlaneCollection.length\r\n : clippingPlaneCollection.length * 2;\r\n var requiredResolution = computeTextureResolution(pixelsNeeded, result);\r\n\r\n // Allocate twice as much space as needed to avoid frequent texture reallocation.\r\n requiredResolution.y *= 2;\r\n return requiredResolution;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see ClippingPlaneCollection#destroy\r\n */\r\nClippingPlaneCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * clippingPlanes = clippingPlanes && clippingPlanes.destroy();\r\n *\r\n * @see ClippingPlaneCollection#isDestroyed\r\n */\r\nClippingPlaneCollection.prototype.destroy = function () {\r\n this._clippingPlanesTexture =\r\n this._clippingPlanesTexture && this._clippingPlanesTexture.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default ClippingPlaneCollection;\r\n","import CesiumMath from \"../Core/Math.js\";\r\n\r\n/**\r\n * Defines different modes for blending between a target color and a primitive's source color.\r\n *\r\n * HIGHLIGHT multiplies the source color by the target color\r\n * REPLACE replaces the source color with the target color\r\n * MIX blends the source color and target color together\r\n *\r\n * @enum {Number}\r\n *\r\n * @see Model.colorBlendMode\r\n */\r\nvar ColorBlendMode = {\r\n HIGHLIGHT: 0,\r\n REPLACE: 1,\r\n MIX: 2,\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nColorBlendMode.getColorBlend = function (colorBlendMode, colorBlendAmount) {\r\n if (colorBlendMode === ColorBlendMode.HIGHLIGHT) {\r\n return 0.0;\r\n } else if (colorBlendMode === ColorBlendMode.REPLACE) {\r\n return 1.0;\r\n } else if (colorBlendMode === ColorBlendMode.MIX) {\r\n // The value 0.0 is reserved for highlight, so clamp to just above 0.0.\r\n return CesiumMath.clamp(colorBlendAmount, CesiumMath.EPSILON4, 1.0);\r\n }\r\n};\r\nexport default Object.freeze(ColorBlendMode);\r\n","import arraySlice from \"../Core/arraySlice.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport TaskProcessor from \"../Core/TaskProcessor.js\";\r\nimport ForEach from \"../ThirdParty/GltfPipeline/ForEach.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DracoLoader() {}\r\n\r\n// Maximum concurrency to use when decoding draco models\r\nDracoLoader._maxDecodingConcurrency = Math.max(\r\n FeatureDetection.hardwareConcurrency - 1,\r\n 1\r\n);\r\n\r\n// Exposed for testing purposes\r\nDracoLoader._decoderTaskProcessor = undefined;\r\nDracoLoader._taskProcessorReady = false;\r\nDracoLoader._getDecoderTaskProcessor = function () {\r\n if (!defined(DracoLoader._decoderTaskProcessor)) {\r\n var processor = new TaskProcessor(\r\n \"decodeDraco\",\r\n DracoLoader._maxDecodingConcurrency\r\n );\r\n processor\r\n .initWebAssemblyModule({\r\n modulePath: \"ThirdParty/Workers/draco_wasm_wrapper.js\",\r\n wasmBinaryFile: \"ThirdParty/draco_decoder.wasm\",\r\n fallbackModulePath: \"ThirdParty/Workers/draco_decoder.js\",\r\n })\r\n .then(function () {\r\n DracoLoader._taskProcessorReady = true;\r\n });\r\n DracoLoader._decoderTaskProcessor = processor;\r\n }\r\n\r\n return DracoLoader._decoderTaskProcessor;\r\n};\r\n\r\n/**\r\n * Returns true if the model uses or requires KHR_draco_mesh_compression.\r\n *\r\n * @private\r\n */\r\nDracoLoader.hasExtension = function (model) {\r\n return (\r\n defined(model.extensionsRequired.KHR_draco_mesh_compression) ||\r\n defined(model.extensionsUsed.KHR_draco_mesh_compression)\r\n );\r\n};\r\n\r\nfunction addBufferToLoadResources(loadResources, typedArray) {\r\n // Create a new id to differentiate from original glTF bufferViews\r\n var bufferViewId =\r\n \"runtime.\" + Object.keys(loadResources.createdBufferViews).length;\r\n\r\n var loadResourceBuffers = loadResources.buffers;\r\n var id = Object.keys(loadResourceBuffers).length;\r\n loadResourceBuffers[id] = typedArray;\r\n loadResources.createdBufferViews[bufferViewId] = {\r\n buffer: id,\r\n byteOffset: 0,\r\n byteLength: typedArray.byteLength,\r\n };\r\n\r\n return bufferViewId;\r\n}\r\n\r\nfunction addNewVertexBuffer(typedArray, model, context) {\r\n var loadResources = model._loadResources;\r\n var id = addBufferToLoadResources(loadResources, typedArray);\r\n loadResources.vertexBuffersToCreate.enqueue(id);\r\n return id;\r\n}\r\n\r\nfunction addNewIndexBuffer(indexArray, model, context) {\r\n var typedArray = indexArray.typedArray;\r\n var loadResources = model._loadResources;\r\n var id = addBufferToLoadResources(loadResources, typedArray);\r\n loadResources.indexBuffersToCreate.enqueue({\r\n id: id,\r\n componentType: ComponentDatatype.fromTypedArray(typedArray),\r\n });\r\n\r\n return {\r\n bufferViewId: id,\r\n numberOfIndices: indexArray.numberOfIndices,\r\n };\r\n}\r\n\r\nfunction scheduleDecodingTask(\r\n decoderTaskProcessor,\r\n model,\r\n loadResources,\r\n context\r\n) {\r\n if (!DracoLoader._taskProcessorReady) {\r\n // The task processor is not ready to schedule tasks\r\n return;\r\n }\r\n\r\n var taskData = loadResources.primitivesToDecode.peek();\r\n if (!defined(taskData)) {\r\n // All primitives are processing\r\n return;\r\n }\r\n\r\n var promise = decoderTaskProcessor.scheduleTask(taskData, [\r\n taskData.array.buffer,\r\n ]);\r\n if (!defined(promise)) {\r\n // Cannot schedule another task this frame\r\n return;\r\n }\r\n\r\n loadResources.activeDecodingTasks++;\r\n loadResources.primitivesToDecode.dequeue();\r\n return promise.then(function (result) {\r\n loadResources.activeDecodingTasks--;\r\n\r\n var decodedIndexBuffer = addNewIndexBuffer(\r\n result.indexArray,\r\n model,\r\n context\r\n );\r\n\r\n var attributes = {};\r\n var decodedAttributeData = result.attributeData;\r\n for (var attributeName in decodedAttributeData) {\r\n if (decodedAttributeData.hasOwnProperty(attributeName)) {\r\n var attribute = decodedAttributeData[attributeName];\r\n var vertexArray = attribute.array;\r\n var vertexBufferView = addNewVertexBuffer(vertexArray, model, context);\r\n\r\n var data = attribute.data;\r\n data.bufferView = vertexBufferView;\r\n\r\n attributes[attributeName] = data;\r\n }\r\n }\r\n\r\n model._decodedData[taskData.mesh + \".primitive.\" + taskData.primitive] = {\r\n bufferView: decodedIndexBuffer.bufferViewId,\r\n numberOfIndices: decodedIndexBuffer.numberOfIndices,\r\n attributes: attributes,\r\n };\r\n });\r\n}\r\n\r\nDracoLoader._decodedModelResourceCache = undefined;\r\n\r\n/**\r\n * Parses draco extension on model primitives and\r\n * adds the decoding data to the model's load resources.\r\n *\r\n * @private\r\n */\r\nDracoLoader.parse = function (model, context) {\r\n if (!DracoLoader.hasExtension(model)) {\r\n return;\r\n }\r\n\r\n var loadResources = model._loadResources;\r\n var cacheKey = model.cacheKey;\r\n if (defined(cacheKey)) {\r\n if (!defined(DracoLoader._decodedModelResourceCache)) {\r\n if (!defined(context.cache.modelDecodingCache)) {\r\n context.cache.modelDecodingCache = {};\r\n }\r\n\r\n DracoLoader._decodedModelResourceCache = context.cache.modelDecodingCache;\r\n }\r\n\r\n // Decoded data for model will be loaded from cache\r\n var cachedData = DracoLoader._decodedModelResourceCache[cacheKey];\r\n if (defined(cachedData)) {\r\n cachedData.count++;\r\n loadResources.pendingDecodingCache = true;\r\n return;\r\n }\r\n }\r\n\r\n var dequantizeInShader = model._dequantizeInShader;\r\n var gltf = model.gltf;\r\n ForEach.mesh(gltf, function (mesh, meshId) {\r\n ForEach.meshPrimitive(mesh, function (primitive, primitiveId) {\r\n if (!defined(primitive.extensions)) {\r\n return;\r\n }\r\n\r\n var compressionData = primitive.extensions.KHR_draco_mesh_compression;\r\n if (!defined(compressionData)) {\r\n return;\r\n }\r\n\r\n var bufferView = gltf.bufferViews[compressionData.bufferView];\r\n var typedArray = arraySlice(\r\n gltf.buffers[bufferView.buffer].extras._pipeline.source,\r\n bufferView.byteOffset,\r\n bufferView.byteOffset + bufferView.byteLength\r\n );\r\n loadResources.primitivesToDecode.enqueue({\r\n mesh: meshId,\r\n primitive: primitiveId,\r\n array: typedArray,\r\n bufferView: bufferView,\r\n compressedAttributes: compressionData.attributes,\r\n dequantizeInShader: dequantizeInShader,\r\n });\r\n });\r\n });\r\n};\r\n\r\n/**\r\n * Schedules decoding tasks available this frame.\r\n * @private\r\n */\r\nDracoLoader.decodeModel = function (model, context) {\r\n if (!DracoLoader.hasExtension(model)) {\r\n return when.resolve();\r\n }\r\n\r\n var loadResources = model._loadResources;\r\n var cacheKey = model.cacheKey;\r\n if (defined(cacheKey) && defined(DracoLoader._decodedModelResourceCache)) {\r\n var cachedData = DracoLoader._decodedModelResourceCache[cacheKey];\r\n // Load decoded data for model when cache is ready\r\n if (defined(cachedData) && loadResources.pendingDecodingCache) {\r\n return when(cachedData.ready, function () {\r\n model._decodedData = cachedData.data;\r\n loadResources.pendingDecodingCache = false;\r\n });\r\n }\r\n\r\n // Decoded data for model should be cached when ready\r\n DracoLoader._decodedModelResourceCache[cacheKey] = {\r\n ready: false,\r\n count: 1,\r\n data: undefined,\r\n };\r\n }\r\n\r\n if (loadResources.primitivesToDecode.length === 0) {\r\n // No more tasks to schedule\r\n return when.resolve();\r\n }\r\n\r\n var decoderTaskProcessor = DracoLoader._getDecoderTaskProcessor();\r\n var decodingPromises = [];\r\n\r\n var promise = scheduleDecodingTask(\r\n decoderTaskProcessor,\r\n model,\r\n loadResources,\r\n context\r\n );\r\n while (defined(promise)) {\r\n decodingPromises.push(promise);\r\n promise = scheduleDecodingTask(\r\n decoderTaskProcessor,\r\n model,\r\n loadResources,\r\n context\r\n );\r\n }\r\n\r\n return when.all(decodingPromises);\r\n};\r\n\r\n/**\r\n * Decodes a compressed point cloud. Returns undefined if the task cannot be scheduled.\r\n * @private\r\n */\r\nDracoLoader.decodePointCloud = function (parameters) {\r\n var decoderTaskProcessor = DracoLoader._getDecoderTaskProcessor();\r\n if (!DracoLoader._taskProcessorReady) {\r\n // The task processor is not ready to schedule tasks\r\n return;\r\n }\r\n return decoderTaskProcessor.scheduleTask(parameters, [\r\n parameters.buffer.buffer,\r\n ]);\r\n};\r\n\r\n/**\r\n * Caches a models decoded data so it doesn't need to decode more than once.\r\n * @private\r\n */\r\nDracoLoader.cacheDataForModel = function (model) {\r\n var cacheKey = model.cacheKey;\r\n if (defined(cacheKey) && defined(DracoLoader._decodedModelResourceCache)) {\r\n var cachedData = DracoLoader._decodedModelResourceCache[cacheKey];\r\n if (defined(cachedData)) {\r\n cachedData.ready = true;\r\n cachedData.data = model._decodedData;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Destroys the cached data that this model references if it is no longer in use.\r\n * @private\r\n */\r\nDracoLoader.destroyCachedDataForModel = function (model) {\r\n var cacheKey = model.cacheKey;\r\n if (defined(cacheKey) && defined(DracoLoader._decodedModelResourceCache)) {\r\n var cachedData = DracoLoader._decodedModelResourceCache[cacheKey];\r\n if (defined(cachedData) && --cachedData.count === 0) {\r\n delete DracoLoader._decodedModelResourceCache[cacheKey];\r\n }\r\n }\r\n};\r\nexport default DracoLoader;\r\n","import Check from \"../Core/Check.js\";\r\n\r\n/**\r\n * Gets a GLSL snippet that clips a fragment using the `clip` function from {@link getClippingFunction} and styles it.\r\n *\r\n * @param {String} samplerUniformName Name of the uniform for the clipping planes texture sampler.\r\n * @param {String} matrixUniformName Name of the uniform for the clipping planes matrix.\r\n * @param {String} styleUniformName Name of the uniform for the clipping planes style, a vec4.\r\n * @returns {String} A string containing GLSL that clips and styles the current fragment.\r\n * @private\r\n */\r\nfunction getClipAndStyleCode(\r\n samplerUniformName,\r\n matrixUniformName,\r\n styleUniformName\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.string(\"samplerUniformName\", samplerUniformName);\r\n Check.typeOf.string(\"matrixUniformName\", matrixUniformName);\r\n Check.typeOf.string(\"styleUniformName\", styleUniformName);\r\n //>>includeEnd('debug');\r\n\r\n var shaderCode =\r\n \" float clipDistance = clip(gl_FragCoord, \" +\r\n samplerUniformName +\r\n \", \" +\r\n matrixUniformName +\r\n \"); \\n\" +\r\n \" vec4 clippingPlanesEdgeColor = vec4(1.0); \\n\" +\r\n \" clippingPlanesEdgeColor.rgb = \" +\r\n styleUniformName +\r\n \".rgb; \\n\" +\r\n \" float clippingPlanesEdgeWidth = \" +\r\n styleUniformName +\r\n \".a; \\n\" +\r\n \" if (clipDistance > 0.0 && clipDistance < clippingPlanesEdgeWidth) \\n\" +\r\n \" { \\n\" +\r\n \" gl_FragColor = clippingPlanesEdgeColor;\\n\" +\r\n \" } \\n\";\r\n return shaderCode;\r\n}\r\nexport default getClipAndStyleCode;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport ClippingPlaneCollection from \"./ClippingPlaneCollection.js\";\r\n\r\nvar textureResolutionScratch = new Cartesian2();\r\n/**\r\n * Gets the GLSL functions needed to retrieve clipping planes from a ClippingPlaneCollection's texture.\r\n *\r\n * @param {ClippingPlaneCollection} clippingPlaneCollection ClippingPlaneCollection with a defined texture.\r\n * @param {Context} context The current rendering context.\r\n * @returns {String} A string containing GLSL functions for retrieving clipping planes.\r\n * @private\r\n */\r\nfunction getClippingFunction(clippingPlaneCollection, context) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"clippingPlaneCollection\", clippingPlaneCollection);\r\n Check.typeOf.object(\"context\", context);\r\n //>>includeEnd('debug');\r\n var unionClippingRegions = clippingPlaneCollection.unionClippingRegions;\r\n var clippingPlanesLength = clippingPlaneCollection.length;\r\n var usingFloatTexture = ClippingPlaneCollection.useFloatTexture(context);\r\n var textureResolution = ClippingPlaneCollection.getTextureResolution(\r\n clippingPlaneCollection,\r\n context,\r\n textureResolutionScratch\r\n );\r\n var width = textureResolution.x;\r\n var height = textureResolution.y;\r\n\r\n var functions = usingFloatTexture\r\n ? getClippingPlaneFloat(width, height)\r\n : getClippingPlaneUint8(width, height);\r\n functions += \"\\n\";\r\n functions += unionClippingRegions\r\n ? clippingFunctionUnion(clippingPlanesLength)\r\n : clippingFunctionIntersect(clippingPlanesLength);\r\n return functions;\r\n}\r\n\r\nfunction clippingFunctionUnion(clippingPlanesLength) {\r\n var functionString =\r\n \"float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\\n\" +\r\n \"{\\n\" +\r\n \" vec4 position = czm_windowToEyeCoordinates(fragCoord);\\n\" +\r\n \" vec3 clipNormal = vec3(0.0);\\n\" +\r\n \" vec3 clipPosition = vec3(0.0);\\n\" +\r\n \" float clipAmount;\\n\" + // For union planes, we want to get the min distance. So we set the initial value to the first plane distance in the loop below.\r\n \" float pixelWidth = czm_metersPerPixel(position);\\n\" +\r\n \" bool breakAndDiscard = false;\\n\" +\r\n \" for (int i = 0; i < \" +\r\n clippingPlanesLength +\r\n \"; ++i)\\n\" +\r\n \" {\\n\" +\r\n \" vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\\n\" +\r\n \" clipNormal = clippingPlane.xyz;\\n\" +\r\n \" clipPosition = -clippingPlane.w * clipNormal;\\n\" +\r\n \" float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\\n\" +\r\n \" clipAmount = czm_branchFreeTernary(i == 0, amount, min(amount, clipAmount));\\n\" +\r\n \" if (amount <= 0.0)\\n\" +\r\n \" {\\n\" +\r\n \" breakAndDiscard = true;\\n\" +\r\n \" break;\\n\" + // HLSL compiler bug if we discard here: https://bugs.chromium.org/p/angleproject/issues/detail?id=1945#c6\r\n \" }\\n\" +\r\n \" }\\n\" +\r\n \" if (breakAndDiscard) {\\n\" +\r\n \" discard;\\n\" +\r\n \" }\\n\" +\r\n \" return clipAmount;\\n\" +\r\n \"}\\n\";\r\n return functionString;\r\n}\r\n\r\nfunction clippingFunctionIntersect(clippingPlanesLength) {\r\n var functionString =\r\n \"float clip(vec4 fragCoord, sampler2D clippingPlanes, mat4 clippingPlanesMatrix)\\n\" +\r\n \"{\\n\" +\r\n \" bool clipped = true;\\n\" +\r\n \" vec4 position = czm_windowToEyeCoordinates(fragCoord);\\n\" +\r\n \" vec3 clipNormal = vec3(0.0);\\n\" +\r\n \" vec3 clipPosition = vec3(0.0);\\n\" +\r\n \" float clipAmount = 0.0;\\n\" +\r\n \" float pixelWidth = czm_metersPerPixel(position);\\n\" +\r\n \" for (int i = 0; i < \" +\r\n clippingPlanesLength +\r\n \"; ++i)\\n\" +\r\n \" {\\n\" +\r\n \" vec4 clippingPlane = getClippingPlane(clippingPlanes, i, clippingPlanesMatrix);\\n\" +\r\n \" clipNormal = clippingPlane.xyz;\\n\" +\r\n \" clipPosition = -clippingPlane.w * clipNormal;\\n\" +\r\n \" float amount = dot(clipNormal, (position.xyz - clipPosition)) / pixelWidth;\\n\" +\r\n \" clipAmount = max(amount, clipAmount);\\n\" +\r\n \" clipped = clipped && (amount <= 0.0);\\n\" +\r\n \" }\\n\" +\r\n \" if (clipped)\\n\" +\r\n \" {\\n\" +\r\n \" discard;\\n\" +\r\n \" }\\n\" +\r\n \" return clipAmount;\\n\" +\r\n \"}\\n\";\r\n return functionString;\r\n}\r\n\r\nfunction getClippingPlaneFloat(width, height) {\r\n var pixelWidth = 1.0 / width;\r\n var pixelHeight = 1.0 / height;\r\n\r\n var pixelWidthString = pixelWidth + \"\";\r\n if (pixelWidthString.indexOf(\".\") === -1) {\r\n pixelWidthString += \".0\";\r\n }\r\n var pixelHeightString = pixelHeight + \"\";\r\n if (pixelHeightString.indexOf(\".\") === -1) {\r\n pixelHeightString += \".0\";\r\n }\r\n\r\n var functionString =\r\n \"vec4 getClippingPlane(highp sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\\n\" +\r\n \"{\\n\" +\r\n \" int pixY = clippingPlaneNumber / \" +\r\n width +\r\n \";\\n\" +\r\n \" int pixX = clippingPlaneNumber - (pixY * \" +\r\n width +\r\n \");\\n\" +\r\n \" float u = (float(pixX) + 0.5) * \" +\r\n pixelWidthString +\r\n \";\\n\" + // sample from center of pixel\r\n \" float v = (float(pixY) + 0.5) * \" +\r\n pixelHeightString +\r\n \";\\n\" +\r\n \" vec4 plane = texture2D(packedClippingPlanes, vec2(u, v));\\n\" +\r\n \" return czm_transformPlane(plane, transform);\\n\" +\r\n \"}\\n\";\r\n return functionString;\r\n}\r\n\r\nfunction getClippingPlaneUint8(width, height) {\r\n var pixelWidth = 1.0 / width;\r\n var pixelHeight = 1.0 / height;\r\n\r\n var pixelWidthString = pixelWidth + \"\";\r\n if (pixelWidthString.indexOf(\".\") === -1) {\r\n pixelWidthString += \".0\";\r\n }\r\n var pixelHeightString = pixelHeight + \"\";\r\n if (pixelHeightString.indexOf(\".\") === -1) {\r\n pixelHeightString += \".0\";\r\n }\r\n\r\n var functionString =\r\n \"vec4 getClippingPlane(highp sampler2D packedClippingPlanes, int clippingPlaneNumber, mat4 transform)\\n\" +\r\n \"{\\n\" +\r\n \" int clippingPlaneStartIndex = clippingPlaneNumber * 2;\\n\" + // clipping planes are two pixels each\r\n \" int pixY = clippingPlaneStartIndex / \" +\r\n width +\r\n \";\\n\" +\r\n \" int pixX = clippingPlaneStartIndex - (pixY * \" +\r\n width +\r\n \");\\n\" +\r\n \" float u = (float(pixX) + 0.5) * \" +\r\n pixelWidthString +\r\n \";\\n\" + // sample from center of pixel\r\n \" float v = (float(pixY) + 0.5) * \" +\r\n pixelHeightString +\r\n \";\\n\" +\r\n \" vec4 oct32 = texture2D(packedClippingPlanes, vec2(u, v)) * 255.0;\\n\" +\r\n \" vec2 oct = vec2(oct32.x * 256.0 + oct32.y, oct32.z * 256.0 + oct32.w);\\n\" +\r\n \" vec4 plane;\\n\" +\r\n \" plane.xyz = czm_octDecode(oct, 65535.0);\\n\" +\r\n \" plane.w = czm_unpackFloat(texture2D(packedClippingPlanes, vec2(u + \" +\r\n pixelWidthString +\r\n \", v)));\\n\" +\r\n \" return czm_transformPlane(plane, transform);\\n\" +\r\n \"}\\n\";\r\n return functionString;\r\n}\r\nexport default getClippingFunction;\r\n","/**\r\n * @private\r\n */\r\nvar JobType = {\r\n TEXTURE: 0,\r\n PROGRAM: 1,\r\n BUFFER: 2,\r\n NUMBER_OF_JOB_TYPES: 3,\r\n};\r\nexport default Object.freeze(JobType);\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport LinearSpline from \"../Core/LinearSpline.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Quaternion from \"../Core/Quaternion.js\";\r\nimport QuaternionSpline from \"../Core/QuaternionSpline.js\";\r\nimport Spline from \"../Core/Spline.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport WeightSpline from \"../Core/WeightSpline.js\";\r\nimport getAccessorByteStride from \"../ThirdParty/GltfPipeline/getAccessorByteStride.js\";\r\nimport numberOfComponentsForType from \"../ThirdParty/GltfPipeline/numberOfComponentsForType.js\";\r\nimport AttributeType from \"./AttributeType.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction ModelAnimationCache() {}\r\n\r\nvar dataUriRegex = /^data\\:/i;\r\n\r\nfunction getAccessorKey(model, accessor) {\r\n var gltf = model.gltf;\r\n var buffers = gltf.buffers;\r\n var bufferViews = gltf.bufferViews;\r\n\r\n var bufferView = bufferViews[accessor.bufferView];\r\n var buffer = buffers[bufferView.buffer];\r\n\r\n var byteOffset = bufferView.byteOffset + accessor.byteOffset;\r\n var byteLength = accessor.count * numberOfComponentsForType(accessor.type);\r\n\r\n var uriKey = dataUriRegex.test(buffer.uri) ? \"\" : buffer.uri;\r\n return model.cacheKey + \"//\" + uriKey + \"/\" + byteOffset + \"/\" + byteLength;\r\n}\r\n\r\nvar cachedAnimationParameters = {};\r\n\r\nModelAnimationCache.getAnimationParameterValues = function (model, accessor) {\r\n var key = getAccessorKey(model, accessor);\r\n var values = cachedAnimationParameters[key];\r\n\r\n if (!defined(values)) {\r\n // Cache miss\r\n var gltf = model.gltf;\r\n\r\n var buffers = gltf.buffers;\r\n var bufferViews = gltf.bufferViews;\r\n\r\n var bufferView = bufferViews[accessor.bufferView];\r\n var bufferId = bufferView.buffer;\r\n var buffer = buffers[bufferId];\r\n var source = buffer.extras._pipeline.source;\r\n\r\n var componentType = accessor.componentType;\r\n var type = accessor.type;\r\n var numberOfComponents = numberOfComponentsForType(type);\r\n var count = accessor.count;\r\n var byteStride = getAccessorByteStride(gltf, accessor);\r\n\r\n values = new Array(count);\r\n var accessorByteOffset = defaultValue(accessor.byteOffset, 0);\r\n var byteOffset = bufferView.byteOffset + accessorByteOffset;\r\n for (var i = 0; i < count; i++) {\r\n var typedArrayView = ComponentDatatype.createArrayBufferView(\r\n componentType,\r\n source.buffer,\r\n source.byteOffset + byteOffset,\r\n numberOfComponents\r\n );\r\n if (type === \"SCALAR\") {\r\n values[i] = typedArrayView[0];\r\n } else if (type === \"VEC3\") {\r\n values[i] = Cartesian3.fromArray(typedArrayView);\r\n } else if (type === \"VEC4\") {\r\n values[i] = Quaternion.unpack(typedArrayView);\r\n }\r\n byteOffset += byteStride;\r\n }\r\n // GLTF_SPEC: Support more parameter types when glTF supports targeting materials. https://github.com/KhronosGroup/glTF/issues/142\r\n\r\n if (defined(model.cacheKey)) {\r\n // Only cache when we can create a unique id\r\n cachedAnimationParameters[key] = values;\r\n }\r\n }\r\n\r\n return values;\r\n};\r\n\r\nvar cachedAnimationSplines = {};\r\n\r\nfunction getAnimationSplineKey(model, animationName, samplerName) {\r\n return model.cacheKey + \"//\" + animationName + \"/\" + samplerName;\r\n}\r\n\r\nfunction ConstantSpline(value) {\r\n this._value = value;\r\n}\r\nConstantSpline.prototype.evaluate = function (time, result) {\r\n return this._value;\r\n};\r\nConstantSpline.prototype.wrapTime = function (time) {\r\n return 0.0;\r\n};\r\nConstantSpline.prototype.clampTime = function (time) {\r\n return 0.0;\r\n};\r\n\r\nfunction SteppedSpline(backingSpline) {\r\n this._spline = backingSpline;\r\n this._lastTimeIndex = 0;\r\n}\r\nSteppedSpline.prototype.findTimeInterval = Spline.prototype.findTimeInterval;\r\nSteppedSpline.prototype.evaluate = function (time, result) {\r\n var i = (this._lastTimeIndex = this.findTimeInterval(\r\n time,\r\n this._lastTimeIndex\r\n ));\r\n var times = this._spline.times;\r\n var steppedTime = time >= times[i + 1] ? times[i + 1] : times[i];\r\n return this._spline.evaluate(steppedTime, result);\r\n};\r\nObject.defineProperties(SteppedSpline.prototype, {\r\n times: {\r\n get: function () {\r\n return this._spline.times;\r\n },\r\n },\r\n});\r\nSteppedSpline.prototype.wrapTime = function (time) {\r\n return this._spline.wrapTime(time);\r\n};\r\nSteppedSpline.prototype.clampTime = function (time) {\r\n return this._spline.clampTime(time);\r\n};\r\n\r\nModelAnimationCache.getAnimationSpline = function (\r\n model,\r\n animationName,\r\n animation,\r\n samplerName,\r\n sampler,\r\n input,\r\n path,\r\n output\r\n) {\r\n var key = getAnimationSplineKey(model, animationName, samplerName);\r\n var spline = cachedAnimationSplines[key];\r\n\r\n if (!defined(spline)) {\r\n var times = input;\r\n var controlPoints = output;\r\n\r\n if (times.length === 1 && controlPoints.length === 1) {\r\n spline = new ConstantSpline(controlPoints[0]);\r\n } else if (\r\n sampler.interpolation === \"LINEAR\" ||\r\n sampler.interpolation === \"STEP\"\r\n ) {\r\n if (path === \"translation\" || path === \"scale\") {\r\n spline = new LinearSpline({\r\n times: times,\r\n points: controlPoints,\r\n });\r\n } else if (path === \"rotation\") {\r\n spline = new QuaternionSpline({\r\n times: times,\r\n points: controlPoints,\r\n });\r\n } else if (path === \"weights\") {\r\n spline = new WeightSpline({\r\n times: times,\r\n weights: controlPoints,\r\n });\r\n }\r\n\r\n if (defined(spline) && sampler.interpolation === \"STEP\") {\r\n spline = new SteppedSpline(spline);\r\n }\r\n }\r\n\r\n if (defined(model.cacheKey)) {\r\n // Only cache when we can create a unique id\r\n cachedAnimationSplines[key] = spline;\r\n }\r\n }\r\n\r\n return spline;\r\n};\r\n\r\nvar cachedSkinInverseBindMatrices = {};\r\n\r\nModelAnimationCache.getSkinInverseBindMatrices = function (model, accessor) {\r\n var key = getAccessorKey(model, accessor);\r\n var matrices = cachedSkinInverseBindMatrices[key];\r\n\r\n if (!defined(matrices)) {\r\n // Cache miss\r\n var gltf = model.gltf;\r\n var buffers = gltf.buffers;\r\n var bufferViews = gltf.bufferViews;\r\n\r\n var bufferViewId = accessor.bufferView;\r\n var bufferView = bufferViews[bufferViewId];\r\n var bufferId = bufferView.buffer;\r\n var buffer = buffers[bufferId];\r\n var source = buffer.extras._pipeline.source;\r\n\r\n var componentType = accessor.componentType;\r\n var type = accessor.type;\r\n var count = accessor.count;\r\n var byteStride = getAccessorByteStride(gltf, accessor);\r\n var byteOffset = bufferView.byteOffset + accessor.byteOffset;\r\n var numberOfComponents = numberOfComponentsForType(type);\r\n\r\n matrices = new Array(count);\r\n\r\n if (componentType === WebGLConstants.FLOAT && type === AttributeType.MAT4) {\r\n for (var i = 0; i < count; ++i) {\r\n var typedArrayView = ComponentDatatype.createArrayBufferView(\r\n componentType,\r\n source.buffer,\r\n source.byteOffset + byteOffset,\r\n numberOfComponents\r\n );\r\n matrices[i] = Matrix4.fromArray(typedArrayView);\r\n byteOffset += byteStride;\r\n }\r\n }\r\n\r\n cachedSkinInverseBindMatrices[key] = matrices;\r\n }\r\n\r\n return matrices;\r\n};\r\nexport default ModelAnimationCache;\r\n","/**\r\n * Determines if and how a glTF animation is looped.\r\n *\r\n * @enum {Number}\r\n *\r\n * @see ModelAnimationCollection#add\r\n */\r\nvar ModelAnimationLoop = {\r\n /**\r\n * Play the animation once; do not loop it.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n NONE: 0,\r\n\r\n /**\r\n * Loop the animation playing it from the start immediately after it stops.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n REPEAT: 1,\r\n\r\n /**\r\n * Loop the animation. First, playing it forward, then in reverse, then forward, and so on.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n MIRRORED_REPEAT: 2,\r\n};\r\nexport default Object.freeze(ModelAnimationLoop);\r\n","/**\r\n * @private\r\n */\r\nexport default Object.freeze({\r\n STOPPED: 0,\r\n ANIMATING: 1,\r\n});\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport ModelAnimationLoop from \"./ModelAnimationLoop.js\";\r\nimport ModelAnimationState from \"./ModelAnimationState.js\";\r\n\r\n/**\r\n * An active glTF animation. A glTF asset can contain animations. An active animation\r\n * is an animation that is currently playing or scheduled to be played because it was\r\n * added to a model's {@link ModelAnimationCollection}. An active animation is an\r\n * instance of an animation; for example, there can be multiple active animations\r\n * for the same glTF animation, each with a different start time.\r\n *

\r\n * Create this by calling {@link ModelAnimationCollection#add}.\r\n *

\r\n *\r\n * @alias ModelAnimation\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @see ModelAnimationCollection#add\r\n */\r\nfunction ModelAnimation(options, model, runtimeAnimation) {\r\n this._name = runtimeAnimation.name;\r\n this._startTime = JulianDate.clone(options.startTime);\r\n this._delay = defaultValue(options.delay, 0.0); // in seconds\r\n this._stopTime = options.stopTime;\r\n\r\n /**\r\n * When true, the animation is removed after it stops playing.\r\n * This is slightly more efficient that not removing it, but if, for example,\r\n * time is reversed, the animation is not played again.\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.removeOnStop = defaultValue(options.removeOnStop, false);\r\n this._multiplier = defaultValue(options.multiplier, 1.0);\r\n this._reverse = defaultValue(options.reverse, false);\r\n this._loop = defaultValue(options.loop, ModelAnimationLoop.NONE);\r\n\r\n /**\r\n * The event fired when this animation is started. This can be used, for\r\n * example, to play a sound or start a particle system, when the animation starts.\r\n *

\r\n * This event is fired at the end of the frame after the scene is rendered.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * animation.start.addEventListener(function(model, animation) {\r\n * console.log('Animation started: ' + animation.name);\r\n * });\r\n */\r\n this.start = new Event();\r\n\r\n /**\r\n * The event fired when on each frame when this animation is updated. The\r\n * current time of the animation, relative to the glTF animation time span, is\r\n * passed to the event, which allows, for example, starting new animations at a\r\n * specific time relative to a playing animation.\r\n *

\r\n * This event is fired at the end of the frame after the scene is rendered.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * animation.update.addEventListener(function(model, animation, time) {\r\n * console.log('Animation updated: ' + animation.name + '. glTF animation time: ' + time);\r\n * });\r\n */\r\n this.update = new Event();\r\n\r\n /**\r\n * The event fired when this animation is stopped. This can be used, for\r\n * example, to play a sound or start a particle system, when the animation stops.\r\n *

\r\n * This event is fired at the end of the frame after the scene is rendered.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * animation.stop.addEventListener(function(model, animation) {\r\n * console.log('Animation stopped: ' + animation.name);\r\n * });\r\n */\r\n this.stop = new Event();\r\n\r\n this._state = ModelAnimationState.STOPPED;\r\n this._runtimeAnimation = runtimeAnimation;\r\n\r\n // Set during animation update\r\n this._computedStartTime = undefined;\r\n this._duration = undefined;\r\n\r\n // To avoid allocations in ModelAnimationCollection.update\r\n var that = this;\r\n this._raiseStartEvent = function () {\r\n that.start.raiseEvent(model, that);\r\n };\r\n this._updateEventTime = 0.0;\r\n this._raiseUpdateEvent = function () {\r\n that.update.raiseEvent(model, that, that._updateEventTime);\r\n };\r\n this._raiseStopEvent = function () {\r\n that.stop.raiseEvent(model, that);\r\n };\r\n}\r\n\r\nObject.defineProperties(ModelAnimation.prototype, {\r\n /**\r\n * The glTF animation name that identifies this animation.\r\n *\r\n * @memberof ModelAnimation.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n name: {\r\n get: function () {\r\n return this._name;\r\n },\r\n },\r\n\r\n /**\r\n * The scene time to start playing this animation. When this is undefined,\r\n * the animation starts at the next frame.\r\n *\r\n * @memberof ModelAnimation.prototype\r\n *\r\n * @type {JulianDate}\r\n * @readonly\r\n *\r\n * @default undefined\r\n */\r\n startTime: {\r\n get: function () {\r\n return this._startTime;\r\n },\r\n },\r\n\r\n /**\r\n * The delay, in seconds, from {@link ModelAnimation#startTime} to start playing.\r\n *\r\n * @memberof ModelAnimation.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n *\r\n * @default undefined\r\n */\r\n delay: {\r\n get: function () {\r\n return this._delay;\r\n },\r\n },\r\n\r\n /**\r\n * The scene time to stop playing this animation. When this is undefined,\r\n * the animation is played for its full duration and perhaps repeated depending on\r\n * {@link ModelAnimation#loop}.\r\n *\r\n * @memberof ModelAnimation.prototype\r\n *\r\n * @type {JulianDate}\r\n * @readonly\r\n *\r\n * @default undefined\r\n */\r\n stopTime: {\r\n get: function () {\r\n return this._stopTime;\r\n },\r\n },\r\n /**\r\n * Values greater than 1.0 increase the speed that the animation is played relative\r\n * to the scene clock speed; values less than 1.0 decrease the speed. A value of\r\n * 1.0 plays the animation at the speed in the glTF animation mapped to the scene\r\n * clock speed. For example, if the scene is played at 2x real-time, a two-second glTF animation\r\n * will play in one second even if multiplier is 1.0.\r\n *\r\n * @memberof ModelAnimation.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n *\r\n * @default 1.0\r\n */\r\n multiplier: {\r\n get: function () {\r\n return this._multiplier;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the animation is played in reverse.\r\n *\r\n * @memberof ModelAnimation.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n reverse: {\r\n get: function () {\r\n return this._reverse;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if and how the animation is looped.\r\n *\r\n * @memberof ModelAnimation.prototype\r\n *\r\n * @type {ModelAnimationLoop}\r\n * @readonly\r\n *\r\n * @default {@link ModelAnimationLoop.NONE}\r\n */\r\n loop: {\r\n get: function () {\r\n return this._loop;\r\n },\r\n },\r\n});\r\nexport default ModelAnimation;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport ModelAnimation from \"./ModelAnimation.js\";\r\nimport ModelAnimationLoop from \"./ModelAnimationLoop.js\";\r\nimport ModelAnimationState from \"./ModelAnimationState.js\";\r\n\r\n/**\r\n * A collection of active model animations. Access this using {@link Model#activeAnimations}.\r\n *\r\n * @alias ModelAnimationCollection\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @see Model#activeAnimations\r\n */\r\nfunction ModelAnimationCollection(model) {\r\n /**\r\n * The event fired when an animation is added to the collection. This can be used, for\r\n * example, to keep a UI in sync.\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * model.activeAnimations.animationAdded.addEventListener(function(model, animation) {\r\n * console.log('Animation added: ' + animation.name);\r\n * });\r\n */\r\n this.animationAdded = new Event();\r\n\r\n /**\r\n * The event fired when an animation is removed from the collection. This can be used, for\r\n * example, to keep a UI in sync.\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * model.activeAnimations.animationRemoved.addEventListener(function(model, animation) {\r\n * console.log('Animation removed: ' + animation.name);\r\n * });\r\n */\r\n this.animationRemoved = new Event();\r\n\r\n this._model = model;\r\n this._scheduledAnimations = [];\r\n this._previousTime = undefined;\r\n}\r\n\r\nObject.defineProperties(ModelAnimationCollection.prototype, {\r\n /**\r\n * The number of animations in the collection.\r\n *\r\n * @memberof ModelAnimationCollection.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._scheduledAnimations.length;\r\n },\r\n },\r\n});\r\n\r\nfunction add(collection, index, options) {\r\n var model = collection._model;\r\n var animations = model._runtime.animations;\r\n var animation = animations[index];\r\n var scheduledAnimation = new ModelAnimation(options, model, animation);\r\n collection._scheduledAnimations.push(scheduledAnimation);\r\n collection.animationAdded.raiseEvent(model, scheduledAnimation);\r\n return scheduledAnimation;\r\n}\r\n\r\n/**\r\n * Creates and adds an animation with the specified initial properties to the collection.\r\n *

\r\n * This raises the {@link ModelAnimationCollection#animationAdded} event so, for example, a UI can stay in sync.\r\n *

\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {String} [options.name] The glTF animation name that identifies the animation. Must be defined if options.index is undefined.\r\n * @param {Number} [options.index] The glTF animation index that identifies the animation. Must be defined if options.name is undefined.\r\n * @param {JulianDate} [options.startTime] The scene time to start playing the animation. When this is undefined, the animation starts at the next frame.\r\n * @param {Number} [options.delay=0.0] The delay, in seconds, from startTime to start playing.\r\n * @param {JulianDate} [options.stopTime] The scene time to stop playing the animation. When this is undefined, the animation is played for its full duration.\r\n * @param {Boolean} [options.removeOnStop=false] When true, the animation is removed after it stops playing.\r\n * @param {Number} [options.multiplier=1.0] Values greater than 1.0 increase the speed that the animation is played relative to the scene clock speed; values less than 1.0 decrease the speed.\r\n * @param {Boolean} [options.reverse=false] When true, the animation is played in reverse.\r\n * @param {ModelAnimationLoop} [options.loop=ModelAnimationLoop.NONE] Determines if and how the animation is looped.\r\n * @returns {ModelAnimation} The animation that was added to the collection.\r\n *\r\n * @exception {DeveloperError} Animations are not loaded. Wait for the {@link Model#readyPromise} to resolve.\r\n * @exception {DeveloperError} options.name must be a valid animation name.\r\n * @exception {DeveloperError} options.index must be a valid animation index.\r\n * @exception {DeveloperError} Either options.name or options.index must be defined.\r\n * @exception {DeveloperError} options.multiplier must be greater than zero.\r\n *\r\n * @example\r\n * // Example 1. Add an animation by name\r\n * model.activeAnimations.add({\r\n * name : 'animation name'\r\n * });\r\n *\r\n * // Example 2. Add an animation by index\r\n * model.activeAnimations.add({\r\n * index : 0\r\n * });\r\n *\r\n * @example\r\n * // Example 3. Add an animation and provide all properties and events\r\n * var startTime = Cesium.JulianDate.now();\r\n *\r\n * var animation = model.activeAnimations.add({\r\n * name : 'another animation name',\r\n * startTime : startTime,\r\n * delay : 0.0, // Play at startTime (default)\r\n * stopTime : Cesium.JulianDate.addSeconds(startTime, 4.0, new Cesium.JulianDate()),\r\n * removeOnStop : false, // Do not remove when animation stops (default)\r\n * multiplier : 2.0, // Play at double speed\r\n * reverse : true, // Play in reverse\r\n * loop : Cesium.ModelAnimationLoop.REPEAT // Loop the animation\r\n * });\r\n *\r\n * animation.start.addEventListener(function(model, animation) {\r\n * console.log('Animation started: ' + animation.name);\r\n * });\r\n * animation.update.addEventListener(function(model, animation, time) {\r\n * console.log('Animation updated: ' + animation.name + '. glTF animation time: ' + time);\r\n * });\r\n * animation.stop.addEventListener(function(model, animation) {\r\n * console.log('Animation stopped: ' + animation.name);\r\n * });\r\n */\r\nModelAnimationCollection.prototype.add = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var model = this._model;\r\n var animations = model._runtime.animations;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(animations)) {\r\n throw new DeveloperError(\r\n \"Animations are not loaded. Wait for Model.readyPromise to resolve.\"\r\n );\r\n }\r\n if (!defined(options.name) && !defined(options.index)) {\r\n throw new DeveloperError(\r\n \"Either options.name or options.index must be defined.\"\r\n );\r\n }\r\n\r\n if (defined(options.multiplier) && options.multiplier <= 0.0) {\r\n throw new DeveloperError(\"options.multiplier must be greater than zero.\");\r\n }\r\n if (\r\n defined(options.index) &&\r\n (options.index >= animations.length || options.index < 0)\r\n ) {\r\n throw new DeveloperError(\"options.index must be a valid animation index.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (defined(options.index)) {\r\n return add(this, options.index, options);\r\n }\r\n\r\n // Find the index of the animation with the given name\r\n var index;\r\n var length = animations.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (animations[i].name === options.name) {\r\n index = i;\r\n break;\r\n }\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"options.name must be a valid animation name.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return add(this, index, options);\r\n};\r\n\r\n/**\r\n * Creates and adds an animation with the specified initial properties to the collection\r\n * for each animation in the model.\r\n *

\r\n * This raises the {@link ModelAnimationCollection#animationAdded} event for each model so, for example, a UI can stay in sync.\r\n *

\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {JulianDate} [options.startTime] The scene time to start playing the animations. When this is undefined, the animations starts at the next frame.\r\n * @param {Number} [options.delay=0.0] The delay, in seconds, from startTime to start playing.\r\n * @param {JulianDate} [options.stopTime] The scene time to stop playing the animations. When this is undefined, the animations are played for its full duration.\r\n * @param {Boolean} [options.removeOnStop=false] When true, the animations are removed after they stop playing.\r\n * @param {Number} [options.multiplier=1.0] Values greater than 1.0 increase the speed that the animations play relative to the scene clock speed; values less than 1.0 decrease the speed.\r\n * @param {Boolean} [options.reverse=false] When true, the animations are played in reverse.\r\n * @param {ModelAnimationLoop} [options.loop=ModelAnimationLoop.NONE] Determines if and how the animations are looped.\r\n * @returns {ModelAnimation[]} An array of {@link ModelAnimation} objects, one for each animation added to the collection. If there are no glTF animations, the array is empty.\r\n *\r\n * @exception {DeveloperError} Animations are not loaded. Wait for the {@link Model#readyPromise} to resolve.\r\n * @exception {DeveloperError} options.multiplier must be greater than zero.\r\n *\r\n * @example\r\n * model.activeAnimations.addAll({\r\n * multiplier : 0.5, // Play at half-speed\r\n * loop : Cesium.ModelAnimationLoop.REPEAT // Loop the animations\r\n * });\r\n */\r\nModelAnimationCollection.prototype.addAll = function (options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(this._model._runtime.animations)) {\r\n throw new DeveloperError(\r\n \"Animations are not loaded. Wait for Model.readyPromise to resolve.\"\r\n );\r\n }\r\n\r\n if (defined(options.multiplier) && options.multiplier <= 0.0) {\r\n throw new DeveloperError(\"options.multiplier must be greater than zero.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var scheduledAnimations = [];\r\n var model = this._model;\r\n var animations = model._runtime.animations;\r\n var length = animations.length;\r\n for (var i = 0; i < length; ++i) {\r\n scheduledAnimations.push(add(this, i, options));\r\n }\r\n return scheduledAnimations;\r\n};\r\n\r\n/**\r\n * Removes an animation from the collection.\r\n *

\r\n * This raises the {@link ModelAnimationCollection#animationRemoved} event so, for example, a UI can stay in sync.\r\n *

\r\n *

\r\n * An animation can also be implicitly removed from the collection by setting {@link ModelAnimation#removeOnStop} to\r\n * true. The {@link ModelAnimationCollection#animationRemoved} event is still fired when the animation is removed.\r\n *

\r\n *\r\n * @param {ModelAnimation} animation The animation to remove.\r\n * @returns {Boolean} true if the animation was removed; false if the animation was not found in the collection.\r\n *\r\n * @example\r\n * var a = model.activeAnimations.add({\r\n * name : 'animation name'\r\n * });\r\n * model.activeAnimations.remove(a); // Returns true\r\n */\r\nModelAnimationCollection.prototype.remove = function (animation) {\r\n if (defined(animation)) {\r\n var animations = this._scheduledAnimations;\r\n var i = animations.indexOf(animation);\r\n if (i !== -1) {\r\n animations.splice(i, 1);\r\n this.animationRemoved.raiseEvent(this._model, animation);\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes all animations from the collection.\r\n *

\r\n * This raises the {@link ModelAnimationCollection#animationRemoved} event for each\r\n * animation so, for example, a UI can stay in sync.\r\n *

\r\n */\r\nModelAnimationCollection.prototype.removeAll = function () {\r\n var model = this._model;\r\n var animations = this._scheduledAnimations;\r\n var length = animations.length;\r\n\r\n this._scheduledAnimations = [];\r\n\r\n for (var i = 0; i < length; ++i) {\r\n this.animationRemoved.raiseEvent(model, animations[i]);\r\n }\r\n};\r\n\r\n/**\r\n * Determines whether this collection contains a given animation.\r\n *\r\n * @param {ModelAnimation} animation The animation to check for.\r\n * @returns {Boolean} true if this collection contains the animation, false otherwise.\r\n */\r\nModelAnimationCollection.prototype.contains = function (animation) {\r\n if (defined(animation)) {\r\n return this._scheduledAnimations.indexOf(animation) !== -1;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Returns the animation in the collection at the specified index. Indices are zero-based\r\n * and increase as animations are added. Removing an animation shifts all animations after\r\n * it to the left, changing their indices. This function is commonly used to iterate over\r\n * all the animations in the collection.\r\n *\r\n * @param {Number} index The zero-based index of the animation.\r\n * @returns {ModelAnimation} The animation at the specified index.\r\n *\r\n * @example\r\n * // Output the names of all the animations in the collection.\r\n * var animations = model.activeAnimations;\r\n * var length = animations.length;\r\n * for (var i = 0; i < length; ++i) {\r\n * console.log(animations.get(i).name);\r\n * }\r\n */\r\nModelAnimationCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._scheduledAnimations[index];\r\n};\r\n\r\nfunction animateChannels(runtimeAnimation, localAnimationTime) {\r\n var channelEvaluators = runtimeAnimation.channelEvaluators;\r\n var length = channelEvaluators.length;\r\n for (var i = 0; i < length; ++i) {\r\n channelEvaluators[i](localAnimationTime);\r\n }\r\n}\r\n\r\nvar animationsToRemove = [];\r\n\r\nfunction createAnimationRemovedFunction(\r\n modelAnimationCollection,\r\n model,\r\n animation\r\n) {\r\n return function () {\r\n modelAnimationCollection.animationRemoved.raiseEvent(model, animation);\r\n };\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nModelAnimationCollection.prototype.update = function (frameState) {\r\n var scheduledAnimations = this._scheduledAnimations;\r\n var length = scheduledAnimations.length;\r\n\r\n if (length === 0) {\r\n // No animations - quick return for performance\r\n this._previousTime = undefined;\r\n return false;\r\n }\r\n\r\n if (JulianDate.equals(frameState.time, this._previousTime)) {\r\n // Animations are currently only time-dependent so do not animate when paused or picking\r\n return false;\r\n }\r\n this._previousTime = JulianDate.clone(frameState.time, this._previousTime);\r\n\r\n var animationOccured = false;\r\n var sceneTime = frameState.time;\r\n var model = this._model;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var scheduledAnimation = scheduledAnimations[i];\r\n var runtimeAnimation = scheduledAnimation._runtimeAnimation;\r\n\r\n if (!defined(scheduledAnimation._computedStartTime)) {\r\n scheduledAnimation._computedStartTime = JulianDate.addSeconds(\r\n defaultValue(scheduledAnimation.startTime, sceneTime),\r\n scheduledAnimation.delay,\r\n new JulianDate()\r\n );\r\n }\r\n\r\n if (!defined(scheduledAnimation._duration)) {\r\n scheduledAnimation._duration =\r\n runtimeAnimation.stopTime * (1.0 / scheduledAnimation.multiplier);\r\n }\r\n\r\n var startTime = scheduledAnimation._computedStartTime;\r\n var duration = scheduledAnimation._duration;\r\n var stopTime = scheduledAnimation.stopTime;\r\n\r\n // [0.0, 1.0] normalized local animation time\r\n var delta =\r\n duration !== 0.0\r\n ? JulianDate.secondsDifference(sceneTime, startTime) / duration\r\n : 0.0;\r\n\r\n // Clamp delta to stop time, if defined.\r\n if (\r\n duration !== 0.0 &&\r\n defined(stopTime) &&\r\n JulianDate.greaterThan(sceneTime, stopTime)\r\n ) {\r\n delta = JulianDate.secondsDifference(stopTime, startTime) / duration;\r\n }\r\n\r\n var pastStartTime = delta >= 0.0;\r\n\r\n // Play animation if\r\n // * we are after the start time or the animation is being repeated, and\r\n // * before the end of the animation's duration or the animation is being repeated, and\r\n // * we did not reach a user-provided stop time.\r\n\r\n var repeat =\r\n scheduledAnimation.loop === ModelAnimationLoop.REPEAT ||\r\n scheduledAnimation.loop === ModelAnimationLoop.MIRRORED_REPEAT;\r\n\r\n var play =\r\n (pastStartTime || (repeat && !defined(scheduledAnimation.startTime))) &&\r\n (delta <= 1.0 || repeat) &&\r\n (!defined(stopTime) || JulianDate.lessThanOrEquals(sceneTime, stopTime));\r\n\r\n // If it IS, or WAS, animating...\r\n if (play || scheduledAnimation._state === ModelAnimationState.ANIMATING) {\r\n // STOPPED -> ANIMATING state transition?\r\n if (play && scheduledAnimation._state === ModelAnimationState.STOPPED) {\r\n scheduledAnimation._state = ModelAnimationState.ANIMATING;\r\n if (scheduledAnimation.start.numberOfListeners > 0) {\r\n frameState.afterRender.push(scheduledAnimation._raiseStartEvent);\r\n }\r\n }\r\n\r\n // Truncate to [0.0, 1.0] for repeating animations\r\n if (scheduledAnimation.loop === ModelAnimationLoop.REPEAT) {\r\n delta = delta - Math.floor(delta);\r\n } else if (\r\n scheduledAnimation.loop === ModelAnimationLoop.MIRRORED_REPEAT\r\n ) {\r\n var floor = Math.floor(delta);\r\n var fract = delta - floor;\r\n // When even use (1.0 - fract) to mirror repeat\r\n delta = floor % 2 === 1.0 ? 1.0 - fract : fract;\r\n }\r\n\r\n if (scheduledAnimation.reverse) {\r\n delta = 1.0 - delta;\r\n }\r\n\r\n var localAnimationTime = delta * duration * scheduledAnimation.multiplier;\r\n // Clamp in case floating-point roundoff goes outside the animation's first or last keyframe\r\n localAnimationTime = CesiumMath.clamp(\r\n localAnimationTime,\r\n runtimeAnimation.startTime,\r\n runtimeAnimation.stopTime\r\n );\r\n\r\n animateChannels(runtimeAnimation, localAnimationTime);\r\n\r\n if (scheduledAnimation.update.numberOfListeners > 0) {\r\n scheduledAnimation._updateEventTime = localAnimationTime;\r\n frameState.afterRender.push(scheduledAnimation._raiseUpdateEvent);\r\n }\r\n animationOccured = true;\r\n\r\n if (!play) {\r\n // ANIMATING -> STOPPED state transition?\r\n scheduledAnimation._state = ModelAnimationState.STOPPED;\r\n if (scheduledAnimation.stop.numberOfListeners > 0) {\r\n frameState.afterRender.push(scheduledAnimation._raiseStopEvent);\r\n }\r\n\r\n if (scheduledAnimation.removeOnStop) {\r\n animationsToRemove.push(scheduledAnimation);\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Remove animations that stopped\r\n length = animationsToRemove.length;\r\n for (var j = 0; j < length; ++j) {\r\n var animationToRemove = animationsToRemove[j];\r\n scheduledAnimations.splice(\r\n scheduledAnimations.indexOf(animationToRemove),\r\n 1\r\n );\r\n frameState.afterRender.push(\r\n createAnimationRemovedFunction(this, model, animationToRemove)\r\n );\r\n }\r\n animationsToRemove.length = 0;\r\n\r\n return animationOccured;\r\n};\r\nexport default ModelAnimationCollection;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\n\r\n/**\r\n * A model's material with modifiable parameters. A glTF material\r\n * contains parameters defined by the material's technique with values\r\n * defined by the technique and potentially overridden by the material.\r\n * This class allows changing these values at runtime.\r\n *

\r\n * Use {@link Model#getMaterial} to create an instance.\r\n *

\r\n *\r\n * @alias ModelMaterial\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @see Model#getMaterial\r\n */\r\nfunction ModelMaterial(model, material, id) {\r\n this._name = material.name;\r\n this._id = id;\r\n this._uniformMap = model._uniformMaps[id];\r\n\r\n this._technique = undefined;\r\n this._program = undefined;\r\n this._values = undefined;\r\n}\r\n\r\nObject.defineProperties(ModelMaterial.prototype, {\r\n /**\r\n * The value of the name property of this material.\r\n *\r\n * @memberof ModelMaterial.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n name: {\r\n get: function () {\r\n return this._name;\r\n },\r\n },\r\n\r\n /**\r\n * The index of the material.\r\n *\r\n * @memberof ModelMaterial.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Assigns a value to a material parameter. The type for value\r\n * depends on the glTF type of the parameter. It will be a floating-point\r\n * number, Cartesian, or matrix.\r\n *\r\n * @param {String} name The name of the parameter.\r\n * @param {*} [value] The value to assign to the parameter.\r\n *\r\n * @exception {DeveloperError} name must match a parameter name in the material's technique that is targetable and not optimized out.\r\n *\r\n * @example\r\n * material.setValue('diffuse', new Cesium.Cartesian4(1.0, 0.0, 0.0, 1.0)); // vec4\r\n * material.setValue('shininess', 256.0); // scalar\r\n */\r\nModelMaterial.prototype.setValue = function (name, value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(name)) {\r\n throw new DeveloperError(\"name is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var uniformName = \"u_\" + name;\r\n var v = this._uniformMap.values[uniformName];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(v)) {\r\n throw new DeveloperError(\r\n \"name must match a parameter name in the material's technique that is targetable and not optimized out.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n v.value = v.clone(value, v.value);\r\n};\r\n\r\n/**\r\n * Returns the value of the parameter with the given name. The type of the\r\n * returned object depends on the glTF type of the parameter. It will be a floating-point\r\n * number, Cartesian, or matrix.\r\n *\r\n * @param {String} name The name of the parameter.\r\n * @returns {*} The value of the parameter or undefined if the parameter does not exist.\r\n */\r\nModelMaterial.prototype.getValue = function (name) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(name)) {\r\n throw new DeveloperError(\"name is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var uniformName = \"u_\" + name;\r\n var v = this._uniformMap.values[uniformName];\r\n\r\n if (!defined(v)) {\r\n return undefined;\r\n }\r\n\r\n return v.value;\r\n};\r\nexport default ModelMaterial;\r\n","/**\r\n * A model's mesh and its materials.\r\n *

\r\n * Use {@link Model#getMesh} to create an instance.\r\n *

\r\n *\r\n * @alias ModelMesh\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @see Model#getMesh\r\n */\r\nfunction ModelMesh(mesh, runtimeMaterialsById, id) {\r\n var materials = [];\r\n var primitives = mesh.primitives;\r\n var length = primitives.length;\r\n for (var i = 0; i < length; ++i) {\r\n var p = primitives[i];\r\n materials[i] = runtimeMaterialsById[p.material];\r\n }\r\n\r\n this._name = mesh.name;\r\n this._materials = materials;\r\n this._id = id;\r\n}\r\n\r\nObject.defineProperties(ModelMesh.prototype, {\r\n /**\r\n * The value of the name property of this mesh.\r\n *\r\n * @memberof ModelMesh.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n name: {\r\n get: function () {\r\n return this._name;\r\n },\r\n },\r\n\r\n /**\r\n * The index of the mesh.\r\n *\r\n * @memberof ModelMesh.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n\r\n /**\r\n * An array of {@link ModelMaterial} instances indexed by the mesh's\r\n * primitive indices.\r\n *\r\n * @memberof ModelMesh.prototype\r\n *\r\n * @type {ModelMaterial[]}\r\n * @readonly\r\n */\r\n materials: {\r\n get: function () {\r\n return this._materials;\r\n },\r\n },\r\n});\r\nexport default ModelMesh;\r\n","import Matrix4 from \"../Core/Matrix4.js\";\r\n\r\n/**\r\n * A model node with a transform for user-defined animations. A glTF asset can\r\n * contain animations that target a node's transform. This class allows\r\n * changing a node's transform externally so animation can be driven by another\r\n * source, not just an animation in the glTF asset.\r\n *

\r\n * Use {@link Model#getNode} to create an instance.\r\n *

\r\n *\r\n * @alias ModelNode\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @example\r\n * var node = model.getNode('LOD3sp');\r\n * node.matrix = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(5.0, 1.0, 1.0), node.matrix);\r\n *\r\n * @see Model#getNode\r\n */\r\nfunction ModelNode(model, node, runtimeNode, id, matrix) {\r\n this._model = model;\r\n this._runtimeNode = runtimeNode;\r\n this._name = node.name;\r\n this._id = id;\r\n\r\n /**\r\n * @private\r\n */\r\n this.useMatrix = false;\r\n\r\n this._show = true;\r\n this._matrix = Matrix4.clone(matrix);\r\n this._originalMatrix = Matrix4.clone(matrix);\r\n}\r\n\r\nObject.defineProperties(ModelNode.prototype, {\r\n /**\r\n * The value of the name property of this node.\r\n *\r\n * @memberof ModelNode.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n name: {\r\n get: function () {\r\n return this._name;\r\n },\r\n },\r\n\r\n /**\r\n * The index of the node.\r\n *\r\n * @memberof ModelNode.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if this node and its children will be shown.\r\n *\r\n * @memberof ModelNode.prototype\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n show: {\r\n get: function () {\r\n return this._show;\r\n },\r\n set: function (value) {\r\n if (this._show !== value) {\r\n this._show = value;\r\n this._model._perNodeShowDirty = true;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The node's 4x4 matrix transform from its local coordinates to\r\n * its parent's.\r\n *

\r\n * For changes to take effect, this property must be assigned to;\r\n * setting individual elements of the matrix will not work.\r\n *

\r\n *\r\n * @memberof ModelNode.prototype\r\n * @type {Matrix4}\r\n */\r\n matrix: {\r\n get: function () {\r\n return this._matrix;\r\n },\r\n set: function (value) {\r\n this._matrix = Matrix4.clone(value, this._matrix);\r\n this.useMatrix = true;\r\n\r\n var model = this._model;\r\n model._cesiumAnimationsDirty = true;\r\n this._runtimeNode.dirtyNumber = model._maxDirtyNumber;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the node's original 4x4 matrix transform from its local coordinates to\r\n * its parent's, without any node transformations or articulations applied.\r\n *\r\n * @memberof ModelNode.prototype\r\n * @type {Matrix4}\r\n */\r\n originalMatrix: {\r\n get: function () {\r\n return this._originalMatrix;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @private\r\n */\r\nModelNode.prototype.setMatrix = function (matrix) {\r\n // Update matrix but do not set the dirty flag since this is used internally\r\n // to keep the matrix in-sync during a glTF animation.\r\n Matrix4.clone(matrix, this._matrix);\r\n};\r\nexport default ModelNode;\r\n","import defined from \"../Core/defined.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport ContextLimits from \"../Renderer/ContextLimits.js\";\r\nimport Sampler from \"../Renderer/Sampler.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport TextureMagnificationFilter from \"../Renderer/TextureMagnificationFilter.js\";\r\nimport TextureMinificationFilter from \"../Renderer/TextureMinificationFilter.js\";\r\nimport TextureWrap from \"../Renderer/TextureWrap.js\";\r\nimport ForEach from \"../ThirdParty/GltfPipeline/ForEach.js\";\r\n\r\n// glTF does not allow an index value of 65535 because this is the primitive\r\n// restart value in some APIs.\r\nvar MAX_GLTF_UINT16_INDEX = 65534;\r\n\r\n/**\r\n * Creates face outlines for glTF primitives with the `CESIUM_primitive_outline` extension.\r\n * @private\r\n */\r\nfunction ModelOutlineLoader() {}\r\n\r\n/**\r\n * Returns true if the model uses or requires CESIUM_primitive_outline.\r\n * @private\r\n */\r\nModelOutlineLoader.hasExtension = function (model) {\r\n return (\r\n defined(model.extensionsRequired.CESIUM_primitive_outline) ||\r\n defined(model.extensionsUsed.CESIUM_primitive_outline)\r\n );\r\n};\r\n\r\n/**\r\n * Arranges to outline any primitives with the CESIUM_primitive_outline extension.\r\n * It is expected that all buffer data is loaded and available in\r\n * `extras._pipeline.source` before this function is called, and that vertex\r\n * and index WebGL buffers are not yet created.\r\n * @private\r\n */\r\nModelOutlineLoader.outlinePrimitives = function (model) {\r\n if (!ModelOutlineLoader.hasExtension(model)) {\r\n return;\r\n }\r\n\r\n var gltf = model.gltf;\r\n\r\n // Assumption: A single bufferView contains a single zero-indexed range of vertices.\r\n // No trickery with using large accessor byteOffsets to store multiple zero-based\r\n // ranges of vertices in a single bufferView. Use separate bufferViews for that,\r\n // you monster.\r\n // Note that interleaved vertex attributes (e.g. position0, normal0, uv0,\r\n // position1, normal1, uv1, ...) _are_ supported and should not be confused with\r\n // the above.\r\n\r\n var vertexNumberingScopes = [];\r\n\r\n ForEach.mesh(gltf, function (mesh, meshId) {\r\n ForEach.meshPrimitive(mesh, function (primitive, primitiveId) {\r\n if (!defined(primitive.extensions)) {\r\n return;\r\n }\r\n\r\n var outlineData = primitive.extensions.CESIUM_primitive_outline;\r\n if (!defined(outlineData)) {\r\n return;\r\n }\r\n\r\n var vertexNumberingScope = getVertexNumberingScope(model, primitive);\r\n if (vertexNumberingScope === undefined) {\r\n return;\r\n }\r\n\r\n if (vertexNumberingScopes.indexOf(vertexNumberingScope) < 0) {\r\n vertexNumberingScopes.push(vertexNumberingScope);\r\n }\r\n\r\n // Add the outline to this primitive\r\n addOutline(\r\n model,\r\n meshId,\r\n primitiveId,\r\n outlineData.indices,\r\n vertexNumberingScope\r\n );\r\n });\r\n });\r\n\r\n // Update all relevant bufferViews to include the duplicate vertices that are\r\n // needed for outlining.\r\n for (var i = 0; i < vertexNumberingScopes.length; ++i) {\r\n updateBufferViewsWithNewVertices(\r\n model,\r\n vertexNumberingScopes[i].bufferViews\r\n );\r\n }\r\n\r\n // Remove data not referenced by any bufferViews anymore.\r\n compactBuffers(model);\r\n};\r\n\r\nModelOutlineLoader.createTexture = function (model, context) {\r\n var cache = context.cache.modelOutliningCache;\r\n if (!defined(cache)) {\r\n cache = context.cache.modelOutliningCache = {};\r\n }\r\n\r\n if (defined(cache.outlineTexture)) {\r\n return cache.outlineTexture;\r\n }\r\n\r\n var maxSize = Math.min(4096, ContextLimits.maximumTextureSize);\r\n\r\n var size = maxSize;\r\n var levelZero = createTexture(size);\r\n\r\n var mipLevels = [];\r\n\r\n while (size > 1) {\r\n size >>= 1;\r\n mipLevels.push(createTexture(size));\r\n }\r\n\r\n var texture = new Texture({\r\n context: context,\r\n source: {\r\n arrayBufferView: levelZero,\r\n mipLevels: mipLevels,\r\n },\r\n width: maxSize,\r\n height: 1,\r\n pixelFormat: PixelFormat.LUMINANCE,\r\n sampler: new Sampler({\r\n wrapS: TextureWrap.CLAMP_TO_EDGE,\r\n wrapT: TextureWrap.CLAMP_TO_EDGE,\r\n minificationFilter: TextureMinificationFilter.LINEAR_MIPMAP_LINEAR,\r\n magnificationFilter: TextureMagnificationFilter.LINEAR,\r\n }),\r\n });\r\n\r\n cache.outlineTexture = texture;\r\n\r\n return texture;\r\n};\r\n\r\nfunction addOutline(\r\n model,\r\n meshId,\r\n primitiveId,\r\n edgeIndicesAccessorId,\r\n vertexNumberingScope\r\n) {\r\n var vertexCopies = vertexNumberingScope.vertexCopies;\r\n var extraVertices = vertexNumberingScope.extraVertices;\r\n var outlineCoordinates = vertexNumberingScope.outlineCoordinates;\r\n\r\n var gltf = model.gltf;\r\n var mesh = gltf.meshes[meshId];\r\n var primitive = mesh.primitives[primitiveId];\r\n var accessors = gltf.accessors;\r\n var bufferViews = gltf.bufferViews;\r\n\r\n // Find the number of vertices in this primitive by looking at\r\n // the first attribute. Others are required to be the same.\r\n var numVertices;\r\n for (var semantic in primitive.attributes) {\r\n if (primitive.attributes.hasOwnProperty(semantic)) {\r\n var attributeId = primitive.attributes[semantic];\r\n var accessor = accessors[attributeId];\r\n if (defined(accessor)) {\r\n numVertices = accessor.count;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!defined(numVertices)) {\r\n return undefined;\r\n }\r\n\r\n var triangleIndexAccessorGltf = accessors[primitive.indices];\r\n var triangleIndexBufferViewGltf =\r\n bufferViews[triangleIndexAccessorGltf.bufferView];\r\n var edgeIndexAccessorGltf = accessors[edgeIndicesAccessorId];\r\n var edgeIndexBufferViewGltf = bufferViews[edgeIndexAccessorGltf.bufferView];\r\n\r\n var loadResources = model._loadResources;\r\n var triangleIndexBufferView = loadResources.getBuffer(\r\n triangleIndexBufferViewGltf\r\n );\r\n var edgeIndexBufferView = loadResources.getBuffer(edgeIndexBufferViewGltf);\r\n\r\n var triangleIndices =\r\n triangleIndexAccessorGltf.componentType === 5123\r\n ? new Uint16Array(\r\n triangleIndexBufferView.buffer,\r\n triangleIndexBufferView.byteOffset +\r\n triangleIndexAccessorGltf.byteOffset,\r\n triangleIndexAccessorGltf.count\r\n )\r\n : new Uint32Array(\r\n triangleIndexBufferView.buffer,\r\n triangleIndexBufferView.byteOffset +\r\n triangleIndexAccessorGltf.byteOffset,\r\n triangleIndexAccessorGltf.count\r\n );\r\n var edgeIndices =\r\n edgeIndexAccessorGltf.componentType === 5123\r\n ? new Uint16Array(\r\n edgeIndexBufferView.buffer,\r\n edgeIndexBufferView.byteOffset + edgeIndexAccessorGltf.byteOffset,\r\n edgeIndexAccessorGltf.count\r\n )\r\n : new Uint32Array(\r\n edgeIndexBufferView.buffer,\r\n edgeIndexBufferView.byteOffset + edgeIndexAccessorGltf.byteOffset,\r\n edgeIndexAccessorGltf.count\r\n );\r\n\r\n // Make a hash table for quick lookups of whether an edge exists between two\r\n // vertices. The hash is a sparse array indexed by\r\n // `smallerVertexIndex * totalNumberOfVertices + biggerVertexIndex`\r\n // A value of 1 indicates an edge exists between the two vertex indices; any\r\n // other value indicates that it does not. We store the\r\n // `edgeSmallMultipler` - that is, the number of vertices in the equation\r\n // above - at index 0 for easy access to it later.\r\n\r\n var edgeSmallMultiplier = numVertices;\r\n\r\n var edges = [edgeSmallMultiplier];\r\n var i;\r\n for (i = 0; i < edgeIndices.length; i += 2) {\r\n var a = edgeIndices[i];\r\n var b = edgeIndices[i + 1];\r\n var small = Math.min(a, b);\r\n var big = Math.max(a, b);\r\n edges[small * edgeSmallMultiplier + big] = 1;\r\n }\r\n\r\n // For each triangle, adjust vertex data so that the correct edges are outlined.\r\n for (i = 0; i < triangleIndices.length; i += 3) {\r\n var i0 = triangleIndices[i];\r\n var i1 = triangleIndices[i + 1];\r\n var i2 = triangleIndices[i + 2];\r\n\r\n var all = false; // set this to true to draw a full wireframe.\r\n var has01 = all || isHighlighted(edges, i0, i1);\r\n var has12 = all || isHighlighted(edges, i1, i2);\r\n var has20 = all || isHighlighted(edges, i2, i0);\r\n\r\n var unmatchableVertexIndex = matchAndStoreCoordinates(\r\n outlineCoordinates,\r\n i0,\r\n i1,\r\n i2,\r\n has01,\r\n has12,\r\n has20\r\n );\r\n while (unmatchableVertexIndex >= 0) {\r\n // Copy the unmatchable index and try again.\r\n var copy;\r\n if (unmatchableVertexIndex === i0) {\r\n copy = vertexCopies[i0];\r\n } else if (unmatchableVertexIndex === i1) {\r\n copy = vertexCopies[i1];\r\n } else {\r\n copy = vertexCopies[i2];\r\n }\r\n\r\n if (copy === undefined) {\r\n copy = numVertices + extraVertices.length;\r\n\r\n var original = unmatchableVertexIndex;\r\n while (original >= numVertices) {\r\n original = extraVertices[original - numVertices];\r\n }\r\n extraVertices.push(original);\r\n vertexCopies[unmatchableVertexIndex] = copy;\r\n }\r\n\r\n if (\r\n copy > MAX_GLTF_UINT16_INDEX &&\r\n triangleIndices instanceof Uint16Array\r\n ) {\r\n // We outgrew a 16-bit index buffer, switch to 32-bit.\r\n triangleIndices = new Uint32Array(triangleIndices);\r\n triangleIndexAccessorGltf.componentType = 5125; // UNSIGNED_INT\r\n triangleIndexBufferViewGltf.buffer =\r\n gltf.buffers.push({\r\n byteLength: triangleIndices.byteLength,\r\n extras: {\r\n _pipeline: {\r\n source: triangleIndices.buffer,\r\n },\r\n },\r\n }) - 1;\r\n triangleIndexBufferViewGltf.byteLength = triangleIndices.byteLength;\r\n triangleIndexBufferViewGltf.byteOffset = 0;\r\n model._loadResources.buffers[\r\n triangleIndexBufferViewGltf.buffer\r\n ] = new Uint8Array(\r\n triangleIndices.buffer,\r\n 0,\r\n triangleIndices.byteLength\r\n );\r\n\r\n // The index componentType is also squirreled away in ModelLoadResources.\r\n // Hackily update it, or else we'll end up creating the wrong type\r\n // of index buffer later.\r\n loadResources.indexBuffersToCreate._array.forEach(function (toCreate) {\r\n if (toCreate.id === triangleIndexAccessorGltf.bufferView) {\r\n toCreate.componentType = triangleIndexAccessorGltf.componentType;\r\n }\r\n });\r\n }\r\n\r\n if (unmatchableVertexIndex === i0) {\r\n i0 = copy;\r\n triangleIndices[i] = copy;\r\n } else if (unmatchableVertexIndex === i1) {\r\n i1 = copy;\r\n triangleIndices[i + 1] = copy;\r\n } else {\r\n i2 = copy;\r\n triangleIndices[i + 2] = copy;\r\n }\r\n\r\n if (defined(triangleIndexAccessorGltf.max)) {\r\n triangleIndexAccessorGltf.max[0] = Math.max(\r\n triangleIndexAccessorGltf.max[0],\r\n copy\r\n );\r\n }\r\n\r\n unmatchableVertexIndex = matchAndStoreCoordinates(\r\n outlineCoordinates,\r\n i0,\r\n i1,\r\n i2,\r\n has01,\r\n has12,\r\n has20\r\n );\r\n }\r\n }\r\n}\r\n\r\n// Each vertex has three coordinates, a, b, and c.\r\n// a is the coordinate that applies to edge 2-0 for the vertex.\r\n// b is the coordinate that applies to edge 0-1 for the vertex.\r\n// c is the coordinate that applies to edge 1-2 for the vertex.\r\n\r\n// A single triangle with all edges highlighted:\r\n//\r\n// | a | b | c |\r\n// | 1 | 1 | 0 |\r\n// 0\r\n// / \\\r\n// / \\\r\n// edge 0-1 / \\ edge 2-0\r\n// / \\\r\n// / \\\r\n// | a | b | c | 1-----------2 | a | b | c |\r\n// | 0 | 1 | 1 | edge 1-2 | 1 | 0 | 1 |\r\n//\r\n// There are 6 possible orderings of coordinates a, b, and c:\r\n// 0 - abc\r\n// 1 - acb\r\n// 2 - bac\r\n// 3 - bca\r\n// 4 - cab\r\n// 5 - cba\r\n\r\n// All vertices must use the _same ordering_ for the edges to be rendered\r\n// correctly. So we compute a bitmask for each vertex, where the bit at\r\n// each position indicates whether that ordering works (i.e. doesn't\r\n// conflict with already-assigned coordinates) for that vertex.\r\n\r\n// Then we can find an ordering that works for all three vertices with a\r\n// bitwise AND.\r\n\r\nfunction computeOrderMask(outlineCoordinates, vertexIndex, a, b, c) {\r\n var startIndex = vertexIndex * 3;\r\n var first = outlineCoordinates[startIndex];\r\n var second = outlineCoordinates[startIndex + 1];\r\n var third = outlineCoordinates[startIndex + 2];\r\n\r\n if (first === undefined) {\r\n // If one coordinate is undefined, they all are, and all orderings are fine.\r\n return 63; // 0b111111;\r\n }\r\n\r\n return (\r\n ((first === a && second === b && third === c) << 0) +\r\n ((first === a && second === c && third === b) << 1) +\r\n ((first === b && second === a && third === c) << 2) +\r\n ((first === b && second === c && third === a) << 3) +\r\n ((first === c && second === a && third === b) << 4) +\r\n ((first === c && second === b && third === a) << 5)\r\n );\r\n}\r\n\r\n// popcount for integers 0-63, inclusive.\r\n// i.e. how many 1s are in the binary representation of the integer.\r\nfunction popcount0to63(value) {\r\n return (\r\n (value & 1) +\r\n ((value >> 1) & 1) +\r\n ((value >> 2) & 1) +\r\n ((value >> 3) & 1) +\r\n ((value >> 4) & 1) +\r\n ((value >> 5) & 1)\r\n );\r\n}\r\n\r\nfunction matchAndStoreCoordinates(\r\n outlineCoordinates,\r\n i0,\r\n i1,\r\n i2,\r\n has01,\r\n has12,\r\n has20\r\n) {\r\n var a0 = has20 ? 1.0 : 0.0;\r\n var b0 = has01 ? 1.0 : 0.0;\r\n var c0 = 0.0;\r\n\r\n var i0Mask = computeOrderMask(outlineCoordinates, i0, a0, b0, c0);\r\n if (i0Mask === 0) {\r\n return i0;\r\n }\r\n\r\n var a1 = 0.0;\r\n var b1 = has01 ? 1.0 : 0.0;\r\n var c1 = has12 ? 1.0 : 0.0;\r\n\r\n var i1Mask = computeOrderMask(outlineCoordinates, i1, a1, b1, c1);\r\n if (i1Mask === 0) {\r\n return i1;\r\n }\r\n\r\n var a2 = has20 ? 1.0 : 0.0;\r\n var b2 = 0.0;\r\n var c2 = has12 ? 1.0 : 0.0;\r\n\r\n var i2Mask = computeOrderMask(outlineCoordinates, i2, a2, b2, c2);\r\n if (i2Mask === 0) {\r\n return i2;\r\n }\r\n\r\n var workingOrders = i0Mask & i1Mask & i2Mask;\r\n\r\n var a, b, c;\r\n\r\n if (workingOrders & (1 << 0)) {\r\n // 0 - abc\r\n a = 0;\r\n b = 1;\r\n c = 2;\r\n } else if (workingOrders & (1 << 1)) {\r\n // 1 - acb\r\n a = 0;\r\n c = 1;\r\n b = 2;\r\n } else if (workingOrders & (1 << 2)) {\r\n // 2 - bac\r\n b = 0;\r\n a = 1;\r\n c = 2;\r\n } else if (workingOrders & (1 << 3)) {\r\n // 3 - bca\r\n b = 0;\r\n c = 1;\r\n a = 2;\r\n } else if (workingOrders & (1 << 4)) {\r\n // 4 - cab\r\n c = 0;\r\n a = 1;\r\n b = 2;\r\n } else if (workingOrders & (1 << 5)) {\r\n // 5 - cba\r\n c = 0;\r\n b = 1;\r\n a = 2;\r\n } else {\r\n // No ordering works.\r\n // Report the most constrained vertex as unmatched so we copy that one.\r\n var i0Popcount = popcount0to63(i0Mask);\r\n var i1Popcount = popcount0to63(i1Mask);\r\n var i2Popcount = popcount0to63(i2Mask);\r\n if (i0Popcount < i1Popcount && i0Popcount < i2Popcount) {\r\n return i0;\r\n } else if (i1Popcount < i2Popcount) {\r\n return i1;\r\n }\r\n return i2;\r\n }\r\n\r\n var i0Start = i0 * 3;\r\n outlineCoordinates[i0Start + a] = a0;\r\n outlineCoordinates[i0Start + b] = b0;\r\n outlineCoordinates[i0Start + c] = c0;\r\n\r\n var i1Start = i1 * 3;\r\n outlineCoordinates[i1Start + a] = a1;\r\n outlineCoordinates[i1Start + b] = b1;\r\n outlineCoordinates[i1Start + c] = c1;\r\n\r\n var i2Start = i2 * 3;\r\n outlineCoordinates[i2Start + a] = a2;\r\n outlineCoordinates[i2Start + b] = b2;\r\n outlineCoordinates[i2Start + c] = c2;\r\n\r\n return -1;\r\n}\r\n\r\nfunction isHighlighted(edges, i0, i1) {\r\n var edgeSmallMultiplier = edges[0];\r\n var index = Math.min(i0, i1) * edgeSmallMultiplier + Math.max(i0, i1);\r\n\r\n // If i0 and i1 are both 0, then our index will be 0 and we'll end up\r\n // accessing the edgeSmallMultiplier that we've sneakily squirreled away\r\n // in index 0. But it makes no sense to have an edge between vertex 0 and\r\n // itself, so for any edgeSmallMultiplier other than 1 we'll return the\r\n // correct answer: false. If edgeSmallMultiplier is 1, that means there is\r\n // only a single vertex, so no danger of forming a meaningful triangle\r\n // with that.\r\n return edges[index] === 1;\r\n}\r\n\r\nfunction createTexture(size) {\r\n var texture = new Uint8Array(size);\r\n texture[size - 1] = 192;\r\n if (size === 8) {\r\n texture[size - 1] = 96;\r\n } else if (size === 4) {\r\n texture[size - 1] = 48;\r\n } else if (size === 2) {\r\n texture[size - 1] = 24;\r\n } else if (size === 1) {\r\n texture[size - 1] = 12;\r\n }\r\n return texture;\r\n}\r\n\r\nfunction updateBufferViewsWithNewVertices(model, bufferViews) {\r\n var gltf = model.gltf;\r\n var loadResources = model._loadResources;\r\n\r\n var i, j;\r\n for (i = 0; i < bufferViews.length; ++i) {\r\n var bufferView = bufferViews[i];\r\n var vertexNumberingScope = bufferView.extras._pipeline.vertexNumberingScope;\r\n\r\n // Let the temporary data be garbage collected.\r\n bufferView.extras._pipeline.vertexNumberingScope = undefined;\r\n\r\n var newVertices = vertexNumberingScope.extraVertices;\r\n\r\n var sourceData = loadResources.getBuffer(bufferView);\r\n var byteStride = bufferView.byteStride || 4;\r\n var newVerticesLength = newVertices.length;\r\n var destData = new Uint8Array(\r\n sourceData.byteLength + newVerticesLength * byteStride\r\n );\r\n\r\n // Copy the original vertices\r\n destData.set(sourceData);\r\n\r\n // Copy the vertices added for outlining\r\n for (j = 0; j < newVerticesLength; ++j) {\r\n var sourceIndex = newVertices[j] * byteStride;\r\n var destIndex = sourceData.length + j * byteStride;\r\n for (var k = 0; k < byteStride; ++k) {\r\n destData[destIndex + k] = destData[sourceIndex + k];\r\n }\r\n }\r\n\r\n // This bufferView is an independent buffer now. Update the model accordingly.\r\n bufferView.byteOffset = 0;\r\n bufferView.byteLength = destData.byteLength;\r\n\r\n var bufferId =\r\n gltf.buffers.push({\r\n byteLength: destData.byteLength,\r\n extras: {\r\n _pipeline: {\r\n source: destData.buffer,\r\n },\r\n },\r\n }) - 1;\r\n\r\n bufferView.buffer = bufferId;\r\n loadResources.buffers[bufferId] = destData;\r\n\r\n // Update the accessors to reflect the added vertices.\r\n var accessors = vertexNumberingScope.accessors;\r\n for (j = 0; j < accessors.length; ++j) {\r\n var accessorId = accessors[j];\r\n gltf.accessors[accessorId].count += newVerticesLength;\r\n }\r\n\r\n if (!vertexNumberingScope.createdOutlines) {\r\n // Create the buffers, views, and accessors for the outline texture coordinates.\r\n var outlineCoordinates = vertexNumberingScope.outlineCoordinates;\r\n var outlineCoordinateBuffer = new Float32Array(outlineCoordinates);\r\n var bufferIndex =\r\n model.gltf.buffers.push({\r\n byteLength: outlineCoordinateBuffer.byteLength,\r\n extras: {\r\n _pipeline: {\r\n source: outlineCoordinateBuffer.buffer,\r\n },\r\n },\r\n }) - 1;\r\n loadResources.buffers[bufferIndex] = new Uint8Array(\r\n outlineCoordinateBuffer.buffer,\r\n 0,\r\n outlineCoordinateBuffer.byteLength\r\n );\r\n\r\n var bufferViewIndex =\r\n model.gltf.bufferViews.push({\r\n buffer: bufferIndex,\r\n byteLength: outlineCoordinateBuffer.byteLength,\r\n byteOffset: 0,\r\n byteStride: 3 * Float32Array.BYTES_PER_ELEMENT,\r\n target: 34962,\r\n }) - 1;\r\n\r\n var accessorIndex =\r\n model.gltf.accessors.push({\r\n bufferView: bufferViewIndex,\r\n byteOffset: 0,\r\n componentType: 5126,\r\n count: outlineCoordinateBuffer.length / 3,\r\n type: \"VEC3\",\r\n min: [0.0, 0.0, 0.0],\r\n max: [1.0, 1.0, 1.0],\r\n }) - 1;\r\n\r\n var primitives = vertexNumberingScope.primitives;\r\n for (j = 0; j < primitives.length; ++j) {\r\n primitives[j].attributes._OUTLINE_COORDINATES = accessorIndex;\r\n }\r\n\r\n loadResources.vertexBuffersToCreate.enqueue(bufferViewIndex);\r\n\r\n vertexNumberingScope.createdOutlines = true;\r\n }\r\n }\r\n}\r\n\r\nfunction compactBuffers(model) {\r\n var gltf = model.gltf;\r\n var loadResources = model._loadResources;\r\n\r\n var i;\r\n for (i = 0; i < gltf.buffers.length; ++i) {\r\n var buffer = gltf.buffers[i];\r\n var bufferViewsUsingThisBuffer = gltf.bufferViews.filter(\r\n usesBuffer.bind(undefined, i)\r\n );\r\n var newLength = bufferViewsUsingThisBuffer.reduce(function (\r\n previous,\r\n current\r\n ) {\r\n return previous + current.byteLength;\r\n },\r\n 0);\r\n if (newLength === buffer.byteLength) {\r\n continue;\r\n }\r\n\r\n var newBuffer = new Uint8Array(newLength);\r\n var offset = 0;\r\n for (var j = 0; j < bufferViewsUsingThisBuffer.length; ++j) {\r\n var bufferView = bufferViewsUsingThisBuffer[j];\r\n var sourceData = loadResources.getBuffer(bufferView);\r\n newBuffer.set(sourceData, offset);\r\n\r\n bufferView.byteOffset = offset;\r\n offset += sourceData.byteLength;\r\n }\r\n\r\n loadResources.buffers[i] = newBuffer;\r\n buffer.extras._pipeline.source = newBuffer.buffer;\r\n buffer.byteLength = newLength;\r\n }\r\n}\r\n\r\nfunction usesBuffer(bufferId, bufferView) {\r\n return bufferView.buffer === bufferId;\r\n}\r\n\r\nfunction getVertexNumberingScope(model, primitive) {\r\n var attributes = primitive.attributes;\r\n if (attributes === undefined) {\r\n return undefined;\r\n }\r\n\r\n var gltf = model.gltf;\r\n\r\n var vertexNumberingScope;\r\n\r\n // Initialize common details for all bufferViews used by this primitive's vertices.\r\n // All bufferViews used by this primitive must use a common vertex numbering scheme.\r\n for (var semantic in attributes) {\r\n if (!attributes.hasOwnProperty(semantic)) {\r\n continue;\r\n }\r\n\r\n var accessorId = attributes[semantic];\r\n var accessor = gltf.accessors[accessorId];\r\n var bufferViewId = accessor.bufferView;\r\n var bufferView = gltf.bufferViews[bufferViewId];\r\n\r\n if (!defined(bufferView.extras)) {\r\n bufferView.extras = {};\r\n }\r\n if (!defined(bufferView.extras._pipeline)) {\r\n bufferView.extras._pipeline = {};\r\n }\r\n\r\n if (!defined(bufferView.extras._pipeline.vertexNumberingScope)) {\r\n bufferView.extras._pipeline.vertexNumberingScope = vertexNumberingScope || {\r\n // Each element in this array is:\r\n // a) undefined, if the vertex at this index has no copies\r\n // b) the index of the copy.\r\n vertexCopies: [],\r\n\r\n // Extra vertices appended after the ones originally included in the model.\r\n // Each element is the index of the vertex that this one is a copy of.\r\n extraVertices: [],\r\n\r\n // The texture coordinates used for outlining, three floats per vertex.\r\n outlineCoordinates: [],\r\n\r\n // The IDs of accessors that use this vertex numbering.\r\n accessors: [],\r\n\r\n // The IDs of bufferViews that use this vertex numbering.\r\n bufferViews: [],\r\n\r\n // The primitives that use this vertex numbering.\r\n primitives: [],\r\n\r\n // True if the buffer for the outlines has already been created.\r\n createdOutlines: false,\r\n };\r\n } else if (\r\n vertexNumberingScope !== undefined &&\r\n bufferView.extras._pipeline.vertexNumberingScope !== vertexNumberingScope\r\n ) {\r\n // Conflicting vertex numbering, let's give up.\r\n return undefined;\r\n }\r\n\r\n vertexNumberingScope = bufferView.extras._pipeline.vertexNumberingScope;\r\n\r\n if (vertexNumberingScope.bufferViews.indexOf(bufferView) < 0) {\r\n vertexNumberingScope.bufferViews.push(bufferView);\r\n }\r\n\r\n if (vertexNumberingScope.accessors.indexOf(accessorId) < 0) {\r\n vertexNumberingScope.accessors.push(accessorId);\r\n }\r\n }\r\n\r\n vertexNumberingScope.primitives.push(primitive);\r\n\r\n return vertexNumberingScope;\r\n}\r\n\r\nexport default ModelOutlineLoader;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport Pass from \"./Pass.js\";\r\n\r\n/**\r\n * Represents a command to the renderer for GPU Compute (using old-school GPGPU).\r\n *\r\n * @private\r\n * @constructor\r\n */\r\nfunction ComputeCommand(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * The vertex array. If none is provided, a viewport quad will be used.\r\n *\r\n * @type {VertexArray}\r\n * @default undefined\r\n */\r\n this.vertexArray = options.vertexArray;\r\n\r\n /**\r\n * The fragment shader source. The default vertex shader is ViewportQuadVS.\r\n *\r\n * @type {ShaderSource}\r\n * @default undefined\r\n */\r\n this.fragmentShaderSource = options.fragmentShaderSource;\r\n\r\n /**\r\n * The shader program to apply.\r\n *\r\n * @type {ShaderProgram}\r\n * @default undefined\r\n */\r\n this.shaderProgram = options.shaderProgram;\r\n\r\n /**\r\n * An object with functions whose names match the uniforms in the shader program\r\n * and return values to set those uniforms.\r\n *\r\n * @type {Object}\r\n * @default undefined\r\n */\r\n this.uniformMap = options.uniformMap;\r\n\r\n /**\r\n * Texture to use for offscreen rendering.\r\n *\r\n * @type {Texture}\r\n * @default undefined\r\n */\r\n this.outputTexture = options.outputTexture;\r\n\r\n /**\r\n * Function that is called immediately before the ComputeCommand is executed. Used to\r\n * update any renderer resources. Takes the ComputeCommand as its single argument.\r\n *\r\n * @type {Function}\r\n * @default undefined\r\n */\r\n this.preExecute = options.preExecute;\r\n\r\n /**\r\n * Function that is called after the ComputeCommand is executed. Takes the output\r\n * texture as its single argument.\r\n *\r\n * @type {Function}\r\n * @default undefined\r\n */\r\n this.postExecute = options.postExecute;\r\n\r\n /**\r\n * Function that is called when the command is canceled\r\n *\r\n * @type {Function}\r\n * @default undefined\r\n */\r\n this.canceled = options.canceled;\r\n\r\n /**\r\n * Whether the renderer resources will persist beyond this call. If not, they\r\n * will be destroyed after completion.\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.persists = defaultValue(options.persists, false);\r\n\r\n /**\r\n * The pass when to render. Always compute pass.\r\n *\r\n * @type {Pass}\r\n * @default Pass.COMPUTE;\r\n */\r\n this.pass = Pass.COMPUTE;\r\n\r\n /**\r\n * The object who created this command. This is useful for debugging command\r\n * execution; it allows us to see who created a command when we only have a\r\n * reference to the command, and can be used to selectively execute commands\r\n * with {@link Scene#debugCommandFilter}.\r\n *\r\n * @type {Object}\r\n * @default undefined\r\n *\r\n * @see Scene#debugCommandFilter\r\n */\r\n this.owner = options.owner;\r\n}\r\n\r\n/**\r\n * Executes the compute command.\r\n *\r\n * @param {ComputeEngine} computeEngine The context that processes the compute command.\r\n */\r\nComputeCommand.prototype.execute = function (computeEngine) {\r\n computeEngine.execute(this);\r\n};\r\nexport default ComputeCommand;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec2 v_textureCoordinates;\\n\\\nuniform float originalSize;\\n\\\nuniform sampler2D texture0;\\n\\\nuniform sampler2D texture1;\\n\\\nuniform sampler2D texture2;\\n\\\nuniform sampler2D texture3;\\n\\\nuniform sampler2D texture4;\\n\\\nuniform sampler2D texture5;\\n\\\nconst float yMipLevel1 = 1.0 - (1.0 / pow(2.0, 1.0));\\n\\\nconst float yMipLevel2 = 1.0 - (1.0 / pow(2.0, 2.0));\\n\\\nconst float yMipLevel3 = 1.0 - (1.0 / pow(2.0, 3.0));\\n\\\nconst float yMipLevel4 = 1.0 - (1.0 / pow(2.0, 4.0));\\n\\\nvoid main()\\n\\\n{\\n\\\nvec2 uv = v_textureCoordinates;\\n\\\nvec2 textureSize = vec2(originalSize * 1.5 + 2.0, originalSize);\\n\\\nvec2 pixel = 1.0 / textureSize;\\n\\\nfloat mipLevel = 0.0;\\n\\\nif (uv.x - pixel.x > (textureSize.y / textureSize.x))\\n\\\n{\\n\\\nmipLevel = 1.0;\\n\\\nif (uv.y - pixel.y > yMipLevel1)\\n\\\n{\\n\\\nmipLevel = 2.0;\\n\\\nif (uv.y - pixel.y * 3.0 > yMipLevel2)\\n\\\n{\\n\\\nmipLevel = 3.0;\\n\\\nif (uv.y - pixel.y * 5.0 > yMipLevel3)\\n\\\n{\\n\\\nmipLevel = 4.0;\\n\\\nif (uv.y - pixel.y * 7.0 > yMipLevel4)\\n\\\n{\\n\\\nmipLevel = 5.0;\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\nif (mipLevel > 0.0)\\n\\\n{\\n\\\nfloat scale = pow(2.0, mipLevel);\\n\\\nuv.y -= (pixel.y * (mipLevel - 1.0) * 2.0);\\n\\\nuv.x *= ((textureSize.x - 2.0) / textureSize.y);\\n\\\nuv.x -= 1.0 + pixel.x;\\n\\\nuv.y -= (1.0 - (1.0 / pow(2.0, mipLevel - 1.0)));\\n\\\nuv *= scale;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nuv.x *= (textureSize.x / textureSize.y);\\n\\\n}\\n\\\nif(mipLevel == 0.0)\\n\\\n{\\n\\\ngl_FragColor = texture2D(texture0, uv);\\n\\\n}\\n\\\nelse if(mipLevel == 1.0)\\n\\\n{\\n\\\ngl_FragColor = texture2D(texture1, uv);\\n\\\n}\\n\\\nelse if(mipLevel == 2.0)\\n\\\n{\\n\\\ngl_FragColor = texture2D(texture2, uv);\\n\\\n}\\n\\\nelse if(mipLevel == 3.0)\\n\\\n{\\n\\\ngl_FragColor = texture2D(texture3, uv);\\n\\\n}\\n\\\nelse if(mipLevel == 4.0)\\n\\\n{\\n\\\ngl_FragColor = texture2D(texture4, uv);\\n\\\n}\\n\\\nelse if(mipLevel == 5.0)\\n\\\n{\\n\\\ngl_FragColor = texture2D(texture5, uv);\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\ngl_FragColor = vec4(0.0);\\n\\\n}\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec3 v_cubeMapCoordinates;\\n\\\nuniform samplerCube cubeMap;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec4 rgbm = textureCube(cubeMap, v_cubeMapCoordinates);\\n\\\nfloat m = rgbm.a * 16.0;\\n\\\nvec3 r = rgbm.rgb * m;\\n\\\ngl_FragColor = vec4(r * r, 1.0);\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec4 position;\\n\\\nattribute vec3 cubeMapCoordinates;\\n\\\nvarying vec3 v_cubeMapCoordinates;\\n\\\nvoid main()\\n\\\n{\\n\\\ngl_Position = position;\\n\\\nv_cubeMapCoordinates = cubeMapCoordinates;\\n\\\n}\\n\\\n\";\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport loadKTX from \"../Core/loadKTX.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport ComputeCommand from \"../Renderer/ComputeCommand.js\";\r\nimport CubeMap from \"../Renderer/CubeMap.js\";\r\nimport PixelDatatype from \"../Renderer/PixelDatatype.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport VertexArray from \"../Renderer/VertexArray.js\";\r\nimport OctahedralProjectionAtlasFS from \"../Shaders/OctahedralProjectionAtlasFS.js\";\r\nimport OctahedralProjectionFS from \"../Shaders/OctahedralProjectionFS.js\";\r\nimport OctahedralProjectionVS from \"../Shaders/OctahedralProjectionVS.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\n\r\n/**\r\n * Packs all mip levels of a cube map into a 2D texture atlas.\r\n *\r\n * Octahedral projection is a way of putting the cube maps onto a 2D texture\r\n * with minimal distortion and easy look up.\r\n * See Chapter 16 of WebGL Insights \"HDR Image-Based Lighting on the Web\" by Jeff Russell\r\n * and \"Octahedron Environment Maps\" for reference.\r\n *\r\n * @private\r\n */\r\nfunction OctahedralProjectedCubeMap(url) {\r\n this._url = url;\r\n\r\n this._cubeMapBuffers = undefined;\r\n this._cubeMaps = undefined;\r\n this._texture = undefined;\r\n this._mipTextures = undefined;\r\n this._va = undefined;\r\n this._sp = undefined;\r\n\r\n this._maximumMipmapLevel = undefined;\r\n\r\n this._loading = false;\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n}\r\n\r\nObject.defineProperties(OctahedralProjectedCubeMap.prototype, {\r\n /**\r\n * The url to the KTX file containing the specular environment map and convoluted mipmaps.\r\n * @memberof OctahedralProjectedCubeMap.prototype\r\n * @type {String}\r\n * @readonly\r\n */\r\n url: {\r\n get: function () {\r\n return this._url;\r\n },\r\n },\r\n /**\r\n * A texture containing all the packed convolutions.\r\n * @memberof OctahedralProjectedCubeMap.prototype\r\n * @type {Texture}\r\n * @readonly\r\n */\r\n texture: {\r\n get: function () {\r\n return this._texture;\r\n },\r\n },\r\n /**\r\n * The maximum number of mip levels.\r\n * @memberOf OctahedralProjectedCubeMap.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n maximumMipmapLevel: {\r\n get: function () {\r\n return this._maximumMipmapLevel;\r\n },\r\n },\r\n /**\r\n * Determines if the texture atlas is complete and ready to use.\r\n * @memberof OctahedralProjectedCubeMap.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n /**\r\n * Gets a promise that resolves when the texture atlas is ready to use.\r\n * @memberof OctahedralProjectedCubeMap.prototype\r\n * @type {Promise}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n});\r\n\r\nOctahedralProjectedCubeMap.isSupported = function (context) {\r\n return (\r\n (context.colorBufferHalfFloat && context.halfFloatingPointTexture) ||\r\n (context.floatingPointTexture && context.colorBufferFloat)\r\n );\r\n};\r\n\r\n// These vertices are based on figure 1 from \"Octahedron Environment Maps\".\r\nvar v1 = new Cartesian3(1.0, 0.0, 0.0);\r\nvar v2 = new Cartesian3(0.0, 0.0, 1.0);\r\nvar v3 = new Cartesian3(-1.0, 0.0, 0.0);\r\nvar v4 = new Cartesian3(0.0, 0.0, -1.0);\r\nvar v5 = new Cartesian3(0.0, 1.0, 0.0);\r\nvar v6 = new Cartesian3(0.0, -1.0, 0.0);\r\n\r\n// top left, left, top, center, right, top right, bottom, bottom left, bottom right\r\nvar cubeMapCoordinates = [v5, v3, v2, v6, v1, v5, v4, v5, v5];\r\nvar length = cubeMapCoordinates.length;\r\nvar flatCubeMapCoordinates = new Float32Array(length * 3);\r\n\r\nvar offset = 0;\r\nfor (var i = 0; i < length; ++i, offset += 3) {\r\n Cartesian3.pack(cubeMapCoordinates[i], flatCubeMapCoordinates, offset);\r\n}\r\n\r\nvar flatPositions = new Float32Array([\r\n -1.0,\r\n 1.0, // top left\r\n -1.0,\r\n 0.0, // left\r\n 0.0,\r\n 1.0, // top\r\n 0.0,\r\n 0.0, // center\r\n 1.0,\r\n 0.0, // right\r\n 1.0,\r\n 1.0, // top right\r\n 0.0,\r\n -1.0, // bottom\r\n -1.0,\r\n -1.0, // bottom left\r\n 1.0,\r\n -1.0, // bottom right\r\n]);\r\nvar indices = new Uint16Array([\r\n 0,\r\n 1,\r\n 2, // top left, left, top,\r\n 2,\r\n 3,\r\n 1, // top, center, left,\r\n 7,\r\n 6,\r\n 1, // bottom left, bottom, left,\r\n 3,\r\n 6,\r\n 1, // center, bottom, left,\r\n 2,\r\n 5,\r\n 4, // top, top right, right,\r\n 3,\r\n 4,\r\n 2, // center, right, top,\r\n 4,\r\n 8,\r\n 6, // right, bottom right, bottom,\r\n 3,\r\n 4,\r\n 6, //center, right, bottom\r\n]);\r\n\r\nfunction createVertexArray(context) {\r\n var positionBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: flatPositions,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var cubeMapCoordinatesBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: flatCubeMapCoordinates,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: indices,\r\n usage: BufferUsage.STATIC_DRAW,\r\n indexDatatype: IndexDatatype.UNSIGNED_SHORT,\r\n });\r\n\r\n var attributes = [\r\n {\r\n index: 0,\r\n vertexBuffer: positionBuffer,\r\n componentsPerAttribute: 2,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n },\r\n {\r\n index: 1,\r\n vertexBuffer: cubeMapCoordinatesBuffer,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n },\r\n ];\r\n return new VertexArray({\r\n context: context,\r\n attributes: attributes,\r\n indexBuffer: indexBuffer,\r\n });\r\n}\r\n\r\nfunction createUniformTexture(texture) {\r\n return function () {\r\n return texture;\r\n };\r\n}\r\n\r\nfunction cleanupResources(map) {\r\n map._va = map._va && map._va.destroy();\r\n map._sp = map._sp && map._sp.destroy();\r\n\r\n var i;\r\n var length;\r\n\r\n var cubeMaps = map._cubeMaps;\r\n if (defined(cubeMaps)) {\r\n length = cubeMaps.length;\r\n for (i = 0; i < length; ++i) {\r\n cubeMaps[i].destroy();\r\n }\r\n }\r\n var mipTextures = map._mipTextures;\r\n if (defined(mipTextures)) {\r\n length = mipTextures.length;\r\n for (i = 0; i < length; ++i) {\r\n mipTextures[i].destroy();\r\n }\r\n }\r\n\r\n map._va = undefined;\r\n map._sp = undefined;\r\n map._cubeMaps = undefined;\r\n map._cubeMapBuffers = undefined;\r\n map._mipTextures = undefined;\r\n}\r\n\r\n/**\r\n * Creates compute commands to generate octahedral projections of each cube map\r\n * and then renders them to an atlas.\r\n *

\r\n * Only needs to be called twice. The first call queues the compute commands to generate the atlas.\r\n * The second call cleans up unused resources. Every call afterwards is a no-op.\r\n *

\r\n *\r\n * @param {FrameState} frameState The frame state.\r\n *\r\n * @private\r\n */\r\nOctahedralProjectedCubeMap.prototype.update = function (frameState) {\r\n var context = frameState.context;\r\n\r\n if (!OctahedralProjectedCubeMap.isSupported(context)) {\r\n return;\r\n }\r\n\r\n if (defined(this._texture) && defined(this._va)) {\r\n cleanupResources(this);\r\n }\r\n if (defined(this._texture)) {\r\n return;\r\n }\r\n\r\n if (!defined(this._texture) && !this._loading) {\r\n var cachedTexture = context.textureCache.getTexture(this._url);\r\n if (defined(cachedTexture)) {\r\n cleanupResources(this);\r\n this._texture = cachedTexture;\r\n this._maximumMipmapLevel = this._texture.maximumMipmapLevel;\r\n this._ready = true;\r\n this._readyPromise.resolve();\r\n return;\r\n }\r\n }\r\n\r\n var cubeMapBuffers = this._cubeMapBuffers;\r\n if (!defined(cubeMapBuffers) && !this._loading) {\r\n var that = this;\r\n loadKTX(this._url)\r\n .then(function (buffers) {\r\n that._cubeMapBuffers = buffers;\r\n that._loading = false;\r\n })\r\n .otherwise(this._readyPromise.reject);\r\n this._loading = true;\r\n }\r\n if (!defined(this._cubeMapBuffers)) {\r\n return;\r\n }\r\n\r\n this._va = createVertexArray(context);\r\n this._sp = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: OctahedralProjectionVS,\r\n fragmentShaderSource: OctahedralProjectionFS,\r\n attributeLocations: {\r\n position: 0,\r\n cubeMapCoordinates: 1,\r\n },\r\n });\r\n\r\n // We only need up to 6 mip levels to avoid artifacts.\r\n var length = Math.min(cubeMapBuffers.length, 6);\r\n this._maximumMipmapLevel = length - 1;\r\n var cubeMaps = (this._cubeMaps = new Array(length));\r\n var mipTextures = (this._mipTextures = new Array(length));\r\n var originalSize = cubeMapBuffers[0].positiveX.width * 2.0;\r\n var uniformMap = {\r\n originalSize: function () {\r\n return originalSize;\r\n },\r\n };\r\n\r\n var pixelDatatype = context.halfFloatingPointTexture\r\n ? PixelDatatype.HALF_FLOAT\r\n : PixelDatatype.FLOAT;\r\n var pixelFormat = PixelFormat.RGBA;\r\n\r\n // First we project each cubemap onto a flat octahedron, and write that to a texture.\r\n for (var i = 0; i < length; ++i) {\r\n // Swap +Y/-Y faces since the octahedral projection expects this order.\r\n var positiveY = cubeMapBuffers[i].positiveY;\r\n cubeMapBuffers[i].positiveY = cubeMapBuffers[i].negativeY;\r\n cubeMapBuffers[i].negativeY = positiveY;\r\n\r\n var cubeMap = (cubeMaps[i] = new CubeMap({\r\n context: context,\r\n source: cubeMapBuffers[i],\r\n }));\r\n var size = cubeMaps[i].width * 2;\r\n\r\n var mipTexture = (mipTextures[i] = new Texture({\r\n context: context,\r\n width: size,\r\n height: size,\r\n pixelDatatype: pixelDatatype,\r\n pixelFormat: pixelFormat,\r\n }));\r\n\r\n var command = new ComputeCommand({\r\n vertexArray: this._va,\r\n shaderProgram: this._sp,\r\n uniformMap: {\r\n cubeMap: createUniformTexture(cubeMap),\r\n },\r\n outputTexture: mipTexture,\r\n persists: true,\r\n owner: this,\r\n });\r\n frameState.commandList.push(command);\r\n\r\n uniformMap[\"texture\" + i] = createUniformTexture(mipTexture);\r\n }\r\n\r\n this._texture = new Texture({\r\n context: context,\r\n width: originalSize * 1.5 + 2.0, // We add a 1 pixel border to avoid linear sampling artifacts.\r\n height: originalSize,\r\n pixelDatatype: pixelDatatype,\r\n pixelFormat: pixelFormat,\r\n });\r\n\r\n this._texture.maximumMipmapLevel = this._maximumMipmapLevel;\r\n context.textureCache.addTexture(this._url, this._texture);\r\n\r\n var atlasCommand = new ComputeCommand({\r\n fragmentShaderSource: OctahedralProjectionAtlasFS,\r\n uniformMap: uniformMap,\r\n outputTexture: this._texture,\r\n persists: false,\r\n owner: this,\r\n });\r\n frameState.commandList.push(atlasCommand);\r\n\r\n this._ready = true;\r\n this._readyPromise.resolve();\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see OctahedralProjectedCubeMap#destroy\r\n */\r\nOctahedralProjectedCubeMap.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see OctahedralProjectedCubeMap#isDestroyed\r\n */\r\nOctahedralProjectedCubeMap.prototype.destroy = function () {\r\n cleanupResources(this);\r\n this._texture = this._texture && this._texture.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default OctahedralProjectedCubeMap;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport clone from \"../Core/clone.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport Credit from \"../Core/Credit.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport getAbsoluteUri from \"../Core/getAbsoluteUri.js\";\r\nimport getJsonFromTypedArray from \"../Core/getJsonFromTypedArray.js\";\r\nimport getMagic from \"../Core/getMagic.js\";\r\nimport getStringFromTypedArray from \"../Core/getStringFromTypedArray.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport loadCRN from \"../Core/loadCRN.js\";\r\nimport loadImageFromTypedArray from \"../Core/loadImageFromTypedArray.js\";\r\nimport loadKTX from \"../Core/loadKTX.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport PrimitiveType from \"../Core/PrimitiveType.js\";\r\nimport Quaternion from \"../Core/Quaternion.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport Sampler from \"../Renderer/Sampler.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport TextureMinificationFilter from \"../Renderer/TextureMinificationFilter.js\";\r\nimport TextureWrap from \"../Renderer/TextureWrap.js\";\r\nimport VertexArray from \"../Renderer/VertexArray.js\";\r\nimport addDefaults from \"../ThirdParty/GltfPipeline/addDefaults.js\";\r\nimport addPipelineExtras from \"../ThirdParty/GltfPipeline/addPipelineExtras.js\";\r\nimport ForEach from \"../ThirdParty/GltfPipeline/ForEach.js\";\r\nimport getAccessorByteStride from \"../ThirdParty/GltfPipeline/getAccessorByteStride.js\";\r\nimport hasExtension from \"../ThirdParty/GltfPipeline/hasExtension.js\";\r\nimport numberOfComponentsForType from \"../ThirdParty/GltfPipeline/numberOfComponentsForType.js\";\r\nimport parseGlb from \"../ThirdParty/GltfPipeline/parseGlb.js\";\r\nimport updateVersion from \"../ThirdParty/GltfPipeline/updateVersion.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Axis from \"./Axis.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport ClippingPlaneCollection from \"./ClippingPlaneCollection.js\";\r\nimport ColorBlendMode from \"./ColorBlendMode.js\";\r\nimport DepthFunction from \"./DepthFunction.js\";\r\nimport DracoLoader from \"./DracoLoader.js\";\r\nimport getClipAndStyleCode from \"./getClipAndStyleCode.js\";\r\nimport getClippingFunction from \"./getClippingFunction.js\";\r\nimport HeightReference from \"./HeightReference.js\";\r\nimport JobType from \"./JobType.js\";\r\nimport ModelAnimationCache from \"./ModelAnimationCache.js\";\r\nimport ModelAnimationCollection from \"./ModelAnimationCollection.js\";\r\nimport ModelLoadResources from \"./ModelLoadResources.js\";\r\nimport ModelMaterial from \"./ModelMaterial.js\";\r\nimport ModelMesh from \"./ModelMesh.js\";\r\nimport ModelNode from \"./ModelNode.js\";\r\nimport ModelOutlineLoader from \"./ModelOutlineLoader.js\";\r\nimport ModelUtility from \"./ModelUtility.js\";\r\nimport OctahedralProjectedCubeMap from \"./OctahedralProjectedCubeMap.js\";\r\nimport processModelMaterialsCommon from \"./processModelMaterialsCommon.js\";\r\nimport processPbrMaterials from \"./processPbrMaterials.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport ShadowMode from \"./ShadowMode.js\";\r\nimport StencilConstants from \"./StencilConstants.js\";\r\n\r\nvar boundingSphereCartesian3Scratch = new Cartesian3();\r\n\r\nvar ModelState = ModelUtility.ModelState;\r\n\r\n// glTF MIME types discussed in https://github.com/KhronosGroup/glTF/issues/412 and https://github.com/KhronosGroup/glTF/issues/943\r\nvar defaultModelAccept =\r\n \"model/gltf-binary,model/gltf+json;q=0.8,application/json;q=0.2,*/*;q=0.01\";\r\n\r\nvar articulationEpsilon = CesiumMath.EPSILON16;\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction setCachedGltf(model, cachedGltf) {\r\n model._cachedGltf = cachedGltf;\r\n}\r\n\r\n// glTF JSON can be big given embedded geometry, textures, and animations, so we\r\n// cache it across all models using the same url/cache-key. This also reduces the\r\n// slight overhead in assigning defaults to missing values.\r\n//\r\n// Note that this is a global cache, compared to renderer resources, which\r\n// are cached per context.\r\nfunction CachedGltf(options) {\r\n this._gltf = options.gltf;\r\n this.ready = options.ready;\r\n this.modelsToLoad = [];\r\n this.count = 0;\r\n}\r\n\r\nObject.defineProperties(CachedGltf.prototype, {\r\n gltf: {\r\n set: function (value) {\r\n this._gltf = value;\r\n },\r\n\r\n get: function () {\r\n return this._gltf;\r\n },\r\n },\r\n});\r\n\r\nCachedGltf.prototype.makeReady = function (gltfJson) {\r\n this.gltf = gltfJson;\r\n\r\n var models = this.modelsToLoad;\r\n var length = models.length;\r\n for (var i = 0; i < length; ++i) {\r\n var m = models[i];\r\n if (!m.isDestroyed()) {\r\n setCachedGltf(m, this);\r\n }\r\n }\r\n this.modelsToLoad = undefined;\r\n this.ready = true;\r\n};\r\n\r\nvar gltfCache = {};\r\nvar uriToGuid = {};\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n/**\r\n * A 3D model based on glTF, the runtime asset format for WebGL, OpenGL ES, and OpenGL.\r\n *

\r\n * Cesium includes support for geometry and materials, glTF animations, and glTF skinning.\r\n * In addition, individual glTF nodes are pickable with {@link Scene#pick} and animatable\r\n * with {@link Model#getNode}. glTF cameras and lights are not currently supported.\r\n *

\r\n *

\r\n * An external glTF asset is created with {@link Model.fromGltf}. glTF JSON can also be\r\n * created at runtime and passed to this constructor function. In either case, the\r\n * {@link Model#readyPromise} is resolved when the model is ready to render, i.e.,\r\n * when the external binary, image, and shader files are downloaded and the WebGL\r\n * resources are created.\r\n *

\r\n *

\r\n * Cesium supports glTF assets with the following extensions:\r\n *

    \r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Khronos/KHR_binary_glTF/README.md|KHR_binary_glTF (glTF 1.0)}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Khronos/KHR_materials_common/README.md|KHR_materials_common (glTF 1.0)}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Vendor/WEB3D_quantized_attributes/README.md|WEB3D_quantized_attributes (glTF 1.0)}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/AGI_articulations/README.md|AGI_articulations}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/pull/1302|KHR_blend (draft)}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md|KHR_draco_mesh_compression}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/README.md|KHR_materials_pbrSpecularGlossiness}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit/README.md|KHR_materials_unlit}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_techniques_webgl/README.md|KHR_techniques_webgl}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_texture_transform/README.md|KHR_texture_transform}\r\n *
  • \r\n *
\r\n *

\r\n *

\r\n * For high-precision rendering, Cesium supports the {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Vendor/CESIUM_RTC/README.md|CESIUM_RTC} extension, which introduces the\r\n * CESIUM_RTC_MODELVIEW parameter semantic that says the node is in WGS84 coordinates translated\r\n * relative to a local origin.\r\n *

\r\n *\r\n * @alias Model\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Object|ArrayBuffer|Uint8Array} [options.gltf] A glTF JSON object, or a binary glTF buffer.\r\n * @param {Resource|String} [options.basePath=''] The base path that paths in the glTF JSON are relative to.\r\n * @param {Boolean} [options.show=true] Determines if the model primitive will be shown.\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms the model from model to world coordinates.\r\n * @param {Number} [options.scale=1.0] A uniform scale applied to this model.\r\n * @param {Number} [options.minimumPixelSize=0.0] The approximate minimum pixel size of the model regardless of zoom.\r\n * @param {Number} [options.maximumScale] The maximum scale size of a model. An upper limit for minimumPixelSize.\r\n * @param {Object} [options.id] A user-defined object to return when the model is picked with {@link Scene#pick}.\r\n * @param {Boolean} [options.allowPicking=true] When true, each glTF mesh and primitive is pickable with {@link Scene#pick}.\r\n * @param {Boolean} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded.\r\n * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded.\r\n * @param {Boolean} [options.clampAnimations=true] Determines if the model's animations should hold a pose over frames where no keyframes are specified.\r\n * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from light sources.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each draw command in the model.\r\n * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe.\r\n * @param {HeightReference} [options.heightReference=HeightReference.NONE] Determines how the model is drawn relative to terrain.\r\n * @param {Scene} [options.scene] Must be passed in for models that use the height reference property.\r\n * @param {DistanceDisplayCondition} [options.distanceDisplayCondition] The condition specifying at what distance from the camera that this model will be displayed.\r\n * @param {Color} [options.color=Color.WHITE] A color that blends with the model's rendered color.\r\n * @param {ColorBlendMode} [options.colorBlendMode=ColorBlendMode.HIGHLIGHT] Defines how the color blends with the model.\r\n * @param {Number} [options.colorBlendAmount=0.5] Value used to determine the color strength when the colorBlendMode is MIX. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.\r\n * @param {Color} [options.silhouetteColor=Color.RED] The silhouette color. If more than 256 models have silhouettes enabled, there is a small chance that overlapping models will have minor artifacts.\r\n * @param {Number} [options.silhouetteSize=0.0] The size of the silhouette in pixels.\r\n * @param {ClippingPlaneCollection} [options.clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the model.\r\n * @param {Boolean} [options.dequantizeInShader=true] Determines if a {@link https://github.com/google/draco|Draco} encoded model is dequantized on the GPU. This decreases total memory usage for encoded models.\r\n * @param {Cartesian2} [options.imageBasedLightingFactor=Cartesian2(1.0, 1.0)] Scales diffuse and specular image-based lighting from the earth, sky, atmosphere and star skybox.\r\n * @param {Cartesian3} [options.lightColor] The light color when shading the model. When undefined the scene's light color is used instead.\r\n * @param {Number} [options.luminanceAtZenith=0.2] The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map.\r\n * @param {Cartesian3[]} [options.sphericalHarmonicCoefficients] The third order spherical harmonic coefficients used for the diffuse color of image-based lighting.\r\n * @param {String} [options.specularEnvironmentMaps] A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.\r\n * @param {Credit|String} [options.credit] A credit for the data source, which is displayed on the canvas.\r\n * @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the material's doubleSided property; when false, back face culling is disabled. Back faces are not culled if {@link Model#color} is translucent or {@link Model#silhouetteSize} is greater than 0.0.\r\n *\r\n * @see Model.fromGltf\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=3D%20Models.html|Cesium Sandcastle Models Demo}\r\n */\r\nfunction Model(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var cacheKey = options.cacheKey;\r\n this._cacheKey = cacheKey;\r\n this._cachedGltf = undefined;\r\n this._releaseGltfJson = defaultValue(options.releaseGltfJson, false);\r\n\r\n var cachedGltf;\r\n if (\r\n defined(cacheKey) &&\r\n defined(gltfCache[cacheKey]) &&\r\n gltfCache[cacheKey].ready\r\n ) {\r\n // glTF JSON is in cache and ready\r\n cachedGltf = gltfCache[cacheKey];\r\n ++cachedGltf.count;\r\n } else {\r\n // glTF was explicitly provided, e.g., when a user uses the Model constructor directly\r\n var gltf = options.gltf;\r\n\r\n if (defined(gltf)) {\r\n if (gltf instanceof ArrayBuffer) {\r\n gltf = new Uint8Array(gltf);\r\n }\r\n\r\n if (gltf instanceof Uint8Array) {\r\n // Binary glTF\r\n var parsedGltf = parseGlb(gltf);\r\n\r\n cachedGltf = new CachedGltf({\r\n gltf: parsedGltf,\r\n ready: true,\r\n });\r\n } else {\r\n // Normal glTF (JSON)\r\n cachedGltf = new CachedGltf({\r\n gltf: options.gltf,\r\n ready: true,\r\n });\r\n }\r\n\r\n cachedGltf.count = 1;\r\n\r\n if (defined(cacheKey)) {\r\n gltfCache[cacheKey] = cachedGltf;\r\n }\r\n }\r\n }\r\n setCachedGltf(this, cachedGltf);\r\n\r\n var basePath = defaultValue(options.basePath, \"\");\r\n this._resource = Resource.createIfNeeded(basePath);\r\n\r\n // User specified credit\r\n var credit = options.credit;\r\n if (typeof credit === \"string\") {\r\n credit = new Credit(credit);\r\n }\r\n this._credit = credit;\r\n\r\n // Create a list of Credit's so they can be added from the Resource later\r\n this._resourceCredits = [];\r\n\r\n /**\r\n * Determines if the model primitive will be shown.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * The silhouette color.\r\n *\r\n * @type {Color}\r\n *\r\n * @default Color.RED\r\n */\r\n this.silhouetteColor = defaultValue(options.silhouetteColor, Color.RED);\r\n this._silhouetteColor = new Color();\r\n this._silhouetteColorPreviousAlpha = 1.0;\r\n this._normalAttributeName = undefined;\r\n\r\n /**\r\n * The size of the silhouette in pixels.\r\n *\r\n * @type {Number}\r\n *\r\n * @default 0.0\r\n */\r\n this.silhouetteSize = defaultValue(options.silhouetteSize, 0.0);\r\n\r\n /**\r\n * The 4x4 transformation matrix that transforms the model from model to world coordinates.\r\n * When this is the identity matrix, the model is drawn in world coordinates, i.e., Earth's WGS84 coordinates.\r\n * Local reference frames can be used by providing a different transformation matrix, like that returned\r\n * by {@link Transforms.eastNorthUpToFixedFrame}.\r\n *\r\n * @type {Matrix4}\r\n *\r\n * @default {@link Matrix4.IDENTITY}\r\n *\r\n * @example\r\n * var origin = Cesium.Cartesian3.fromDegrees(-95.0, 40.0, 200000.0);\r\n * m.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n this._modelMatrix = Matrix4.clone(this.modelMatrix);\r\n this._clampedModelMatrix = undefined;\r\n\r\n /**\r\n * A uniform scale applied to this model before the {@link Model#modelMatrix}.\r\n * Values greater than 1.0 increase the size of the model; values\r\n * less than 1.0 decrease.\r\n *\r\n * @type {Number}\r\n *\r\n * @default 1.0\r\n */\r\n this.scale = defaultValue(options.scale, 1.0);\r\n this._scale = this.scale;\r\n\r\n /**\r\n * The approximate minimum pixel size of the model regardless of zoom.\r\n * This can be used to ensure that a model is visible even when the viewer\r\n * zooms out. When 0.0, no minimum size is enforced.\r\n *\r\n * @type {Number}\r\n *\r\n * @default 0.0\r\n */\r\n this.minimumPixelSize = defaultValue(options.minimumPixelSize, 0.0);\r\n this._minimumPixelSize = this.minimumPixelSize;\r\n\r\n /**\r\n * The maximum scale size for a model. This can be used to give\r\n * an upper limit to the {@link Model#minimumPixelSize}, ensuring that the model\r\n * is never an unreasonable scale.\r\n *\r\n * @type {Number}\r\n */\r\n this.maximumScale = options.maximumScale;\r\n this._maximumScale = this.maximumScale;\r\n\r\n /**\r\n * User-defined object returned when the model is picked.\r\n *\r\n * @type Object\r\n *\r\n * @default undefined\r\n *\r\n * @see Scene#pick\r\n */\r\n this.id = options.id;\r\n this._id = options.id;\r\n\r\n /**\r\n * Returns the height reference of the model\r\n *\r\n * @type {HeightReference}\r\n *\r\n * @default HeightReference.NONE\r\n */\r\n this.heightReference = defaultValue(\r\n options.heightReference,\r\n HeightReference.NONE\r\n );\r\n this._heightReference = this.heightReference;\r\n this._heightChanged = false;\r\n this._removeUpdateHeightCallback = undefined;\r\n var scene = options.scene;\r\n this._scene = scene;\r\n if (defined(scene) && defined(scene.terrainProviderChanged)) {\r\n this._terrainProviderChangedCallback = scene.terrainProviderChanged.addEventListener(\r\n function () {\r\n this._heightChanged = true;\r\n },\r\n this\r\n );\r\n }\r\n\r\n /**\r\n * Used for picking primitives that wrap a model.\r\n *\r\n * @private\r\n */\r\n this._pickObject = options.pickObject;\r\n this._allowPicking = defaultValue(options.allowPicking, true);\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n /**\r\n * The currently playing glTF animations.\r\n *\r\n * @type {ModelAnimationCollection}\r\n */\r\n this.activeAnimations = new ModelAnimationCollection(this);\r\n\r\n /**\r\n * Determines if the model's animations should hold a pose over frames where no keyframes are specified.\r\n *\r\n * @type {Boolean}\r\n */\r\n this.clampAnimations = defaultValue(options.clampAnimations, true);\r\n\r\n this._defaultTexture = undefined;\r\n this._incrementallyLoadTextures = defaultValue(\r\n options.incrementallyLoadTextures,\r\n true\r\n );\r\n this._asynchronous = defaultValue(options.asynchronous, true);\r\n\r\n /**\r\n * Determines whether the model casts or receives shadows from light sources.\r\n *\r\n * @type {ShadowMode}\r\n *\r\n * @default ShadowMode.ENABLED\r\n */\r\n this.shadows = defaultValue(options.shadows, ShadowMode.ENABLED);\r\n this._shadows = this.shadows;\r\n\r\n /**\r\n * A color that blends with the model's rendered color.\r\n *\r\n * @type {Color}\r\n *\r\n * @default Color.WHITE\r\n */\r\n this.color = Color.clone(defaultValue(options.color, Color.WHITE));\r\n this._colorPreviousAlpha = 1.0;\r\n\r\n /**\r\n * Defines how the color blends with the model.\r\n *\r\n * @type {ColorBlendMode}\r\n *\r\n * @default ColorBlendMode.HIGHLIGHT\r\n */\r\n this.colorBlendMode = defaultValue(\r\n options.colorBlendMode,\r\n ColorBlendMode.HIGHLIGHT\r\n );\r\n\r\n /**\r\n * Value used to determine the color strength when the colorBlendMode is MIX.\r\n * A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with\r\n * any value in-between resulting in a mix of the two.\r\n *\r\n * @type {Number}\r\n *\r\n * @default 0.5\r\n */\r\n this.colorBlendAmount = defaultValue(options.colorBlendAmount, 0.5);\r\n\r\n this._colorShadingEnabled = false;\r\n\r\n this._clippingPlanes = undefined;\r\n this.clippingPlanes = options.clippingPlanes;\r\n // Used for checking if shaders need to be regenerated due to clipping plane changes.\r\n this._clippingPlanesState = 0;\r\n\r\n // If defined, use this matrix to transform miscellaneous properties like\r\n // clipping planes and IBL instead of the modelMatrix. This is so that when\r\n // models are part of a tileset these properties get transformed relative to\r\n // a common reference (such as the root).\r\n this.referenceMatrix = undefined;\r\n\r\n /**\r\n * Whether to cull back-facing geometry. When true, back face culling is\r\n * determined by the material's doubleSided property; when false, back face\r\n * culling is disabled. Back faces are not culled if {@link Model#color} is\r\n * translucent or {@link Model#silhouetteSize} is greater than 0.0.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n this.backFaceCulling = defaultValue(options.backFaceCulling, true);\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the model. A glTF primitive corresponds\r\n * to one draw command. A glTF mesh has an array of primitives, often of length one.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n this._debugShowBoundingVolume = false;\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the model in wireframe.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugWireframe = defaultValue(options.debugWireframe, false);\r\n this._debugWireframe = false;\r\n\r\n this._distanceDisplayCondition = options.distanceDisplayCondition;\r\n\r\n // Undocumented options\r\n this._addBatchIdToGeneratedShaders = options.addBatchIdToGeneratedShaders;\r\n this._precreatedAttributes = options.precreatedAttributes;\r\n this._vertexShaderLoaded = options.vertexShaderLoaded;\r\n this._fragmentShaderLoaded = options.fragmentShaderLoaded;\r\n this._uniformMapLoaded = options.uniformMapLoaded;\r\n this._pickIdLoaded = options.pickIdLoaded;\r\n this._ignoreCommands = defaultValue(options.ignoreCommands, false);\r\n this._requestType = options.requestType;\r\n this._upAxis = defaultValue(options.upAxis, Axis.Y);\r\n this._gltfForwardAxis = Axis.Z;\r\n this._forwardAxis = options.forwardAxis;\r\n\r\n /**\r\n * @private\r\n * @readonly\r\n */\r\n this.cull = defaultValue(options.cull, true);\r\n\r\n /**\r\n * @private\r\n * @readonly\r\n */\r\n this.opaquePass = defaultValue(options.opaquePass, Pass.OPAQUE);\r\n\r\n this._computedModelMatrix = new Matrix4(); // Derived from modelMatrix and scale\r\n this._clippingPlanesMatrix = Matrix4.clone(Matrix4.IDENTITY); // Derived from reference matrix and the current view matrix\r\n this._iblReferenceFrameMatrix = Matrix3.clone(Matrix3.IDENTITY); // Derived from reference matrix and the current view matrix\r\n this._initialRadius = undefined; // Radius without model's scale property, model-matrix scale, animations, or skins\r\n this._boundingSphere = undefined;\r\n this._scaledBoundingSphere = new BoundingSphere();\r\n this._state = ModelState.NEEDS_LOAD;\r\n this._loadResources = undefined;\r\n\r\n this._mode = undefined;\r\n\r\n this._perNodeShowDirty = false; // true when the Cesium API was used to change a node's show property\r\n this._cesiumAnimationsDirty = false; // true when the Cesium API, not a glTF animation, changed a node transform\r\n this._dirty = false; // true when the model was transformed this frame\r\n this._maxDirtyNumber = 0; // Used in place of a dirty boolean flag to avoid an extra graph traversal\r\n\r\n this._runtime = {\r\n animations: undefined,\r\n articulationsByName: undefined,\r\n articulationsByStageKey: undefined,\r\n stagesByKey: undefined,\r\n rootNodes: undefined,\r\n nodes: undefined, // Indexed with the node's index\r\n nodesByName: undefined, // Indexed with name property in the node\r\n skinnedNodes: undefined,\r\n meshesByName: undefined, // Indexed with the name property in the mesh\r\n materialsByName: undefined, // Indexed with the name property in the material\r\n materialsById: undefined, // Indexed with the material's index\r\n };\r\n\r\n this._uniformMaps = {}; // Not cached since it can be targeted by glTF animation\r\n this._extensionsUsed = undefined; // Cached used glTF extensions\r\n this._extensionsRequired = undefined; // Cached required glTF extensions\r\n this._quantizedUniforms = {}; // Quantized uniforms for each program for WEB3D_quantized_attributes\r\n this._programPrimitives = {};\r\n this._rendererResources = {\r\n // Cached between models with the same url/cache-key\r\n buffers: {},\r\n vertexArrays: {},\r\n programs: {},\r\n sourceShaders: {},\r\n silhouettePrograms: {},\r\n textures: {},\r\n samplers: {},\r\n renderStates: {},\r\n };\r\n this._cachedRendererResources = undefined;\r\n this._loadRendererResourcesFromCache = false;\r\n\r\n this._dequantizeInShader = defaultValue(options.dequantizeInShader, true);\r\n this._decodedData = {};\r\n\r\n this._cachedGeometryByteLength = 0;\r\n this._cachedTexturesByteLength = 0;\r\n this._geometryByteLength = 0;\r\n this._texturesByteLength = 0;\r\n this._trianglesLength = 0;\r\n\r\n // Hold references for shader reconstruction.\r\n // Hold these separately because _cachedGltf may get released (this.releaseGltfJson)\r\n this._sourceTechniques = {};\r\n this._sourcePrograms = {};\r\n this._quantizedVertexShaders = {};\r\n\r\n this._nodeCommands = [];\r\n this._pickIds = [];\r\n\r\n // CESIUM_RTC extension\r\n this._rtcCenter = undefined; // reference to either 3D or 2D\r\n this._rtcCenterEye = undefined; // in eye coordinates\r\n this._rtcCenter3D = undefined; // in world coordinates\r\n this._rtcCenter2D = undefined; // in projected world coordinates\r\n\r\n this._sourceVersion = undefined;\r\n this._sourceKHRTechniquesWebGL = undefined;\r\n\r\n this._imageBasedLightingFactor = new Cartesian2(1.0, 1.0);\r\n Cartesian2.clone(\r\n options.imageBasedLightingFactor,\r\n this._imageBasedLightingFactor\r\n );\r\n this._lightColor = Cartesian3.clone(options.lightColor);\r\n\r\n this._luminanceAtZenith = undefined;\r\n this.luminanceAtZenith = defaultValue(options.luminanceAtZenith, 0.2);\r\n\r\n this._sphericalHarmonicCoefficients = options.sphericalHarmonicCoefficients;\r\n this._specularEnvironmentMaps = options.specularEnvironmentMaps;\r\n this._shouldUpdateSpecularMapAtlas = true;\r\n this._specularEnvironmentMapAtlas = undefined;\r\n\r\n this._useDefaultSphericalHarmonics = false;\r\n this._useDefaultSpecularMaps = false;\r\n\r\n this._shouldRegenerateShaders = false;\r\n}\r\n\r\nObject.defineProperties(Model.prototype, {\r\n /**\r\n * The object for the glTF JSON, including properties with default values omitted\r\n * from the JSON provided to this model.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n *\r\n * @default undefined\r\n */\r\n gltf: {\r\n get: function () {\r\n return defined(this._cachedGltf) ? this._cachedGltf.gltf : undefined;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the glTF JSON is not stored with the model once the model is\r\n * loaded (when {@link Model#ready} is true). This saves memory when\r\n * geometry, textures, and animations are embedded in the .gltf file.\r\n * This is especially useful for cases like 3D buildings, where each .gltf model is unique\r\n * and caching the glTF JSON is not effective.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n *\r\n * @private\r\n */\r\n releaseGltfJson: {\r\n get: function () {\r\n return this._releaseGltfJson;\r\n },\r\n },\r\n\r\n /**\r\n * The key identifying this model in the model cache for glTF JSON, renderer resources, and animations.\r\n * Caching saves memory and improves loading speed when several models with the same url are created.\r\n *

\r\n * This key is automatically generated when the model is created with {@link Model.fromGltf}. If the model\r\n * is created directly from glTF JSON using the {@link Model} constructor, this key can be manually\r\n * provided; otherwise, the model will not be changed.\r\n *

\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n cacheKey: {\r\n get: function () {\r\n return this._cacheKey;\r\n },\r\n },\r\n\r\n /**\r\n * The base path that paths in the glTF JSON are relative to. The base\r\n * path is the same path as the path containing the .gltf file\r\n * minus the .gltf file, when binary, image, and shader files are\r\n * in the same directory as the .gltf. When this is '',\r\n * the app's base path is used.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n *\r\n * @default ''\r\n */\r\n basePath: {\r\n get: function () {\r\n return this._resource.url;\r\n },\r\n },\r\n\r\n /**\r\n * The model's bounding sphere in its local coordinate system. This does not take into\r\n * account glTF animations and skins nor does it take into account {@link Model#minimumPixelSize}.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {BoundingSphere}\r\n * @readonly\r\n *\r\n * @default undefined\r\n *\r\n * @exception {DeveloperError} The model is not loaded. Use Model.readyPromise or wait for Model.ready to be true.\r\n *\r\n * @example\r\n * // Center in WGS84 coordinates\r\n * var center = Cesium.Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, new Cesium.Cartesian3());\r\n */\r\n boundingSphere: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (this._state !== ModelState.LOADED) {\r\n throw new DeveloperError(\r\n \"The model is not loaded. Use Model.readyPromise or wait for Model.ready to be true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var modelMatrix = this.modelMatrix;\r\n if (\r\n this.heightReference !== HeightReference.NONE &&\r\n this._clampedModelMatrix\r\n ) {\r\n modelMatrix = this._clampedModelMatrix;\r\n }\r\n\r\n var nonUniformScale = Matrix4.getScale(\r\n modelMatrix,\r\n boundingSphereCartesian3Scratch\r\n );\r\n var scale = defined(this.maximumScale)\r\n ? Math.min(this.maximumScale, this.scale)\r\n : this.scale;\r\n Cartesian3.multiplyByScalar(nonUniformScale, scale, nonUniformScale);\r\n\r\n var scaledBoundingSphere = this._scaledBoundingSphere;\r\n scaledBoundingSphere.center = Cartesian3.multiplyComponents(\r\n this._boundingSphere.center,\r\n nonUniformScale,\r\n scaledBoundingSphere.center\r\n );\r\n scaledBoundingSphere.radius =\r\n Cartesian3.maximumComponent(nonUniformScale) * this._initialRadius;\r\n\r\n if (defined(this._rtcCenter)) {\r\n Cartesian3.add(\r\n this._rtcCenter,\r\n scaledBoundingSphere.center,\r\n scaledBoundingSphere.center\r\n );\r\n }\r\n\r\n return scaledBoundingSphere;\r\n },\r\n },\r\n\r\n /**\r\n * When true, this model is ready to render, i.e., the external binary, image,\r\n * and shader files were downloaded and the WebGL resources were created. This is set to\r\n * true right before {@link Model#readyPromise} is resolved.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the promise that will be resolved when this model is ready to render, i.e., when the external binary, image,\r\n * and shader files were downloaded and the WebGL resources were created.\r\n *

\r\n * This promise is resolved at the end of the frame before the first frame the model is rendered in.\r\n *

\r\n *\r\n * @memberof Model.prototype\r\n * @type {Promise.}\r\n * @readonly\r\n *\r\n * @example\r\n * // Play all animations at half-speed when the model is ready to render\r\n * Cesium.when(model.readyPromise).then(function(model) {\r\n * model.activeAnimations.addAll({\r\n * multiplier : 0.5\r\n * });\r\n * }).otherwise(function(error){\r\n * window.alert(error);\r\n * });\r\n *\r\n * @see Model#ready\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if model WebGL resource creation will be spread out over several frames or\r\n * block until completion once all glTF files are loaded.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n asynchronous: {\r\n get: function () {\r\n return this._asynchronous;\r\n },\r\n },\r\n\r\n /**\r\n * When true, each glTF mesh and primitive is pickable with {@link Scene#pick}. When false, GPU memory is saved.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n allowPicking: {\r\n get: function () {\r\n return this._allowPicking;\r\n },\r\n },\r\n\r\n /**\r\n * Determine if textures may continue to stream in after the model is loaded.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default true\r\n */\r\n incrementallyLoadTextures: {\r\n get: function () {\r\n return this._incrementallyLoadTextures;\r\n },\r\n },\r\n\r\n /**\r\n * Return the number of pending texture loads.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n pendingTextureLoads: {\r\n get: function () {\r\n return defined(this._loadResources)\r\n ? this._loadResources.pendingTextureLoads\r\n : 0;\r\n },\r\n },\r\n\r\n /**\r\n * Returns true if the model was transformed this frame\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n dirty: {\r\n get: function () {\r\n return this._dirty;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the condition specifying at what distance from the camera that this model will be displayed.\r\n * @memberof Model.prototype\r\n * @type {DistanceDisplayCondition}\r\n * @default undefined\r\n */\r\n distanceDisplayCondition: {\r\n get: function () {\r\n return this._distanceDisplayCondition;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\"far must be greater than near\");\r\n }\r\n //>>includeEnd('debug');\r\n this._distanceDisplayCondition = DistanceDisplayCondition.clone(\r\n value,\r\n this._distanceDisplayCondition\r\n );\r\n },\r\n },\r\n\r\n extensionsUsed: {\r\n get: function () {\r\n if (!defined(this._extensionsUsed)) {\r\n this._extensionsUsed = ModelUtility.getUsedExtensions(this.gltf);\r\n }\r\n return this._extensionsUsed;\r\n },\r\n },\r\n\r\n extensionsRequired: {\r\n get: function () {\r\n if (!defined(this._extensionsRequired)) {\r\n this._extensionsRequired = ModelUtility.getRequiredExtensions(\r\n this.gltf\r\n );\r\n }\r\n return this._extensionsRequired;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's up-axis.\r\n * By default models are y-up according to the glTF spec, however geo-referenced models will typically be z-up.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Number}\r\n * @default Axis.Y\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n upAxis: {\r\n get: function () {\r\n return this._upAxis;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's forward axis.\r\n * By default, glTF 2.0 models are z-forward according to the glTF spec, however older\r\n * glTF (1.0, 0.8) models used x-forward. Note that only Axis.X and Axis.Z are supported.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Number}\r\n * @default Axis.Z\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n forwardAxis: {\r\n get: function () {\r\n if (defined(this._forwardAxis)) {\r\n return this._forwardAxis;\r\n }\r\n return this._gltfForwardAxis;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's triangle count.\r\n *\r\n * @private\r\n */\r\n trianglesLength: {\r\n get: function () {\r\n return this._trianglesLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's geometry memory in bytes. This includes all vertex and index buffers.\r\n *\r\n * @private\r\n */\r\n geometryByteLength: {\r\n get: function () {\r\n return this._geometryByteLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's texture memory in bytes.\r\n *\r\n * @private\r\n */\r\n texturesByteLength: {\r\n get: function () {\r\n return this._texturesByteLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's cached geometry memory in bytes. This includes all vertex and index buffers.\r\n *\r\n * @private\r\n */\r\n cachedGeometryByteLength: {\r\n get: function () {\r\n return this._cachedGeometryByteLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the model's cached texture memory in bytes.\r\n *\r\n * @private\r\n */\r\n cachedTexturesByteLength: {\r\n get: function () {\r\n return this._cachedTexturesByteLength;\r\n },\r\n },\r\n\r\n /**\r\n * The {@link ClippingPlaneCollection} used to selectively disable rendering the model.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {ClippingPlaneCollection}\r\n */\r\n clippingPlanes: {\r\n get: function () {\r\n return this._clippingPlanes;\r\n },\r\n set: function (value) {\r\n if (value === this._clippingPlanes) {\r\n return;\r\n }\r\n // Handle destroying, checking of unknown, checking for existing ownership\r\n ClippingPlaneCollection.setOwner(value, this, \"_clippingPlanes\");\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n pickIds: {\r\n get: function () {\r\n return this._pickIds;\r\n },\r\n },\r\n\r\n /**\r\n * Cesium adds lighting from the earth, sky, atmosphere, and star skybox. This cartesian is used to scale the final\r\n * diffuse and specular lighting contribution from those sources to the final color. A value of 0.0 will disable those light sources.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Cartesian2}\r\n * @default Cartesian2(1.0, 1.0)\r\n */\r\n imageBasedLightingFactor: {\r\n get: function () {\r\n return this._imageBasedLightingFactor;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"imageBasedLightingFactor\", value);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"imageBasedLightingFactor.x\",\r\n value.x,\r\n 0.0\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"imageBasedLightingFactor.x\",\r\n value.x,\r\n 1.0\r\n );\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"imageBasedLightingFactor.y\",\r\n value.y,\r\n 0.0\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"imageBasedLightingFactor.y\",\r\n value.y,\r\n 1.0\r\n );\r\n //>>includeEnd('debug');\r\n var imageBasedLightingFactor = this._imageBasedLightingFactor;\r\n if (\r\n value === imageBasedLightingFactor ||\r\n Cartesian2.equals(value, imageBasedLightingFactor)\r\n ) {\r\n return;\r\n }\r\n this._shouldRegenerateShaders =\r\n this._shouldRegenerateShaders ||\r\n (this._imageBasedLightingFactor.x > 0.0 && value.x === 0.0) ||\r\n (this._imageBasedLightingFactor.x === 0.0 && value.x > 0.0);\r\n this._shouldRegenerateShaders =\r\n this._shouldRegenerateShaders ||\r\n (this._imageBasedLightingFactor.y > 0.0 && value.y === 0.0) ||\r\n (this._imageBasedLightingFactor.y === 0.0 && value.y > 0.0);\r\n Cartesian2.clone(value, this._imageBasedLightingFactor);\r\n },\r\n },\r\n\r\n /**\r\n * The light color when shading the model. When undefined the scene's light color is used instead.\r\n *

\r\n * For example, disabling additional light sources by setting model.imageBasedLightingFactor = new Cesium.Cartesian2(0.0, 0.0) will make the\r\n * model much darker. Here, increasing the intensity of the light source will make the model brighter.\r\n *

\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Cartesian3}\r\n * @default undefined\r\n */\r\n lightColor: {\r\n get: function () {\r\n return this._lightColor;\r\n },\r\n set: function (value) {\r\n var lightColor = this._lightColor;\r\n if (value === lightColor || Cartesian3.equals(value, lightColor)) {\r\n return;\r\n }\r\n this._shouldRegenerateShaders =\r\n this._shouldRegenerateShaders ||\r\n (defined(lightColor) && !defined(value)) ||\r\n (defined(value) && !defined(lightColor));\r\n this._lightColor = Cartesian3.clone(value, lightColor);\r\n },\r\n },\r\n\r\n /**\r\n * The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map.\r\n * This is used when {@link Model#specularEnvironmentMaps} and {@link Model#sphericalHarmonicCoefficients} are not defined.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Image-Based Lighting.html|Sandcastle Image Based Lighting Demo}\r\n * @type {Number}\r\n * @default 0.2\r\n */\r\n luminanceAtZenith: {\r\n get: function () {\r\n return this._luminanceAtZenith;\r\n },\r\n set: function (value) {\r\n var lum = this._luminanceAtZenith;\r\n if (value === lum) {\r\n return;\r\n }\r\n this._shouldRegenerateShaders =\r\n this._shouldRegenerateShaders ||\r\n (defined(lum) && !defined(value)) ||\r\n (defined(value) && !defined(lum));\r\n this._luminanceAtZenith = value;\r\n },\r\n },\r\n\r\n /**\r\n * The third order spherical harmonic coefficients used for the diffuse color of image-based lighting. When undefined, a diffuse irradiance\r\n * computed from the atmosphere color is used.\r\n *

\r\n * There are nine Cartesian3 coefficients.\r\n * The order of the coefficients is: L00, L1-1, L10, L11, L2-2, L2-1, L20, L21, L22\r\n *

\r\n *\r\n * These values can be obtained by preprocessing the environment map using the cmgen tool of\r\n * {@link https://github.com/google/filament/releases|Google's Filament project}. This will also generate a KTX file that can be\r\n * supplied to {@link Model#specularEnvironmentMaps}.\r\n *\r\n * @memberof Model.prototype\r\n *\r\n * @type {Cartesian3[]}\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Image-Based Lighting.html|Sandcastle Image Based Lighting Demo}\r\n * @see {@link https://graphics.stanford.edu/papers/envmap/envmap.pdf|An Efficient Representation for Irradiance Environment Maps}\r\n */\r\n sphericalHarmonicCoefficients: {\r\n get: function () {\r\n return this._sphericalHarmonicCoefficients;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && (!Array.isArray(value) || value.length !== 9)) {\r\n throw new DeveloperError(\r\n \"sphericalHarmonicCoefficients must be an array of 9 Cartesian3 values.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n if (value === this._sphericalHarmonicCoefficients) {\r\n return;\r\n }\r\n this._sphericalHarmonicCoefficients = value;\r\n this._shouldRegenerateShaders = true;\r\n },\r\n },\r\n\r\n /**\r\n * A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.\r\n *\r\n * @memberof Model.prototype\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Image-Based Lighting.html|Sandcastle Image Based Lighting Demo}\r\n * @type {String}\r\n * @see Model#sphericalHarmonicCoefficients\r\n */\r\n specularEnvironmentMaps: {\r\n get: function () {\r\n return this._specularEnvironmentMaps;\r\n },\r\n set: function (value) {\r\n this._shouldUpdateSpecularMapAtlas =\r\n this._shouldUpdateSpecularMapAtlas ||\r\n value !== this._specularEnvironmentMaps;\r\n this._specularEnvironmentMaps = value;\r\n },\r\n },\r\n /**\r\n * Gets the credit that will be displayed for the model\r\n * @memberof Model.prototype\r\n * @type {Credit}\r\n */\r\n credit: {\r\n get: function () {\r\n return this._credit;\r\n },\r\n },\r\n});\r\n\r\nfunction silhouetteSupported(context) {\r\n return context.stencilBuffer;\r\n}\r\n\r\nfunction isColorShadingEnabled(model) {\r\n return (\r\n !Color.equals(model.color, Color.WHITE) ||\r\n model.colorBlendMode !== ColorBlendMode.HIGHLIGHT\r\n );\r\n}\r\n\r\nfunction isClippingEnabled(model) {\r\n var clippingPlanes = model._clippingPlanes;\r\n return (\r\n defined(clippingPlanes) &&\r\n clippingPlanes.enabled &&\r\n clippingPlanes.length !== 0\r\n );\r\n}\r\n\r\n/**\r\n * Determines if silhouettes are supported.\r\n *\r\n * @param {Scene} scene The scene.\r\n * @returns {Boolean} true if silhouettes are supported; otherwise, returns false\r\n */\r\nModel.silhouetteSupported = function (scene) {\r\n return silhouetteSupported(scene.context);\r\n};\r\n\r\nfunction containsGltfMagic(uint8Array) {\r\n var magic = getMagic(uint8Array);\r\n return magic === \"glTF\";\r\n}\r\n\r\n/**\r\n *

\r\n * Creates a model from a glTF asset. When the model is ready to render, i.e., when the external binary, image,\r\n * and shader files are downloaded and the WebGL resources are created, the {@link Model#readyPromise} is resolved.\r\n *

\r\n *

\r\n * The model can be a traditional glTF asset with a .gltf extension or a Binary glTF using the .glb extension.\r\n *

\r\n *

\r\n * Cesium supports glTF assets with the following extensions:\r\n *

    \r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Khronos/KHR_binary_glTF/README.md|KHR_binary_glTF (glTF 1.0)}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Khronos/KHR_materials_common/README.md|KHR_materials_common (glTF 1.0)}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Vendor/WEB3D_quantized_attributes/README.md|WEB3D_quantized_attributes (glTF 1.0)}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/AGI_articulations/README.md|AGI_articulations}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/pull/1302|KHR_blend (draft)}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md|KHR_draco_mesh_compression}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness/README.md|KHR_materials_pbrSpecularGlossiness}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit/README.md|KHR_materials_unlit}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_techniques_webgl/README.md|KHR_techniques_webgl}\r\n *
  • \r\n * {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/2.0/Khronos/KHR_texture_transform/README.md|KHR_texture_transform}\r\n *
  • \r\n *
\r\n *

\r\n *

\r\n * For high-precision rendering, Cesium supports the {@link https://github.com/KhronosGroup/glTF/blob/master/extensions/1.0/Vendor/CESIUM_RTC/README.md|CESIUM_RTC} extension, which introduces the\r\n * CESIUM_RTC_MODELVIEW parameter semantic that says the node is in WGS84 coordinates translated\r\n * relative to a local origin.\r\n *

\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Resource|String} options.url The url to the .gltf file.\r\n * @param {Resource|String} [options.basePath] The base path that paths in the glTF JSON are relative to.\r\n * @param {Boolean} [options.show=true] Determines if the model primitive will be shown.\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms the model from model to world coordinates.\r\n * @param {Number} [options.scale=1.0] A uniform scale applied to this model.\r\n * @param {Number} [options.minimumPixelSize=0.0] The approximate minimum pixel size of the model regardless of zoom.\r\n * @param {Number} [options.maximumScale] The maximum scale for the model.\r\n * @param {Object} [options.id] A user-defined object to return when the model is picked with {@link Scene#pick}.\r\n * @param {Boolean} [options.allowPicking=true] When true, each glTF mesh and primitive is pickable with {@link Scene#pick}.\r\n * @param {Boolean} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded.\r\n * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded.\r\n * @param {Boolean} [options.clampAnimations=true] Determines if the model's animations should hold a pose over frames where no keyframes are specified.\r\n * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from light sources.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each draw command in the model.\r\n * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe.\r\n * @param {HeightReference} [options.heightReference=HeightReference.NONE] Determines how the model is drawn relative to terrain.\r\n * @param {Scene} [options.scene] Must be passed in for models that use the height reference property.\r\n * @param {DistanceDisplayCondition} [options.distanceDisplayCondition] The condition specifying at what distance from the camera that this model will be displayed.\r\n * @param {Color} [options.color=Color.WHITE] A color that blends with the model's rendered color.\r\n * @param {ColorBlendMode} [options.colorBlendMode=ColorBlendMode.HIGHLIGHT] Defines how the color blends with the model.\r\n * @param {Number} [options.colorBlendAmount=0.5] Value used to determine the color strength when the colorBlendMode is MIX. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.\r\n * @param {Color} [options.silhouetteColor=Color.RED] The silhouette color. If more than 256 models have silhouettes enabled, there is a small chance that overlapping models will have minor artifacts.\r\n * @param {Number} [options.silhouetteSize=0.0] The size of the silhouette in pixels.\r\n * @param {ClippingPlaneCollection} [options.clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the model.\r\n * @param {Boolean} [options.dequantizeInShader=true] Determines if a {@link https://github.com/google/draco|Draco} encoded model is dequantized on the GPU. This decreases total memory usage for encoded models.\r\n * @param {Credit|String} [options.credit] A credit for the model, which is displayed on the canvas.\r\n * @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the material's doubleSided property; when false, back face culling is disabled. Back faces are not culled if {@link Model#color} is translucent or {@link Model#silhouetteSize} is greater than 0.0.\r\n *\r\n * @returns {Model} The newly created model.\r\n *\r\n * @example\r\n * // Example 1. Create a model from a glTF asset\r\n * var model = scene.primitives.add(Cesium.Model.fromGltf({\r\n * url : './duck/duck.gltf'\r\n * }));\r\n *\r\n * @example\r\n * // Example 2. Create model and provide all properties and events\r\n * var origin = Cesium.Cartesian3.fromDegrees(-95.0, 40.0, 200000.0);\r\n * var modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(origin);\r\n *\r\n * var model = scene.primitives.add(Cesium.Model.fromGltf({\r\n * url : './duck/duck.gltf',\r\n * show : true, // default\r\n * modelMatrix : modelMatrix,\r\n * scale : 2.0, // double size\r\n * minimumPixelSize : 128, // never smaller than 128 pixels\r\n * maximumScale: 20000, // never larger than 20000 * model size (overrides minimumPixelSize)\r\n * allowPicking : false, // not pickable\r\n * debugShowBoundingVolume : false, // default\r\n * debugWireframe : false\r\n * }));\r\n *\r\n * model.readyPromise.then(function(model) {\r\n * // Play all animations when the model is ready to render\r\n * model.activeAnimations.addAll();\r\n * });\r\n */\r\nModel.fromGltf = function (options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options) || !defined(options.url)) {\r\n throw new DeveloperError(\"options.url is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var url = options.url;\r\n options = clone(options);\r\n\r\n // Create resource for the model file\r\n var modelResource = Resource.createIfNeeded(url);\r\n\r\n // Setup basePath to get dependent files\r\n var basePath = defaultValue(options.basePath, modelResource.clone());\r\n var resource = Resource.createIfNeeded(basePath);\r\n\r\n // If no cache key is provided, use a GUID.\r\n // Check using a URI to GUID dictionary that we have not already added this model.\r\n var cacheKey = defaultValue(\r\n options.cacheKey,\r\n uriToGuid[getAbsoluteUri(modelResource.url)]\r\n );\r\n if (!defined(cacheKey)) {\r\n cacheKey = createGuid();\r\n uriToGuid[getAbsoluteUri(modelResource.url)] = cacheKey;\r\n }\r\n\r\n if (defined(options.basePath) && !defined(options.cacheKey)) {\r\n cacheKey += resource.url;\r\n }\r\n options.cacheKey = cacheKey;\r\n options.basePath = resource;\r\n\r\n var model = new Model(options);\r\n\r\n var cachedGltf = gltfCache[cacheKey];\r\n if (!defined(cachedGltf)) {\r\n cachedGltf = new CachedGltf({\r\n ready: false,\r\n });\r\n cachedGltf.count = 1;\r\n cachedGltf.modelsToLoad.push(model);\r\n setCachedGltf(model, cachedGltf);\r\n gltfCache[cacheKey] = cachedGltf;\r\n\r\n // Add Accept header if we need it\r\n if (!defined(modelResource.headers.Accept)) {\r\n modelResource.headers.Accept = defaultModelAccept;\r\n }\r\n\r\n modelResource\r\n .fetchArrayBuffer()\r\n .then(function (arrayBuffer) {\r\n var array = new Uint8Array(arrayBuffer);\r\n if (containsGltfMagic(array)) {\r\n // Load binary glTF\r\n var parsedGltf = parseGlb(array);\r\n cachedGltf.makeReady(parsedGltf);\r\n } else {\r\n // Load text (JSON) glTF\r\n var json = getJsonFromTypedArray(array);\r\n cachedGltf.makeReady(json);\r\n }\r\n\r\n var resourceCredits = model._resourceCredits;\r\n var credits = modelResource.credits;\r\n if (defined(credits)) {\r\n var length = credits.length;\r\n for (var i = 0; i < length; i++) {\r\n resourceCredits.push(credits[i]);\r\n }\r\n }\r\n })\r\n .otherwise(\r\n ModelUtility.getFailedLoadFunction(model, \"model\", modelResource.url)\r\n );\r\n } else if (!cachedGltf.ready) {\r\n // Cache hit but the fetchArrayBuffer() or fetchText() request is still pending\r\n ++cachedGltf.count;\r\n cachedGltf.modelsToLoad.push(model);\r\n }\r\n // else if the cached glTF is defined and ready, the\r\n // model constructor will pick it up using the cache key.\r\n\r\n return model;\r\n};\r\n\r\n/**\r\n * For the unit tests to verify model caching.\r\n *\r\n * @private\r\n */\r\nModel._gltfCache = gltfCache;\r\n\r\nfunction getRuntime(model, runtimeName, name) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (model._state !== ModelState.LOADED) {\r\n throw new DeveloperError(\r\n \"The model is not loaded. Use Model.readyPromise or wait for Model.ready to be true.\"\r\n );\r\n }\r\n\r\n if (!defined(name)) {\r\n throw new DeveloperError(\"name is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return model._runtime[runtimeName][name];\r\n}\r\n\r\n/**\r\n * Returns the glTF node with the given name property. This is used to\r\n * modify a node's transform for animation outside of glTF animations.\r\n *\r\n * @param {String} name The glTF name of the node.\r\n * @returns {ModelNode} The node or undefined if no node with name exists.\r\n *\r\n * @exception {DeveloperError} The model is not loaded. Use Model.readyPromise or wait for Model.ready to be true.\r\n *\r\n * @example\r\n * // Apply non-uniform scale to node LOD3sp\r\n * var node = model.getNode('LOD3sp');\r\n * node.matrix = Cesium.Matrix4.fromScale(new Cesium.Cartesian3(5.0, 1.0, 1.0), node.matrix);\r\n */\r\nModel.prototype.getNode = function (name) {\r\n var node = getRuntime(this, \"nodesByName\", name);\r\n return defined(node) ? node.publicNode : undefined;\r\n};\r\n\r\n/**\r\n * Returns the glTF mesh with the given name property.\r\n *\r\n * @param {String} name The glTF name of the mesh.\r\n *\r\n * @returns {ModelMesh} The mesh or undefined if no mesh with name exists.\r\n *\r\n * @exception {DeveloperError} The model is not loaded. Use Model.readyPromise or wait for Model.ready to be true.\r\n */\r\nModel.prototype.getMesh = function (name) {\r\n return getRuntime(this, \"meshesByName\", name);\r\n};\r\n\r\n/**\r\n * Returns the glTF material with the given name property.\r\n *\r\n * @param {String} name The glTF name of the material.\r\n * @returns {ModelMaterial} The material or undefined if no material with name exists.\r\n *\r\n * @exception {DeveloperError} The model is not loaded. Use Model.readyPromise or wait for Model.ready to be true.\r\n */\r\nModel.prototype.getMaterial = function (name) {\r\n return getRuntime(this, \"materialsByName\", name);\r\n};\r\n\r\n/**\r\n * Sets the current value of an articulation stage. After setting one or multiple stage values, call\r\n * Model.applyArticulations() to cause the node matrices to be recalculated.\r\n *\r\n * @param {String} articulationStageKey The name of the articulation, a space, and the name of the stage.\r\n * @param {Number} value The numeric value of this stage of the articulation.\r\n *\r\n * @exception {DeveloperError} The model is not loaded. Use Model.readyPromise or wait for Model.ready to be true.\r\n *\r\n * @see Model#applyArticulations\r\n */\r\nModel.prototype.setArticulationStage = function (articulationStageKey, value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number(\"value\", value);\r\n //>>includeEnd('debug');\r\n\r\n var stage = getRuntime(this, \"stagesByKey\", articulationStageKey);\r\n var articulation = getRuntime(\r\n this,\r\n \"articulationsByStageKey\",\r\n articulationStageKey\r\n );\r\n if (defined(stage) && defined(articulation)) {\r\n value = CesiumMath.clamp(value, stage.minimumValue, stage.maximumValue);\r\n if (\r\n !CesiumMath.equalsEpsilon(stage.currentValue, value, articulationEpsilon)\r\n ) {\r\n stage.currentValue = value;\r\n articulation.isDirty = true;\r\n }\r\n }\r\n};\r\n\r\nvar scratchArticulationCartesian = new Cartesian3();\r\nvar scratchArticulationRotation = new Matrix3();\r\n\r\n/**\r\n * Modifies a Matrix4 by applying a transformation for a given value of a stage. Note this is different usage\r\n * from the typical result parameter, in that the incoming value of result is\r\n * meaningful. Various stages of an articulation can be multiplied together, so their\r\n * transformations are all merged into a composite Matrix4 representing them all.\r\n *\r\n * @param {object} stage The stage of an articulation that is being evaluated.\r\n * @param {Matrix4} result The matrix to be modified.\r\n * @returns {Matrix4} A matrix transformed as requested by the articulation stage.\r\n *\r\n * @private\r\n */\r\nfunction applyArticulationStageMatrix(stage, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"stage\", stage);\r\n Check.typeOf.object(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var value = stage.currentValue;\r\n var cartesian = scratchArticulationCartesian;\r\n var rotation;\r\n switch (stage.type) {\r\n case \"xRotate\":\r\n rotation = Matrix3.fromRotationX(\r\n CesiumMath.toRadians(value),\r\n scratchArticulationRotation\r\n );\r\n Matrix4.multiplyByMatrix3(result, rotation, result);\r\n break;\r\n case \"yRotate\":\r\n rotation = Matrix3.fromRotationY(\r\n CesiumMath.toRadians(value),\r\n scratchArticulationRotation\r\n );\r\n Matrix4.multiplyByMatrix3(result, rotation, result);\r\n break;\r\n case \"zRotate\":\r\n rotation = Matrix3.fromRotationZ(\r\n CesiumMath.toRadians(value),\r\n scratchArticulationRotation\r\n );\r\n Matrix4.multiplyByMatrix3(result, rotation, result);\r\n break;\r\n case \"xTranslate\":\r\n cartesian.x = value;\r\n cartesian.y = 0.0;\r\n cartesian.z = 0.0;\r\n Matrix4.multiplyByTranslation(result, cartesian, result);\r\n break;\r\n case \"yTranslate\":\r\n cartesian.x = 0.0;\r\n cartesian.y = value;\r\n cartesian.z = 0.0;\r\n Matrix4.multiplyByTranslation(result, cartesian, result);\r\n break;\r\n case \"zTranslate\":\r\n cartesian.x = 0.0;\r\n cartesian.y = 0.0;\r\n cartesian.z = value;\r\n Matrix4.multiplyByTranslation(result, cartesian, result);\r\n break;\r\n case \"xScale\":\r\n cartesian.x = value;\r\n cartesian.y = 1.0;\r\n cartesian.z = 1.0;\r\n Matrix4.multiplyByScale(result, cartesian, result);\r\n break;\r\n case \"yScale\":\r\n cartesian.x = 1.0;\r\n cartesian.y = value;\r\n cartesian.z = 1.0;\r\n Matrix4.multiplyByScale(result, cartesian, result);\r\n break;\r\n case \"zScale\":\r\n cartesian.x = 1.0;\r\n cartesian.y = 1.0;\r\n cartesian.z = value;\r\n Matrix4.multiplyByScale(result, cartesian, result);\r\n break;\r\n case \"uniformScale\":\r\n Matrix4.multiplyByUniformScale(result, value, result);\r\n break;\r\n default:\r\n break;\r\n }\r\n return result;\r\n}\r\n\r\nvar scratchApplyArticulationTransform = new Matrix4();\r\n\r\n/**\r\n * Applies any modified articulation stages to the matrix of each node that participates\r\n * in any articulation. Note that this will overwrite any nodeTransformations on participating nodes.\r\n *\r\n * @exception {DeveloperError} The model is not loaded. Use Model.readyPromise or wait for Model.ready to be true.\r\n */\r\nModel.prototype.applyArticulations = function () {\r\n var articulationsByName = this._runtime.articulationsByName;\r\n for (var articulationName in articulationsByName) {\r\n if (articulationsByName.hasOwnProperty(articulationName)) {\r\n var articulation = articulationsByName[articulationName];\r\n if (articulation.isDirty) {\r\n articulation.isDirty = false;\r\n var numNodes = articulation.nodes.length;\r\n for (var n = 0; n < numNodes; ++n) {\r\n var node = articulation.nodes[n];\r\n var transform = Matrix4.clone(\r\n node.originalMatrix,\r\n scratchApplyArticulationTransform\r\n );\r\n\r\n var numStages = articulation.stages.length;\r\n for (var s = 0; s < numStages; ++s) {\r\n var stage = articulation.stages[s];\r\n transform = applyArticulationStageMatrix(stage, transform);\r\n }\r\n node.matrix = transform;\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction addBuffersToLoadResources(model) {\r\n var gltf = model.gltf;\r\n var loadResources = model._loadResources;\r\n ForEach.buffer(gltf, function (buffer, id) {\r\n loadResources.buffers[id] = buffer.extras._pipeline.source;\r\n });\r\n}\r\n\r\nfunction bufferLoad(model, id) {\r\n return function (arrayBuffer) {\r\n var loadResources = model._loadResources;\r\n var buffer = new Uint8Array(arrayBuffer);\r\n --loadResources.pendingBufferLoads;\r\n model.gltf.buffers[id].extras._pipeline.source = buffer;\r\n };\r\n}\r\n\r\nfunction parseBufferViews(model) {\r\n var bufferViews = model.gltf.bufferViews;\r\n var vertexBuffersToCreate = model._loadResources.vertexBuffersToCreate;\r\n\r\n // Only ARRAY_BUFFER here. ELEMENT_ARRAY_BUFFER created below.\r\n ForEach.bufferView(model.gltf, function (bufferView, id) {\r\n if (bufferView.target === WebGLConstants.ARRAY_BUFFER) {\r\n vertexBuffersToCreate.enqueue(id);\r\n }\r\n });\r\n\r\n var indexBuffersToCreate = model._loadResources.indexBuffersToCreate;\r\n var indexBufferIds = {};\r\n\r\n // The Cesium Renderer requires knowing the datatype for an index buffer\r\n // at creation type, which is not part of the glTF bufferview so loop\r\n // through glTF accessors to create the bufferview's index buffer.\r\n ForEach.accessor(model.gltf, function (accessor) {\r\n var bufferViewId = accessor.bufferView;\r\n if (!defined(bufferViewId)) {\r\n return;\r\n }\r\n\r\n var bufferView = bufferViews[bufferViewId];\r\n if (\r\n bufferView.target === WebGLConstants.ELEMENT_ARRAY_BUFFER &&\r\n !defined(indexBufferIds[bufferViewId])\r\n ) {\r\n indexBufferIds[bufferViewId] = true;\r\n indexBuffersToCreate.enqueue({\r\n id: bufferViewId,\r\n componentType: accessor.componentType,\r\n });\r\n }\r\n });\r\n}\r\n\r\nfunction parseTechniques(model) {\r\n // retain references to gltf techniques\r\n var gltf = model.gltf;\r\n if (!hasExtension(gltf, \"KHR_techniques_webgl\")) {\r\n return;\r\n }\r\n\r\n var sourcePrograms = model._sourcePrograms;\r\n var sourceTechniques = model._sourceTechniques;\r\n var programs = gltf.extensions.KHR_techniques_webgl.programs;\r\n\r\n ForEach.technique(gltf, function (technique, techniqueId) {\r\n sourceTechniques[techniqueId] = clone(technique);\r\n\r\n var programId = technique.program;\r\n if (!defined(sourcePrograms[programId])) {\r\n sourcePrograms[programId] = clone(programs[programId]);\r\n }\r\n });\r\n}\r\n\r\nfunction shaderLoad(model, type, id) {\r\n return function (source) {\r\n var loadResources = model._loadResources;\r\n loadResources.shaders[id] = {\r\n source: source,\r\n type: type,\r\n bufferView: undefined,\r\n };\r\n --loadResources.pendingShaderLoads;\r\n model._rendererResources.sourceShaders[id] = source;\r\n };\r\n}\r\n\r\nfunction parseShaders(model) {\r\n var gltf = model.gltf;\r\n var buffers = gltf.buffers;\r\n var bufferViews = gltf.bufferViews;\r\n var sourceShaders = model._rendererResources.sourceShaders;\r\n ForEach.shader(gltf, function (shader, id) {\r\n // Shader references either uri (external or base64-encoded) or bufferView\r\n if (defined(shader.bufferView)) {\r\n var bufferViewId = shader.bufferView;\r\n var bufferView = bufferViews[bufferViewId];\r\n var bufferId = bufferView.buffer;\r\n var buffer = buffers[bufferId];\r\n var source = getStringFromTypedArray(\r\n buffer.extras._pipeline.source,\r\n bufferView.byteOffset,\r\n bufferView.byteLength\r\n );\r\n sourceShaders[id] = source;\r\n } else if (defined(shader.extras._pipeline.source)) {\r\n sourceShaders[id] = shader.extras._pipeline.source;\r\n } else {\r\n ++model._loadResources.pendingShaderLoads;\r\n\r\n var shaderResource = model._resource.getDerivedResource({\r\n url: shader.uri,\r\n });\r\n\r\n shaderResource\r\n .fetchText()\r\n .then(shaderLoad(model, shader.type, id))\r\n .otherwise(\r\n ModelUtility.getFailedLoadFunction(\r\n model,\r\n \"shader\",\r\n shaderResource.url\r\n )\r\n );\r\n }\r\n });\r\n}\r\n\r\nfunction parsePrograms(model) {\r\n var sourceTechniques = model._sourceTechniques;\r\n for (var techniqueId in sourceTechniques) {\r\n if (sourceTechniques.hasOwnProperty(techniqueId)) {\r\n var technique = sourceTechniques[techniqueId];\r\n model._loadResources.programsToCreate.enqueue({\r\n programId: technique.program,\r\n techniqueId: techniqueId,\r\n });\r\n }\r\n }\r\n}\r\n\r\nfunction parseArticulations(model) {\r\n var articulationsByName = {};\r\n var articulationsByStageKey = {};\r\n var runtimeStagesByKey = {};\r\n\r\n model._runtime.articulationsByName = articulationsByName;\r\n model._runtime.articulationsByStageKey = articulationsByStageKey;\r\n model._runtime.stagesByKey = runtimeStagesByKey;\r\n\r\n var gltf = model.gltf;\r\n if (\r\n !hasExtension(gltf, \"AGI_articulations\") ||\r\n !defined(gltf.extensions) ||\r\n !defined(gltf.extensions.AGI_articulations)\r\n ) {\r\n return;\r\n }\r\n\r\n var gltfArticulations = gltf.extensions.AGI_articulations.articulations;\r\n if (!defined(gltfArticulations)) {\r\n return;\r\n }\r\n\r\n var numArticulations = gltfArticulations.length;\r\n for (var i = 0; i < numArticulations; ++i) {\r\n var articulation = clone(gltfArticulations[i]);\r\n articulation.nodes = [];\r\n articulation.isDirty = true;\r\n articulationsByName[articulation.name] = articulation;\r\n\r\n var numStages = articulation.stages.length;\r\n for (var s = 0; s < numStages; ++s) {\r\n var stage = articulation.stages[s];\r\n stage.currentValue = stage.initialValue;\r\n\r\n var stageKey = articulation.name + \" \" + stage.name;\r\n articulationsByStageKey[stageKey] = articulation;\r\n runtimeStagesByKey[stageKey] = stage;\r\n }\r\n }\r\n}\r\n\r\nfunction imageLoad(model, textureId) {\r\n return function (image) {\r\n var loadResources = model._loadResources;\r\n --loadResources.pendingTextureLoads;\r\n loadResources.texturesToCreate.enqueue({\r\n id: textureId,\r\n image: image,\r\n bufferView: image.bufferView,\r\n width: image.width,\r\n height: image.height,\r\n internalFormat: image.internalFormat,\r\n });\r\n };\r\n}\r\n\r\nvar ktxRegex = /(^data:image\\/ktx)|(\\.ktx$)/i;\r\nvar crnRegex = /(^data:image\\/crn)|(\\.crn$)/i;\r\n\r\nfunction parseTextures(model, context, supportsWebP) {\r\n var gltf = model.gltf;\r\n var images = gltf.images;\r\n var uri;\r\n ForEach.texture(gltf, function (texture, id) {\r\n var imageId = texture.source;\r\n\r\n if (\r\n defined(texture.extensions) &&\r\n defined(texture.extensions.EXT_texture_webp) &&\r\n supportsWebP\r\n ) {\r\n imageId = texture.extensions.EXT_texture_webp.source;\r\n }\r\n\r\n var gltfImage = images[imageId];\r\n var extras = gltfImage.extras;\r\n\r\n var bufferViewId = gltfImage.bufferView;\r\n var mimeType = gltfImage.mimeType;\r\n uri = gltfImage.uri;\r\n\r\n // First check for a compressed texture\r\n if (defined(extras) && defined(extras.compressedImage3DTiles)) {\r\n var crunch = extras.compressedImage3DTiles.crunch;\r\n var s3tc = extras.compressedImage3DTiles.s3tc;\r\n var pvrtc = extras.compressedImage3DTiles.pvrtc1;\r\n var etc1 = extras.compressedImage3DTiles.etc1;\r\n\r\n if (context.s3tc && defined(crunch)) {\r\n mimeType = crunch.mimeType;\r\n if (defined(crunch.bufferView)) {\r\n bufferViewId = crunch.bufferView;\r\n } else {\r\n uri = crunch.uri;\r\n }\r\n } else if (context.s3tc && defined(s3tc)) {\r\n mimeType = s3tc.mimeType;\r\n if (defined(s3tc.bufferView)) {\r\n bufferViewId = s3tc.bufferView;\r\n } else {\r\n uri = s3tc.uri;\r\n }\r\n } else if (context.pvrtc && defined(pvrtc)) {\r\n mimeType = pvrtc.mimeType;\r\n if (defined(pvrtc.bufferView)) {\r\n bufferViewId = pvrtc.bufferView;\r\n } else {\r\n uri = pvrtc.uri;\r\n }\r\n } else if (context.etc1 && defined(etc1)) {\r\n mimeType = etc1.mimeType;\r\n if (defined(etc1.bufferView)) {\r\n bufferViewId = etc1.bufferView;\r\n } else {\r\n uri = etc1.uri;\r\n }\r\n }\r\n }\r\n\r\n // Image references either uri (external or base64-encoded) or bufferView\r\n if (defined(bufferViewId)) {\r\n model._loadResources.texturesToCreateFromBufferView.enqueue({\r\n id: id,\r\n image: undefined,\r\n bufferView: bufferViewId,\r\n mimeType: mimeType,\r\n });\r\n } else {\r\n ++model._loadResources.pendingTextureLoads;\r\n\r\n var imageResource = model._resource.getDerivedResource({\r\n url: uri,\r\n });\r\n\r\n var promise;\r\n if (ktxRegex.test(uri)) {\r\n promise = loadKTX(imageResource);\r\n } else if (crnRegex.test(uri)) {\r\n promise = loadCRN(imageResource);\r\n } else {\r\n promise = imageResource.fetchImage();\r\n }\r\n promise\r\n .then(imageLoad(model, id, imageId))\r\n .otherwise(\r\n ModelUtility.getFailedLoadFunction(model, \"image\", imageResource.url)\r\n );\r\n }\r\n });\r\n}\r\n\r\nvar scratchArticulationStageInitialTransform = new Matrix4();\r\n\r\nfunction parseNodes(model) {\r\n var runtimeNodes = {};\r\n var runtimeNodesByName = {};\r\n var skinnedNodes = [];\r\n\r\n var skinnedNodesIds = model._loadResources.skinnedNodesIds;\r\n var articulationsByName = model._runtime.articulationsByName;\r\n\r\n ForEach.node(model.gltf, function (node, id) {\r\n var runtimeNode = {\r\n // Animation targets\r\n matrix: undefined,\r\n translation: undefined,\r\n rotation: undefined,\r\n scale: undefined,\r\n\r\n // Per-node show inherited from parent\r\n computedShow: true,\r\n\r\n // Computed transforms\r\n transformToRoot: new Matrix4(),\r\n computedMatrix: new Matrix4(),\r\n dirtyNumber: 0, // The frame this node was made dirty by an animation; for graph traversal\r\n\r\n // Rendering\r\n commands: [], // empty for transform, light, and camera nodes\r\n\r\n // Skinned node\r\n inverseBindMatrices: undefined, // undefined when node is not skinned\r\n bindShapeMatrix: undefined, // undefined when node is not skinned or identity\r\n joints: [], // empty when node is not skinned\r\n computedJointMatrices: [], // empty when node is not skinned\r\n\r\n // Joint node\r\n jointName: node.jointName, // undefined when node is not a joint\r\n\r\n weights: [],\r\n\r\n // Graph pointers\r\n children: [], // empty for leaf nodes\r\n parents: [], // empty for root nodes\r\n\r\n // Publicly-accessible ModelNode instance to modify animation targets\r\n publicNode: undefined,\r\n };\r\n runtimeNode.publicNode = new ModelNode(\r\n model,\r\n node,\r\n runtimeNode,\r\n id,\r\n ModelUtility.getTransform(node)\r\n );\r\n\r\n runtimeNodes[id] = runtimeNode;\r\n runtimeNodesByName[node.name] = runtimeNode;\r\n\r\n if (defined(node.skin)) {\r\n skinnedNodesIds.push(id);\r\n skinnedNodes.push(runtimeNode);\r\n }\r\n\r\n if (\r\n defined(node.extensions) &&\r\n defined(node.extensions.AGI_articulations)\r\n ) {\r\n var articulationName = node.extensions.AGI_articulations.articulationName;\r\n if (defined(articulationName)) {\r\n var transform = Matrix4.clone(\r\n runtimeNode.publicNode.originalMatrix,\r\n scratchArticulationStageInitialTransform\r\n );\r\n var articulation = articulationsByName[articulationName];\r\n articulation.nodes.push(runtimeNode.publicNode);\r\n\r\n var numStages = articulation.stages.length;\r\n for (var s = 0; s < numStages; ++s) {\r\n var stage = articulation.stages[s];\r\n transform = applyArticulationStageMatrix(stage, transform);\r\n }\r\n runtimeNode.publicNode.matrix = transform;\r\n }\r\n }\r\n });\r\n\r\n model._runtime.nodes = runtimeNodes;\r\n model._runtime.nodesByName = runtimeNodesByName;\r\n model._runtime.skinnedNodes = skinnedNodes;\r\n}\r\n\r\nfunction parseMaterials(model) {\r\n var gltf = model.gltf;\r\n var techniques = model._sourceTechniques;\r\n\r\n var runtimeMaterialsByName = {};\r\n var runtimeMaterialsById = {};\r\n var uniformMaps = model._uniformMaps;\r\n\r\n ForEach.material(gltf, function (material, materialId) {\r\n // Allocated now so ModelMaterial can keep a reference to it.\r\n uniformMaps[materialId] = {\r\n uniformMap: undefined,\r\n values: undefined,\r\n jointMatrixUniformName: undefined,\r\n morphWeightsUniformName: undefined,\r\n };\r\n\r\n var modelMaterial = new ModelMaterial(model, material, materialId);\r\n\r\n if (\r\n defined(material.extensions) &&\r\n defined(material.extensions.KHR_techniques_webgl)\r\n ) {\r\n var techniqueId = material.extensions.KHR_techniques_webgl.technique;\r\n modelMaterial._technique = techniqueId;\r\n modelMaterial._program = techniques[techniqueId].program;\r\n\r\n ForEach.materialValue(material, function (value, uniformName) {\r\n if (!defined(modelMaterial._values)) {\r\n modelMaterial._values = {};\r\n }\r\n\r\n modelMaterial._values[uniformName] = clone(value);\r\n });\r\n }\r\n\r\n runtimeMaterialsByName[material.name] = modelMaterial;\r\n runtimeMaterialsById[materialId] = modelMaterial;\r\n });\r\n\r\n model._runtime.materialsByName = runtimeMaterialsByName;\r\n model._runtime.materialsById = runtimeMaterialsById;\r\n}\r\n\r\nfunction parseMeshes(model) {\r\n var runtimeMeshesByName = {};\r\n var runtimeMaterialsById = model._runtime.materialsById;\r\n\r\n ForEach.mesh(model.gltf, function (mesh, meshId) {\r\n runtimeMeshesByName[mesh.name] = new ModelMesh(\r\n mesh,\r\n runtimeMaterialsById,\r\n meshId\r\n );\r\n if (\r\n defined(model.extensionsUsed.WEB3D_quantized_attributes) ||\r\n model._dequantizeInShader\r\n ) {\r\n // Cache primitives according to their program\r\n ForEach.meshPrimitive(mesh, function (primitive, primitiveId) {\r\n var programId = getProgramForPrimitive(model, primitive);\r\n var programPrimitives = model._programPrimitives[programId];\r\n if (!defined(programPrimitives)) {\r\n programPrimitives = {};\r\n model._programPrimitives[programId] = programPrimitives;\r\n }\r\n programPrimitives[meshId + \".primitive.\" + primitiveId] = primitive;\r\n });\r\n }\r\n });\r\n\r\n model._runtime.meshesByName = runtimeMeshesByName;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar CreateVertexBufferJob = function () {\r\n this.id = undefined;\r\n this.model = undefined;\r\n this.context = undefined;\r\n};\r\n\r\nCreateVertexBufferJob.prototype.set = function (id, model, context) {\r\n this.id = id;\r\n this.model = model;\r\n this.context = context;\r\n};\r\n\r\nCreateVertexBufferJob.prototype.execute = function () {\r\n createVertexBuffer(this.id, this.model, this.context);\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction createVertexBuffer(bufferViewId, model, context) {\r\n var loadResources = model._loadResources;\r\n var bufferViews = model.gltf.bufferViews;\r\n var bufferView = bufferViews[bufferViewId];\r\n\r\n // Use bufferView created at runtime\r\n if (!defined(bufferView)) {\r\n bufferView = loadResources.createdBufferViews[bufferViewId];\r\n }\r\n\r\n var vertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: loadResources.getBuffer(bufferView),\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n vertexBuffer.vertexArrayDestroyable = false;\r\n model._rendererResources.buffers[bufferViewId] = vertexBuffer;\r\n model._geometryByteLength += vertexBuffer.sizeInBytes;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar CreateIndexBufferJob = function () {\r\n this.id = undefined;\r\n this.componentType = undefined;\r\n this.model = undefined;\r\n this.context = undefined;\r\n};\r\n\r\nCreateIndexBufferJob.prototype.set = function (\r\n id,\r\n componentType,\r\n model,\r\n context\r\n) {\r\n this.id = id;\r\n this.componentType = componentType;\r\n this.model = model;\r\n this.context = context;\r\n};\r\n\r\nCreateIndexBufferJob.prototype.execute = function () {\r\n createIndexBuffer(this.id, this.componentType, this.model, this.context);\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction createIndexBuffer(bufferViewId, componentType, model, context) {\r\n var loadResources = model._loadResources;\r\n var bufferViews = model.gltf.bufferViews;\r\n var bufferView = bufferViews[bufferViewId];\r\n\r\n // Use bufferView created at runtime\r\n if (!defined(bufferView)) {\r\n bufferView = loadResources.createdBufferViews[bufferViewId];\r\n }\r\n\r\n var indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: loadResources.getBuffer(bufferView),\r\n usage: BufferUsage.STATIC_DRAW,\r\n indexDatatype: componentType,\r\n });\r\n indexBuffer.vertexArrayDestroyable = false;\r\n model._rendererResources.buffers[bufferViewId] = indexBuffer;\r\n model._geometryByteLength += indexBuffer.sizeInBytes;\r\n}\r\n\r\nvar scratchVertexBufferJob = new CreateVertexBufferJob();\r\nvar scratchIndexBufferJob = new CreateIndexBufferJob();\r\n\r\nfunction createBuffers(model, frameState) {\r\n var loadResources = model._loadResources;\r\n\r\n if (loadResources.pendingBufferLoads !== 0) {\r\n return;\r\n }\r\n\r\n var context = frameState.context;\r\n var vertexBuffersToCreate = loadResources.vertexBuffersToCreate;\r\n var indexBuffersToCreate = loadResources.indexBuffersToCreate;\r\n var i;\r\n\r\n if (model.asynchronous) {\r\n while (vertexBuffersToCreate.length > 0) {\r\n scratchVertexBufferJob.set(vertexBuffersToCreate.peek(), model, context);\r\n if (\r\n !frameState.jobScheduler.execute(scratchVertexBufferJob, JobType.BUFFER)\r\n ) {\r\n break;\r\n }\r\n vertexBuffersToCreate.dequeue();\r\n }\r\n\r\n while (indexBuffersToCreate.length > 0) {\r\n i = indexBuffersToCreate.peek();\r\n scratchIndexBufferJob.set(i.id, i.componentType, model, context);\r\n if (\r\n !frameState.jobScheduler.execute(scratchIndexBufferJob, JobType.BUFFER)\r\n ) {\r\n break;\r\n }\r\n indexBuffersToCreate.dequeue();\r\n }\r\n } else {\r\n while (vertexBuffersToCreate.length > 0) {\r\n createVertexBuffer(vertexBuffersToCreate.dequeue(), model, context);\r\n }\r\n\r\n while (indexBuffersToCreate.length > 0) {\r\n i = indexBuffersToCreate.dequeue();\r\n createIndexBuffer(i.id, i.componentType, model, context);\r\n }\r\n }\r\n}\r\n\r\nfunction getProgramForPrimitive(model, primitive) {\r\n var material = model._runtime.materialsById[primitive.material];\r\n if (!defined(material)) {\r\n return;\r\n }\r\n\r\n return material._program;\r\n}\r\n\r\nfunction modifyShaderForQuantizedAttributes(shader, programName, model) {\r\n var primitive;\r\n var primitives = model._programPrimitives[programName];\r\n\r\n // If no primitives were cached for this program, there's no need to modify the shader\r\n if (!defined(primitives)) {\r\n return shader;\r\n }\r\n\r\n var primitiveId;\r\n for (primitiveId in primitives) {\r\n if (primitives.hasOwnProperty(primitiveId)) {\r\n primitive = primitives[primitiveId];\r\n if (getProgramForPrimitive(model, primitive) === programName) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // This is not needed after the program is processed, free the memory\r\n model._programPrimitives[programName] = undefined;\r\n\r\n var result;\r\n if (model.extensionsUsed.WEB3D_quantized_attributes) {\r\n result = ModelUtility.modifyShaderForQuantizedAttributes(\r\n model.gltf,\r\n primitive,\r\n shader\r\n );\r\n model._quantizedUniforms[programName] = result.uniforms;\r\n } else {\r\n var decodedData = model._decodedData[primitiveId];\r\n if (defined(decodedData)) {\r\n result = ModelUtility.modifyShaderForDracoQuantizedAttributes(\r\n model.gltf,\r\n primitive,\r\n shader,\r\n decodedData.attributes\r\n );\r\n } else {\r\n return shader;\r\n }\r\n }\r\n\r\n return result.shader;\r\n}\r\n\r\nfunction modifyShaderForColor(shader) {\r\n shader = ShaderSource.replaceMain(shader, \"gltf_blend_main\");\r\n shader +=\r\n \"uniform vec4 gltf_color; \\n\" +\r\n \"uniform float gltf_colorBlend; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" gltf_blend_main(); \\n\" +\r\n \" gl_FragColor.rgb = mix(gl_FragColor.rgb, gltf_color.rgb, gltf_colorBlend); \\n\" +\r\n \" float highlight = ceil(gltf_colorBlend); \\n\" +\r\n \" gl_FragColor.rgb *= mix(gltf_color.rgb, vec3(1.0), highlight); \\n\" +\r\n \" gl_FragColor.a *= gltf_color.a; \\n\" +\r\n \"} \\n\";\r\n\r\n return shader;\r\n}\r\n\r\nfunction modifyShader(shader, programName, callback) {\r\n if (defined(callback)) {\r\n shader = callback(shader, programName);\r\n }\r\n return shader;\r\n}\r\n\r\nvar CreateProgramJob = function () {\r\n this.programToCreate = undefined;\r\n this.model = undefined;\r\n this.context = undefined;\r\n};\r\n\r\nCreateProgramJob.prototype.set = function (programToCreate, model, context) {\r\n this.programToCreate = programToCreate;\r\n this.model = model;\r\n this.context = context;\r\n};\r\n\r\nCreateProgramJob.prototype.execute = function () {\r\n createProgram(this.programToCreate, this.model, this.context);\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n// When building programs for the first time, do not include modifiers for clipping planes and color\r\n// since this is the version of the program that will be cached for use with other Models.\r\nfunction createProgram(programToCreate, model, context) {\r\n var programId = programToCreate.programId;\r\n var techniqueId = programToCreate.techniqueId;\r\n var program = model._sourcePrograms[programId];\r\n var shaders = model._rendererResources.sourceShaders;\r\n\r\n var vs = shaders[program.vertexShader];\r\n var fs = shaders[program.fragmentShader];\r\n\r\n var quantizedVertexShaders = model._quantizedVertexShaders;\r\n\r\n if (\r\n model.extensionsUsed.WEB3D_quantized_attributes ||\r\n model._dequantizeInShader\r\n ) {\r\n var quantizedVS = quantizedVertexShaders[programId];\r\n if (!defined(quantizedVS)) {\r\n quantizedVS = modifyShaderForQuantizedAttributes(vs, programId, model);\r\n quantizedVertexShaders[programId] = quantizedVS;\r\n }\r\n vs = quantizedVS;\r\n }\r\n\r\n var drawVS = modifyShader(vs, programId, model._vertexShaderLoaded);\r\n var drawFS = modifyShader(fs, programId, model._fragmentShaderLoaded);\r\n\r\n if (!defined(model._uniformMapLoaded)) {\r\n drawFS = \"uniform vec4 czm_pickColor;\\n\" + drawFS;\r\n }\r\n\r\n var useIBL =\r\n model._imageBasedLightingFactor.x > 0.0 ||\r\n model._imageBasedLightingFactor.y > 0.0;\r\n if (useIBL) {\r\n drawFS = \"#define USE_IBL_LIGHTING \\n\\n\" + drawFS;\r\n }\r\n\r\n if (defined(model._lightColor)) {\r\n drawFS = \"#define USE_CUSTOM_LIGHT_COLOR \\n\\n\" + drawFS;\r\n }\r\n\r\n if (model._sourceVersion !== \"2.0\" || model._sourceKHRTechniquesWebGL) {\r\n drawFS = ShaderSource.replaceMain(drawFS, \"non_gamma_corrected_main\");\r\n drawFS =\r\n drawFS +\r\n \"\\n\" +\r\n \"void main() { \\n\" +\r\n \" non_gamma_corrected_main(); \\n\" +\r\n \" gl_FragColor = czm_gammaCorrect(gl_FragColor); \\n\" +\r\n \"} \\n\";\r\n }\r\n\r\n if (OctahedralProjectedCubeMap.isSupported(context)) {\r\n var usesSH =\r\n defined(model._sphericalHarmonicCoefficients) ||\r\n model._useDefaultSphericalHarmonics;\r\n var usesSM =\r\n (defined(model._specularEnvironmentMapAtlas) &&\r\n model._specularEnvironmentMapAtlas.ready) ||\r\n model._useDefaultSpecularMaps;\r\n var addMatrix = usesSH || usesSM || useIBL;\r\n if (addMatrix) {\r\n drawFS = \"uniform mat3 gltf_iblReferenceFrameMatrix; \\n\" + drawFS;\r\n }\r\n\r\n if (defined(model._sphericalHarmonicCoefficients)) {\r\n drawFS =\r\n \"#define DIFFUSE_IBL \\n\" +\r\n \"#define CUSTOM_SPHERICAL_HARMONICS \\n\" +\r\n \"uniform vec3 gltf_sphericalHarmonicCoefficients[9]; \\n\" +\r\n drawFS;\r\n } else if (model._useDefaultSphericalHarmonics) {\r\n drawFS = \"#define DIFFUSE_IBL \\n\" + drawFS;\r\n }\r\n\r\n if (\r\n defined(model._specularEnvironmentMapAtlas) &&\r\n model._specularEnvironmentMapAtlas.ready\r\n ) {\r\n drawFS =\r\n \"#define SPECULAR_IBL \\n\" +\r\n \"#define CUSTOM_SPECULAR_IBL \\n\" +\r\n \"uniform sampler2D gltf_specularMap; \\n\" +\r\n \"uniform vec2 gltf_specularMapSize; \\n\" +\r\n \"uniform float gltf_maxSpecularLOD; \\n\" +\r\n drawFS;\r\n } else if (model._useDefaultSpecularMaps) {\r\n drawFS = \"#define SPECULAR_IBL \\n\" + drawFS;\r\n }\r\n }\r\n\r\n if (defined(model._luminanceAtZenith)) {\r\n drawFS =\r\n \"#define USE_SUN_LUMINANCE \\n\" +\r\n \"uniform float gltf_luminanceAtZenith;\\n\" +\r\n drawFS;\r\n }\r\n\r\n createAttributesAndProgram(\r\n programId,\r\n techniqueId,\r\n drawFS,\r\n drawVS,\r\n model,\r\n context\r\n );\r\n}\r\n\r\nfunction recreateProgram(programToCreate, model, context) {\r\n var programId = programToCreate.programId;\r\n var techniqueId = programToCreate.techniqueId;\r\n var program = model._sourcePrograms[programId];\r\n var shaders = model._rendererResources.sourceShaders;\r\n\r\n var quantizedVertexShaders = model._quantizedVertexShaders;\r\n\r\n var clippingPlaneCollection = model.clippingPlanes;\r\n var addClippingPlaneCode = isClippingEnabled(model);\r\n\r\n var vs = shaders[program.vertexShader];\r\n var fs = shaders[program.fragmentShader];\r\n\r\n if (\r\n model.extensionsUsed.WEB3D_quantized_attributes ||\r\n model._dequantizeInShader\r\n ) {\r\n vs = quantizedVertexShaders[programId];\r\n }\r\n\r\n var finalFS = fs;\r\n if (isColorShadingEnabled(model)) {\r\n finalFS = Model._modifyShaderForColor(finalFS);\r\n }\r\n if (addClippingPlaneCode) {\r\n finalFS = modifyShaderForClippingPlanes(\r\n finalFS,\r\n clippingPlaneCollection,\r\n context\r\n );\r\n }\r\n\r\n var drawVS = modifyShader(vs, programId, model._vertexShaderLoaded);\r\n var drawFS = modifyShader(finalFS, programId, model._fragmentShaderLoaded);\r\n\r\n if (!defined(model._uniformMapLoaded)) {\r\n drawFS = \"uniform vec4 czm_pickColor;\\n\" + drawFS;\r\n }\r\n\r\n var useIBL =\r\n model._imageBasedLightingFactor.x > 0.0 ||\r\n model._imageBasedLightingFactor.y > 0.0;\r\n if (useIBL) {\r\n drawFS = \"#define USE_IBL_LIGHTING \\n\\n\" + drawFS;\r\n }\r\n\r\n if (defined(model._lightColor)) {\r\n drawFS = \"#define USE_CUSTOM_LIGHT_COLOR \\n\\n\" + drawFS;\r\n }\r\n\r\n if (model._sourceVersion !== \"2.0\" || model._sourceKHRTechniquesWebGL) {\r\n drawFS = ShaderSource.replaceMain(drawFS, \"non_gamma_corrected_main\");\r\n drawFS =\r\n drawFS +\r\n \"\\n\" +\r\n \"void main() { \\n\" +\r\n \" non_gamma_corrected_main(); \\n\" +\r\n \" gl_FragColor = czm_gammaCorrect(gl_FragColor); \\n\" +\r\n \"} \\n\";\r\n }\r\n\r\n if (OctahedralProjectedCubeMap.isSupported(context)) {\r\n var usesSH =\r\n defined(model._sphericalHarmonicCoefficients) ||\r\n model._useDefaultSphericalHarmonics;\r\n var usesSM =\r\n (defined(model._specularEnvironmentMapAtlas) &&\r\n model._specularEnvironmentMapAtlas.ready) ||\r\n model._useDefaultSpecularMaps;\r\n var addMatrix = usesSH || usesSM || useIBL;\r\n if (addMatrix) {\r\n drawFS = \"uniform mat3 gltf_iblReferenceFrameMatrix; \\n\" + drawFS;\r\n }\r\n\r\n if (defined(model._sphericalHarmonicCoefficients)) {\r\n drawFS =\r\n \"#define DIFFUSE_IBL \\n\" +\r\n \"#define CUSTOM_SPHERICAL_HARMONICS \\n\" +\r\n \"uniform vec3 gltf_sphericalHarmonicCoefficients[9]; \\n\" +\r\n drawFS;\r\n } else if (model._useDefaultSphericalHarmonics) {\r\n drawFS = \"#define DIFFUSE_IBL \\n\" + drawFS;\r\n }\r\n\r\n if (\r\n defined(model._specularEnvironmentMapAtlas) &&\r\n model._specularEnvironmentMapAtlas.ready\r\n ) {\r\n drawFS =\r\n \"#define SPECULAR_IBL \\n\" +\r\n \"#define CUSTOM_SPECULAR_IBL \\n\" +\r\n \"uniform sampler2D gltf_specularMap; \\n\" +\r\n \"uniform vec2 gltf_specularMapSize; \\n\" +\r\n \"uniform float gltf_maxSpecularLOD; \\n\" +\r\n drawFS;\r\n } else if (model._useDefaultSpecularMaps) {\r\n drawFS = \"#define SPECULAR_IBL \\n\" + drawFS;\r\n }\r\n }\r\n\r\n if (defined(model._luminanceAtZenith)) {\r\n drawFS =\r\n \"#define USE_SUN_LUMINANCE \\n\" +\r\n \"uniform float gltf_luminanceAtZenith;\\n\" +\r\n drawFS;\r\n }\r\n\r\n createAttributesAndProgram(\r\n programId,\r\n techniqueId,\r\n drawFS,\r\n drawVS,\r\n model,\r\n context\r\n );\r\n}\r\n\r\nfunction createAttributesAndProgram(\r\n programId,\r\n techniqueId,\r\n drawFS,\r\n drawVS,\r\n model,\r\n context\r\n) {\r\n var technique = model._sourceTechniques[techniqueId];\r\n var attributeLocations = ModelUtility.createAttributeLocations(\r\n technique,\r\n model._precreatedAttributes\r\n );\r\n\r\n model._rendererResources.programs[programId] = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: drawVS,\r\n fragmentShaderSource: drawFS,\r\n attributeLocations: attributeLocations,\r\n });\r\n}\r\n\r\nvar scratchCreateProgramJob = new CreateProgramJob();\r\n\r\nfunction createPrograms(model, frameState) {\r\n var loadResources = model._loadResources;\r\n var programsToCreate = loadResources.programsToCreate;\r\n\r\n if (loadResources.pendingShaderLoads !== 0) {\r\n return;\r\n }\r\n\r\n // PERFORMANCE_IDEA: this could be more fine-grained by looking\r\n // at the shader's bufferView's to determine the buffer dependencies.\r\n if (loadResources.pendingBufferLoads !== 0) {\r\n return;\r\n }\r\n\r\n var context = frameState.context;\r\n\r\n if (model.asynchronous) {\r\n while (programsToCreate.length > 0) {\r\n scratchCreateProgramJob.set(programsToCreate.peek(), model, context);\r\n if (\r\n !frameState.jobScheduler.execute(\r\n scratchCreateProgramJob,\r\n JobType.PROGRAM\r\n )\r\n ) {\r\n break;\r\n }\r\n programsToCreate.dequeue();\r\n }\r\n } else {\r\n // Create all loaded programs this frame\r\n while (programsToCreate.length > 0) {\r\n createProgram(programsToCreate.dequeue(), model, context);\r\n }\r\n }\r\n}\r\n\r\nfunction getOnImageCreatedFromTypedArray(loadResources, gltfTexture) {\r\n return function (image) {\r\n loadResources.texturesToCreate.enqueue({\r\n id: gltfTexture.id,\r\n image: image,\r\n bufferView: undefined,\r\n });\r\n\r\n --loadResources.pendingBufferViewToImage;\r\n };\r\n}\r\n\r\nfunction loadTexturesFromBufferViews(model) {\r\n var loadResources = model._loadResources;\r\n\r\n if (loadResources.pendingBufferLoads !== 0) {\r\n return;\r\n }\r\n\r\n while (loadResources.texturesToCreateFromBufferView.length > 0) {\r\n var gltfTexture = loadResources.texturesToCreateFromBufferView.dequeue();\r\n\r\n var gltf = model.gltf;\r\n var bufferView = gltf.bufferViews[gltfTexture.bufferView];\r\n var imageId = gltf.textures[gltfTexture.id].source;\r\n\r\n var onerror = ModelUtility.getFailedLoadFunction(\r\n model,\r\n \"image\",\r\n \"id: \" + gltfTexture.id + \", bufferView: \" + gltfTexture.bufferView\r\n );\r\n\r\n if (gltfTexture.mimeType === \"image/ktx\") {\r\n loadKTX(loadResources.getBuffer(bufferView))\r\n .then(imageLoad(model, gltfTexture.id, imageId))\r\n .otherwise(onerror);\r\n ++model._loadResources.pendingTextureLoads;\r\n } else if (gltfTexture.mimeType === \"image/crn\") {\r\n loadCRN(loadResources.getBuffer(bufferView))\r\n .then(imageLoad(model, gltfTexture.id, imageId))\r\n .otherwise(onerror);\r\n ++model._loadResources.pendingTextureLoads;\r\n } else {\r\n var onload = getOnImageCreatedFromTypedArray(loadResources, gltfTexture);\r\n loadImageFromTypedArray({\r\n uint8Array: loadResources.getBuffer(bufferView),\r\n format: gltfTexture.mimeType,\r\n flipY: false,\r\n })\r\n .then(onload)\r\n .otherwise(onerror);\r\n ++loadResources.pendingBufferViewToImage;\r\n }\r\n }\r\n}\r\n\r\nfunction createSamplers(model) {\r\n var loadResources = model._loadResources;\r\n if (loadResources.createSamplers) {\r\n loadResources.createSamplers = false;\r\n\r\n var rendererSamplers = model._rendererResources.samplers;\r\n ForEach.sampler(model.gltf, function (sampler, samplerId) {\r\n rendererSamplers[samplerId] = new Sampler({\r\n wrapS: sampler.wrapS,\r\n wrapT: sampler.wrapT,\r\n minificationFilter: sampler.minFilter,\r\n magnificationFilter: sampler.magFilter,\r\n });\r\n });\r\n }\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar CreateTextureJob = function () {\r\n this.gltfTexture = undefined;\r\n this.model = undefined;\r\n this.context = undefined;\r\n};\r\n\r\nCreateTextureJob.prototype.set = function (gltfTexture, model, context) {\r\n this.gltfTexture = gltfTexture;\r\n this.model = model;\r\n this.context = context;\r\n};\r\n\r\nCreateTextureJob.prototype.execute = function () {\r\n createTexture(this.gltfTexture, this.model, this.context);\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction createTexture(gltfTexture, model, context) {\r\n var textures = model.gltf.textures;\r\n var texture = textures[gltfTexture.id];\r\n\r\n var rendererSamplers = model._rendererResources.samplers;\r\n var sampler = rendererSamplers[texture.sampler];\r\n if (!defined(sampler)) {\r\n sampler = new Sampler({\r\n wrapS: TextureWrap.REPEAT,\r\n wrapT: TextureWrap.REPEAT,\r\n });\r\n }\r\n\r\n var usesTextureTransform = false;\r\n var materials = model.gltf.materials;\r\n var materialsLength = materials.length;\r\n for (var i = 0; i < materialsLength; ++i) {\r\n var material = materials[i];\r\n if (\r\n defined(material.extensions) &&\r\n defined(material.extensions.KHR_techniques_webgl)\r\n ) {\r\n var values = material.extensions.KHR_techniques_webgl.values;\r\n for (var valueName in values) {\r\n if (\r\n values.hasOwnProperty(valueName) &&\r\n valueName.indexOf(\"Texture\") !== -1\r\n ) {\r\n var value = values[valueName];\r\n if (\r\n value.index === gltfTexture.id &&\r\n defined(value.extensions) &&\r\n defined(value.extensions.KHR_texture_transform)\r\n ) {\r\n usesTextureTransform = true;\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n if (usesTextureTransform) {\r\n break;\r\n }\r\n }\r\n\r\n var wrapS = sampler.wrapS;\r\n var wrapT = sampler.wrapT;\r\n var minFilter = sampler.minificationFilter;\r\n\r\n if (\r\n usesTextureTransform &&\r\n minFilter !== TextureMinificationFilter.LINEAR &&\r\n minFilter !== TextureMinificationFilter.NEAREST\r\n ) {\r\n if (\r\n minFilter === TextureMinificationFilter.NEAREST_MIPMAP_NEAREST ||\r\n minFilter === TextureMinificationFilter.NEAREST_MIPMAP_LINEAR\r\n ) {\r\n minFilter = TextureMinificationFilter.NEAREST;\r\n } else {\r\n minFilter = TextureMinificationFilter.LINEAR;\r\n }\r\n\r\n sampler = new Sampler({\r\n wrapS: sampler.wrapS,\r\n wrapT: sampler.wrapT,\r\n textureMinificationFilter: minFilter,\r\n textureMagnificationFilter: sampler.magnificationFilter,\r\n });\r\n }\r\n\r\n var internalFormat = gltfTexture.internalFormat;\r\n\r\n var mipmap =\r\n !(\r\n defined(internalFormat) && PixelFormat.isCompressedFormat(internalFormat)\r\n ) &&\r\n (minFilter === TextureMinificationFilter.NEAREST_MIPMAP_NEAREST ||\r\n minFilter === TextureMinificationFilter.NEAREST_MIPMAP_LINEAR ||\r\n minFilter === TextureMinificationFilter.LINEAR_MIPMAP_NEAREST ||\r\n minFilter === TextureMinificationFilter.LINEAR_MIPMAP_LINEAR);\r\n var requiresNpot =\r\n mipmap ||\r\n wrapS === TextureWrap.REPEAT ||\r\n wrapS === TextureWrap.MIRRORED_REPEAT ||\r\n wrapT === TextureWrap.REPEAT ||\r\n wrapT === TextureWrap.MIRRORED_REPEAT;\r\n\r\n var tx;\r\n var source = gltfTexture.image;\r\n\r\n if (defined(internalFormat)) {\r\n tx = new Texture({\r\n context: context,\r\n source: {\r\n arrayBufferView: gltfTexture.bufferView,\r\n },\r\n width: gltfTexture.width,\r\n height: gltfTexture.height,\r\n pixelFormat: internalFormat,\r\n sampler: sampler,\r\n });\r\n } else if (defined(source)) {\r\n var npot =\r\n !CesiumMath.isPowerOfTwo(source.width) ||\r\n !CesiumMath.isPowerOfTwo(source.height);\r\n\r\n if (requiresNpot && npot) {\r\n // WebGL requires power-of-two texture dimensions for mipmapping and REPEAT/MIRRORED_REPEAT wrap modes.\r\n var canvas = document.createElement(\"canvas\");\r\n canvas.width = CesiumMath.nextPowerOfTwo(source.width);\r\n canvas.height = CesiumMath.nextPowerOfTwo(source.height);\r\n var canvasContext = canvas.getContext(\"2d\");\r\n canvasContext.drawImage(\r\n source,\r\n 0,\r\n 0,\r\n source.width,\r\n source.height,\r\n 0,\r\n 0,\r\n canvas.width,\r\n canvas.height\r\n );\r\n source = canvas;\r\n }\r\n\r\n tx = new Texture({\r\n context: context,\r\n source: source,\r\n pixelFormat: texture.internalFormat,\r\n pixelDatatype: texture.type,\r\n sampler: sampler,\r\n flipY: false,\r\n });\r\n // GLTF_SPEC: Support TEXTURE_CUBE_MAP. https://github.com/KhronosGroup/glTF/issues/40\r\n if (mipmap) {\r\n tx.generateMipmap();\r\n }\r\n }\r\n if (defined(tx)) {\r\n model._rendererResources.textures[gltfTexture.id] = tx;\r\n model._texturesByteLength += tx.sizeInBytes;\r\n }\r\n}\r\n\r\nvar scratchCreateTextureJob = new CreateTextureJob();\r\n\r\nfunction createTextures(model, frameState) {\r\n var context = frameState.context;\r\n var texturesToCreate = model._loadResources.texturesToCreate;\r\n\r\n if (model.asynchronous) {\r\n while (texturesToCreate.length > 0) {\r\n scratchCreateTextureJob.set(texturesToCreate.peek(), model, context);\r\n if (\r\n !frameState.jobScheduler.execute(\r\n scratchCreateTextureJob,\r\n JobType.TEXTURE\r\n )\r\n ) {\r\n break;\r\n }\r\n texturesToCreate.dequeue();\r\n }\r\n } else {\r\n // Create all loaded textures this frame\r\n while (texturesToCreate.length > 0) {\r\n createTexture(texturesToCreate.dequeue(), model, context);\r\n }\r\n }\r\n}\r\n\r\nfunction getAttributeLocations(model, primitive) {\r\n var techniques = model._sourceTechniques;\r\n\r\n // Retrieve the compiled shader program to assign index values to attributes\r\n var attributeLocations = {};\r\n\r\n var location;\r\n var index;\r\n var material = model._runtime.materialsById[primitive.material];\r\n if (!defined(material)) {\r\n return attributeLocations;\r\n }\r\n\r\n var technique = techniques[material._technique];\r\n if (!defined(technique)) {\r\n return attributeLocations;\r\n }\r\n\r\n var attributes = technique.attributes;\r\n var program = model._rendererResources.programs[technique.program];\r\n var programAttributeLocations = program._attributeLocations;\r\n\r\n for (location in programAttributeLocations) {\r\n if (programAttributeLocations.hasOwnProperty(location)) {\r\n var attribute = attributes[location];\r\n if (defined(attribute)) {\r\n index = programAttributeLocations[location];\r\n attributeLocations[attribute.semantic] = index;\r\n }\r\n }\r\n }\r\n\r\n // Add pre-created attributes.\r\n var precreatedAttributes = model._precreatedAttributes;\r\n if (defined(precreatedAttributes)) {\r\n for (location in precreatedAttributes) {\r\n if (precreatedAttributes.hasOwnProperty(location)) {\r\n index = programAttributeLocations[location];\r\n attributeLocations[location] = index;\r\n }\r\n }\r\n }\r\n\r\n return attributeLocations;\r\n}\r\n\r\nfunction createJoints(model, runtimeSkins) {\r\n var gltf = model.gltf;\r\n var skins = gltf.skins;\r\n var nodes = gltf.nodes;\r\n var runtimeNodes = model._runtime.nodes;\r\n\r\n var skinnedNodesIds = model._loadResources.skinnedNodesIds;\r\n var length = skinnedNodesIds.length;\r\n for (var j = 0; j < length; ++j) {\r\n var id = skinnedNodesIds[j];\r\n var skinnedNode = runtimeNodes[id];\r\n var node = nodes[id];\r\n\r\n var runtimeSkin = runtimeSkins[node.skin];\r\n skinnedNode.inverseBindMatrices = runtimeSkin.inverseBindMatrices;\r\n skinnedNode.bindShapeMatrix = runtimeSkin.bindShapeMatrix;\r\n\r\n var gltfJoints = skins[node.skin].joints;\r\n var jointsLength = gltfJoints.length;\r\n for (var i = 0; i < jointsLength; ++i) {\r\n var nodeId = gltfJoints[i];\r\n var jointNode = runtimeNodes[nodeId];\r\n skinnedNode.joints.push(jointNode);\r\n }\r\n }\r\n}\r\n\r\nfunction createSkins(model) {\r\n var loadResources = model._loadResources;\r\n\r\n if (loadResources.pendingBufferLoads !== 0) {\r\n return;\r\n }\r\n\r\n if (!loadResources.createSkins) {\r\n return;\r\n }\r\n loadResources.createSkins = false;\r\n\r\n var gltf = model.gltf;\r\n var accessors = gltf.accessors;\r\n var runtimeSkins = {};\r\n\r\n ForEach.skin(gltf, function (skin, id) {\r\n var accessor = accessors[skin.inverseBindMatrices];\r\n\r\n var bindShapeMatrix;\r\n if (!Matrix4.equals(skin.bindShapeMatrix, Matrix4.IDENTITY)) {\r\n bindShapeMatrix = Matrix4.clone(skin.bindShapeMatrix);\r\n }\r\n\r\n runtimeSkins[id] = {\r\n inverseBindMatrices: ModelAnimationCache.getSkinInverseBindMatrices(\r\n model,\r\n accessor\r\n ),\r\n bindShapeMatrix: bindShapeMatrix, // not used when undefined\r\n };\r\n });\r\n\r\n createJoints(model, runtimeSkins);\r\n}\r\n\r\nfunction getChannelEvaluator(model, runtimeNode, targetPath, spline) {\r\n return function (localAnimationTime) {\r\n if (defined(spline)) {\r\n localAnimationTime = model.clampAnimations\r\n ? spline.clampTime(localAnimationTime)\r\n : spline.wrapTime(localAnimationTime);\r\n runtimeNode[targetPath] = spline.evaluate(\r\n localAnimationTime,\r\n runtimeNode[targetPath]\r\n );\r\n runtimeNode.dirtyNumber = model._maxDirtyNumber;\r\n }\r\n };\r\n}\r\n\r\nfunction createRuntimeAnimations(model) {\r\n var loadResources = model._loadResources;\r\n\r\n if (!loadResources.finishedPendingBufferLoads()) {\r\n return;\r\n }\r\n\r\n if (!loadResources.createRuntimeAnimations) {\r\n return;\r\n }\r\n loadResources.createRuntimeAnimations = false;\r\n\r\n model._runtime.animations = [];\r\n\r\n var runtimeNodes = model._runtime.nodes;\r\n var accessors = model.gltf.accessors;\r\n\r\n ForEach.animation(model.gltf, function (animation, i) {\r\n var channels = animation.channels;\r\n var samplers = animation.samplers;\r\n\r\n // Find start and stop time for the entire animation\r\n var startTime = Number.MAX_VALUE;\r\n var stopTime = -Number.MAX_VALUE;\r\n\r\n var channelsLength = channels.length;\r\n var channelEvaluators = new Array(channelsLength);\r\n\r\n for (var j = 0; j < channelsLength; ++j) {\r\n var channel = channels[j];\r\n var target = channel.target;\r\n var path = target.path;\r\n var sampler = samplers[channel.sampler];\r\n var input = ModelAnimationCache.getAnimationParameterValues(\r\n model,\r\n accessors[sampler.input]\r\n );\r\n var output = ModelAnimationCache.getAnimationParameterValues(\r\n model,\r\n accessors[sampler.output]\r\n );\r\n\r\n startTime = Math.min(startTime, input[0]);\r\n stopTime = Math.max(stopTime, input[input.length - 1]);\r\n\r\n var spline = ModelAnimationCache.getAnimationSpline(\r\n model,\r\n i,\r\n animation,\r\n channel.sampler,\r\n sampler,\r\n input,\r\n path,\r\n output\r\n );\r\n\r\n channelEvaluators[j] = getChannelEvaluator(\r\n model,\r\n runtimeNodes[target.node],\r\n target.path,\r\n spline\r\n );\r\n }\r\n\r\n model._runtime.animations[i] = {\r\n name: animation.name,\r\n startTime: startTime,\r\n stopTime: stopTime,\r\n channelEvaluators: channelEvaluators,\r\n };\r\n });\r\n}\r\n\r\nfunction createVertexArrays(model, context) {\r\n var loadResources = model._loadResources;\r\n if (\r\n !loadResources.finishedBuffersCreation() ||\r\n !loadResources.finishedProgramCreation() ||\r\n !loadResources.createVertexArrays\r\n ) {\r\n return;\r\n }\r\n loadResources.createVertexArrays = false;\r\n\r\n var rendererBuffers = model._rendererResources.buffers;\r\n var rendererVertexArrays = model._rendererResources.vertexArrays;\r\n var gltf = model.gltf;\r\n var accessors = gltf.accessors;\r\n ForEach.mesh(gltf, function (mesh, meshId) {\r\n ForEach.meshPrimitive(mesh, function (primitive, primitiveId) {\r\n var attributes = [];\r\n var attributeLocation;\r\n var attributeLocations = getAttributeLocations(model, primitive);\r\n var decodedData =\r\n model._decodedData[meshId + \".primitive.\" + primitiveId];\r\n ForEach.meshPrimitiveAttribute(primitive, function (\r\n accessorId,\r\n attributeName\r\n ) {\r\n // Skip if the attribute is not used by the material, e.g., because the asset\r\n // was exported with an attribute that wasn't used and the asset wasn't optimized.\r\n attributeLocation = attributeLocations[attributeName];\r\n if (defined(attributeLocation)) {\r\n // Use attributes of previously decoded draco geometry\r\n if (defined(decodedData)) {\r\n var decodedAttributes = decodedData.attributes;\r\n if (decodedAttributes.hasOwnProperty(attributeName)) {\r\n var decodedAttribute = decodedAttributes[attributeName];\r\n attributes.push({\r\n index: attributeLocation,\r\n vertexBuffer: rendererBuffers[decodedAttribute.bufferView],\r\n componentsPerAttribute: decodedAttribute.componentsPerAttribute,\r\n componentDatatype: decodedAttribute.componentDatatype,\r\n normalize: decodedAttribute.normalized,\r\n offsetInBytes: decodedAttribute.byteOffset,\r\n strideInBytes: decodedAttribute.byteStride,\r\n });\r\n\r\n return;\r\n }\r\n }\r\n\r\n var a = accessors[accessorId];\r\n var normalize = defined(a.normalized) && a.normalized;\r\n attributes.push({\r\n index: attributeLocation,\r\n vertexBuffer: rendererBuffers[a.bufferView],\r\n componentsPerAttribute: numberOfComponentsForType(a.type),\r\n componentDatatype: a.componentType,\r\n normalize: normalize,\r\n offsetInBytes: a.byteOffset,\r\n strideInBytes: getAccessorByteStride(gltf, a),\r\n });\r\n }\r\n });\r\n\r\n // Add pre-created attributes\r\n var attribute;\r\n var attributeName;\r\n var precreatedAttributes = model._precreatedAttributes;\r\n if (defined(precreatedAttributes)) {\r\n for (attributeName in precreatedAttributes) {\r\n if (precreatedAttributes.hasOwnProperty(attributeName)) {\r\n attributeLocation = attributeLocations[attributeName];\r\n if (defined(attributeLocation)) {\r\n attribute = precreatedAttributes[attributeName];\r\n attribute.index = attributeLocation;\r\n attributes.push(attribute);\r\n }\r\n }\r\n }\r\n }\r\n\r\n var indexBuffer;\r\n if (defined(primitive.indices)) {\r\n var accessor = accessors[primitive.indices];\r\n var bufferView = accessor.bufferView;\r\n\r\n // Use buffer of previously decoded draco geometry\r\n if (defined(decodedData)) {\r\n bufferView = decodedData.bufferView;\r\n }\r\n\r\n indexBuffer = rendererBuffers[bufferView];\r\n }\r\n rendererVertexArrays[\r\n meshId + \".primitive.\" + primitiveId\r\n ] = new VertexArray({\r\n context: context,\r\n attributes: attributes,\r\n indexBuffer: indexBuffer,\r\n });\r\n });\r\n });\r\n}\r\n\r\nfunction createRenderStates(model) {\r\n var loadResources = model._loadResources;\r\n if (loadResources.createRenderStates) {\r\n loadResources.createRenderStates = false;\r\n\r\n ForEach.material(model.gltf, function (material, materialId) {\r\n createRenderStateForMaterial(model, material, materialId);\r\n });\r\n }\r\n}\r\n\r\nfunction createRenderStateForMaterial(model, material, materialId) {\r\n var rendererRenderStates = model._rendererResources.renderStates;\r\n\r\n var blendEquationSeparate = [\r\n WebGLConstants.FUNC_ADD,\r\n WebGLConstants.FUNC_ADD,\r\n ];\r\n var blendFuncSeparate = [\r\n WebGLConstants.ONE,\r\n WebGLConstants.ONE_MINUS_SRC_ALPHA,\r\n WebGLConstants.ONE,\r\n WebGLConstants.ONE_MINUS_SRC_ALPHA,\r\n ];\r\n\r\n if (defined(material.extensions) && defined(material.extensions.KHR_blend)) {\r\n blendEquationSeparate = material.extensions.KHR_blend.blendEquation;\r\n blendFuncSeparate = material.extensions.KHR_blend.blendFactors;\r\n }\r\n\r\n var enableCulling = !material.doubleSided;\r\n var blendingEnabled = material.alphaMode === \"BLEND\";\r\n rendererRenderStates[materialId] = RenderState.fromCache({\r\n cull: {\r\n enabled: enableCulling,\r\n },\r\n depthTest: {\r\n enabled: true,\r\n func: DepthFunction.LESS_OR_EQUAL,\r\n },\r\n depthMask: !blendingEnabled,\r\n blending: {\r\n enabled: blendingEnabled,\r\n equationRgb: blendEquationSeparate[0],\r\n equationAlpha: blendEquationSeparate[1],\r\n functionSourceRgb: blendFuncSeparate[0],\r\n functionDestinationRgb: blendFuncSeparate[1],\r\n functionSourceAlpha: blendFuncSeparate[2],\r\n functionDestinationAlpha: blendFuncSeparate[3],\r\n },\r\n });\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar gltfUniformsFromNode = {\r\n MODEL: function (uniformState, model, runtimeNode) {\r\n return function () {\r\n return runtimeNode.computedMatrix;\r\n };\r\n },\r\n VIEW: function (uniformState, model, runtimeNode) {\r\n return function () {\r\n return uniformState.view;\r\n };\r\n },\r\n PROJECTION: function (uniformState, model, runtimeNode) {\r\n return function () {\r\n return uniformState.projection;\r\n };\r\n },\r\n MODELVIEW: function (uniformState, model, runtimeNode) {\r\n var mv = new Matrix4();\r\n return function () {\r\n return Matrix4.multiplyTransformation(\r\n uniformState.view,\r\n runtimeNode.computedMatrix,\r\n mv\r\n );\r\n };\r\n },\r\n CESIUM_RTC_MODELVIEW: function (uniformState, model, runtimeNode) {\r\n // CESIUM_RTC extension\r\n var mvRtc = new Matrix4();\r\n return function () {\r\n Matrix4.multiplyTransformation(\r\n uniformState.view,\r\n runtimeNode.computedMatrix,\r\n mvRtc\r\n );\r\n return Matrix4.setTranslation(mvRtc, model._rtcCenterEye, mvRtc);\r\n };\r\n },\r\n MODELVIEWPROJECTION: function (uniformState, model, runtimeNode) {\r\n var mvp = new Matrix4();\r\n return function () {\r\n Matrix4.multiplyTransformation(\r\n uniformState.view,\r\n runtimeNode.computedMatrix,\r\n mvp\r\n );\r\n return Matrix4.multiply(uniformState._projection, mvp, mvp);\r\n };\r\n },\r\n MODELINVERSE: function (uniformState, model, runtimeNode) {\r\n var mInverse = new Matrix4();\r\n return function () {\r\n return Matrix4.inverse(runtimeNode.computedMatrix, mInverse);\r\n };\r\n },\r\n VIEWINVERSE: function (uniformState, model) {\r\n return function () {\r\n return uniformState.inverseView;\r\n };\r\n },\r\n PROJECTIONINVERSE: function (uniformState, model, runtimeNode) {\r\n return function () {\r\n return uniformState.inverseProjection;\r\n };\r\n },\r\n MODELVIEWINVERSE: function (uniformState, model, runtimeNode) {\r\n var mv = new Matrix4();\r\n var mvInverse = new Matrix4();\r\n return function () {\r\n Matrix4.multiplyTransformation(\r\n uniformState.view,\r\n runtimeNode.computedMatrix,\r\n mv\r\n );\r\n return Matrix4.inverse(mv, mvInverse);\r\n };\r\n },\r\n MODELVIEWPROJECTIONINVERSE: function (uniformState, model, runtimeNode) {\r\n var mvp = new Matrix4();\r\n var mvpInverse = new Matrix4();\r\n return function () {\r\n Matrix4.multiplyTransformation(\r\n uniformState.view,\r\n runtimeNode.computedMatrix,\r\n mvp\r\n );\r\n Matrix4.multiply(uniformState._projection, mvp, mvp);\r\n return Matrix4.inverse(mvp, mvpInverse);\r\n };\r\n },\r\n MODELINVERSETRANSPOSE: function (uniformState, model, runtimeNode) {\r\n var mInverse = new Matrix4();\r\n var mInverseTranspose = new Matrix3();\r\n return function () {\r\n Matrix4.inverse(runtimeNode.computedMatrix, mInverse);\r\n Matrix4.getMatrix3(mInverse, mInverseTranspose);\r\n return Matrix3.transpose(mInverseTranspose, mInverseTranspose);\r\n };\r\n },\r\n MODELVIEWINVERSETRANSPOSE: function (uniformState, model, runtimeNode) {\r\n var mv = new Matrix4();\r\n var mvInverse = new Matrix4();\r\n var mvInverseTranspose = new Matrix3();\r\n return function () {\r\n Matrix4.multiplyTransformation(\r\n uniformState.view,\r\n runtimeNode.computedMatrix,\r\n mv\r\n );\r\n Matrix4.inverse(mv, mvInverse);\r\n Matrix4.getMatrix3(mvInverse, mvInverseTranspose);\r\n return Matrix3.transpose(mvInverseTranspose, mvInverseTranspose);\r\n };\r\n },\r\n VIEWPORT: function (uniformState, model, runtimeNode) {\r\n return function () {\r\n return uniformState.viewportCartesian4;\r\n };\r\n },\r\n};\r\n\r\nfunction getUniformFunctionFromSource(source, model, semantic, uniformState) {\r\n var runtimeNode = model._runtime.nodes[source];\r\n return gltfUniformsFromNode[semantic](uniformState, model, runtimeNode);\r\n}\r\n\r\nfunction createUniformsForMaterial(\r\n model,\r\n material,\r\n technique,\r\n instanceValues,\r\n context,\r\n textures,\r\n defaultTexture\r\n) {\r\n var uniformMap = {};\r\n var uniformValues = {};\r\n var jointMatrixUniformName;\r\n var morphWeightsUniformName;\r\n\r\n ForEach.techniqueUniform(technique, function (uniform, uniformName) {\r\n // GLTF_SPEC: This does not take into account uniform arrays,\r\n // indicated by uniforms with a count property.\r\n //\r\n // https://github.com/KhronosGroup/glTF/issues/258\r\n\r\n // GLTF_SPEC: In this implementation, material parameters with a\r\n // semantic or targeted via a source (for animation) are not\r\n // targetable for material animations. Is this too strict?\r\n //\r\n // https://github.com/KhronosGroup/glTF/issues/142\r\n\r\n var uv;\r\n if (defined(instanceValues) && defined(instanceValues[uniformName])) {\r\n // Parameter overrides by the instance technique\r\n uv = ModelUtility.createUniformFunction(\r\n uniform.type,\r\n instanceValues[uniformName],\r\n textures,\r\n defaultTexture\r\n );\r\n uniformMap[uniformName] = uv.func;\r\n uniformValues[uniformName] = uv;\r\n } else if (defined(uniform.node)) {\r\n uniformMap[uniformName] = getUniformFunctionFromSource(\r\n uniform.node,\r\n model,\r\n uniform.semantic,\r\n context.uniformState\r\n );\r\n } else if (defined(uniform.semantic)) {\r\n if (uniform.semantic === \"JOINTMATRIX\") {\r\n jointMatrixUniformName = uniformName;\r\n } else if (uniform.semantic === \"MORPHWEIGHTS\") {\r\n morphWeightsUniformName = uniformName;\r\n } else if (uniform.semantic === \"ALPHACUTOFF\") {\r\n // The material's alphaCutoff value uses a uniform with semantic ALPHACUTOFF.\r\n // A uniform with this semantic will ignore the instance or default values.\r\n var alphaMode = material.alphaMode;\r\n if (defined(alphaMode) && alphaMode === \"MASK\") {\r\n var alphaCutoffValue = defaultValue(material.alphaCutoff, 0.5);\r\n uv = ModelUtility.createUniformFunction(\r\n uniform.type,\r\n alphaCutoffValue,\r\n textures,\r\n defaultTexture\r\n );\r\n uniformMap[uniformName] = uv.func;\r\n uniformValues[uniformName] = uv;\r\n }\r\n } else {\r\n // Map glTF semantic to Cesium automatic uniform\r\n uniformMap[uniformName] = ModelUtility.getGltfSemanticUniforms()[\r\n uniform.semantic\r\n ](context.uniformState, model);\r\n }\r\n } else if (defined(uniform.value)) {\r\n // Technique value that isn't overridden by a material\r\n var uv2 = ModelUtility.createUniformFunction(\r\n uniform.type,\r\n uniform.value,\r\n textures,\r\n defaultTexture\r\n );\r\n uniformMap[uniformName] = uv2.func;\r\n uniformValues[uniformName] = uv2;\r\n }\r\n });\r\n\r\n return {\r\n map: uniformMap,\r\n values: uniformValues,\r\n jointMatrixUniformName: jointMatrixUniformName,\r\n morphWeightsUniformName: morphWeightsUniformName,\r\n };\r\n}\r\n\r\nfunction createUniformMaps(model, context) {\r\n var loadResources = model._loadResources;\r\n\r\n if (!loadResources.finishedProgramCreation()) {\r\n return;\r\n }\r\n\r\n if (!loadResources.createUniformMaps) {\r\n return;\r\n }\r\n loadResources.createUniformMaps = false;\r\n\r\n var gltf = model.gltf;\r\n var techniques = model._sourceTechniques;\r\n var uniformMaps = model._uniformMaps;\r\n\r\n var textures = model._rendererResources.textures;\r\n var defaultTexture = model._defaultTexture;\r\n\r\n ForEach.material(gltf, function (material, materialId) {\r\n var modelMaterial = model._runtime.materialsById[materialId];\r\n var technique = techniques[modelMaterial._technique];\r\n var instanceValues = modelMaterial._values;\r\n\r\n var uniforms = createUniformsForMaterial(\r\n model,\r\n material,\r\n technique,\r\n instanceValues,\r\n context,\r\n textures,\r\n defaultTexture\r\n );\r\n\r\n var u = uniformMaps[materialId];\r\n u.uniformMap = uniforms.map; // uniform name -> function for the renderer\r\n u.values = uniforms.values; // material parameter name -> ModelMaterial for modifying the parameter at runtime\r\n u.jointMatrixUniformName = uniforms.jointMatrixUniformName;\r\n u.morphWeightsUniformName = uniforms.morphWeightsUniformName;\r\n\r\n if (defined(technique.attributes.a_outlineCoordinates)) {\r\n var outlineTexture = ModelOutlineLoader.createTexture(model, context);\r\n u.uniformMap.u_outlineTexture = function () {\r\n return outlineTexture;\r\n };\r\n }\r\n });\r\n}\r\n\r\nfunction createUniformsForDracoQuantizedAttributes(decodedData) {\r\n return ModelUtility.createUniformsForDracoQuantizedAttributes(\r\n decodedData.attributes\r\n );\r\n}\r\n\r\nfunction createUniformsForQuantizedAttributes(model, primitive) {\r\n var programId = getProgramForPrimitive(model, primitive);\r\n var quantizedUniforms = model._quantizedUniforms[programId];\r\n return ModelUtility.createUniformsForQuantizedAttributes(\r\n model.gltf,\r\n primitive,\r\n quantizedUniforms\r\n );\r\n}\r\n\r\nfunction createPickColorFunction(color) {\r\n return function () {\r\n return color;\r\n };\r\n}\r\n\r\nfunction createJointMatricesFunction(runtimeNode) {\r\n return function () {\r\n return runtimeNode.computedJointMatrices;\r\n };\r\n}\r\n\r\nfunction createMorphWeightsFunction(runtimeNode) {\r\n return function () {\r\n return runtimeNode.weights;\r\n };\r\n}\r\n\r\nfunction createSilhouetteColorFunction(model) {\r\n return function () {\r\n return model.silhouetteColor;\r\n };\r\n}\r\n\r\nfunction createSilhouetteSizeFunction(model) {\r\n return function () {\r\n return model.silhouetteSize;\r\n };\r\n}\r\n\r\nfunction createColorFunction(model) {\r\n return function () {\r\n return model.color;\r\n };\r\n}\r\n\r\nfunction createClippingPlanesMatrixFunction(model) {\r\n return function () {\r\n return model._clippingPlanesMatrix;\r\n };\r\n}\r\n\r\nfunction createIBLReferenceFrameMatrixFunction(model) {\r\n return function () {\r\n return model._iblReferenceFrameMatrix;\r\n };\r\n}\r\n\r\nfunction createClippingPlanesFunction(model) {\r\n return function () {\r\n var clippingPlanes = model.clippingPlanes;\r\n return !defined(clippingPlanes) || !clippingPlanes.enabled\r\n ? model._defaultTexture\r\n : clippingPlanes.texture;\r\n };\r\n}\r\n\r\nfunction createClippingPlanesEdgeStyleFunction(model) {\r\n return function () {\r\n var clippingPlanes = model.clippingPlanes;\r\n if (!defined(clippingPlanes)) {\r\n return Color.WHITE.withAlpha(0.0);\r\n }\r\n\r\n var style = Color.clone(clippingPlanes.edgeColor);\r\n style.alpha = clippingPlanes.edgeWidth;\r\n return style;\r\n };\r\n}\r\n\r\nfunction createColorBlendFunction(model) {\r\n return function () {\r\n return ColorBlendMode.getColorBlend(\r\n model.colorBlendMode,\r\n model.colorBlendAmount\r\n );\r\n };\r\n}\r\n\r\nfunction createIBLFactorFunction(model) {\r\n return function () {\r\n return model._imageBasedLightingFactor;\r\n };\r\n}\r\n\r\nfunction createLightColorFunction(model) {\r\n return function () {\r\n return model._lightColor;\r\n };\r\n}\r\n\r\nfunction createLuminanceAtZenithFunction(model) {\r\n return function () {\r\n return model.luminanceAtZenith;\r\n };\r\n}\r\n\r\nfunction createSphericalHarmonicCoefficientsFunction(model) {\r\n return function () {\r\n return model._sphericalHarmonicCoefficients;\r\n };\r\n}\r\n\r\nfunction createSpecularEnvironmentMapFunction(model) {\r\n return function () {\r\n return model._specularEnvironmentMapAtlas.texture;\r\n };\r\n}\r\n\r\nfunction createSpecularEnvironmentMapSizeFunction(model) {\r\n return function () {\r\n return model._specularEnvironmentMapAtlas.texture.dimensions;\r\n };\r\n}\r\n\r\nfunction createSpecularEnvironmentMapLOD(model) {\r\n return function () {\r\n return model._specularEnvironmentMapAtlas.maximumMipmapLevel;\r\n };\r\n}\r\n\r\nfunction triangleCountFromPrimitiveIndices(primitive, indicesCount) {\r\n switch (primitive.mode) {\r\n case PrimitiveType.TRIANGLES:\r\n return indicesCount / 3;\r\n case PrimitiveType.TRIANGLE_STRIP:\r\n case PrimitiveType.TRIANGLE_FAN:\r\n return Math.max(indicesCount - 2, 0);\r\n default:\r\n return 0;\r\n }\r\n}\r\n\r\nfunction createCommand(model, gltfNode, runtimeNode, context, scene3DOnly) {\r\n var nodeCommands = model._nodeCommands;\r\n var pickIds = model._pickIds;\r\n var allowPicking = model.allowPicking;\r\n var runtimeMeshesByName = model._runtime.meshesByName;\r\n\r\n var resources = model._rendererResources;\r\n var rendererVertexArrays = resources.vertexArrays;\r\n var rendererPrograms = resources.programs;\r\n var rendererRenderStates = resources.renderStates;\r\n var uniformMaps = model._uniformMaps;\r\n\r\n var gltf = model.gltf;\r\n var accessors = gltf.accessors;\r\n var gltfMeshes = gltf.meshes;\r\n\r\n var id = gltfNode.mesh;\r\n var mesh = gltfMeshes[id];\r\n\r\n var primitives = mesh.primitives;\r\n var length = primitives.length;\r\n\r\n // The glTF node hierarchy is a DAG so a node can have more than one\r\n // parent, so a node may already have commands. If so, append more\r\n // since they will have a different model matrix.\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var primitive = primitives[i];\r\n var ix = accessors[primitive.indices];\r\n var material = model._runtime.materialsById[primitive.material];\r\n var programId = material._program;\r\n var decodedData = model._decodedData[id + \".primitive.\" + i];\r\n\r\n var boundingSphere;\r\n var positionAccessor = primitive.attributes.POSITION;\r\n if (defined(positionAccessor)) {\r\n var minMax = ModelUtility.getAccessorMinMax(gltf, positionAccessor);\r\n boundingSphere = BoundingSphere.fromCornerPoints(\r\n Cartesian3.fromArray(minMax.min),\r\n Cartesian3.fromArray(minMax.max)\r\n );\r\n }\r\n\r\n var vertexArray = rendererVertexArrays[id + \".primitive.\" + i];\r\n var offset;\r\n var count;\r\n\r\n // Use indices of the previously decoded Draco geometry.\r\n if (defined(decodedData)) {\r\n count = decodedData.numberOfIndices;\r\n offset = 0;\r\n } else if (defined(ix)) {\r\n count = ix.count;\r\n offset = ix.byteOffset / IndexDatatype.getSizeInBytes(ix.componentType); // glTF has offset in bytes. Cesium has offsets in indices\r\n } else {\r\n var positions = accessors[primitive.attributes.POSITION];\r\n count = positions.count;\r\n offset = 0;\r\n }\r\n\r\n // Update model triangle count using number of indices\r\n model._trianglesLength += triangleCountFromPrimitiveIndices(\r\n primitive,\r\n count\r\n );\r\n\r\n var um = uniformMaps[primitive.material];\r\n var uniformMap = um.uniformMap;\r\n if (defined(um.jointMatrixUniformName)) {\r\n var jointUniformMap = {};\r\n jointUniformMap[um.jointMatrixUniformName] = createJointMatricesFunction(\r\n runtimeNode\r\n );\r\n\r\n uniformMap = combine(uniformMap, jointUniformMap);\r\n }\r\n if (defined(um.morphWeightsUniformName)) {\r\n var morphWeightsUniformMap = {};\r\n morphWeightsUniformMap[\r\n um.morphWeightsUniformName\r\n ] = createMorphWeightsFunction(runtimeNode);\r\n\r\n uniformMap = combine(uniformMap, morphWeightsUniformMap);\r\n }\r\n\r\n uniformMap = combine(uniformMap, {\r\n gltf_color: createColorFunction(model),\r\n gltf_colorBlend: createColorBlendFunction(model),\r\n gltf_clippingPlanes: createClippingPlanesFunction(model),\r\n gltf_clippingPlanesEdgeStyle: createClippingPlanesEdgeStyleFunction(\r\n model\r\n ),\r\n gltf_clippingPlanesMatrix: createClippingPlanesMatrixFunction(model),\r\n gltf_iblReferenceFrameMatrix: createIBLReferenceFrameMatrixFunction(\r\n model\r\n ),\r\n gltf_iblFactor: createIBLFactorFunction(model),\r\n gltf_lightColor: createLightColorFunction(model),\r\n gltf_sphericalHarmonicCoefficients: createSphericalHarmonicCoefficientsFunction(\r\n model\r\n ),\r\n gltf_specularMap: createSpecularEnvironmentMapFunction(model),\r\n gltf_specularMapSize: createSpecularEnvironmentMapSizeFunction(model),\r\n gltf_maxSpecularLOD: createSpecularEnvironmentMapLOD(model),\r\n gltf_luminanceAtZenith: createLuminanceAtZenithFunction(model),\r\n });\r\n\r\n // Allow callback to modify the uniformMap\r\n if (defined(model._uniformMapLoaded)) {\r\n uniformMap = model._uniformMapLoaded(uniformMap, programId, runtimeNode);\r\n }\r\n\r\n // Add uniforms for decoding quantized attributes if used\r\n var quantizedUniformMap = {};\r\n if (model.extensionsUsed.WEB3D_quantized_attributes) {\r\n quantizedUniformMap = createUniformsForQuantizedAttributes(\r\n model,\r\n primitive\r\n );\r\n } else if (model._dequantizeInShader && defined(decodedData)) {\r\n quantizedUniformMap = createUniformsForDracoQuantizedAttributes(\r\n decodedData\r\n );\r\n }\r\n uniformMap = combine(uniformMap, quantizedUniformMap);\r\n\r\n var rs = rendererRenderStates[primitive.material];\r\n var isTranslucent = rs.blending.enabled;\r\n\r\n var owner = model._pickObject;\r\n if (!defined(owner)) {\r\n owner = {\r\n primitive: model,\r\n id: model.id,\r\n node: runtimeNode.publicNode,\r\n mesh: runtimeMeshesByName[mesh.name],\r\n };\r\n }\r\n\r\n var castShadows = ShadowMode.castShadows(model._shadows);\r\n var receiveShadows = ShadowMode.receiveShadows(model._shadows);\r\n\r\n var pickId;\r\n if (allowPicking && !defined(model._uniformMapLoaded)) {\r\n pickId = context.createPickId(owner);\r\n pickIds.push(pickId);\r\n var pickUniforms = {\r\n czm_pickColor: createPickColorFunction(pickId.color),\r\n };\r\n uniformMap = combine(uniformMap, pickUniforms);\r\n }\r\n\r\n if (allowPicking) {\r\n if (defined(model._pickIdLoaded) && defined(model._uniformMapLoaded)) {\r\n pickId = model._pickIdLoaded();\r\n } else {\r\n pickId = \"czm_pickColor\";\r\n }\r\n }\r\n\r\n var command = new DrawCommand({\r\n boundingVolume: new BoundingSphere(), // updated in update()\r\n cull: model.cull,\r\n modelMatrix: new Matrix4(), // computed in update()\r\n primitiveType: primitive.mode,\r\n vertexArray: vertexArray,\r\n count: count,\r\n offset: offset,\r\n shaderProgram: rendererPrograms[programId],\r\n castShadows: castShadows,\r\n receiveShadows: receiveShadows,\r\n uniformMap: uniformMap,\r\n renderState: rs,\r\n owner: owner,\r\n pass: isTranslucent ? Pass.TRANSLUCENT : model.opaquePass,\r\n pickId: pickId,\r\n });\r\n\r\n var command2D;\r\n if (!scene3DOnly) {\r\n command2D = DrawCommand.shallowClone(command);\r\n command2D.boundingVolume = new BoundingSphere(); // updated in update()\r\n command2D.modelMatrix = new Matrix4(); // updated in update()\r\n }\r\n\r\n var nodeCommand = {\r\n show: true,\r\n boundingSphere: boundingSphere,\r\n command: command,\r\n command2D: command2D,\r\n // Generated on demand when silhouette size is greater than 0.0 and silhouette alpha is greater than 0.0\r\n silhouetteModelCommand: undefined,\r\n silhouetteModelCommand2D: undefined,\r\n silhouetteColorCommand: undefined,\r\n silhouetteColorCommand2D: undefined,\r\n // Generated on demand when color alpha is less than 1.0\r\n translucentCommand: undefined,\r\n translucentCommand2D: undefined,\r\n // Generated on demand when back face culling is false\r\n disableCullingCommand: undefined,\r\n disableCullingCommand2D: undefined,\r\n // For updating node commands on shader reconstruction\r\n programId: programId,\r\n };\r\n runtimeNode.commands.push(nodeCommand);\r\n nodeCommands.push(nodeCommand);\r\n }\r\n}\r\n\r\nfunction createRuntimeNodes(model, context, scene3DOnly) {\r\n var loadResources = model._loadResources;\r\n\r\n if (!loadResources.finishedEverythingButTextureCreation()) {\r\n return;\r\n }\r\n\r\n if (!loadResources.createRuntimeNodes) {\r\n return;\r\n }\r\n loadResources.createRuntimeNodes = false;\r\n\r\n var rootNodes = [];\r\n var runtimeNodes = model._runtime.nodes;\r\n\r\n var gltf = model.gltf;\r\n var nodes = gltf.nodes;\r\n\r\n var scene = gltf.scenes[gltf.scene];\r\n var sceneNodes = scene.nodes;\r\n var length = sceneNodes.length;\r\n\r\n var stack = [];\r\n var seen = {};\r\n\r\n for (var i = 0; i < length; ++i) {\r\n stack.push({\r\n parentRuntimeNode: undefined,\r\n gltfNode: nodes[sceneNodes[i]],\r\n id: sceneNodes[i],\r\n });\r\n\r\n while (stack.length > 0) {\r\n var n = stack.pop();\r\n seen[n.id] = true;\r\n var parentRuntimeNode = n.parentRuntimeNode;\r\n var gltfNode = n.gltfNode;\r\n\r\n // Node hierarchy is a DAG so a node can have more than one parent so it may already exist\r\n var runtimeNode = runtimeNodes[n.id];\r\n if (runtimeNode.parents.length === 0) {\r\n if (defined(gltfNode.matrix)) {\r\n runtimeNode.matrix = Matrix4.fromColumnMajorArray(gltfNode.matrix);\r\n } else {\r\n // TRS converted to Cesium types\r\n var rotation = gltfNode.rotation;\r\n runtimeNode.translation = Cartesian3.fromArray(gltfNode.translation);\r\n runtimeNode.rotation = Quaternion.unpack(rotation);\r\n runtimeNode.scale = Cartesian3.fromArray(gltfNode.scale);\r\n }\r\n }\r\n\r\n if (defined(parentRuntimeNode)) {\r\n parentRuntimeNode.children.push(runtimeNode);\r\n runtimeNode.parents.push(parentRuntimeNode);\r\n } else {\r\n rootNodes.push(runtimeNode);\r\n }\r\n\r\n if (defined(gltfNode.mesh)) {\r\n createCommand(model, gltfNode, runtimeNode, context, scene3DOnly);\r\n }\r\n\r\n var children = gltfNode.children;\r\n if (defined(children)) {\r\n var childrenLength = children.length;\r\n for (var j = 0; j < childrenLength; j++) {\r\n var childId = children[j];\r\n if (!seen[childId]) {\r\n stack.push({\r\n parentRuntimeNode: runtimeNode,\r\n gltfNode: nodes[childId],\r\n id: children[j],\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n model._runtime.rootNodes = rootNodes;\r\n model._runtime.nodes = runtimeNodes;\r\n}\r\n\r\nfunction getGeometryByteLength(buffers) {\r\n var memory = 0;\r\n for (var id in buffers) {\r\n if (buffers.hasOwnProperty(id)) {\r\n memory += buffers[id].sizeInBytes;\r\n }\r\n }\r\n return memory;\r\n}\r\n\r\nfunction getTexturesByteLength(textures) {\r\n var memory = 0;\r\n for (var id in textures) {\r\n if (textures.hasOwnProperty(id)) {\r\n memory += textures[id].sizeInBytes;\r\n }\r\n }\r\n return memory;\r\n}\r\n\r\nfunction createResources(model, frameState) {\r\n var context = frameState.context;\r\n var scene3DOnly = frameState.scene3DOnly;\r\n var quantizedVertexShaders = model._quantizedVertexShaders;\r\n var techniques = model._sourceTechniques;\r\n var programs = model._sourcePrograms;\r\n\r\n var resources = model._rendererResources;\r\n var shaders = resources.sourceShaders;\r\n if (model._loadRendererResourcesFromCache) {\r\n shaders = resources.sourceShaders =\r\n model._cachedRendererResources.sourceShaders;\r\n }\r\n\r\n for (var techniqueId in techniques) {\r\n if (techniques.hasOwnProperty(techniqueId)) {\r\n var programId = techniques[techniqueId].program;\r\n var program = programs[programId];\r\n var shader = shaders[program.vertexShader];\r\n\r\n ModelUtility.checkSupportedGlExtensions(program.glExtensions, context);\r\n\r\n if (\r\n model.extensionsUsed.WEB3D_quantized_attributes ||\r\n model._dequantizeInShader\r\n ) {\r\n var quantizedVS = quantizedVertexShaders[programId];\r\n if (!defined(quantizedVS)) {\r\n quantizedVS = modifyShaderForQuantizedAttributes(\r\n shader,\r\n programId,\r\n model\r\n );\r\n quantizedVertexShaders[programId] = quantizedVS;\r\n }\r\n shader = quantizedVS;\r\n }\r\n\r\n shader = modifyShader(shader, programId, model._vertexShaderLoaded);\r\n }\r\n }\r\n\r\n if (model._loadRendererResourcesFromCache) {\r\n var cachedResources = model._cachedRendererResources;\r\n\r\n resources.buffers = cachedResources.buffers;\r\n resources.vertexArrays = cachedResources.vertexArrays;\r\n resources.programs = cachedResources.programs;\r\n resources.silhouettePrograms = cachedResources.silhouettePrograms;\r\n resources.textures = cachedResources.textures;\r\n resources.samplers = cachedResources.samplers;\r\n resources.renderStates = cachedResources.renderStates;\r\n\r\n // Vertex arrays are unique to this model, create instead of using the cache.\r\n if (defined(model._precreatedAttributes)) {\r\n createVertexArrays(model, context);\r\n }\r\n\r\n model._cachedGeometryByteLength += getGeometryByteLength(\r\n cachedResources.buffers\r\n );\r\n model._cachedTexturesByteLength += getTexturesByteLength(\r\n cachedResources.textures\r\n );\r\n } else {\r\n createBuffers(model, frameState); // using glTF bufferViews\r\n createPrograms(model, frameState);\r\n createSamplers(model, context);\r\n loadTexturesFromBufferViews(model);\r\n createTextures(model, frameState);\r\n }\r\n\r\n createSkins(model);\r\n createRuntimeAnimations(model);\r\n\r\n if (!model._loadRendererResourcesFromCache) {\r\n createVertexArrays(model, context); // using glTF meshes\r\n createRenderStates(model); // using glTF materials/techniques/states\r\n // Long-term, we might not cache render states if they could change\r\n // due to an animation, e.g., a uniform going from opaque to transparent.\r\n // Could use copy-on-write if it is worth it. Probably overkill.\r\n }\r\n\r\n createUniformMaps(model, context); // using glTF materials/techniques\r\n createRuntimeNodes(model, context, scene3DOnly); // using glTF scene\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction getNodeMatrix(node, result) {\r\n var publicNode = node.publicNode;\r\n var publicMatrix = publicNode.matrix;\r\n\r\n if (publicNode.useMatrix && defined(publicMatrix)) {\r\n // Public matrix overrides original glTF matrix and glTF animations\r\n Matrix4.clone(publicMatrix, result);\r\n } else if (defined(node.matrix)) {\r\n Matrix4.clone(node.matrix, result);\r\n } else {\r\n Matrix4.fromTranslationQuaternionRotationScale(\r\n node.translation,\r\n node.rotation,\r\n node.scale,\r\n result\r\n );\r\n // Keep matrix returned by the node in-sync if the node is targeted by an animation. Only TRS nodes can be targeted.\r\n publicNode.setMatrix(result);\r\n }\r\n}\r\n\r\nvar scratchNodeStack = [];\r\nvar scratchComputedTranslation = new Cartesian4();\r\nvar scratchComputedMatrixIn2D = new Matrix4();\r\n\r\nfunction updateNodeHierarchyModelMatrix(\r\n model,\r\n modelTransformChanged,\r\n justLoaded,\r\n projection\r\n) {\r\n var maxDirtyNumber = model._maxDirtyNumber;\r\n\r\n var rootNodes = model._runtime.rootNodes;\r\n var length = rootNodes.length;\r\n\r\n var nodeStack = scratchNodeStack;\r\n var computedModelMatrix = model._computedModelMatrix;\r\n\r\n if (model._mode !== SceneMode.SCENE3D && !model._ignoreCommands) {\r\n var translation = Matrix4.getColumn(\r\n computedModelMatrix,\r\n 3,\r\n scratchComputedTranslation\r\n );\r\n if (!Cartesian4.equals(translation, Cartesian4.UNIT_W)) {\r\n computedModelMatrix = Transforms.basisTo2D(\r\n projection,\r\n computedModelMatrix,\r\n scratchComputedMatrixIn2D\r\n );\r\n model._rtcCenter = model._rtcCenter3D;\r\n } else {\r\n var center = model.boundingSphere.center;\r\n var to2D = Transforms.wgs84To2DModelMatrix(\r\n projection,\r\n center,\r\n scratchComputedMatrixIn2D\r\n );\r\n computedModelMatrix = Matrix4.multiply(\r\n to2D,\r\n computedModelMatrix,\r\n scratchComputedMatrixIn2D\r\n );\r\n\r\n if (defined(model._rtcCenter)) {\r\n Matrix4.setTranslation(\r\n computedModelMatrix,\r\n Cartesian4.UNIT_W,\r\n computedModelMatrix\r\n );\r\n model._rtcCenter = model._rtcCenter2D;\r\n }\r\n }\r\n }\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var n = rootNodes[i];\r\n\r\n getNodeMatrix(n, n.transformToRoot);\r\n nodeStack.push(n);\r\n\r\n while (nodeStack.length > 0) {\r\n n = nodeStack.pop();\r\n var transformToRoot = n.transformToRoot;\r\n var commands = n.commands;\r\n\r\n if (\r\n n.dirtyNumber === maxDirtyNumber ||\r\n modelTransformChanged ||\r\n justLoaded\r\n ) {\r\n var nodeMatrix = Matrix4.multiplyTransformation(\r\n computedModelMatrix,\r\n transformToRoot,\r\n n.computedMatrix\r\n );\r\n var commandsLength = commands.length;\r\n if (commandsLength > 0) {\r\n // Node has meshes, which has primitives. Update their commands.\r\n for (var j = 0; j < commandsLength; ++j) {\r\n var primitiveCommand = commands[j];\r\n var command = primitiveCommand.command;\r\n Matrix4.clone(nodeMatrix, command.modelMatrix);\r\n\r\n // PERFORMANCE_IDEA: Can use transformWithoutScale if no node up to the root has scale (including animation)\r\n BoundingSphere.transform(\r\n primitiveCommand.boundingSphere,\r\n command.modelMatrix,\r\n command.boundingVolume\r\n );\r\n\r\n if (defined(model._rtcCenter)) {\r\n Cartesian3.add(\r\n model._rtcCenter,\r\n command.boundingVolume.center,\r\n command.boundingVolume.center\r\n );\r\n }\r\n\r\n // If the model crosses the IDL in 2D, it will be drawn in one viewport, but part of it\r\n // will be clipped by the viewport. We create a second command that translates the model\r\n // model matrix to the opposite side of the map so the part that was clipped in one viewport\r\n // is drawn in the other.\r\n command = primitiveCommand.command2D;\r\n if (defined(command) && model._mode === SceneMode.SCENE2D) {\r\n Matrix4.clone(nodeMatrix, command.modelMatrix);\r\n command.modelMatrix[13] -=\r\n CesiumMath.sign(command.modelMatrix[13]) *\r\n 2.0 *\r\n CesiumMath.PI *\r\n projection.ellipsoid.maximumRadius;\r\n BoundingSphere.transform(\r\n primitiveCommand.boundingSphere,\r\n command.modelMatrix,\r\n command.boundingVolume\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n var children = n.children;\r\n if (defined(children)) {\r\n var childrenLength = children.length;\r\n for (var k = 0; k < childrenLength; ++k) {\r\n var child = children[k];\r\n\r\n // A node's transform needs to be updated if\r\n // - It was targeted for animation this frame, or\r\n // - Any of its ancestors were targeted for animation this frame\r\n\r\n // PERFORMANCE_IDEA: if a child has multiple parents and only one of the parents\r\n // is dirty, all the subtrees for each child instance will be dirty; we probably\r\n // won't see this in the wild often.\r\n child.dirtyNumber = Math.max(child.dirtyNumber, n.dirtyNumber);\r\n\r\n if (child.dirtyNumber === maxDirtyNumber || justLoaded) {\r\n // Don't check for modelTransformChanged since if only the model's model matrix changed,\r\n // we do not need to rebuild the local transform-to-root, only the final\r\n // [model's-model-matrix][transform-to-root] above.\r\n getNodeMatrix(child, child.transformToRoot);\r\n Matrix4.multiplyTransformation(\r\n transformToRoot,\r\n child.transformToRoot,\r\n child.transformToRoot\r\n );\r\n }\r\n\r\n nodeStack.push(child);\r\n }\r\n }\r\n }\r\n }\r\n\r\n ++model._maxDirtyNumber;\r\n}\r\n\r\nvar scratchObjectSpace = new Matrix4();\r\n\r\nfunction applySkins(model) {\r\n var skinnedNodes = model._runtime.skinnedNodes;\r\n var length = skinnedNodes.length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var node = skinnedNodes[i];\r\n\r\n scratchObjectSpace = Matrix4.inverseTransformation(\r\n node.transformToRoot,\r\n scratchObjectSpace\r\n );\r\n\r\n var computedJointMatrices = node.computedJointMatrices;\r\n var joints = node.joints;\r\n var bindShapeMatrix = node.bindShapeMatrix;\r\n var inverseBindMatrices = node.inverseBindMatrices;\r\n var inverseBindMatricesLength = inverseBindMatrices.length;\r\n\r\n for (var m = 0; m < inverseBindMatricesLength; ++m) {\r\n // [joint-matrix] = [node-to-root^-1][joint-to-root][inverse-bind][bind-shape]\r\n if (!defined(computedJointMatrices[m])) {\r\n computedJointMatrices[m] = new Matrix4();\r\n }\r\n computedJointMatrices[m] = Matrix4.multiplyTransformation(\r\n scratchObjectSpace,\r\n joints[m].transformToRoot,\r\n computedJointMatrices[m]\r\n );\r\n computedJointMatrices[m] = Matrix4.multiplyTransformation(\r\n computedJointMatrices[m],\r\n inverseBindMatrices[m],\r\n computedJointMatrices[m]\r\n );\r\n if (defined(bindShapeMatrix)) {\r\n // NOTE: bindShapeMatrix is glTF 1.0 only, removed in glTF 2.0.\r\n computedJointMatrices[m] = Matrix4.multiplyTransformation(\r\n computedJointMatrices[m],\r\n bindShapeMatrix,\r\n computedJointMatrices[m]\r\n );\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction updatePerNodeShow(model) {\r\n // Totally not worth it, but we could optimize this:\r\n // http://help.agi.com/AGIComponents/html/BlogDeletionInBoundingVolumeHierarchies.htm\r\n\r\n var rootNodes = model._runtime.rootNodes;\r\n var length = rootNodes.length;\r\n\r\n var nodeStack = scratchNodeStack;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var n = rootNodes[i];\r\n n.computedShow = n.publicNode.show;\r\n nodeStack.push(n);\r\n\r\n while (nodeStack.length > 0) {\r\n n = nodeStack.pop();\r\n var show = n.computedShow;\r\n\r\n var nodeCommands = n.commands;\r\n var nodeCommandsLength = nodeCommands.length;\r\n for (var j = 0; j < nodeCommandsLength; ++j) {\r\n nodeCommands[j].show = show;\r\n }\r\n // if commandsLength is zero, the node has a light or camera\r\n\r\n var children = n.children;\r\n if (defined(children)) {\r\n var childrenLength = children.length;\r\n for (var k = 0; k < childrenLength; ++k) {\r\n var child = children[k];\r\n // Parent needs to be shown for child to be shown.\r\n child.computedShow = show && child.publicNode.show;\r\n nodeStack.push(child);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction updatePickIds(model, context) {\r\n var id = model.id;\r\n if (model._id !== id) {\r\n model._id = id;\r\n\r\n var pickIds = model._pickIds;\r\n var length = pickIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n pickIds[i].object.id = id;\r\n }\r\n }\r\n}\r\n\r\nfunction updateWireframe(model) {\r\n if (model._debugWireframe !== model.debugWireframe) {\r\n model._debugWireframe = model.debugWireframe;\r\n\r\n // This assumes the original primitive was TRIANGLES and that the triangles\r\n // are connected for the wireframe to look perfect.\r\n var primitiveType = model.debugWireframe\r\n ? PrimitiveType.LINES\r\n : PrimitiveType.TRIANGLES;\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n nodeCommands[i].command.primitiveType = primitiveType;\r\n }\r\n }\r\n}\r\n\r\nfunction updateShowBoundingVolume(model) {\r\n if (model.debugShowBoundingVolume !== model._debugShowBoundingVolume) {\r\n model._debugShowBoundingVolume = model.debugShowBoundingVolume;\r\n\r\n var debugShowBoundingVolume = model.debugShowBoundingVolume;\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n nodeCommands[i].command.debugShowBoundingVolume = debugShowBoundingVolume;\r\n }\r\n }\r\n}\r\n\r\nfunction updateShadows(model) {\r\n if (model.shadows !== model._shadows) {\r\n model._shadows = model.shadows;\r\n\r\n var castShadows = ShadowMode.castShadows(model.shadows);\r\n var receiveShadows = ShadowMode.receiveShadows(model.shadows);\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n\r\n for (var i = 0; i < length; i++) {\r\n var nodeCommand = nodeCommands[i];\r\n nodeCommand.command.castShadows = castShadows;\r\n nodeCommand.command.receiveShadows = receiveShadows;\r\n }\r\n }\r\n}\r\n\r\nfunction getTranslucentRenderState(model, renderState) {\r\n var rs = clone(renderState, true);\r\n rs.cull.enabled = false;\r\n rs.depthTest.enabled = true;\r\n rs.depthMask = false;\r\n rs.blending = BlendingState.ALPHA_BLEND;\r\n\r\n if (model.opaquePass === Pass.CESIUM_3D_TILE) {\r\n rs.stencilTest = StencilConstants.setCesium3DTileBit();\r\n rs.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;\r\n }\r\n\r\n return RenderState.fromCache(rs);\r\n}\r\n\r\nfunction deriveTranslucentCommand(model, command) {\r\n var translucentCommand = DrawCommand.shallowClone(command);\r\n translucentCommand.pass = Pass.TRANSLUCENT;\r\n translucentCommand.renderState = getTranslucentRenderState(\r\n model,\r\n command.renderState\r\n );\r\n return translucentCommand;\r\n}\r\n\r\nfunction updateColor(model, frameState, forceDerive) {\r\n // Generate translucent commands when the blend color has an alpha in the range (0.0, 1.0) exclusive\r\n var scene3DOnly = frameState.scene3DOnly;\r\n var alpha = model.color.alpha;\r\n if (alpha > 0.0 && alpha < 1.0) {\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n if (\r\n length > 0 &&\r\n (!defined(nodeCommands[0].translucentCommand) || forceDerive)\r\n ) {\r\n for (var i = 0; i < length; ++i) {\r\n var nodeCommand = nodeCommands[i];\r\n var command = nodeCommand.command;\r\n nodeCommand.translucentCommand = deriveTranslucentCommand(\r\n model,\r\n command\r\n );\r\n if (!scene3DOnly) {\r\n var command2D = nodeCommand.command2D;\r\n nodeCommand.translucentCommand2D = deriveTranslucentCommand(\r\n model,\r\n command2D\r\n );\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction getDisableCullingRenderState(renderState) {\r\n var rs = clone(renderState, true);\r\n rs.cull.enabled = false;\r\n return RenderState.fromCache(rs);\r\n}\r\n\r\nfunction deriveDisableCullingCommand(command) {\r\n var disableCullingCommand = DrawCommand.shallowClone(command);\r\n disableCullingCommand.renderState = getDisableCullingRenderState(\r\n command.renderState\r\n );\r\n return disableCullingCommand;\r\n}\r\n\r\nfunction updateBackFaceCulling(model, frameState, forceDerive) {\r\n var scene3DOnly = frameState.scene3DOnly;\r\n var backFaceCulling = model.backFaceCulling;\r\n if (!backFaceCulling) {\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n if (\r\n length > 0 &&\r\n (!defined(nodeCommands[0].disableCullingCommand) || forceDerive)\r\n ) {\r\n for (var i = 0; i < length; ++i) {\r\n var nodeCommand = nodeCommands[i];\r\n var command = nodeCommand.command;\r\n nodeCommand.disableCullingCommand = deriveDisableCullingCommand(\r\n command\r\n );\r\n if (!scene3DOnly) {\r\n var command2D = nodeCommand.command2D;\r\n nodeCommand.disableCullingCommand2D = deriveDisableCullingCommand(\r\n command2D\r\n );\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction getProgramId(model, program) {\r\n var programs = model._rendererResources.programs;\r\n for (var id in programs) {\r\n if (programs.hasOwnProperty(id)) {\r\n if (programs[id] === program) {\r\n return id;\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction createSilhouetteProgram(model, program, frameState) {\r\n var vs = program.vertexShaderSource.sources[0];\r\n var attributeLocations = program._attributeLocations;\r\n var normalAttributeName = model._normalAttributeName;\r\n\r\n // Modified from http://forum.unity3d.com/threads/toon-outline-but-with-diffuse-surface.24668/\r\n vs = ShaderSource.replaceMain(vs, \"gltf_silhouette_main\");\r\n vs +=\r\n \"uniform float gltf_silhouetteSize; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" gltf_silhouette_main(); \\n\" +\r\n \" vec3 n = normalize(czm_normal3D * \" +\r\n normalAttributeName +\r\n \"); \\n\" +\r\n \" n.x *= czm_projection[0][0]; \\n\" +\r\n \" n.y *= czm_projection[1][1]; \\n\" +\r\n \" vec4 clip = gl_Position; \\n\" +\r\n \" clip.xy += n.xy * clip.w * gltf_silhouetteSize * czm_pixelRatio / czm_viewport.z; \\n\" +\r\n \" gl_Position = clip; \\n\" +\r\n \"}\";\r\n\r\n var fs =\r\n \"uniform vec4 gltf_silhouetteColor; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" gl_FragColor = czm_gammaCorrect(gltf_silhouetteColor); \\n\" +\r\n \"}\";\r\n\r\n return ShaderProgram.fromCache({\r\n context: frameState.context,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n}\r\n\r\nfunction hasSilhouette(model, frameState) {\r\n return (\r\n silhouetteSupported(frameState.context) &&\r\n model.silhouetteSize > 0.0 &&\r\n model.silhouetteColor.alpha > 0.0 &&\r\n defined(model._normalAttributeName)\r\n );\r\n}\r\n\r\nfunction hasTranslucentCommands(model) {\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n for (var i = 0; i < length; ++i) {\r\n var nodeCommand = nodeCommands[i];\r\n var command = nodeCommand.command;\r\n if (command.pass === Pass.TRANSLUCENT) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nfunction isTranslucent(model) {\r\n return model.color.alpha > 0.0 && model.color.alpha < 1.0;\r\n}\r\n\r\nfunction isInvisible(model) {\r\n return model.color.alpha === 0.0;\r\n}\r\n\r\nfunction alphaDirty(currAlpha, prevAlpha) {\r\n // Returns whether the alpha state has changed between invisible, translucent, or opaque\r\n return (\r\n Math.floor(currAlpha) !== Math.floor(prevAlpha) ||\r\n Math.ceil(currAlpha) !== Math.ceil(prevAlpha)\r\n );\r\n}\r\n\r\nvar silhouettesLength = 0;\r\n\r\nfunction createSilhouetteCommands(model, frameState) {\r\n // Wrap around after exceeding the 8-bit stencil limit.\r\n // The reference is unique to each model until this point.\r\n var stencilReference = ++silhouettesLength % 255;\r\n\r\n // If the model is translucent the silhouette needs to be in the translucent pass.\r\n // Otherwise the silhouette would be rendered before the model.\r\n var silhouetteTranslucent =\r\n hasTranslucentCommands(model) ||\r\n isTranslucent(model) ||\r\n model.silhouetteColor.alpha < 1.0;\r\n var silhouettePrograms = model._rendererResources.silhouettePrograms;\r\n var scene3DOnly = frameState.scene3DOnly;\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n for (var i = 0; i < length; ++i) {\r\n var nodeCommand = nodeCommands[i];\r\n var command = nodeCommand.command;\r\n\r\n // Create model command\r\n var modelCommand = isTranslucent(model)\r\n ? nodeCommand.translucentCommand\r\n : command;\r\n var silhouetteModelCommand = DrawCommand.shallowClone(modelCommand);\r\n var renderState = clone(modelCommand.renderState);\r\n\r\n // Write the reference value into the stencil buffer.\r\n renderState.stencilTest = {\r\n enabled: true,\r\n frontFunction: WebGLConstants.ALWAYS,\r\n backFunction: WebGLConstants.ALWAYS,\r\n reference: stencilReference,\r\n mask: ~0,\r\n frontOperation: {\r\n fail: WebGLConstants.KEEP,\r\n zFail: WebGLConstants.KEEP,\r\n zPass: WebGLConstants.REPLACE,\r\n },\r\n backOperation: {\r\n fail: WebGLConstants.KEEP,\r\n zFail: WebGLConstants.KEEP,\r\n zPass: WebGLConstants.REPLACE,\r\n },\r\n };\r\n\r\n if (isInvisible(model)) {\r\n // When the model is invisible disable color and depth writes but still write into the stencil buffer\r\n renderState.colorMask = {\r\n red: false,\r\n green: false,\r\n blue: false,\r\n alpha: false,\r\n };\r\n renderState.depthMask = false;\r\n }\r\n renderState = RenderState.fromCache(renderState);\r\n silhouetteModelCommand.renderState = renderState;\r\n nodeCommand.silhouetteModelCommand = silhouetteModelCommand;\r\n\r\n // Create color command\r\n var silhouetteColorCommand = DrawCommand.shallowClone(command);\r\n renderState = clone(command.renderState, true);\r\n renderState.depthTest.enabled = true;\r\n renderState.cull.enabled = false;\r\n if (silhouetteTranslucent) {\r\n silhouetteColorCommand.pass = Pass.TRANSLUCENT;\r\n renderState.depthMask = false;\r\n renderState.blending = BlendingState.ALPHA_BLEND;\r\n }\r\n\r\n // Only render silhouette if the value in the stencil buffer equals the reference\r\n renderState.stencilTest = {\r\n enabled: true,\r\n frontFunction: WebGLConstants.NOTEQUAL,\r\n backFunction: WebGLConstants.NOTEQUAL,\r\n reference: stencilReference,\r\n mask: ~0,\r\n frontOperation: {\r\n fail: WebGLConstants.KEEP,\r\n zFail: WebGLConstants.KEEP,\r\n zPass: WebGLConstants.KEEP,\r\n },\r\n backOperation: {\r\n fail: WebGLConstants.KEEP,\r\n zFail: WebGLConstants.KEEP,\r\n zPass: WebGLConstants.KEEP,\r\n },\r\n };\r\n renderState = RenderState.fromCache(renderState);\r\n\r\n // If the silhouette program has already been cached use it\r\n var program = command.shaderProgram;\r\n var id = getProgramId(model, program);\r\n var silhouetteProgram = silhouettePrograms[id];\r\n if (!defined(silhouetteProgram)) {\r\n silhouetteProgram = createSilhouetteProgram(model, program, frameState);\r\n silhouettePrograms[id] = silhouetteProgram;\r\n }\r\n\r\n var silhouetteUniformMap = combine(command.uniformMap, {\r\n gltf_silhouetteColor: createSilhouetteColorFunction(model),\r\n gltf_silhouetteSize: createSilhouetteSizeFunction(model),\r\n });\r\n\r\n silhouetteColorCommand.renderState = renderState;\r\n silhouetteColorCommand.shaderProgram = silhouetteProgram;\r\n silhouetteColorCommand.uniformMap = silhouetteUniformMap;\r\n silhouetteColorCommand.castShadows = false;\r\n silhouetteColorCommand.receiveShadows = false;\r\n nodeCommand.silhouetteColorCommand = silhouetteColorCommand;\r\n\r\n if (!scene3DOnly) {\r\n var command2D = nodeCommand.command2D;\r\n var silhouetteModelCommand2D = DrawCommand.shallowClone(\r\n silhouetteModelCommand\r\n );\r\n silhouetteModelCommand2D.boundingVolume = command2D.boundingVolume;\r\n silhouetteModelCommand2D.modelMatrix = command2D.modelMatrix;\r\n nodeCommand.silhouetteModelCommand2D = silhouetteModelCommand2D;\r\n\r\n var silhouetteColorCommand2D = DrawCommand.shallowClone(\r\n silhouetteColorCommand\r\n );\r\n silhouetteModelCommand2D.boundingVolume = command2D.boundingVolume;\r\n silhouetteModelCommand2D.modelMatrix = command2D.modelMatrix;\r\n nodeCommand.silhouetteColorCommand2D = silhouetteColorCommand2D;\r\n }\r\n }\r\n}\r\n\r\nfunction modifyShaderForClippingPlanes(\r\n shader,\r\n clippingPlaneCollection,\r\n context\r\n) {\r\n shader = ShaderSource.replaceMain(shader, \"gltf_clip_main\");\r\n shader += Model._getClippingFunction(clippingPlaneCollection, context) + \"\\n\";\r\n shader +=\r\n \"uniform highp sampler2D gltf_clippingPlanes; \\n\" +\r\n \"uniform mat4 gltf_clippingPlanesMatrix; \\n\" +\r\n \"uniform vec4 gltf_clippingPlanesEdgeStyle; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" gltf_clip_main(); \\n\" +\r\n getClipAndStyleCode(\r\n \"gltf_clippingPlanes\",\r\n \"gltf_clippingPlanesMatrix\",\r\n \"gltf_clippingPlanesEdgeStyle\"\r\n ) +\r\n \"} \\n\";\r\n return shader;\r\n}\r\n\r\nfunction updateSilhouette(model, frameState, force) {\r\n // Generate silhouette commands when the silhouette size is greater than 0.0 and the alpha is greater than 0.0\r\n // There are two silhouette commands:\r\n // 1. silhouetteModelCommand : render model normally while enabling stencil mask\r\n // 2. silhouetteColorCommand : render enlarged model with a solid color while enabling stencil tests\r\n if (!hasSilhouette(model, frameState)) {\r\n return;\r\n }\r\n\r\n var nodeCommands = model._nodeCommands;\r\n var dirty =\r\n nodeCommands.length > 0 &&\r\n (alphaDirty(model.color.alpha, model._colorPreviousAlpha) ||\r\n alphaDirty(\r\n model.silhouetteColor.alpha,\r\n model._silhouetteColorPreviousAlpha\r\n ) ||\r\n !defined(nodeCommands[0].silhouetteModelCommand));\r\n\r\n model._colorPreviousAlpha = model.color.alpha;\r\n model._silhouetteColorPreviousAlpha = model.silhouetteColor.alpha;\r\n\r\n if (dirty || force) {\r\n createSilhouetteCommands(model, frameState);\r\n }\r\n}\r\n\r\nfunction updateClippingPlanes(model, frameState) {\r\n var clippingPlanes = model._clippingPlanes;\r\n if (defined(clippingPlanes) && clippingPlanes.owner === model) {\r\n if (clippingPlanes.enabled) {\r\n clippingPlanes.update(frameState);\r\n }\r\n }\r\n}\r\n\r\nvar scratchBoundingSphere = new BoundingSphere();\r\n\r\nfunction scaleInPixels(positionWC, radius, frameState) {\r\n scratchBoundingSphere.center = positionWC;\r\n scratchBoundingSphere.radius = radius;\r\n return frameState.camera.getPixelSize(\r\n scratchBoundingSphere,\r\n frameState.context.drawingBufferWidth,\r\n frameState.context.drawingBufferHeight\r\n );\r\n}\r\n\r\nvar scratchPosition = new Cartesian3();\r\nvar scratchCartographic = new Cartographic();\r\n\r\nfunction getScale(model, frameState) {\r\n var scale = model.scale;\r\n\r\n if (model.minimumPixelSize !== 0.0) {\r\n // Compute size of bounding sphere in pixels\r\n var context = frameState.context;\r\n var maxPixelSize = Math.max(\r\n context.drawingBufferWidth,\r\n context.drawingBufferHeight\r\n );\r\n var m = defined(model._clampedModelMatrix)\r\n ? model._clampedModelMatrix\r\n : model.modelMatrix;\r\n scratchPosition.x = m[12];\r\n scratchPosition.y = m[13];\r\n scratchPosition.z = m[14];\r\n\r\n if (defined(model._rtcCenter)) {\r\n Cartesian3.add(model._rtcCenter, scratchPosition, scratchPosition);\r\n }\r\n\r\n if (model._mode !== SceneMode.SCENE3D) {\r\n var projection = frameState.mapProjection;\r\n var cartographic = projection.ellipsoid.cartesianToCartographic(\r\n scratchPosition,\r\n scratchCartographic\r\n );\r\n projection.project(cartographic, scratchPosition);\r\n Cartesian3.fromElements(\r\n scratchPosition.z,\r\n scratchPosition.x,\r\n scratchPosition.y,\r\n scratchPosition\r\n );\r\n }\r\n\r\n var radius = model.boundingSphere.radius;\r\n var metersPerPixel = scaleInPixels(scratchPosition, radius, frameState);\r\n\r\n // metersPerPixel is always > 0.0\r\n var pixelsPerMeter = 1.0 / metersPerPixel;\r\n var diameterInPixels = Math.min(\r\n pixelsPerMeter * (2.0 * radius),\r\n maxPixelSize\r\n );\r\n\r\n // Maintain model's minimum pixel size\r\n if (diameterInPixels < model.minimumPixelSize) {\r\n scale =\r\n (model.minimumPixelSize * metersPerPixel) /\r\n (2.0 * model._initialRadius);\r\n }\r\n }\r\n\r\n return defined(model.maximumScale)\r\n ? Math.min(model.maximumScale, scale)\r\n : scale;\r\n}\r\n\r\nfunction releaseCachedGltf(model) {\r\n if (\r\n defined(model._cacheKey) &&\r\n defined(model._cachedGltf) &&\r\n --model._cachedGltf.count === 0\r\n ) {\r\n delete gltfCache[model._cacheKey];\r\n }\r\n model._cachedGltf = undefined;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction CachedRendererResources(context, cacheKey) {\r\n this.buffers = undefined;\r\n this.vertexArrays = undefined;\r\n this.programs = undefined;\r\n this.sourceShaders = undefined;\r\n this.silhouettePrograms = undefined;\r\n this.textures = undefined;\r\n this.samplers = undefined;\r\n this.renderStates = undefined;\r\n this.ready = false;\r\n\r\n this.context = context;\r\n this.cacheKey = cacheKey;\r\n this.count = 0;\r\n}\r\n\r\nfunction destroy(property) {\r\n for (var name in property) {\r\n if (property.hasOwnProperty(name)) {\r\n property[name].destroy();\r\n }\r\n }\r\n}\r\n\r\nfunction destroyCachedRendererResources(resources) {\r\n destroy(resources.buffers);\r\n destroy(resources.vertexArrays);\r\n destroy(resources.programs);\r\n destroy(resources.silhouettePrograms);\r\n destroy(resources.textures);\r\n}\r\n\r\nCachedRendererResources.prototype.release = function () {\r\n if (--this.count === 0) {\r\n if (defined(this.cacheKey)) {\r\n // Remove if this was cached\r\n delete this.context.cache.modelRendererResourceCache[this.cacheKey];\r\n }\r\n destroyCachedRendererResources(this);\r\n return destroyObject(this);\r\n }\r\n\r\n return undefined;\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction getUpdateHeightCallback(model, ellipsoid, cartoPosition) {\r\n return function (clampedPosition) {\r\n if (model.heightReference === HeightReference.RELATIVE_TO_GROUND) {\r\n var clampedCart = ellipsoid.cartesianToCartographic(\r\n clampedPosition,\r\n scratchCartographic\r\n );\r\n clampedCart.height += cartoPosition.height;\r\n ellipsoid.cartographicToCartesian(clampedCart, clampedPosition);\r\n }\r\n\r\n var clampedModelMatrix = model._clampedModelMatrix;\r\n\r\n // Modify clamped model matrix to use new height\r\n Matrix4.clone(model.modelMatrix, clampedModelMatrix);\r\n clampedModelMatrix[12] = clampedPosition.x;\r\n clampedModelMatrix[13] = clampedPosition.y;\r\n clampedModelMatrix[14] = clampedPosition.z;\r\n\r\n model._heightChanged = true;\r\n };\r\n}\r\n\r\nfunction updateClamping(model) {\r\n if (defined(model._removeUpdateHeightCallback)) {\r\n model._removeUpdateHeightCallback();\r\n model._removeUpdateHeightCallback = undefined;\r\n }\r\n\r\n var scene = model._scene;\r\n if (\r\n !defined(scene) ||\r\n !defined(scene.globe) ||\r\n model.heightReference === HeightReference.NONE\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (model.heightReference !== HeightReference.NONE) {\r\n throw new DeveloperError(\r\n \"Height reference is not supported without a scene and globe.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n model._clampedModelMatrix = undefined;\r\n return;\r\n }\r\n\r\n var globe = scene.globe;\r\n var ellipsoid = globe.ellipsoid;\r\n\r\n // Compute cartographic position so we don't recompute every update\r\n var modelMatrix = model.modelMatrix;\r\n scratchPosition.x = modelMatrix[12];\r\n scratchPosition.y = modelMatrix[13];\r\n scratchPosition.z = modelMatrix[14];\r\n var cartoPosition = ellipsoid.cartesianToCartographic(scratchPosition);\r\n\r\n if (!defined(model._clampedModelMatrix)) {\r\n model._clampedModelMatrix = Matrix4.clone(modelMatrix, new Matrix4());\r\n }\r\n\r\n // Install callback to handle updating of terrain tiles\r\n var surface = globe._surface;\r\n model._removeUpdateHeightCallback = surface.updateHeight(\r\n cartoPosition,\r\n getUpdateHeightCallback(model, ellipsoid, cartoPosition)\r\n );\r\n\r\n // Set the correct height now\r\n var height = globe.getHeight(cartoPosition);\r\n if (defined(height)) {\r\n // Get callback with cartoPosition being the non-clamped position\r\n var cb = getUpdateHeightCallback(model, ellipsoid, cartoPosition);\r\n\r\n // Compute the clamped cartesian and call updateHeight callback\r\n Cartographic.clone(cartoPosition, scratchCartographic);\r\n scratchCartographic.height = height;\r\n ellipsoid.cartographicToCartesian(scratchCartographic, scratchPosition);\r\n cb(scratchPosition);\r\n }\r\n}\r\n\r\nvar scratchDisplayConditionCartesian = new Cartesian3();\r\nvar scratchDistanceDisplayConditionCartographic = new Cartographic();\r\n\r\nfunction distanceDisplayConditionVisible(model, frameState) {\r\n var distance2;\r\n var ddc = model.distanceDisplayCondition;\r\n var nearSquared = ddc.near * ddc.near;\r\n var farSquared = ddc.far * ddc.far;\r\n\r\n if (frameState.mode === SceneMode.SCENE2D) {\r\n var frustum2DWidth =\r\n frameState.camera.frustum.right - frameState.camera.frustum.left;\r\n distance2 = frustum2DWidth * 0.5;\r\n distance2 = distance2 * distance2;\r\n } else {\r\n // Distance to center of primitive's reference frame\r\n var position = Matrix4.getTranslation(\r\n model.modelMatrix,\r\n scratchDisplayConditionCartesian\r\n );\r\n if (frameState.mode === SceneMode.COLUMBUS_VIEW) {\r\n var projection = frameState.mapProjection;\r\n var ellipsoid = projection.ellipsoid;\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n position,\r\n scratchDistanceDisplayConditionCartographic\r\n );\r\n position = projection.project(cartographic, position);\r\n Cartesian3.fromElements(position.z, position.x, position.y, position);\r\n }\r\n distance2 = Cartesian3.distanceSquared(\r\n position,\r\n frameState.camera.positionWC\r\n );\r\n }\r\n\r\n return distance2 >= nearSquared && distance2 <= farSquared;\r\n}\r\n\r\nvar scratchClippingPlanesMatrix = new Matrix4();\r\nvar scratchIBLReferenceFrameMatrix4 = new Matrix4();\r\nvar scratchIBLReferenceFrameMatrix3 = new Matrix3();\r\n\r\n/**\r\n * Called when {@link Viewer} or {@link CesiumWidget} render the scene to\r\n * get the draw commands needed to render this primitive.\r\n *

\r\n * Do not call this function directly. This is documented just to\r\n * list the exceptions that may be propagated when the scene is rendered:\r\n *

\r\n *\r\n * @exception {RuntimeError} Failed to load external reference.\r\n */\r\nModel.prototype.update = function (frameState) {\r\n if (frameState.mode === SceneMode.MORPHING) {\r\n return;\r\n }\r\n\r\n if (!FeatureDetection.supportsWebP.initialized) {\r\n FeatureDetection.supportsWebP.initialize();\r\n return;\r\n }\r\n var supportsWebP = FeatureDetection.supportsWebP();\r\n\r\n var context = frameState.context;\r\n this._defaultTexture = context.defaultTexture;\r\n\r\n if (this._state === ModelState.NEEDS_LOAD && defined(this.gltf)) {\r\n // Use renderer resources from cache instead of loading/creating them?\r\n var cachedRendererResources;\r\n var cacheKey = this.cacheKey;\r\n if (defined(cacheKey)) {\r\n // cache key given? this model will pull from or contribute to context level cache\r\n context.cache.modelRendererResourceCache = defaultValue(\r\n context.cache.modelRendererResourceCache,\r\n {}\r\n );\r\n var modelCaches = context.cache.modelRendererResourceCache;\r\n\r\n cachedRendererResources = modelCaches[this.cacheKey];\r\n if (defined(cachedRendererResources)) {\r\n if (!cachedRendererResources.ready) {\r\n // Cached resources for the model are not loaded yet. We'll\r\n // try again every frame until they are.\r\n return;\r\n }\r\n\r\n ++cachedRendererResources.count;\r\n this._loadRendererResourcesFromCache = true;\r\n } else {\r\n cachedRendererResources = new CachedRendererResources(\r\n context,\r\n cacheKey\r\n );\r\n cachedRendererResources.count = 1;\r\n modelCaches[this.cacheKey] = cachedRendererResources;\r\n }\r\n this._cachedRendererResources = cachedRendererResources;\r\n } else {\r\n // cache key not given? this model doesn't care about context level cache at all. Cache is here to simplify freeing on destroy.\r\n cachedRendererResources = new CachedRendererResources(context);\r\n cachedRendererResources.count = 1;\r\n this._cachedRendererResources = cachedRendererResources;\r\n }\r\n\r\n this._state = ModelState.LOADING;\r\n if (this._state !== ModelState.FAILED) {\r\n var extensions = this.gltf.extensions;\r\n if (defined(extensions) && defined(extensions.CESIUM_RTC)) {\r\n var center = Cartesian3.fromArray(extensions.CESIUM_RTC.center);\r\n if (!Cartesian3.equals(center, Cartesian3.ZERO)) {\r\n this._rtcCenter3D = center;\r\n\r\n var projection = frameState.mapProjection;\r\n var ellipsoid = projection.ellipsoid;\r\n var cartographic = ellipsoid.cartesianToCartographic(\r\n this._rtcCenter3D\r\n );\r\n var projectedCart = projection.project(cartographic);\r\n Cartesian3.fromElements(\r\n projectedCart.z,\r\n projectedCart.x,\r\n projectedCart.y,\r\n projectedCart\r\n );\r\n this._rtcCenter2D = projectedCart;\r\n\r\n this._rtcCenterEye = new Cartesian3();\r\n this._rtcCenter = this._rtcCenter3D;\r\n }\r\n }\r\n\r\n addPipelineExtras(this.gltf);\r\n\r\n this._loadResources = new ModelLoadResources();\r\n if (!this._loadRendererResourcesFromCache) {\r\n // Buffers are required to updateVersion\r\n ModelUtility.parseBuffers(this, bufferLoad);\r\n }\r\n }\r\n }\r\n\r\n var loadResources = this._loadResources;\r\n var incrementallyLoadTextures = this._incrementallyLoadTextures;\r\n var justLoaded = false;\r\n\r\n if (this._state === ModelState.LOADING) {\r\n // Transition from LOADING -> LOADED once resources are downloaded and created.\r\n // Textures may continue to stream in while in the LOADED state.\r\n if (loadResources.pendingBufferLoads === 0) {\r\n if (!loadResources.initialized) {\r\n frameState.brdfLutGenerator.update(frameState);\r\n\r\n ModelUtility.checkSupportedExtensions(\r\n this.extensionsRequired,\r\n supportsWebP\r\n );\r\n ModelUtility.updateForwardAxis(this);\r\n\r\n // glTF pipeline updates, not needed if loading from cache\r\n if (!defined(this.gltf.extras.sourceVersion)) {\r\n var gltf = this.gltf;\r\n // Add the original version so it remains cached\r\n gltf.extras.sourceVersion = ModelUtility.getAssetVersion(gltf);\r\n gltf.extras.sourceKHRTechniquesWebGL = defined(\r\n ModelUtility.getUsedExtensions(gltf).KHR_techniques_webgl\r\n );\r\n\r\n this._sourceVersion = gltf.extras.sourceVersion;\r\n this._sourceKHRTechniquesWebGL = gltf.extras.sourceKHRTechniquesWebGL;\r\n\r\n updateVersion(gltf);\r\n addDefaults(gltf);\r\n\r\n var options = {\r\n addBatchIdToGeneratedShaders: this._addBatchIdToGeneratedShaders,\r\n };\r\n\r\n processModelMaterialsCommon(gltf, options);\r\n processPbrMaterials(gltf, options);\r\n }\r\n\r\n this._sourceVersion = this.gltf.extras.sourceVersion;\r\n this._sourceKHRTechniquesWebGL = this.gltf.extras.sourceKHRTechniquesWebGL;\r\n\r\n // Skip dequantizing in the shader if not encoded\r\n this._dequantizeInShader =\r\n this._dequantizeInShader && DracoLoader.hasExtension(this);\r\n\r\n // We do this after to make sure that the ids don't change\r\n addBuffersToLoadResources(this);\r\n parseArticulations(this);\r\n parseTechniques(this);\r\n if (!this._loadRendererResourcesFromCache) {\r\n parseBufferViews(this);\r\n parseShaders(this);\r\n parsePrograms(this);\r\n parseTextures(this, context, supportsWebP);\r\n }\r\n parseMaterials(this);\r\n parseMeshes(this);\r\n parseNodes(this);\r\n\r\n // Start draco decoding\r\n DracoLoader.parse(this, context);\r\n\r\n loadResources.initialized = true;\r\n }\r\n\r\n if (!loadResources.finishedDecoding()) {\r\n DracoLoader.decodeModel(this, context).otherwise(\r\n ModelUtility.getFailedLoadFunction(this, \"model\", this.basePath)\r\n );\r\n }\r\n\r\n if (loadResources.finishedDecoding() && !loadResources.resourcesParsed) {\r\n this._boundingSphere = ModelUtility.computeBoundingSphere(this);\r\n this._initialRadius = this._boundingSphere.radius;\r\n\r\n DracoLoader.cacheDataForModel(this);\r\n\r\n loadResources.resourcesParsed = true;\r\n }\r\n\r\n if (\r\n loadResources.resourcesParsed &&\r\n loadResources.pendingShaderLoads === 0\r\n ) {\r\n ModelOutlineLoader.outlinePrimitives(this);\r\n createResources(this, frameState);\r\n }\r\n }\r\n\r\n if (\r\n loadResources.finished() ||\r\n (incrementallyLoadTextures &&\r\n loadResources.finishedEverythingButTextureCreation())\r\n ) {\r\n this._state = ModelState.LOADED;\r\n justLoaded = true;\r\n }\r\n }\r\n\r\n // Incrementally stream textures.\r\n if (defined(loadResources) && this._state === ModelState.LOADED) {\r\n if (incrementallyLoadTextures && !justLoaded) {\r\n createResources(this, frameState);\r\n }\r\n\r\n if (loadResources.finished()) {\r\n this._loadResources = undefined; // Clear CPU memory since WebGL resources were created.\r\n\r\n var resources = this._rendererResources;\r\n var cachedResources = this._cachedRendererResources;\r\n\r\n cachedResources.buffers = resources.buffers;\r\n cachedResources.vertexArrays = resources.vertexArrays;\r\n cachedResources.programs = resources.programs;\r\n cachedResources.sourceShaders = resources.sourceShaders;\r\n cachedResources.silhouettePrograms = resources.silhouettePrograms;\r\n cachedResources.textures = resources.textures;\r\n cachedResources.samplers = resources.samplers;\r\n cachedResources.renderStates = resources.renderStates;\r\n cachedResources.ready = true;\r\n\r\n // The normal attribute name is required for silhouettes, so get it before the gltf JSON is released\r\n this._normalAttributeName = ModelUtility.getAttributeOrUniformBySemantic(\r\n this.gltf,\r\n \"NORMAL\"\r\n );\r\n\r\n // Vertex arrays are unique to this model, do not store in cache.\r\n if (defined(this._precreatedAttributes)) {\r\n cachedResources.vertexArrays = {};\r\n }\r\n\r\n if (this.releaseGltfJson) {\r\n releaseCachedGltf(this);\r\n }\r\n }\r\n }\r\n\r\n var iblSupported = OctahedralProjectedCubeMap.isSupported(context);\r\n if (this._shouldUpdateSpecularMapAtlas && iblSupported) {\r\n this._shouldUpdateSpecularMapAtlas = false;\r\n this._specularEnvironmentMapAtlas =\r\n this._specularEnvironmentMapAtlas &&\r\n this._specularEnvironmentMapAtlas.destroy();\r\n this._specularEnvironmentMapAtlas = undefined;\r\n if (defined(this._specularEnvironmentMaps)) {\r\n this._specularEnvironmentMapAtlas = new OctahedralProjectedCubeMap(\r\n this._specularEnvironmentMaps\r\n );\r\n var that = this;\r\n this._specularEnvironmentMapAtlas.readyPromise\r\n .then(function () {\r\n that._shouldRegenerateShaders = true;\r\n })\r\n .otherwise(function (error) {\r\n console.error(\"Error loading specularEnvironmentMaps: \" + error);\r\n });\r\n }\r\n\r\n // Regenerate shaders to not use an environment map. Will be set to true again if there was a new environment map and it is ready.\r\n this._shouldRegenerateShaders = true;\r\n }\r\n\r\n if (defined(this._specularEnvironmentMapAtlas)) {\r\n this._specularEnvironmentMapAtlas.update(frameState);\r\n }\r\n\r\n var recompileWithDefaultAtlas =\r\n !defined(this._specularEnvironmentMapAtlas) &&\r\n defined(frameState.specularEnvironmentMaps) &&\r\n !this._useDefaultSpecularMaps;\r\n var recompileWithoutDefaultAtlas =\r\n !defined(frameState.specularEnvironmentMaps) &&\r\n this._useDefaultSpecularMaps;\r\n\r\n var recompileWithDefaultSHCoeffs =\r\n !defined(this._sphericalHarmonicCoefficients) &&\r\n defined(frameState.sphericalHarmonicCoefficients) &&\r\n !this._useDefaultSphericalHarmonics;\r\n var recompileWithoutDefaultSHCoeffs =\r\n !defined(frameState.sphericalHarmonicCoefficients) &&\r\n this._useDefaultSphericalHarmonics;\r\n\r\n this._shouldRegenerateShaders =\r\n this._shouldRegenerateShaders ||\r\n recompileWithDefaultAtlas ||\r\n recompileWithoutDefaultAtlas ||\r\n recompileWithDefaultSHCoeffs ||\r\n recompileWithoutDefaultSHCoeffs;\r\n\r\n this._useDefaultSpecularMaps =\r\n !defined(this._specularEnvironmentMapAtlas) &&\r\n defined(frameState.specularEnvironmentMaps);\r\n this._useDefaultSphericalHarmonics =\r\n !defined(this._sphericalHarmonicCoefficients) &&\r\n defined(frameState.sphericalHarmonicCoefficients);\r\n\r\n var silhouette = hasSilhouette(this, frameState);\r\n var translucent = isTranslucent(this);\r\n var invisible = isInvisible(this);\r\n var backFaceCulling = this.backFaceCulling;\r\n var displayConditionPassed = defined(this.distanceDisplayCondition)\r\n ? distanceDisplayConditionVisible(this, frameState)\r\n : true;\r\n var show =\r\n this.show &&\r\n displayConditionPassed &&\r\n this.scale !== 0.0 &&\r\n (!invisible || silhouette);\r\n\r\n if ((show && this._state === ModelState.LOADED) || justLoaded) {\r\n var animated =\r\n this.activeAnimations.update(frameState) || this._cesiumAnimationsDirty;\r\n this._cesiumAnimationsDirty = false;\r\n this._dirty = false;\r\n var modelMatrix = this.modelMatrix;\r\n\r\n var modeChanged = frameState.mode !== this._mode;\r\n this._mode = frameState.mode;\r\n\r\n // Model's model matrix needs to be updated\r\n var modelTransformChanged =\r\n !Matrix4.equals(this._modelMatrix, modelMatrix) ||\r\n this._scale !== this.scale ||\r\n this._minimumPixelSize !== this.minimumPixelSize ||\r\n this.minimumPixelSize !== 0.0 || // Minimum pixel size changed or is enabled\r\n this._maximumScale !== this.maximumScale ||\r\n this._heightReference !== this.heightReference ||\r\n this._heightChanged ||\r\n modeChanged;\r\n\r\n if (modelTransformChanged || justLoaded) {\r\n Matrix4.clone(modelMatrix, this._modelMatrix);\r\n\r\n updateClamping(this);\r\n\r\n if (defined(this._clampedModelMatrix)) {\r\n modelMatrix = this._clampedModelMatrix;\r\n }\r\n\r\n this._scale = this.scale;\r\n this._minimumPixelSize = this.minimumPixelSize;\r\n this._maximumScale = this.maximumScale;\r\n this._heightReference = this.heightReference;\r\n this._heightChanged = false;\r\n\r\n var scale = getScale(this, frameState);\r\n var computedModelMatrix = this._computedModelMatrix;\r\n Matrix4.multiplyByUniformScale(modelMatrix, scale, computedModelMatrix);\r\n if (this._upAxis === Axis.Y) {\r\n Matrix4.multiplyTransformation(\r\n computedModelMatrix,\r\n Axis.Y_UP_TO_Z_UP,\r\n computedModelMatrix\r\n );\r\n } else if (this._upAxis === Axis.X) {\r\n Matrix4.multiplyTransformation(\r\n computedModelMatrix,\r\n Axis.X_UP_TO_Z_UP,\r\n computedModelMatrix\r\n );\r\n }\r\n if (this.forwardAxis === Axis.Z) {\r\n // glTF 2.0 has a Z-forward convention that must be adapted here to X-forward.\r\n Matrix4.multiplyTransformation(\r\n computedModelMatrix,\r\n Axis.Z_UP_TO_X_UP,\r\n computedModelMatrix\r\n );\r\n }\r\n }\r\n\r\n // Update modelMatrix throughout the graph as needed\r\n if (animated || modelTransformChanged || justLoaded) {\r\n updateNodeHierarchyModelMatrix(\r\n this,\r\n modelTransformChanged,\r\n justLoaded,\r\n frameState.mapProjection\r\n );\r\n this._dirty = true;\r\n\r\n if (animated || justLoaded) {\r\n // Apply skins if animation changed any node transforms\r\n applySkins(this);\r\n }\r\n }\r\n\r\n if (this._perNodeShowDirty) {\r\n this._perNodeShowDirty = false;\r\n updatePerNodeShow(this);\r\n }\r\n updatePickIds(this, context);\r\n updateWireframe(this);\r\n updateShowBoundingVolume(this);\r\n updateShadows(this);\r\n updateClippingPlanes(this, frameState);\r\n\r\n // Regenerate shaders if ClippingPlaneCollection state changed or it was removed\r\n var clippingPlanes = this._clippingPlanes;\r\n var currentClippingPlanesState = 0;\r\n var useClippingPlanes =\r\n defined(clippingPlanes) &&\r\n clippingPlanes.enabled &&\r\n clippingPlanes.length > 0;\r\n\r\n // If defined, use the reference matrix to transform miscellaneous properties like\r\n // clipping planes and IBL instead of the modelMatrix. This is so that when\r\n // models are part of a tileset these properties get transformed relative to\r\n // a common reference (such as the root).\r\n var referenceMatrix = defaultValue(this.referenceMatrix, modelMatrix);\r\n\r\n if (useClippingPlanes) {\r\n var clippingPlanesMatrix = scratchClippingPlanesMatrix;\r\n clippingPlanesMatrix = Matrix4.multiply(\r\n context.uniformState.view3D,\r\n referenceMatrix,\r\n clippingPlanesMatrix\r\n );\r\n clippingPlanesMatrix = Matrix4.multiply(\r\n clippingPlanesMatrix,\r\n clippingPlanes.modelMatrix,\r\n clippingPlanesMatrix\r\n );\r\n this._clippingPlanesMatrix = Matrix4.inverseTranspose(\r\n clippingPlanesMatrix,\r\n this._clippingPlanesMatrix\r\n );\r\n currentClippingPlanesState = clippingPlanes.clippingPlanesState;\r\n }\r\n\r\n var usesSH =\r\n defined(this._sphericalHarmonicCoefficients) ||\r\n this._useDefaultSphericalHarmonics;\r\n var usesSM =\r\n (defined(this._specularEnvironmentMapAtlas) &&\r\n this._specularEnvironmentMapAtlas.ready) ||\r\n this._useDefaultSpecularMaps;\r\n\r\n if (usesSH || usesSM) {\r\n var iblReferenceFrameMatrix3 = scratchIBLReferenceFrameMatrix3;\r\n var iblReferenceFrameMatrix4 = scratchIBLReferenceFrameMatrix4;\r\n\r\n iblReferenceFrameMatrix4 = Matrix4.multiply(\r\n context.uniformState.view3D,\r\n referenceMatrix,\r\n iblReferenceFrameMatrix4\r\n );\r\n iblReferenceFrameMatrix3 = Matrix4.getMatrix3(\r\n iblReferenceFrameMatrix4,\r\n iblReferenceFrameMatrix3\r\n );\r\n iblReferenceFrameMatrix3 = Matrix3.getRotation(\r\n iblReferenceFrameMatrix3,\r\n iblReferenceFrameMatrix3\r\n );\r\n this._iblReferenceFrameMatrix = Matrix3.transpose(\r\n iblReferenceFrameMatrix3,\r\n this._iblReferenceFrameMatrix\r\n );\r\n }\r\n\r\n var shouldRegenerateShaders = this._shouldRegenerateShaders;\r\n shouldRegenerateShaders =\r\n shouldRegenerateShaders ||\r\n this._clippingPlanesState !== currentClippingPlanesState;\r\n this._clippingPlanesState = currentClippingPlanesState;\r\n\r\n // Regenerate shaders if color shading changed from last update\r\n var currentlyColorShadingEnabled = isColorShadingEnabled(this);\r\n if (currentlyColorShadingEnabled !== this._colorShadingEnabled) {\r\n this._colorShadingEnabled = currentlyColorShadingEnabled;\r\n shouldRegenerateShaders = true;\r\n }\r\n\r\n if (shouldRegenerateShaders) {\r\n regenerateShaders(this, frameState);\r\n } else {\r\n updateColor(this, frameState, false);\r\n updateBackFaceCulling(this, frameState, false);\r\n updateSilhouette(this, frameState, false);\r\n }\r\n }\r\n\r\n if (justLoaded) {\r\n // Called after modelMatrix update.\r\n var model = this;\r\n frameState.afterRender.push(function () {\r\n model._ready = true;\r\n model._readyPromise.resolve(model);\r\n });\r\n return;\r\n }\r\n\r\n // We don't check show at the top of the function since we\r\n // want to be able to progressively load models when they are not shown,\r\n // and then have them visible immediately when show is set to true.\r\n if (show && !this._ignoreCommands) {\r\n // PERFORMANCE_IDEA: This is terrible\r\n var commandList = frameState.commandList;\r\n var passes = frameState.passes;\r\n var nodeCommands = this._nodeCommands;\r\n var length = nodeCommands.length;\r\n var i;\r\n var nc;\r\n\r\n var idl2D =\r\n frameState.mapProjection.ellipsoid.maximumRadius * CesiumMath.PI;\r\n var boundingVolume;\r\n\r\n if (passes.render || (passes.pick && this.allowPicking)) {\r\n for (i = 0; i < length; ++i) {\r\n nc = nodeCommands[i];\r\n if (nc.show) {\r\n var command = nc.command;\r\n if (silhouette) {\r\n command = nc.silhouetteModelCommand;\r\n } else if (translucent) {\r\n command = nc.translucentCommand;\r\n } else if (!backFaceCulling) {\r\n command = nc.disableCullingCommand;\r\n }\r\n commandList.push(command);\r\n boundingVolume = nc.command.boundingVolume;\r\n if (\r\n frameState.mode === SceneMode.SCENE2D &&\r\n (boundingVolume.center.y + boundingVolume.radius > idl2D ||\r\n boundingVolume.center.y - boundingVolume.radius < idl2D)\r\n ) {\r\n var command2D = nc.command2D;\r\n if (silhouette) {\r\n command2D = nc.silhouetteModelCommand2D;\r\n } else if (translucent) {\r\n command2D = nc.translucentCommand2D;\r\n } else if (!backFaceCulling) {\r\n command2D = nc.disableCullingCommand2D;\r\n }\r\n commandList.push(command2D);\r\n }\r\n }\r\n }\r\n\r\n if (silhouette && !passes.pick) {\r\n // Render second silhouette pass\r\n for (i = 0; i < length; ++i) {\r\n nc = nodeCommands[i];\r\n if (nc.show) {\r\n commandList.push(nc.silhouetteColorCommand);\r\n boundingVolume = nc.command.boundingVolume;\r\n if (\r\n frameState.mode === SceneMode.SCENE2D &&\r\n (boundingVolume.center.y + boundingVolume.radius > idl2D ||\r\n boundingVolume.center.y - boundingVolume.radius < idl2D)\r\n ) {\r\n commandList.push(nc.silhouetteColorCommand2D);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n var credit = this._credit;\r\n if (defined(credit)) {\r\n frameState.creditDisplay.addCredit(credit);\r\n }\r\n\r\n var resourceCredits = this._resourceCredits;\r\n var creditCount = resourceCredits.length;\r\n for (var c = 0; c < creditCount; c++) {\r\n frameState.creditDisplay.addCredit(resourceCredits[c]);\r\n }\r\n};\r\n\r\nfunction destroyIfNotCached(rendererResources, cachedRendererResources) {\r\n if (rendererResources.programs !== cachedRendererResources.programs) {\r\n destroy(rendererResources.programs);\r\n }\r\n if (\r\n rendererResources.silhouettePrograms !==\r\n cachedRendererResources.silhouettePrograms\r\n ) {\r\n destroy(rendererResources.silhouettePrograms);\r\n }\r\n}\r\n\r\n// Run from update iff:\r\n// - everything is loaded\r\n// - clipping planes state change OR color state set\r\n// Run this from destructor after removing color state and clipping plane state\r\nfunction regenerateShaders(model, frameState) {\r\n // In regards to _cachedRendererResources:\r\n // Fair to assume that this is data that should just never get modified due to clipping planes or model color.\r\n // So if clipping planes or model color active:\r\n // - delink _rendererResources.*programs and create new dictionaries.\r\n // - do NOT destroy any programs - might be used by copies of the model or by might be needed in the future if clipping planes/model color is deactivated\r\n\r\n // If clipping planes and model color inactive:\r\n // - destroy _rendererResources.*programs\r\n // - relink _rendererResources.*programs to _cachedRendererResources\r\n\r\n // In both cases, need to mark commands as dirty, re-run derived commands (elsewhere)\r\n\r\n var rendererResources = model._rendererResources;\r\n var cachedRendererResources = model._cachedRendererResources;\r\n destroyIfNotCached(rendererResources, cachedRendererResources);\r\n\r\n var programId;\r\n if (\r\n isClippingEnabled(model) ||\r\n isColorShadingEnabled(model) ||\r\n model._shouldRegenerateShaders\r\n ) {\r\n model._shouldRegenerateShaders = false;\r\n\r\n rendererResources.programs = {};\r\n rendererResources.silhouettePrograms = {};\r\n\r\n var visitedPrograms = {};\r\n var techniques = model._sourceTechniques;\r\n var technique;\r\n\r\n for (var techniqueId in techniques) {\r\n if (techniques.hasOwnProperty(techniqueId)) {\r\n technique = techniques[techniqueId];\r\n programId = technique.program;\r\n if (!visitedPrograms[programId]) {\r\n visitedPrograms[programId] = true;\r\n recreateProgram(\r\n {\r\n programId: programId,\r\n techniqueId: techniqueId,\r\n },\r\n model,\r\n frameState.context\r\n );\r\n }\r\n }\r\n }\r\n } else {\r\n rendererResources.programs = cachedRendererResources.programs;\r\n rendererResources.silhouettePrograms =\r\n cachedRendererResources.silhouettePrograms;\r\n }\r\n\r\n // Fix all the commands, marking them as dirty so everything that derives will re-derive\r\n var rendererPrograms = rendererResources.programs;\r\n\r\n var nodeCommands = model._nodeCommands;\r\n var commandCount = nodeCommands.length;\r\n for (var i = 0; i < commandCount; ++i) {\r\n var nodeCommand = nodeCommands[i];\r\n programId = nodeCommand.programId;\r\n\r\n var renderProgram = rendererPrograms[programId];\r\n nodeCommand.command.shaderProgram = renderProgram;\r\n if (defined(nodeCommand.command2D)) {\r\n nodeCommand.command2D.shaderProgram = renderProgram;\r\n }\r\n }\r\n\r\n // Force update silhouette commands/shaders\r\n updateColor(model, frameState, true);\r\n updateBackFaceCulling(model, frameState, true);\r\n updateSilhouette(model, frameState, true);\r\n}\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see Model#destroy\r\n */\r\nModel.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * model = model && model.destroy();\r\n *\r\n * @see Model#isDestroyed\r\n */\r\nModel.prototype.destroy = function () {\r\n // Vertex arrays are unique to this model, destroy here.\r\n if (defined(this._precreatedAttributes)) {\r\n destroy(this._rendererResources.vertexArrays);\r\n }\r\n\r\n if (defined(this._removeUpdateHeightCallback)) {\r\n this._removeUpdateHeightCallback();\r\n this._removeUpdateHeightCallback = undefined;\r\n }\r\n\r\n if (defined(this._terrainProviderChangedCallback)) {\r\n this._terrainProviderChangedCallback();\r\n this._terrainProviderChangedCallback = undefined;\r\n }\r\n\r\n // Shaders modified for clipping and for color don't get cached, so destroy these manually\r\n if (defined(this._cachedRendererResources)) {\r\n destroyIfNotCached(this._rendererResources, this._cachedRendererResources);\r\n }\r\n\r\n this._rendererResources = undefined;\r\n this._cachedRendererResources =\r\n this._cachedRendererResources && this._cachedRendererResources.release();\r\n DracoLoader.destroyCachedDataForModel(this);\r\n\r\n var pickIds = this._pickIds;\r\n var length = pickIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n pickIds[i].destroy();\r\n }\r\n\r\n releaseCachedGltf(this);\r\n this._quantizedVertexShaders = undefined;\r\n\r\n // Only destroy the ClippingPlaneCollection if this is the owner - if this model is part of a Cesium3DTileset,\r\n // _clippingPlanes references a ClippingPlaneCollection that this model does not own.\r\n var clippingPlaneCollection = this._clippingPlanes;\r\n if (\r\n defined(clippingPlaneCollection) &&\r\n !clippingPlaneCollection.isDestroyed() &&\r\n clippingPlaneCollection.owner === this\r\n ) {\r\n clippingPlaneCollection.destroy();\r\n }\r\n this._clippingPlanes = undefined;\r\n\r\n this._specularEnvironmentMapAtlas =\r\n this._specularEnvironmentMapAtlas &&\r\n this._specularEnvironmentMapAtlas.destroy();\r\n\r\n return destroyObject(this);\r\n};\r\n\r\n// exposed for testing\r\nModel._getClippingFunction = getClippingFunction;\r\nModel._modifyShaderForColor = modifyShaderForColor;\r\nexport default Model;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport deprecationWarning from \"../Core/deprecationWarning.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport getJsonFromTypedArray from \"../Core/getJsonFromTypedArray.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport RequestType from \"../Core/RequestType.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport Axis from \"./Axis.js\";\r\nimport Cesium3DTileBatchTable from \"./Cesium3DTileBatchTable.js\";\r\nimport Cesium3DTileFeature from \"./Cesium3DTileFeature.js\";\r\nimport Cesium3DTileFeatureTable from \"./Cesium3DTileFeatureTable.js\";\r\nimport ClassificationModel from \"./ClassificationModel.js\";\r\nimport Model from \"./Model.js\";\r\nimport ModelUtility from \"./ModelUtility.js\";\r\nimport ModelAnimationLoop from \"./ModelAnimationLoop.js\";\r\n\r\n/**\r\n * Represents the contents of a\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/Batched3DModel|Batched 3D Model}\r\n * tile in a {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles} tileset.\r\n *

\r\n * Implements the {@link Cesium3DTileContent} interface.\r\n *

\r\n *\r\n * @alias Batched3DModel3DTileContent\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction Batched3DModel3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n) {\r\n this._tileset = tileset;\r\n this._tile = tile;\r\n this._resource = resource;\r\n this._model = undefined;\r\n this._batchTable = undefined;\r\n this._features = undefined;\r\n\r\n this._classificationType = tileset.vectorClassificationOnly\r\n ? undefined\r\n : tileset.classificationType;\r\n\r\n // Populate from gltf when available\r\n this._batchIdAttributeName = undefined;\r\n this._diffuseAttributeOrUniformName = {};\r\n\r\n this._rtcCenterTransform = undefined;\r\n this._contentModelMatrix = undefined;\r\n\r\n this.featurePropertiesDirty = false;\r\n\r\n initialize(this, arrayBuffer, byteOffset);\r\n}\r\n\r\n// This can be overridden for testing purposes\r\nBatched3DModel3DTileContent._deprecationWarning = deprecationWarning;\r\n\r\nObject.defineProperties(Batched3DModel3DTileContent.prototype, {\r\n featuresLength: {\r\n get: function () {\r\n return this._batchTable.featuresLength;\r\n },\r\n },\r\n\r\n pointsLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n trianglesLength: {\r\n get: function () {\r\n return this._model.trianglesLength;\r\n },\r\n },\r\n\r\n geometryByteLength: {\r\n get: function () {\r\n return this._model.geometryByteLength;\r\n },\r\n },\r\n\r\n texturesByteLength: {\r\n get: function () {\r\n return this._model.texturesByteLength;\r\n },\r\n },\r\n\r\n batchTableByteLength: {\r\n get: function () {\r\n return this._batchTable.memorySizeInBytes;\r\n },\r\n },\r\n\r\n innerContents: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return this._model.readyPromise;\r\n },\r\n },\r\n\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n tile: {\r\n get: function () {\r\n return this._tile;\r\n },\r\n },\r\n\r\n url: {\r\n get: function () {\r\n return this._resource.getUrlComponent(true);\r\n },\r\n },\r\n\r\n batchTable: {\r\n get: function () {\r\n return this._batchTable;\r\n },\r\n },\r\n});\r\n\r\nvar sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;\r\n\r\nfunction getBatchIdAttributeName(gltf) {\r\n var batchIdAttributeName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"_BATCHID\"\r\n );\r\n if (!defined(batchIdAttributeName)) {\r\n batchIdAttributeName = ModelUtility.getAttributeOrUniformBySemantic(\r\n gltf,\r\n \"BATCHID\"\r\n );\r\n if (defined(batchIdAttributeName)) {\r\n Batched3DModel3DTileContent._deprecationWarning(\r\n \"b3dm-legacy-batchid\",\r\n \"The glTF in this b3dm uses the semantic `BATCHID`. Application-specific semantics should be prefixed with an underscore: `_BATCHID`.\"\r\n );\r\n }\r\n }\r\n return batchIdAttributeName;\r\n}\r\n\r\nfunction getVertexShaderCallback(content) {\r\n return function (vs, programId) {\r\n var batchTable = content._batchTable;\r\n var handleTranslucent = !defined(content._classificationType);\r\n\r\n var gltf = content._model.gltf;\r\n if (defined(gltf)) {\r\n content._batchIdAttributeName = getBatchIdAttributeName(gltf);\r\n content._diffuseAttributeOrUniformName[\r\n programId\r\n ] = ModelUtility.getDiffuseAttributeOrUniform(gltf, programId);\r\n }\r\n\r\n var callback = batchTable.getVertexShaderCallback(\r\n handleTranslucent,\r\n content._batchIdAttributeName,\r\n content._diffuseAttributeOrUniformName[programId]\r\n );\r\n return defined(callback) ? callback(vs) : vs;\r\n };\r\n}\r\n\r\nfunction getFragmentShaderCallback(content) {\r\n return function (fs, programId) {\r\n var batchTable = content._batchTable;\r\n var handleTranslucent = !defined(content._classificationType);\r\n\r\n var gltf = content._model.gltf;\r\n if (defined(gltf)) {\r\n content._diffuseAttributeOrUniformName[\r\n programId\r\n ] = ModelUtility.getDiffuseAttributeOrUniform(gltf, programId);\r\n }\r\n var callback = batchTable.getFragmentShaderCallback(\r\n handleTranslucent,\r\n content._diffuseAttributeOrUniformName[programId],\r\n false\r\n );\r\n return defined(callback) ? callback(fs) : fs;\r\n };\r\n}\r\n\r\nfunction getPickIdCallback(content) {\r\n return function () {\r\n return content._batchTable.getPickId();\r\n };\r\n}\r\n\r\nfunction getClassificationFragmentShaderCallback(content) {\r\n return function (fs) {\r\n var batchTable = content._batchTable;\r\n var callback = batchTable.getClassificationFragmentShaderCallback();\r\n return defined(callback) ? callback(fs) : fs;\r\n };\r\n}\r\n\r\nfunction createColorChangedCallback(content) {\r\n return function (batchId, color) {\r\n content._model.updateCommands(batchId, color);\r\n };\r\n}\r\n\r\nfunction initialize(content, arrayBuffer, byteOffset) {\r\n var tileset = content._tileset;\r\n var tile = content._tile;\r\n var resource = content._resource;\r\n\r\n var byteStart = defaultValue(byteOffset, 0);\r\n byteOffset = byteStart;\r\n\r\n var uint8Array = new Uint8Array(arrayBuffer);\r\n var view = new DataView(arrayBuffer);\r\n byteOffset += sizeOfUint32; // Skip magic\r\n\r\n var version = view.getUint32(byteOffset, true);\r\n if (version !== 1) {\r\n throw new RuntimeError(\r\n \"Only Batched 3D Model version 1 is supported. Version \" +\r\n version +\r\n \" is not.\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n var byteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableJsonByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var batchTableJsonByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var batchTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var batchLength;\r\n\r\n // Legacy header #1: [batchLength] [batchTableByteLength]\r\n // Legacy header #2: [batchTableJsonByteLength] [batchTableBinaryByteLength] [batchLength]\r\n // Current header: [featureTableJsonByteLength] [featureTableBinaryByteLength] [batchTableJsonByteLength] [batchTableBinaryByteLength]\r\n // If the header is in the first legacy format 'batchTableJsonByteLength' will be the start of the JSON string (a quotation mark) or the glTF magic.\r\n // Accordingly its first byte will be either 0x22 or 0x67, and so the minimum uint32 expected is 0x22000000 = 570425344 = 570MB. It is unlikely that the feature table JSON will exceed this length.\r\n // The check for the second legacy format is similar, except it checks 'batchTableBinaryByteLength' instead\r\n if (batchTableJsonByteLength >= 570425344) {\r\n // First legacy check\r\n byteOffset -= sizeOfUint32 * 2;\r\n batchLength = featureTableJsonByteLength;\r\n batchTableJsonByteLength = featureTableBinaryByteLength;\r\n batchTableBinaryByteLength = 0;\r\n featureTableJsonByteLength = 0;\r\n featureTableBinaryByteLength = 0;\r\n Batched3DModel3DTileContent._deprecationWarning(\r\n \"b3dm-legacy-header\",\r\n \"This b3dm header is using the legacy format [batchLength] [batchTableByteLength]. The new format is [featureTableJsonByteLength] [featureTableBinaryByteLength] [batchTableJsonByteLength] [batchTableBinaryByteLength] from https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/Batched3DModel.\"\r\n );\r\n } else if (batchTableBinaryByteLength >= 570425344) {\r\n // Second legacy check\r\n byteOffset -= sizeOfUint32;\r\n batchLength = batchTableJsonByteLength;\r\n batchTableJsonByteLength = featureTableJsonByteLength;\r\n batchTableBinaryByteLength = featureTableBinaryByteLength;\r\n featureTableJsonByteLength = 0;\r\n featureTableBinaryByteLength = 0;\r\n Batched3DModel3DTileContent._deprecationWarning(\r\n \"b3dm-legacy-header\",\r\n \"This b3dm header is using the legacy format [batchTableJsonByteLength] [batchTableBinaryByteLength] [batchLength]. The new format is [featureTableJsonByteLength] [featureTableBinaryByteLength] [batchTableJsonByteLength] [batchTableBinaryByteLength] from https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/Batched3DModel.\"\r\n );\r\n }\r\n\r\n var featureTableJson;\r\n if (featureTableJsonByteLength === 0) {\r\n featureTableJson = {\r\n BATCH_LENGTH: defaultValue(batchLength, 0),\r\n };\r\n } else {\r\n featureTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n featureTableJsonByteLength\r\n );\r\n byteOffset += featureTableJsonByteLength;\r\n }\r\n\r\n var featureTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n featureTableBinaryByteLength\r\n );\r\n byteOffset += featureTableBinaryByteLength;\r\n\r\n var featureTable = new Cesium3DTileFeatureTable(\r\n featureTableJson,\r\n featureTableBinary\r\n );\r\n\r\n batchLength = featureTable.getGlobalProperty(\"BATCH_LENGTH\");\r\n featureTable.featuresLength = batchLength;\r\n\r\n var batchTableJson;\r\n var batchTableBinary;\r\n if (batchTableJsonByteLength > 0) {\r\n // PERFORMANCE_IDEA: is it possible to allocate this on-demand? Perhaps keep the\r\n // arraybuffer/string compressed in memory and then decompress it when it is first accessed.\r\n //\r\n // We could also make another request for it, but that would make the property set/get\r\n // API async, and would double the number of numbers in some cases.\r\n batchTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n batchTableJsonByteLength\r\n );\r\n byteOffset += batchTableJsonByteLength;\r\n\r\n if (batchTableBinaryByteLength > 0) {\r\n // Has a batch table binary\r\n batchTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n batchTableBinaryByteLength\r\n );\r\n // Copy the batchTableBinary section and let the underlying ArrayBuffer be freed\r\n batchTableBinary = new Uint8Array(batchTableBinary);\r\n byteOffset += batchTableBinaryByteLength;\r\n }\r\n }\r\n\r\n var colorChangedCallback;\r\n if (defined(content._classificationType)) {\r\n colorChangedCallback = createColorChangedCallback(content);\r\n }\r\n\r\n var batchTable = new Cesium3DTileBatchTable(\r\n content,\r\n batchLength,\r\n batchTableJson,\r\n batchTableBinary,\r\n colorChangedCallback\r\n );\r\n content._batchTable = batchTable;\r\n\r\n var gltfByteLength = byteStart + byteLength - byteOffset;\r\n if (gltfByteLength === 0) {\r\n throw new RuntimeError(\"glTF byte length must be greater than 0.\");\r\n }\r\n\r\n var gltfView;\r\n if (byteOffset % 4 === 0) {\r\n gltfView = new Uint8Array(arrayBuffer, byteOffset, gltfByteLength);\r\n } else {\r\n // Create a copy of the glb so that it is 4-byte aligned\r\n Batched3DModel3DTileContent._deprecationWarning(\r\n \"b3dm-glb-unaligned\",\r\n \"The embedded glb is not aligned to a 4-byte boundary.\"\r\n );\r\n gltfView = new Uint8Array(\r\n uint8Array.subarray(byteOffset, byteOffset + gltfByteLength)\r\n );\r\n }\r\n\r\n var pickObject = {\r\n content: content,\r\n primitive: tileset,\r\n };\r\n\r\n content._rtcCenterTransform = Matrix4.IDENTITY;\r\n var rtcCenter = featureTable.getGlobalProperty(\r\n \"RTC_CENTER\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n if (defined(rtcCenter)) {\r\n content._rtcCenterTransform = Matrix4.fromTranslation(\r\n Cartesian3.fromArray(rtcCenter)\r\n );\r\n }\r\n\r\n content._contentModelMatrix = Matrix4.multiply(\r\n tile.computedTransform,\r\n content._rtcCenterTransform,\r\n new Matrix4()\r\n );\r\n\r\n if (!defined(content._classificationType)) {\r\n // PERFORMANCE_IDEA: patch the shader on demand, e.g., the first time show/color changes.\r\n // The pick shader still needs to be patched.\r\n content._model = new Model({\r\n gltf: gltfView,\r\n cull: false, // The model is already culled by 3D Tiles\r\n releaseGltfJson: true, // Models are unique and will not benefit from caching so save memory\r\n opaquePass: Pass.CESIUM_3D_TILE, // Draw opaque portions of the model during the 3D Tiles pass\r\n basePath: resource,\r\n requestType: RequestType.TILES3D,\r\n modelMatrix: content._contentModelMatrix,\r\n upAxis: tileset._gltfUpAxis,\r\n forwardAxis: Axis.X,\r\n shadows: tileset.shadows,\r\n debugWireframe: tileset.debugWireframe,\r\n incrementallyLoadTextures: false,\r\n vertexShaderLoaded: getVertexShaderCallback(content),\r\n fragmentShaderLoaded: getFragmentShaderCallback(content),\r\n uniformMapLoaded: batchTable.getUniformMapCallback(),\r\n pickIdLoaded: getPickIdCallback(content),\r\n addBatchIdToGeneratedShaders: batchLength > 0, // If the batch table has values in it, generated shaders will need a batchId attribute\r\n pickObject: pickObject,\r\n imageBasedLightingFactor: tileset.imageBasedLightingFactor,\r\n lightColor: tileset.lightColor,\r\n luminanceAtZenith: tileset.luminanceAtZenith,\r\n sphericalHarmonicCoefficients: tileset.sphericalHarmonicCoefficients,\r\n specularEnvironmentMaps: tileset.specularEnvironmentMaps,\r\n backFaceCulling: tileset.backFaceCulling,\r\n });\r\n content._model.readyPromise.then(function (model) {\r\n model.activeAnimations.addAll({\r\n loop: ModelAnimationLoop.REPEAT,\r\n });\r\n });\r\n } else {\r\n // This transcodes glTF to an internal representation for geometry so we can take advantage of the re-batching of vector data.\r\n // For a list of limitations on the input glTF, see the documentation for classificationType of Cesium3DTileset.\r\n content._model = new ClassificationModel({\r\n gltf: gltfView,\r\n cull: false, // The model is already culled by 3D Tiles\r\n basePath: resource,\r\n requestType: RequestType.TILES3D,\r\n modelMatrix: content._contentModelMatrix,\r\n upAxis: tileset._gltfUpAxis,\r\n forwardAxis: Axis.X,\r\n debugWireframe: tileset.debugWireframe,\r\n vertexShaderLoaded: getVertexShaderCallback(content),\r\n classificationShaderLoaded: getClassificationFragmentShaderCallback(\r\n content\r\n ),\r\n uniformMapLoaded: batchTable.getUniformMapCallback(),\r\n pickIdLoaded: getPickIdCallback(content),\r\n classificationType: content._classificationType,\r\n batchTable: batchTable,\r\n });\r\n }\r\n}\r\n\r\nfunction createFeatures(content) {\r\n var featuresLength = content.featuresLength;\r\n if (!defined(content._features) && featuresLength > 0) {\r\n var features = new Array(featuresLength);\r\n for (var i = 0; i < featuresLength; ++i) {\r\n features[i] = new Cesium3DTileFeature(content, i);\r\n }\r\n content._features = features;\r\n }\r\n}\r\n\r\nBatched3DModel3DTileContent.prototype.hasProperty = function (batchId, name) {\r\n return this._batchTable.hasProperty(batchId, name);\r\n};\r\n\r\nBatched3DModel3DTileContent.prototype.getFeature = function (batchId) {\r\n //>>includeStart('debug', pragmas.debug);\r\n var featuresLength = this.featuresLength;\r\n if (!defined(batchId) || batchId < 0 || batchId >= featuresLength) {\r\n throw new DeveloperError(\r\n \"batchId is required and between zero and featuresLength - 1 (\" +\r\n (featuresLength - 1) +\r\n \").\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n createFeatures(this);\r\n return this._features[batchId];\r\n};\r\n\r\nBatched3DModel3DTileContent.prototype.applyDebugSettings = function (\r\n enabled,\r\n color\r\n) {\r\n color = enabled ? color : Color.WHITE;\r\n if (this.featuresLength === 0) {\r\n this._model.color = color;\r\n } else {\r\n this._batchTable.setAllColor(color);\r\n }\r\n};\r\n\r\nBatched3DModel3DTileContent.prototype.applyStyle = function (style) {\r\n if (this.featuresLength === 0) {\r\n var hasColorStyle = defined(style) && defined(style.color);\r\n var hasShowStyle = defined(style) && defined(style.show);\r\n this._model.color = hasColorStyle\r\n ? style.color.evaluateColor(undefined, this._model.color)\r\n : Color.clone(Color.WHITE, this._model.color);\r\n this._model.show = hasShowStyle ? style.show.evaluate(undefined) : true;\r\n } else {\r\n this._batchTable.applyStyle(style);\r\n }\r\n};\r\n\r\nBatched3DModel3DTileContent.prototype.update = function (tileset, frameState) {\r\n var commandStart = frameState.commandList.length;\r\n\r\n // In the PROCESSING state we may be calling update() to move forward\r\n // the content's resource loading. In the READY state, it will\r\n // actually generate commands.\r\n this._batchTable.update(tileset, frameState);\r\n\r\n this._contentModelMatrix = Matrix4.multiply(\r\n this._tile.computedTransform,\r\n this._rtcCenterTransform,\r\n this._contentModelMatrix\r\n );\r\n this._model.modelMatrix = this._contentModelMatrix;\r\n\r\n this._model.shadows = this._tileset.shadows;\r\n this._model.imageBasedLightingFactor = this._tileset.imageBasedLightingFactor;\r\n this._model.lightColor = this._tileset.lightColor;\r\n this._model.luminanceAtZenith = this._tileset.luminanceAtZenith;\r\n this._model.sphericalHarmonicCoefficients = this._tileset.sphericalHarmonicCoefficients;\r\n this._model.specularEnvironmentMaps = this._tileset.specularEnvironmentMaps;\r\n this._model.backFaceCulling = this._tileset.backFaceCulling;\r\n this._model.debugWireframe = this._tileset.debugWireframe;\r\n\r\n // Update clipping planes\r\n var tilesetClippingPlanes = this._tileset.clippingPlanes;\r\n this._model.referenceMatrix = this._tileset.clippingPlanesOriginMatrix;\r\n if (defined(tilesetClippingPlanes) && this._tile.clippingPlanesDirty) {\r\n // Dereference the clipping planes from the model if they are irrelevant.\r\n // Link/Dereference directly to avoid ownership checks.\r\n // This will also trigger synchronous shader regeneration to remove or add the clipping plane and color blending code.\r\n this._model._clippingPlanes =\r\n tilesetClippingPlanes.enabled && this._tile._isClipped\r\n ? tilesetClippingPlanes\r\n : undefined;\r\n }\r\n\r\n // If the model references a different ClippingPlaneCollection due to the tileset's collection being replaced with a\r\n // ClippingPlaneCollection that gives this tile the same clipping status, update the model to use the new ClippingPlaneCollection.\r\n if (\r\n defined(tilesetClippingPlanes) &&\r\n defined(this._model._clippingPlanes) &&\r\n this._model._clippingPlanes !== tilesetClippingPlanes\r\n ) {\r\n this._model._clippingPlanes = tilesetClippingPlanes;\r\n }\r\n\r\n this._model.update(frameState);\r\n\r\n // If any commands were pushed, add derived commands\r\n var commandEnd = frameState.commandList.length;\r\n if (\r\n commandStart < commandEnd &&\r\n (frameState.passes.render || frameState.passes.pick) &&\r\n !defined(this._classificationType)\r\n ) {\r\n this._batchTable.addDerivedCommands(frameState, commandStart);\r\n }\r\n};\r\n\r\nBatched3DModel3DTileContent.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nBatched3DModel3DTileContent.prototype.destroy = function () {\r\n this._model = this._model && this._model.destroy();\r\n this._batchTable = this._batchTable && this._batchTable.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Batched3DModel3DTileContent;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport getMagic from \"../Core/getMagic.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\n\r\n/**\r\n * Represents the contents of a\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/Composite|Composite}\r\n * tile in a {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles} tileset.\r\n *

\r\n * Implements the {@link Cesium3DTileContent} interface.\r\n *

\r\n *\r\n * @alias Composite3DTileContent\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction Composite3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset,\r\n factory\r\n) {\r\n this._tileset = tileset;\r\n this._tile = tile;\r\n this._resource = resource;\r\n this._contents = [];\r\n this._readyPromise = when.defer();\r\n\r\n initialize(this, arrayBuffer, byteOffset, factory);\r\n}\r\n\r\nObject.defineProperties(Composite3DTileContent.prototype, {\r\n featurePropertiesDirty: {\r\n get: function () {\r\n var contents = this._contents;\r\n var length = contents.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (contents[i].featurePropertiesDirty) {\r\n return true;\r\n }\r\n }\r\n\r\n return false;\r\n },\r\n set: function (value) {\r\n var contents = this._contents;\r\n var length = contents.length;\r\n for (var i = 0; i < length; ++i) {\r\n contents[i].featurePropertiesDirty = value;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns 0. Instead call featuresLength for a tile in the composite.\r\n * @memberof Composite3DTileContent.prototype\r\n */\r\n featuresLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns 0. Instead call pointsLength for a tile in the composite.\r\n * @memberof Composite3DTileContent.prototype\r\n */\r\n pointsLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns 0. Instead call trianglesLength for a tile in the composite.\r\n * @memberof Composite3DTileContent.prototype\r\n */\r\n trianglesLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns 0. Instead call geometryByteLength for a tile in the composite.\r\n * @memberof Composite3DTileContent.prototype\r\n */\r\n geometryByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns 0. Instead call texturesByteLength for a tile in the composite.\r\n * @memberof Composite3DTileContent.prototype\r\n */\r\n texturesByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns 0. Instead call batchTableByteLength for a tile in the composite.\r\n * @memberof Composite3DTileContent.prototype\r\n */\r\n batchTableByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n innerContents: {\r\n get: function () {\r\n return this._contents;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n tile: {\r\n get: function () {\r\n return this._tile;\r\n },\r\n },\r\n\r\n url: {\r\n get: function () {\r\n return this._resource.getUrlComponent(true);\r\n },\r\n },\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns undefined. Instead call batchTable for a tile in the composite.\r\n * @memberof Composite3DTileContent.prototype\r\n */\r\n batchTable: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n});\r\n\r\nvar sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;\r\n\r\nfunction initialize(content, arrayBuffer, byteOffset, factory) {\r\n byteOffset = defaultValue(byteOffset, 0);\r\n\r\n var uint8Array = new Uint8Array(arrayBuffer);\r\n var view = new DataView(arrayBuffer);\r\n byteOffset += sizeOfUint32; // Skip magic\r\n\r\n var version = view.getUint32(byteOffset, true);\r\n if (version !== 1) {\r\n throw new RuntimeError(\r\n \"Only Composite Tile version 1 is supported. Version \" +\r\n version +\r\n \" is not.\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n // Skip byteLength\r\n byteOffset += sizeOfUint32;\r\n\r\n var tilesLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var contentPromises = [];\r\n\r\n for (var i = 0; i < tilesLength; ++i) {\r\n var tileType = getMagic(uint8Array, byteOffset);\r\n\r\n // Tile byte length is stored after magic and version\r\n var tileByteLength = view.getUint32(byteOffset + sizeOfUint32 * 2, true);\r\n\r\n var contentFactory = factory[tileType];\r\n\r\n if (defined(contentFactory)) {\r\n var innerContent = contentFactory(\r\n content._tileset,\r\n content._tile,\r\n content._resource,\r\n arrayBuffer,\r\n byteOffset\r\n );\r\n content._contents.push(innerContent);\r\n contentPromises.push(innerContent.readyPromise);\r\n } else {\r\n throw new RuntimeError(\r\n \"Unknown tile content type, \" + tileType + \", inside Composite tile\"\r\n );\r\n }\r\n\r\n byteOffset += tileByteLength;\r\n }\r\n\r\n when\r\n .all(contentPromises)\r\n .then(function () {\r\n content._readyPromise.resolve(content);\r\n })\r\n .otherwise(function (error) {\r\n content._readyPromise.reject(error);\r\n });\r\n}\r\n\r\n/**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns false. Instead call hasProperty for a tile in the composite.\r\n */\r\nComposite3DTileContent.prototype.hasProperty = function (batchId, name) {\r\n return false;\r\n};\r\n\r\n/**\r\n * Part of the {@link Cesium3DTileContent} interface. Composite3DTileContent\r\n * always returns undefined. Instead call getFeature for a tile in the composite.\r\n */\r\nComposite3DTileContent.prototype.getFeature = function (batchId) {\r\n return undefined;\r\n};\r\n\r\nComposite3DTileContent.prototype.applyDebugSettings = function (\r\n enabled,\r\n color\r\n) {\r\n var contents = this._contents;\r\n var length = contents.length;\r\n for (var i = 0; i < length; ++i) {\r\n contents[i].applyDebugSettings(enabled, color);\r\n }\r\n};\r\n\r\nComposite3DTileContent.prototype.applyStyle = function (style) {\r\n var contents = this._contents;\r\n var length = contents.length;\r\n for (var i = 0; i < length; ++i) {\r\n contents[i].applyStyle(style);\r\n }\r\n};\r\n\r\nComposite3DTileContent.prototype.update = function (tileset, frameState) {\r\n var contents = this._contents;\r\n var length = contents.length;\r\n for (var i = 0; i < length; ++i) {\r\n contents[i].update(tileset, frameState);\r\n }\r\n};\r\n\r\nComposite3DTileContent.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nComposite3DTileContent.prototype.destroy = function () {\r\n var contents = this._contents;\r\n var length = contents.length;\r\n for (var i = 0; i < length; ++i) {\r\n contents[i].destroy();\r\n }\r\n return destroyObject(this);\r\n};\r\nexport default Composite3DTileContent;\r\n","import arraySlice from \"../Core/arraySlice.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport TaskProcessor from \"../Core/TaskProcessor.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport ClassificationType from \"./ClassificationType.js\";\r\nimport Vector3DTileBatch from \"./Vector3DTileBatch.js\";\r\nimport Vector3DTilePrimitive from \"./Vector3DTilePrimitive.js\";\r\n\r\n/**\r\n * Creates a batch of box, cylinder, ellipsoid and/or sphere geometries intersecting terrain or 3D Tiles.\r\n *\r\n * @alias Vector3DTileGeometry\r\n * @constructor\r\n *\r\n * @param {Object} options An object with following properties:\r\n * @param {Float32Array} [options.boxes] The boxes in the tile.\r\n * @param {Uint16Array} [options.boxBatchIds] The batch ids for each box.\r\n * @param {Float32Array} [options.cylinders] The cylinders in the tile.\r\n * @param {Uint16Array} [options.cylinderBatchIds] The batch ids for each cylinder.\r\n * @param {Float32Array} [options.ellipsoids] The ellipsoids in the tile.\r\n * @param {Uint16Array} [options.ellipsoidBatchIds] The batch ids for each ellipsoid.\r\n * @param {Float32Array} [options.spheres] The spheres in the tile.\r\n * @param {Uint16Array} [options.sphereBatchIds] The batch ids for each sphere.\r\n * @param {Cartesian3} options.center The RTC center of all geometries.\r\n * @param {Matrix4} options.modelMatrix The model matrix of all geometries. Applied after the individual geometry model matrices.\r\n * @param {Cesium3DTileBatchTable} options.batchTable The batch table.\r\n * @param {BoundingSphere} options.boundingVolume The bounding volume containing all of the geometry in the tile.\r\n *\r\n * @private\r\n */\r\nfunction Vector3DTileGeometry(options) {\r\n // these will all be released after the primitive is created\r\n this._boxes = options.boxes;\r\n this._boxBatchIds = options.boxBatchIds;\r\n this._cylinders = options.cylinders;\r\n this._cylinderBatchIds = options.cylinderBatchIds;\r\n this._ellipsoids = options.ellipsoids;\r\n this._ellipsoidBatchIds = options.ellipsoidBatchIds;\r\n this._spheres = options.spheres;\r\n this._sphereBatchIds = options.sphereBatchIds;\r\n this._modelMatrix = options.modelMatrix;\r\n this._batchTable = options.batchTable;\r\n this._boundingVolume = options.boundingVolume;\r\n\r\n this._center = options.center;\r\n if (!defined(this._center)) {\r\n if (defined(this._boundingVolume)) {\r\n this._center = Cartesian3.clone(this._boundingVolume.center);\r\n } else {\r\n this._center = Cartesian3.clone(Cartesian3.ZERO);\r\n }\r\n }\r\n\r\n this._boundingVolumes = undefined;\r\n this._batchedIndices = undefined;\r\n\r\n this._indices = undefined;\r\n this._indexOffsets = undefined;\r\n this._indexCounts = undefined;\r\n\r\n this._positions = undefined;\r\n this._vertexBatchIds = undefined;\r\n\r\n this._batchIds = undefined;\r\n\r\n this._batchTableColors = undefined;\r\n this._packedBuffer = undefined;\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._verticesPromise = undefined;\r\n\r\n this._primitive = undefined;\r\n\r\n /**\r\n * Draws the wireframe of the classification geometries.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugWireframe = false;\r\n\r\n /**\r\n * Forces a re-batch instead of waiting after a number of frames have been rendered. For testing only.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.forceRebatch = false;\r\n\r\n /**\r\n * What this tile will classify.\r\n * @type {ClassificationType}\r\n * @default ClassificationType.BOTH\r\n */\r\n this.classificationType = ClassificationType.BOTH;\r\n}\r\n\r\nObject.defineProperties(Vector3DTileGeometry.prototype, {\r\n /**\r\n * Gets the number of triangles.\r\n *\r\n * @memberof Vector3DTileGeometry.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n trianglesLength: {\r\n get: function () {\r\n if (defined(this._primitive)) {\r\n return this._primitive.trianglesLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the geometry memory in bytes.\r\n *\r\n * @memberof Vector3DTileGeometry.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n geometryByteLength: {\r\n get: function () {\r\n if (defined(this._primitive)) {\r\n return this._primitive.geometryByteLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof Vector3DTileGeometry.prototype\r\n * @type {Promise}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n});\r\n\r\nVector3DTileGeometry.packedBoxLength =\r\n Matrix4.packedLength + Cartesian3.packedLength;\r\nVector3DTileGeometry.packedCylinderLength = Matrix4.packedLength + 2;\r\nVector3DTileGeometry.packedEllipsoidLength =\r\n Matrix4.packedLength + Cartesian3.packedLength;\r\nVector3DTileGeometry.packedSphereLength = Cartesian3.packedLength + 1;\r\n\r\nfunction packBuffer(geometries) {\r\n var packedBuffer = new Float64Array(\r\n Matrix4.packedLength + Cartesian3.packedLength\r\n );\r\n\r\n var offset = 0;\r\n Cartesian3.pack(geometries._center, packedBuffer, offset);\r\n offset += Cartesian3.packedLength;\r\n Matrix4.pack(geometries._modelMatrix, packedBuffer, offset);\r\n\r\n return packedBuffer;\r\n}\r\n\r\nfunction unpackBuffer(geometries, packedBuffer) {\r\n var offset = 0;\r\n\r\n var indicesBytesPerElement = packedBuffer[offset++];\r\n var numBVS = packedBuffer[offset++];\r\n var bvs = (geometries._boundingVolumes = new Array(numBVS));\r\n\r\n for (var i = 0; i < numBVS; ++i) {\r\n bvs[i] = BoundingSphere.unpack(packedBuffer, offset);\r\n offset += BoundingSphere.packedLength;\r\n }\r\n\r\n var numBatchedIndices = packedBuffer[offset++];\r\n var bis = (geometries._batchedIndices = new Array(numBatchedIndices));\r\n\r\n for (var j = 0; j < numBatchedIndices; ++j) {\r\n var color = Color.unpack(packedBuffer, offset);\r\n offset += Color.packedLength;\r\n\r\n var indexOffset = packedBuffer[offset++];\r\n var count = packedBuffer[offset++];\r\n\r\n var length = packedBuffer[offset++];\r\n var batchIds = new Array(length);\r\n\r\n for (var k = 0; k < length; ++k) {\r\n batchIds[k] = packedBuffer[offset++];\r\n }\r\n\r\n bis[j] = new Vector3DTileBatch({\r\n color: color,\r\n offset: indexOffset,\r\n count: count,\r\n batchIds: batchIds,\r\n });\r\n }\r\n\r\n return indicesBytesPerElement;\r\n}\r\n\r\nvar createVerticesTaskProcessor = new TaskProcessor(\r\n \"createVectorTileGeometries\",\r\n 5\r\n);\r\nvar scratchColor = new Color();\r\n\r\nfunction createPrimitive(geometries) {\r\n if (defined(geometries._primitive)) {\r\n return;\r\n }\r\n\r\n if (!defined(geometries._verticesPromise)) {\r\n var boxes = geometries._boxes;\r\n var boxBatchIds = geometries._boxBatchIds;\r\n var cylinders = geometries._cylinders;\r\n var cylinderBatchIds = geometries._cylinderBatchIds;\r\n var ellipsoids = geometries._ellipsoids;\r\n var ellipsoidBatchIds = geometries._ellipsoidBatchIds;\r\n var spheres = geometries._spheres;\r\n var sphereBatchIds = geometries._sphereBatchIds;\r\n\r\n var batchTableColors = geometries._batchTableColors;\r\n var packedBuffer = geometries._packedBuffer;\r\n\r\n if (!defined(batchTableColors)) {\r\n // Copy because they may be the views on the same buffer.\r\n var length = 0;\r\n if (defined(geometries._boxes)) {\r\n boxes = geometries._boxes = arraySlice(boxes);\r\n boxBatchIds = geometries._boxBatchIds = arraySlice(boxBatchIds);\r\n length += boxBatchIds.length;\r\n }\r\n if (defined(geometries._cylinders)) {\r\n cylinders = geometries._cylinders = arraySlice(cylinders);\r\n cylinderBatchIds = geometries._cylinderBatchIds = arraySlice(\r\n cylinderBatchIds\r\n );\r\n length += cylinderBatchIds.length;\r\n }\r\n if (defined(geometries._ellipsoids)) {\r\n ellipsoids = geometries._ellipsoids = arraySlice(ellipsoids);\r\n ellipsoidBatchIds = geometries._ellipsoidBatchIds = arraySlice(\r\n ellipsoidBatchIds\r\n );\r\n length += ellipsoidBatchIds.length;\r\n }\r\n if (defined(geometries._spheres)) {\r\n spheres = geometries._sphere = arraySlice(spheres);\r\n sphereBatchIds = geometries._sphereBatchIds = arraySlice(\r\n sphereBatchIds\r\n );\r\n length += sphereBatchIds.length;\r\n }\r\n\r\n batchTableColors = geometries._batchTableColors = new Uint32Array(length);\r\n var batchTable = geometries._batchTable;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var color = batchTable.getColor(i, scratchColor);\r\n batchTableColors[i] = color.toRgba();\r\n }\r\n\r\n packedBuffer = geometries._packedBuffer = packBuffer(geometries);\r\n }\r\n\r\n var transferrableObjects = [];\r\n if (defined(boxes)) {\r\n transferrableObjects.push(boxes.buffer, boxBatchIds.buffer);\r\n }\r\n if (defined(cylinders)) {\r\n transferrableObjects.push(cylinders.buffer, cylinderBatchIds.buffer);\r\n }\r\n if (defined(ellipsoids)) {\r\n transferrableObjects.push(ellipsoids.buffer, ellipsoidBatchIds.buffer);\r\n }\r\n if (defined(spheres)) {\r\n transferrableObjects.push(spheres.buffer, sphereBatchIds.buffer);\r\n }\r\n transferrableObjects.push(batchTableColors.buffer, packedBuffer.buffer);\r\n\r\n var parameters = {\r\n boxes: defined(boxes) ? boxes.buffer : undefined,\r\n boxBatchIds: defined(boxes) ? boxBatchIds.buffer : undefined,\r\n cylinders: defined(cylinders) ? cylinders.buffer : undefined,\r\n cylinderBatchIds: defined(cylinders)\r\n ? cylinderBatchIds.buffer\r\n : undefined,\r\n ellipsoids: defined(ellipsoids) ? ellipsoids.buffer : undefined,\r\n ellipsoidBatchIds: defined(ellipsoids)\r\n ? ellipsoidBatchIds.buffer\r\n : undefined,\r\n spheres: defined(spheres) ? spheres.buffer : undefined,\r\n sphereBatchIds: defined(spheres) ? sphereBatchIds.buffer : undefined,\r\n batchTableColors: batchTableColors.buffer,\r\n packedBuffer: packedBuffer.buffer,\r\n };\r\n\r\n var verticesPromise = (geometries._verticesPromise = createVerticesTaskProcessor.scheduleTask(\r\n parameters,\r\n transferrableObjects\r\n ));\r\n if (!defined(verticesPromise)) {\r\n // Postponed\r\n return;\r\n }\r\n\r\n verticesPromise.then(function (result) {\r\n var packedBuffer = new Float64Array(result.packedBuffer);\r\n var indicesBytesPerElement = unpackBuffer(geometries, packedBuffer);\r\n\r\n if (indicesBytesPerElement === 2) {\r\n geometries._indices = new Uint16Array(result.indices);\r\n } else {\r\n geometries._indices = new Uint32Array(result.indices);\r\n }\r\n\r\n geometries._indexOffsets = new Uint32Array(result.indexOffsets);\r\n geometries._indexCounts = new Uint32Array(result.indexCounts);\r\n\r\n geometries._positions = new Float32Array(result.positions);\r\n geometries._vertexBatchIds = new Uint16Array(result.vertexBatchIds);\r\n\r\n geometries._batchIds = new Uint16Array(result.batchIds);\r\n\r\n geometries._ready = true;\r\n });\r\n }\r\n\r\n if (geometries._ready && !defined(geometries._primitive)) {\r\n geometries._primitive = new Vector3DTilePrimitive({\r\n batchTable: geometries._batchTable,\r\n positions: geometries._positions,\r\n batchIds: geometries._batchIds,\r\n vertexBatchIds: geometries._vertexBatchIds,\r\n indices: geometries._indices,\r\n indexOffsets: geometries._indexOffsets,\r\n indexCounts: geometries._indexCounts,\r\n batchedIndices: geometries._batchedIndices,\r\n boundingVolume: geometries._boundingVolume,\r\n boundingVolumes: geometries._boundingVolumes,\r\n center: geometries._center,\r\n pickObject: defaultValue(geometries._pickObject, geometries),\r\n });\r\n\r\n geometries._boxes = undefined;\r\n geometries._boxBatchIds = undefined;\r\n geometries._cylinders = undefined;\r\n geometries._cylinderBatchIds = undefined;\r\n geometries._ellipsoids = undefined;\r\n geometries._ellipsoidBatchIds = undefined;\r\n geometries._spheres = undefined;\r\n geometries._sphereBatchIds = undefined;\r\n geometries._center = undefined;\r\n geometries._modelMatrix = undefined;\r\n geometries._batchTable = undefined;\r\n geometries._boundingVolume = undefined;\r\n\r\n geometries._boundingVolumes = undefined;\r\n geometries._batchedIndices = undefined;\r\n\r\n geometries._indices = undefined;\r\n geometries._indexOffsets = undefined;\r\n geometries._indexCounts = undefined;\r\n\r\n geometries._positions = undefined;\r\n geometries._vertexBatchIds = undefined;\r\n\r\n geometries._batchIds = undefined;\r\n\r\n geometries._batchTableColors = undefined;\r\n geometries._packedBuffer = undefined;\r\n\r\n geometries._verticesPromise = undefined;\r\n\r\n geometries._readyPromise.resolve();\r\n }\r\n}\r\n\r\n/**\r\n * Creates features for each geometry and places it at the batch id index of features.\r\n *\r\n * @param {Vector3DTileContent} content The vector tile content.\r\n * @param {Cesium3DTileFeature[]} features An array of features where the polygon features will be placed.\r\n */\r\nVector3DTileGeometry.prototype.createFeatures = function (content, features) {\r\n this._primitive.createFeatures(content, features);\r\n};\r\n\r\n/**\r\n * Colors the entire tile when enabled is true. The resulting color will be (geometry batch table color * color).\r\n *\r\n * @param {Boolean} enabled Whether to enable debug coloring.\r\n * @param {Color} color The debug color.\r\n */\r\nVector3DTileGeometry.prototype.applyDebugSettings = function (enabled, color) {\r\n this._primitive.applyDebugSettings(enabled, color);\r\n};\r\n\r\n/**\r\n * Apply a style to the content.\r\n *\r\n * @param {Cesium3DTileStyle} style The style.\r\n * @param {Cesium3DTileFeature[]} features The array of features.\r\n */\r\nVector3DTileGeometry.prototype.applyStyle = function (style, features) {\r\n this._primitive.applyStyle(style, features);\r\n};\r\n\r\n/**\r\n * Call when updating the color of a geometry with batchId changes color. The geometries will need to be re-batched\r\n * on the next update.\r\n *\r\n * @param {Number} batchId The batch id of the geometries whose color has changed.\r\n * @param {Color} color The new polygon color.\r\n */\r\nVector3DTileGeometry.prototype.updateCommands = function (batchId, color) {\r\n this._primitive.updateCommands(batchId, color);\r\n};\r\n\r\n/**\r\n * Updates the batches and queues the commands for rendering.\r\n *\r\n * @param {FrameState} frameState The current frame state.\r\n */\r\nVector3DTileGeometry.prototype.update = function (frameState) {\r\n createPrimitive(this);\r\n\r\n if (!this._ready) {\r\n return;\r\n }\r\n\r\n this._primitive.debugWireframe = this.debugWireframe;\r\n this._primitive.forceRebatch = this.forceRebatch;\r\n this._primitive.classificationType = this.classificationType;\r\n this._primitive.update(frameState);\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n */\r\nVector3DTileGeometry.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nVector3DTileGeometry.prototype.destroy = function () {\r\n this._primitive = this._primitive && this._primitive.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Vector3DTileGeometry;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport getJsonFromTypedArray from \"../Core/getJsonFromTypedArray.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Cesium3DTileBatchTable from \"./Cesium3DTileBatchTable.js\";\r\nimport Vector3DTileGeometry from \"./Vector3DTileGeometry.js\";\r\n\r\n/**\r\n *

\r\n * Implements the {@link Cesium3DTileContent} interface.\r\n *

\r\n *\r\n * @alias Geometry3DTileContent\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction Geometry3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n) {\r\n this._tileset = tileset;\r\n this._tile = tile;\r\n this._resource = resource;\r\n this._geometries = undefined;\r\n\r\n this._contentReadyPromise = undefined;\r\n this._readyPromise = when.defer();\r\n\r\n this._batchTable = undefined;\r\n this._features = undefined;\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface.\r\n */\r\n this.featurePropertiesDirty = false;\r\n\r\n initialize(this, arrayBuffer, byteOffset);\r\n}\r\n\r\nObject.defineProperties(Geometry3DTileContent.prototype, {\r\n featuresLength: {\r\n get: function () {\r\n return defined(this._batchTable) ? this._batchTable.featuresLength : 0;\r\n },\r\n },\r\n\r\n pointsLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n trianglesLength: {\r\n get: function () {\r\n if (defined(this._geometries)) {\r\n return this._geometries.trianglesLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n geometryByteLength: {\r\n get: function () {\r\n if (defined(this._geometries)) {\r\n return this._geometries.geometryByteLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n texturesByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n batchTableByteLength: {\r\n get: function () {\r\n return defined(this._batchTable) ? this._batchTable.memorySizeInBytes : 0;\r\n },\r\n },\r\n\r\n innerContents: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n tile: {\r\n get: function () {\r\n return this._tile;\r\n },\r\n },\r\n\r\n url: {\r\n get: function () {\r\n return this._resource.getUrlComponent(true);\r\n },\r\n },\r\n\r\n batchTable: {\r\n get: function () {\r\n return this._batchTable;\r\n },\r\n },\r\n});\r\n\r\nfunction createColorChangedCallback(content) {\r\n return function (batchId, color) {\r\n if (defined(content._geometries)) {\r\n content._geometries.updateCommands(batchId, color);\r\n }\r\n };\r\n}\r\n\r\nfunction getBatchIds(featureTableJson, featureTableBinary) {\r\n var boxBatchIds;\r\n var cylinderBatchIds;\r\n var ellipsoidBatchIds;\r\n var sphereBatchIds;\r\n var i;\r\n\r\n var numberOfBoxes = defaultValue(featureTableJson.BOXES_LENGTH, 0);\r\n var numberOfCylinders = defaultValue(featureTableJson.CYLINDERS_LENGTH, 0);\r\n var numberOfEllipsoids = defaultValue(featureTableJson.ELLIPSOIDS_LENGTH, 0);\r\n var numberOfSpheres = defaultValue(featureTableJson.SPHERES_LENGTH, 0);\r\n\r\n if (numberOfBoxes > 0 && defined(featureTableJson.BOX_BATCH_IDS)) {\r\n var boxBatchIdsByteOffset =\r\n featureTableBinary.byteOffset + featureTableJson.BOX_BATCH_IDS.byteOffset;\r\n boxBatchIds = new Uint16Array(\r\n featureTableBinary.buffer,\r\n boxBatchIdsByteOffset,\r\n numberOfBoxes\r\n );\r\n }\r\n\r\n if (numberOfCylinders > 0 && defined(featureTableJson.CYLINDER_BATCH_IDS)) {\r\n var cylinderBatchIdsByteOffset =\r\n featureTableBinary.byteOffset +\r\n featureTableJson.CYLINDER_BATCH_IDS.byteOffset;\r\n cylinderBatchIds = new Uint16Array(\r\n featureTableBinary.buffer,\r\n cylinderBatchIdsByteOffset,\r\n numberOfCylinders\r\n );\r\n }\r\n\r\n if (numberOfEllipsoids > 0 && defined(featureTableJson.ELLIPSOID_BATCH_IDS)) {\r\n var ellipsoidBatchIdsByteOffset =\r\n featureTableBinary.byteOffset +\r\n featureTableJson.ELLIPSOID_BATCH_IDS.byteOffset;\r\n ellipsoidBatchIds = new Uint16Array(\r\n featureTableBinary.buffer,\r\n ellipsoidBatchIdsByteOffset,\r\n numberOfEllipsoids\r\n );\r\n }\r\n\r\n if (numberOfSpheres > 0 && defined(featureTableJson.SPHERE_BATCH_IDS)) {\r\n var sphereBatchIdsByteOffset =\r\n featureTableBinary.byteOffset +\r\n featureTableJson.SPHERE_BATCH_IDS.byteOffset;\r\n sphereBatchIds = new Uint16Array(\r\n featureTableBinary.buffer,\r\n sphereBatchIdsByteOffset,\r\n numberOfSpheres\r\n );\r\n }\r\n\r\n var atLeastOneDefined =\r\n defined(boxBatchIds) ||\r\n defined(cylinderBatchIds) ||\r\n defined(ellipsoidBatchIds) ||\r\n defined(sphereBatchIds);\r\n var atLeastOneUndefined =\r\n (numberOfBoxes > 0 && !defined(boxBatchIds)) ||\r\n (numberOfCylinders > 0 && !defined(cylinderBatchIds)) ||\r\n (numberOfEllipsoids > 0 && !defined(ellipsoidBatchIds)) ||\r\n (numberOfSpheres > 0 && !defined(sphereBatchIds));\r\n\r\n if (atLeastOneDefined && atLeastOneUndefined) {\r\n throw new RuntimeError(\r\n \"If one group of batch ids is defined, then all batch ids must be defined.\"\r\n );\r\n }\r\n\r\n var allUndefinedBatchIds =\r\n !defined(boxBatchIds) &&\r\n !defined(cylinderBatchIds) &&\r\n !defined(ellipsoidBatchIds) &&\r\n !defined(sphereBatchIds);\r\n if (allUndefinedBatchIds) {\r\n var id = 0;\r\n if (!defined(boxBatchIds) && numberOfBoxes > 0) {\r\n boxBatchIds = new Uint16Array(numberOfBoxes);\r\n for (i = 0; i < numberOfBoxes; ++i) {\r\n boxBatchIds[i] = id++;\r\n }\r\n }\r\n if (!defined(cylinderBatchIds) && numberOfCylinders > 0) {\r\n cylinderBatchIds = new Uint16Array(numberOfCylinders);\r\n for (i = 0; i < numberOfCylinders; ++i) {\r\n cylinderBatchIds[i] = id++;\r\n }\r\n }\r\n if (!defined(ellipsoidBatchIds) && numberOfEllipsoids > 0) {\r\n ellipsoidBatchIds = new Uint16Array(numberOfEllipsoids);\r\n for (i = 0; i < numberOfEllipsoids; ++i) {\r\n ellipsoidBatchIds[i] = id++;\r\n }\r\n }\r\n if (!defined(sphereBatchIds) && numberOfSpheres > 0) {\r\n sphereBatchIds = new Uint16Array(numberOfSpheres);\r\n for (i = 0; i < numberOfSpheres; ++i) {\r\n sphereBatchIds[i] = id++;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n boxes: boxBatchIds,\r\n cylinders: cylinderBatchIds,\r\n ellipsoids: ellipsoidBatchIds,\r\n spheres: sphereBatchIds,\r\n };\r\n}\r\n\r\nvar sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;\r\n\r\nfunction initialize(content, arrayBuffer, byteOffset) {\r\n byteOffset = defaultValue(byteOffset, 0);\r\n\r\n var uint8Array = new Uint8Array(arrayBuffer);\r\n var view = new DataView(arrayBuffer);\r\n byteOffset += sizeOfUint32; // Skip magic number\r\n\r\n var version = view.getUint32(byteOffset, true);\r\n if (version !== 1) {\r\n throw new RuntimeError(\r\n \"Only Geometry tile version 1 is supported. Version \" +\r\n version +\r\n \" is not.\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n var byteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n if (byteLength === 0) {\r\n content._readyPromise.resolve(content);\r\n return;\r\n }\r\n\r\n var featureTableJSONByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n if (featureTableJSONByteLength === 0) {\r\n throw new RuntimeError(\r\n \"Feature table must have a byte length greater than zero\"\r\n );\r\n }\r\n\r\n var featureTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var batchTableJSONByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var batchTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n featureTableJSONByteLength\r\n );\r\n byteOffset += featureTableJSONByteLength;\r\n\r\n var featureTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n featureTableBinaryByteLength\r\n );\r\n byteOffset += featureTableBinaryByteLength;\r\n\r\n var batchTableJson;\r\n var batchTableBinary;\r\n if (batchTableJSONByteLength > 0) {\r\n // PERFORMANCE_IDEA: is it possible to allocate this on-demand? Perhaps keep the\r\n // arraybuffer/string compressed in memory and then decompress it when it is first accessed.\r\n //\r\n // We could also make another request for it, but that would make the property set/get\r\n // API async, and would double the number of numbers in some cases.\r\n batchTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n batchTableJSONByteLength\r\n );\r\n byteOffset += batchTableJSONByteLength;\r\n\r\n if (batchTableBinaryByteLength > 0) {\r\n // Has a batch table binary\r\n batchTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n batchTableBinaryByteLength\r\n );\r\n // Copy the batchTableBinary section and let the underlying ArrayBuffer be freed\r\n batchTableBinary = new Uint8Array(batchTableBinary);\r\n }\r\n }\r\n\r\n var numberOfBoxes = defaultValue(featureTableJson.BOXES_LENGTH, 0);\r\n var numberOfCylinders = defaultValue(featureTableJson.CYLINDERS_LENGTH, 0);\r\n var numberOfEllipsoids = defaultValue(featureTableJson.ELLIPSOIDS_LENGTH, 0);\r\n var numberOfSpheres = defaultValue(featureTableJson.SPHERES_LENGTH, 0);\r\n\r\n var totalPrimitives =\r\n numberOfBoxes + numberOfCylinders + numberOfEllipsoids + numberOfSpheres;\r\n\r\n var batchTable = new Cesium3DTileBatchTable(\r\n content,\r\n totalPrimitives,\r\n batchTableJson,\r\n batchTableBinary,\r\n createColorChangedCallback(content)\r\n );\r\n content._batchTable = batchTable;\r\n\r\n if (totalPrimitives === 0) {\r\n return;\r\n }\r\n\r\n var modelMatrix = content.tile.computedTransform;\r\n\r\n var center;\r\n if (defined(featureTableJson.RTC_CENTER)) {\r\n center = Cartesian3.unpack(featureTableJson.RTC_CENTER);\r\n Matrix4.multiplyByPoint(modelMatrix, center, center);\r\n }\r\n\r\n var batchIds = getBatchIds(featureTableJson, featureTableBinary);\r\n\r\n if (\r\n numberOfBoxes > 0 ||\r\n numberOfCylinders > 0 ||\r\n numberOfEllipsoids > 0 ||\r\n numberOfSpheres > 0\r\n ) {\r\n var boxes;\r\n var cylinders;\r\n var ellipsoids;\r\n var spheres;\r\n\r\n if (numberOfBoxes > 0) {\r\n var boxesByteOffset =\r\n featureTableBinary.byteOffset + featureTableJson.BOXES.byteOffset;\r\n boxes = new Float32Array(\r\n featureTableBinary.buffer,\r\n boxesByteOffset,\r\n Vector3DTileGeometry.packedBoxLength * numberOfBoxes\r\n );\r\n }\r\n\r\n if (numberOfCylinders > 0) {\r\n var cylindersByteOffset =\r\n featureTableBinary.byteOffset + featureTableJson.CYLINDERS.byteOffset;\r\n cylinders = new Float32Array(\r\n featureTableBinary.buffer,\r\n cylindersByteOffset,\r\n Vector3DTileGeometry.packedCylinderLength * numberOfCylinders\r\n );\r\n }\r\n\r\n if (numberOfEllipsoids > 0) {\r\n var ellipsoidsByteOffset =\r\n featureTableBinary.byteOffset + featureTableJson.ELLIPSOIDS.byteOffset;\r\n ellipsoids = new Float32Array(\r\n featureTableBinary.buffer,\r\n ellipsoidsByteOffset,\r\n Vector3DTileGeometry.packedEllipsoidLength * numberOfEllipsoids\r\n );\r\n }\r\n\r\n if (numberOfSpheres > 0) {\r\n var spheresByteOffset =\r\n featureTableBinary.byteOffset + featureTableJson.SPHERES.byteOffset;\r\n spheres = new Float32Array(\r\n featureTableBinary.buffer,\r\n spheresByteOffset,\r\n Vector3DTileGeometry.packedSphereLength * numberOfSpheres\r\n );\r\n }\r\n\r\n content._geometries = new Vector3DTileGeometry({\r\n boxes: boxes,\r\n boxBatchIds: batchIds.boxes,\r\n cylinders: cylinders,\r\n cylinderBatchIds: batchIds.cylinders,\r\n ellipsoids: ellipsoids,\r\n ellipsoidBatchIds: batchIds.ellipsoids,\r\n spheres: spheres,\r\n sphereBatchIds: batchIds.spheres,\r\n center: center,\r\n modelMatrix: modelMatrix,\r\n batchTable: batchTable,\r\n boundingVolume: content.tile.boundingVolume.boundingVolume,\r\n });\r\n }\r\n}\r\n\r\nfunction createFeatures(content) {\r\n var featuresLength = content.featuresLength;\r\n if (!defined(content._features) && featuresLength > 0) {\r\n var features = new Array(featuresLength);\r\n if (defined(content._geometries)) {\r\n content._geometries.createFeatures(content, features);\r\n }\r\n content._features = features;\r\n }\r\n}\r\n\r\nGeometry3DTileContent.prototype.hasProperty = function (batchId, name) {\r\n return this._batchTable.hasProperty(batchId, name);\r\n};\r\n\r\nGeometry3DTileContent.prototype.getFeature = function (batchId) {\r\n //>>includeStart('debug', pragmas.debug);\r\n var featuresLength = this.featuresLength;\r\n if (!defined(batchId) || batchId < 0 || batchId >= featuresLength) {\r\n throw new DeveloperError(\r\n \"batchId is required and between zero and featuresLength - 1 (\" +\r\n (featuresLength - 1) +\r\n \").\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n createFeatures(this);\r\n return this._features[batchId];\r\n};\r\n\r\nGeometry3DTileContent.prototype.applyDebugSettings = function (enabled, color) {\r\n if (defined(this._geometries)) {\r\n this._geometries.applyDebugSettings(enabled, color);\r\n }\r\n};\r\n\r\nGeometry3DTileContent.prototype.applyStyle = function (style) {\r\n createFeatures(this);\r\n if (defined(this._geometries)) {\r\n this._geometries.applyStyle(style, this._features);\r\n }\r\n};\r\n\r\nGeometry3DTileContent.prototype.update = function (tileset, frameState) {\r\n if (defined(this._geometries)) {\r\n this._geometries.classificationType = this._tileset.classificationType;\r\n this._geometries.debugWireframe = this._tileset.debugWireframe;\r\n this._geometries.update(frameState);\r\n }\r\n if (defined(this._batchTable) && this._geometries._ready) {\r\n this._batchTable.update(tileset, frameState);\r\n }\r\n\r\n if (!defined(this._contentReadyPromise)) {\r\n var that = this;\r\n this._contentReadyPromise = this._geometries.readyPromise.then(function () {\r\n that._readyPromise.resolve(that);\r\n });\r\n }\r\n};\r\n\r\nGeometry3DTileContent.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nGeometry3DTileContent.prototype.destroy = function () {\r\n this._geometries = this._geometries && this._geometries.destroy();\r\n this._batchTable = this._batchTable && this._batchTable.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Geometry3DTileContent;\r\n","import Matrix4 from \"../Core/Matrix4.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction ModelInstance(collection, modelMatrix, instanceId) {\r\n this.primitive = collection;\r\n this._modelMatrix = Matrix4.clone(modelMatrix);\r\n this._instanceId = instanceId;\r\n}\r\n\r\nObject.defineProperties(ModelInstance.prototype, {\r\n instanceId: {\r\n get: function () {\r\n return this._instanceId;\r\n },\r\n },\r\n model: {\r\n get: function () {\r\n return this.primitive._model;\r\n },\r\n },\r\n modelMatrix: {\r\n get: function () {\r\n return Matrix4.clone(this._modelMatrix);\r\n },\r\n set: function (value) {\r\n Matrix4.clone(value, this._modelMatrix);\r\n this.primitive.expandBoundingSphere(this._modelMatrix);\r\n this.primitive._dirty = true;\r\n },\r\n },\r\n});\r\nexport default ModelInstance;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport clone from \"../Core/clone.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport PrimitiveType from \"../Core/PrimitiveType.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport ForEach from \"../ThirdParty/GltfPipeline/ForEach.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Model from \"./Model.js\";\r\nimport ModelInstance from \"./ModelInstance.js\";\r\nimport ModelUtility from \"./ModelUtility.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport ShadowMode from \"./ShadowMode.js\";\r\n\r\nvar LoadState = {\r\n NEEDS_LOAD: 0,\r\n LOADING: 1,\r\n LOADED: 2,\r\n FAILED: 3,\r\n};\r\n\r\n/**\r\n * A 3D model instance collection. All instances reference the same underlying model, but have unique\r\n * per-instance properties like model matrix, pick id, etc.\r\n *\r\n * Instances are rendered relative-to-center and for best results instances should be positioned close to one another.\r\n * Otherwise there may be precision issues if, for example, instances are placed on opposite sides of the globe.\r\n *\r\n * @alias ModelInstanceCollection\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Object[]} [options.instances] An array of instances, where each instance contains a modelMatrix and optional batchId when options.batchTable is defined.\r\n * @param {Cesium3DTileBatchTable} [options.batchTable] The batch table of the instanced 3D Tile.\r\n * @param {Resource|String} [options.url] The url to the .gltf file.\r\n * @param {Object} [options.requestType] The request type, used for request prioritization\r\n * @param {Object|ArrayBuffer|Uint8Array} [options.gltf] A glTF JSON object, or a binary glTF buffer.\r\n * @param {Resource|String} [options.basePath=''] The base path that paths in the glTF JSON are relative to.\r\n * @param {Boolean} [options.dynamic=false] Hint if instance model matrices will be updated frequently.\r\n * @param {Boolean} [options.show=true] Determines if the collection will be shown.\r\n * @param {Boolean} [options.allowPicking=true] When true, each instance is pickable with {@link Scene#pick}.\r\n * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded.\r\n * @param {Boolean} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded.\r\n * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the collection casts or receives shadows from light sources.\r\n * @param {Cartesian2} [options.imageBasedLightingFactor=new Cartesian2(1.0, 1.0)] Scales the diffuse and specular image-based lighting from the earth, sky, atmosphere and star skybox.\r\n * @param {Cartesian3} [options.lightColor] The light color when shading models. When undefined the scene's light color is used instead.\r\n * @param {Number} [options.luminanceAtZenith=0.2] The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map.\r\n * @param {Cartesian3[]} [options.sphericalHarmonicCoefficients] The third order spherical harmonic coefficients used for the diffuse color of image-based lighting.\r\n * @param {String} [options.specularEnvironmentMaps] A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.\r\n * @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the glTF material's doubleSided property; when false, back face culling is disabled.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for the collection.\r\n * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the instances in wireframe.\r\n *\r\n * @exception {DeveloperError} Must specify either or , but not both.\r\n * @exception {DeveloperError} Shader program cannot be optimized for instancing. Parameters cannot have any of the following semantics: MODEL, MODELINVERSE, MODELVIEWINVERSE, MODELVIEWPROJECTIONINVERSE, MODELINVERSETRANSPOSE.\r\n *\r\n * @private\r\n */\r\nfunction ModelInstanceCollection(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options.gltf) && !defined(options.url)) {\r\n throw new DeveloperError(\"Either options.gltf or options.url is required.\");\r\n }\r\n\r\n if (defined(options.gltf) && defined(options.url)) {\r\n throw new DeveloperError(\r\n \"Cannot pass in both options.gltf and options.url.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.show = defaultValue(options.show, true);\r\n\r\n this._instancingSupported = false;\r\n this._dynamic = defaultValue(options.dynamic, false);\r\n this._allowPicking = defaultValue(options.allowPicking, true);\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n this._state = LoadState.NEEDS_LOAD;\r\n this._dirty = false;\r\n\r\n // Undocumented options\r\n this._cull = defaultValue(options.cull, true);\r\n this._opaquePass = defaultValue(options.opaquePass, Pass.OPAQUE);\r\n\r\n this._instances = createInstances(this, options.instances);\r\n\r\n // When the model instance collection is backed by an i3dm tile,\r\n // use its batch table resources to modify the shaders, attributes, and uniform maps.\r\n this._batchTable = options.batchTable;\r\n\r\n this._model = undefined;\r\n this._vertexBufferTypedArray = undefined; // Hold onto the vertex buffer contents when dynamic is true\r\n this._vertexBuffer = undefined;\r\n this._batchIdBuffer = undefined;\r\n this._instancedUniformsByProgram = undefined;\r\n\r\n this._drawCommands = [];\r\n this._modelCommands = undefined;\r\n\r\n this._renderStates = undefined;\r\n this._disableCullingRenderStates = undefined;\r\n\r\n this._boundingSphere = createBoundingSphere(this);\r\n this._center = Cartesian3.clone(this._boundingSphere.center);\r\n this._rtcTransform = new Matrix4();\r\n this._rtcModelView = new Matrix4(); // Holds onto uniform\r\n\r\n this._mode = undefined;\r\n\r\n this.modelMatrix = Matrix4.clone(Matrix4.IDENTITY);\r\n this._modelMatrix = Matrix4.clone(this.modelMatrix);\r\n\r\n // Passed on to Model\r\n this._url = Resource.createIfNeeded(options.url);\r\n this._requestType = options.requestType;\r\n this._gltf = options.gltf;\r\n this._basePath = Resource.createIfNeeded(options.basePath);\r\n this._asynchronous = options.asynchronous;\r\n this._incrementallyLoadTextures = options.incrementallyLoadTextures;\r\n this._upAxis = options.upAxis; // Undocumented option\r\n this._forwardAxis = options.forwardAxis; // Undocumented option\r\n\r\n this.shadows = defaultValue(options.shadows, ShadowMode.ENABLED);\r\n this._shadows = this.shadows;\r\n\r\n this._pickIdLoaded = options.pickIdLoaded;\r\n\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n this._debugShowBoundingVolume = false;\r\n\r\n this.debugWireframe = defaultValue(options.debugWireframe, false);\r\n this._debugWireframe = false;\r\n\r\n this._imageBasedLightingFactor = new Cartesian2(1.0, 1.0);\r\n Cartesian2.clone(\r\n options.imageBasedLightingFactor,\r\n this._imageBasedLightingFactor\r\n );\r\n this.lightColor = options.lightColor;\r\n this.luminanceAtZenith = options.luminanceAtZenith;\r\n this.sphericalHarmonicCoefficients = options.sphericalHarmonicCoefficients;\r\n this.specularEnvironmentMaps = options.specularEnvironmentMaps;\r\n this.backFaceCulling = defaultValue(options.backFaceCulling, true);\r\n this._backFaceCulling = this.backFaceCulling;\r\n}\r\n\r\nObject.defineProperties(ModelInstanceCollection.prototype, {\r\n allowPicking: {\r\n get: function () {\r\n return this._allowPicking;\r\n },\r\n },\r\n length: {\r\n get: function () {\r\n return this._instances.length;\r\n },\r\n },\r\n activeAnimations: {\r\n get: function () {\r\n return this._model.activeAnimations;\r\n },\r\n },\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n imageBasedLightingFactor: {\r\n get: function () {\r\n return this._imageBasedLightingFactor;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"imageBasedLightingFactor\", value);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"imageBasedLightingFactor.x\",\r\n value.x,\r\n 0.0\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"imageBasedLightingFactor.x\",\r\n value.x,\r\n 1.0\r\n );\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"imageBasedLightingFactor.y\",\r\n value.y,\r\n 0.0\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"imageBasedLightingFactor.y\",\r\n value.y,\r\n 1.0\r\n );\r\n //>>includeEnd('debug');\r\n Cartesian2.clone(value, this._imageBasedLightingFactor);\r\n },\r\n },\r\n});\r\n\r\nfunction createInstances(collection, instancesOptions) {\r\n instancesOptions = defaultValue(instancesOptions, []);\r\n var length = instancesOptions.length;\r\n var instances = new Array(length);\r\n for (var i = 0; i < length; ++i) {\r\n var instanceOptions = instancesOptions[i];\r\n var modelMatrix = instanceOptions.modelMatrix;\r\n var instanceId = defaultValue(instanceOptions.batchId, i);\r\n instances[i] = new ModelInstance(collection, modelMatrix, instanceId);\r\n }\r\n return instances;\r\n}\r\n\r\nfunction createBoundingSphere(collection) {\r\n var instancesLength = collection.length;\r\n var points = new Array(instancesLength);\r\n for (var i = 0; i < instancesLength; ++i) {\r\n points[i] = Matrix4.getTranslation(\r\n collection._instances[i]._modelMatrix,\r\n new Cartesian3()\r\n );\r\n }\r\n\r\n return BoundingSphere.fromPoints(points);\r\n}\r\n\r\nvar scratchCartesian = new Cartesian3();\r\nvar scratchMatrix = new Matrix4();\r\n\r\nModelInstanceCollection.prototype.expandBoundingSphere = function (\r\n instanceModelMatrix\r\n) {\r\n var translation = Matrix4.getTranslation(\r\n instanceModelMatrix,\r\n scratchCartesian\r\n );\r\n BoundingSphere.expand(\r\n this._boundingSphere,\r\n translation,\r\n this._boundingSphere\r\n );\r\n};\r\n\r\nfunction getCheckUniformSemanticFunction(\r\n modelSemantics,\r\n supportedSemantics,\r\n programId,\r\n uniformMap\r\n) {\r\n return function (uniform, uniformName) {\r\n var semantic = uniform.semantic;\r\n if (defined(semantic) && modelSemantics.indexOf(semantic) > -1) {\r\n if (supportedSemantics.indexOf(semantic) > -1) {\r\n uniformMap[uniformName] = semantic;\r\n } else {\r\n throw new RuntimeError(\r\n \"Shader program cannot be optimized for instancing. \" +\r\n 'Uniform \"' +\r\n uniformName +\r\n '\" in program \"' +\r\n programId +\r\n '\" uses unsupported semantic \"' +\r\n semantic +\r\n '\"'\r\n );\r\n }\r\n }\r\n };\r\n}\r\n\r\nfunction getInstancedUniforms(collection, programId) {\r\n if (defined(collection._instancedUniformsByProgram)) {\r\n return collection._instancedUniformsByProgram[programId];\r\n }\r\n\r\n var instancedUniformsByProgram = {};\r\n collection._instancedUniformsByProgram = instancedUniformsByProgram;\r\n\r\n // When using CESIUM_RTC_MODELVIEW the CESIUM_RTC center is ignored. Instances are always rendered relative-to-center.\r\n var modelSemantics = [\r\n \"MODEL\",\r\n \"MODELVIEW\",\r\n \"CESIUM_RTC_MODELVIEW\",\r\n \"MODELVIEWPROJECTION\",\r\n \"MODELINVERSE\",\r\n \"MODELVIEWINVERSE\",\r\n \"MODELVIEWPROJECTIONINVERSE\",\r\n \"MODELINVERSETRANSPOSE\",\r\n \"MODELVIEWINVERSETRANSPOSE\",\r\n ];\r\n var supportedSemantics = [\r\n \"MODELVIEW\",\r\n \"CESIUM_RTC_MODELVIEW\",\r\n \"MODELVIEWPROJECTION\",\r\n \"MODELVIEWINVERSETRANSPOSE\",\r\n ];\r\n\r\n var techniques = collection._model._sourceTechniques;\r\n for (var techniqueId in techniques) {\r\n if (techniques.hasOwnProperty(techniqueId)) {\r\n var technique = techniques[techniqueId];\r\n var program = technique.program;\r\n\r\n // Different techniques may share the same program, skip if already processed.\r\n // This assumes techniques that share a program do not declare different semantics for the same uniforms.\r\n if (!defined(instancedUniformsByProgram[program])) {\r\n var uniformMap = {};\r\n instancedUniformsByProgram[program] = uniformMap;\r\n ForEach.techniqueUniform(\r\n technique,\r\n getCheckUniformSemanticFunction(\r\n modelSemantics,\r\n supportedSemantics,\r\n programId,\r\n uniformMap\r\n )\r\n );\r\n }\r\n }\r\n }\r\n\r\n return instancedUniformsByProgram[programId];\r\n}\r\n\r\nfunction getVertexShaderCallback(collection) {\r\n return function (vs, programId) {\r\n var instancedUniforms = getInstancedUniforms(collection, programId);\r\n var usesBatchTable = defined(collection._batchTable);\r\n\r\n var renamedSource = ShaderSource.replaceMain(vs, \"czm_instancing_main\");\r\n\r\n var globalVarsHeader = \"\";\r\n var globalVarsMain = \"\";\r\n for (var uniform in instancedUniforms) {\r\n if (instancedUniforms.hasOwnProperty(uniform)) {\r\n var semantic = instancedUniforms[uniform];\r\n var varName;\r\n if (semantic === \"MODELVIEW\" || semantic === \"CESIUM_RTC_MODELVIEW\") {\r\n varName = \"czm_instanced_modelView\";\r\n } else if (semantic === \"MODELVIEWPROJECTION\") {\r\n varName = \"czm_instanced_modelViewProjection\";\r\n globalVarsHeader += \"mat4 czm_instanced_modelViewProjection;\\n\";\r\n globalVarsMain +=\r\n \"czm_instanced_modelViewProjection = czm_projection * czm_instanced_modelView;\\n\";\r\n } else if (semantic === \"MODELVIEWINVERSETRANSPOSE\") {\r\n varName = \"czm_instanced_modelViewInverseTranspose\";\r\n globalVarsHeader += \"mat3 czm_instanced_modelViewInverseTranspose;\\n\";\r\n globalVarsMain +=\r\n \"czm_instanced_modelViewInverseTranspose = mat3(czm_instanced_modelView);\\n\";\r\n }\r\n\r\n // Remove the uniform declaration\r\n var regex = new RegExp(\"uniform.*\" + uniform + \".*\");\r\n renamedSource = renamedSource.replace(regex, \"\");\r\n\r\n // Replace all occurrences of the uniform with the global variable\r\n regex = new RegExp(uniform + \"\\\\b\", \"g\");\r\n renamedSource = renamedSource.replace(regex, varName);\r\n }\r\n }\r\n\r\n // czm_instanced_model is the model matrix of the instance relative to center\r\n // czm_instanced_modifiedModelView is the transform from the center to view\r\n // czm_instanced_nodeTransform is the local offset of the node within the model\r\n var uniforms =\r\n \"uniform mat4 czm_instanced_modifiedModelView;\\n\" +\r\n \"uniform mat4 czm_instanced_nodeTransform;\\n\";\r\n\r\n var batchIdAttribute;\r\n var pickAttribute;\r\n var pickVarying;\r\n\r\n if (usesBatchTable) {\r\n batchIdAttribute = \"attribute float a_batchId;\\n\";\r\n pickAttribute = \"\";\r\n pickVarying = \"\";\r\n } else {\r\n batchIdAttribute = \"\";\r\n pickAttribute =\r\n \"attribute vec4 pickColor;\\n\" + \"varying vec4 v_pickColor;\\n\";\r\n pickVarying = \" v_pickColor = pickColor;\\n\";\r\n }\r\n\r\n var instancedSource =\r\n uniforms +\r\n globalVarsHeader +\r\n \"mat4 czm_instanced_modelView;\\n\" +\r\n \"attribute vec4 czm_modelMatrixRow0;\\n\" +\r\n \"attribute vec4 czm_modelMatrixRow1;\\n\" +\r\n \"attribute vec4 czm_modelMatrixRow2;\\n\" +\r\n batchIdAttribute +\r\n pickAttribute +\r\n renamedSource +\r\n \"void main()\\n\" +\r\n \"{\\n\" +\r\n \" mat4 czm_instanced_model = mat4(czm_modelMatrixRow0.x, czm_modelMatrixRow1.x, czm_modelMatrixRow2.x, 0.0, czm_modelMatrixRow0.y, czm_modelMatrixRow1.y, czm_modelMatrixRow2.y, 0.0, czm_modelMatrixRow0.z, czm_modelMatrixRow1.z, czm_modelMatrixRow2.z, 0.0, czm_modelMatrixRow0.w, czm_modelMatrixRow1.w, czm_modelMatrixRow2.w, 1.0);\\n\" +\r\n \" czm_instanced_modelView = czm_instanced_modifiedModelView * czm_instanced_model * czm_instanced_nodeTransform;\\n\" +\r\n globalVarsMain +\r\n \" czm_instancing_main();\\n\" +\r\n pickVarying +\r\n \"}\\n\";\r\n\r\n if (usesBatchTable) {\r\n var gltf = collection._model.gltf;\r\n var diffuseAttributeOrUniformName = ModelUtility.getDiffuseAttributeOrUniform(\r\n gltf,\r\n programId\r\n );\r\n instancedSource = collection._batchTable.getVertexShaderCallback(\r\n true,\r\n \"a_batchId\",\r\n diffuseAttributeOrUniformName\r\n )(instancedSource);\r\n }\r\n\r\n return instancedSource;\r\n };\r\n}\r\n\r\nfunction getFragmentShaderCallback(collection) {\r\n return function (fs, programId) {\r\n var batchTable = collection._batchTable;\r\n if (defined(batchTable)) {\r\n var gltf = collection._model.gltf;\r\n var diffuseAttributeOrUniformName = ModelUtility.getDiffuseAttributeOrUniform(\r\n gltf,\r\n programId\r\n );\r\n fs = batchTable.getFragmentShaderCallback(\r\n true,\r\n diffuseAttributeOrUniformName,\r\n false\r\n )(fs);\r\n } else {\r\n fs = \"varying vec4 v_pickColor;\\n\" + fs;\r\n }\r\n return fs;\r\n };\r\n}\r\n\r\nfunction createModifiedModelView(collection, context) {\r\n return function () {\r\n return Matrix4.multiply(\r\n context.uniformState.view,\r\n collection._rtcTransform,\r\n collection._rtcModelView\r\n );\r\n };\r\n}\r\n\r\nfunction createNodeTransformFunction(node) {\r\n return function () {\r\n return node.computedMatrix;\r\n };\r\n}\r\n\r\nfunction getUniformMapCallback(collection, context) {\r\n return function (uniformMap, programId, node) {\r\n uniformMap = clone(uniformMap);\r\n uniformMap.czm_instanced_modifiedModelView = createModifiedModelView(\r\n collection,\r\n context\r\n );\r\n uniformMap.czm_instanced_nodeTransform = createNodeTransformFunction(node);\r\n\r\n // Remove instanced uniforms from the uniform map\r\n var instancedUniforms = getInstancedUniforms(collection, programId);\r\n for (var uniform in instancedUniforms) {\r\n if (instancedUniforms.hasOwnProperty(uniform)) {\r\n delete uniformMap[uniform];\r\n }\r\n }\r\n\r\n if (defined(collection._batchTable)) {\r\n uniformMap = collection._batchTable.getUniformMapCallback()(uniformMap);\r\n }\r\n\r\n return uniformMap;\r\n };\r\n}\r\n\r\nfunction getVertexShaderNonInstancedCallback(collection) {\r\n return function (vs, programId) {\r\n if (defined(collection._batchTable)) {\r\n var gltf = collection._model.gltf;\r\n var diffuseAttributeOrUniformName = ModelUtility.getDiffuseAttributeOrUniform(\r\n gltf,\r\n programId\r\n );\r\n vs = collection._batchTable.getVertexShaderCallback(\r\n true,\r\n \"a_batchId\",\r\n diffuseAttributeOrUniformName\r\n )(vs);\r\n // Treat a_batchId as a uniform rather than a vertex attribute\r\n vs = \"uniform float a_batchId\\n;\" + vs;\r\n }\r\n return vs;\r\n };\r\n}\r\n\r\nfunction getFragmentShaderNonInstancedCallback(collection) {\r\n return function (fs, programId) {\r\n var batchTable = collection._batchTable;\r\n if (defined(batchTable)) {\r\n var gltf = collection._model.gltf;\r\n var diffuseAttributeOrUniformName = ModelUtility.getDiffuseAttributeOrUniform(\r\n gltf,\r\n programId\r\n );\r\n fs = batchTable.getFragmentShaderCallback(\r\n true,\r\n diffuseAttributeOrUniformName,\r\n false\r\n )(fs);\r\n } else {\r\n fs = \"uniform vec4 czm_pickColor;\\n\" + fs;\r\n }\r\n return fs;\r\n };\r\n}\r\n\r\nfunction getUniformMapNonInstancedCallback(collection) {\r\n return function (uniformMap) {\r\n if (defined(collection._batchTable)) {\r\n uniformMap = collection._batchTable.getUniformMapCallback()(uniformMap);\r\n }\r\n\r\n return uniformMap;\r\n };\r\n}\r\n\r\nfunction getVertexBufferTypedArray(collection) {\r\n var instances = collection._instances;\r\n var instancesLength = collection.length;\r\n var collectionCenter = collection._center;\r\n var vertexSizeInFloats = 12;\r\n\r\n var bufferData = collection._vertexBufferTypedArray;\r\n if (!defined(bufferData)) {\r\n bufferData = new Float32Array(instancesLength * vertexSizeInFloats);\r\n }\r\n if (collection._dynamic) {\r\n // Hold onto the buffer data so we don't have to allocate new memory every frame.\r\n collection._vertexBufferTypedArray = bufferData;\r\n }\r\n\r\n for (var i = 0; i < instancesLength; ++i) {\r\n var modelMatrix = instances[i]._modelMatrix;\r\n\r\n // Instance matrix is relative to center\r\n var instanceMatrix = Matrix4.clone(modelMatrix, scratchMatrix);\r\n instanceMatrix[12] -= collectionCenter.x;\r\n instanceMatrix[13] -= collectionCenter.y;\r\n instanceMatrix[14] -= collectionCenter.z;\r\n\r\n var offset = i * vertexSizeInFloats;\r\n\r\n // First three rows of the model matrix\r\n bufferData[offset + 0] = instanceMatrix[0];\r\n bufferData[offset + 1] = instanceMatrix[4];\r\n bufferData[offset + 2] = instanceMatrix[8];\r\n bufferData[offset + 3] = instanceMatrix[12];\r\n bufferData[offset + 4] = instanceMatrix[1];\r\n bufferData[offset + 5] = instanceMatrix[5];\r\n bufferData[offset + 6] = instanceMatrix[9];\r\n bufferData[offset + 7] = instanceMatrix[13];\r\n bufferData[offset + 8] = instanceMatrix[2];\r\n bufferData[offset + 9] = instanceMatrix[6];\r\n bufferData[offset + 10] = instanceMatrix[10];\r\n bufferData[offset + 11] = instanceMatrix[14];\r\n }\r\n\r\n return bufferData;\r\n}\r\n\r\nfunction createVertexBuffer(collection, context) {\r\n var i;\r\n var instances = collection._instances;\r\n var instancesLength = collection.length;\r\n var dynamic = collection._dynamic;\r\n var usesBatchTable = defined(collection._batchTable);\r\n\r\n if (usesBatchTable) {\r\n var batchIdBufferData = new Uint16Array(instancesLength);\r\n for (i = 0; i < instancesLength; ++i) {\r\n batchIdBufferData[i] = instances[i]._instanceId;\r\n }\r\n collection._batchIdBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: batchIdBufferData,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n }\r\n\r\n if (!usesBatchTable) {\r\n var pickIdBuffer = new Uint8Array(instancesLength * 4);\r\n for (i = 0; i < instancesLength; ++i) {\r\n var pickId = collection._pickIds[i];\r\n var pickColor = pickId.color;\r\n var offset = i * 4;\r\n pickIdBuffer[offset] = Color.floatToByte(pickColor.red);\r\n pickIdBuffer[offset + 1] = Color.floatToByte(pickColor.green);\r\n pickIdBuffer[offset + 2] = Color.floatToByte(pickColor.blue);\r\n pickIdBuffer[offset + 3] = Color.floatToByte(pickColor.alpha);\r\n }\r\n collection._pickIdBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: pickIdBuffer,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n }\r\n\r\n var vertexBufferTypedArray = getVertexBufferTypedArray(collection);\r\n collection._vertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: vertexBufferTypedArray,\r\n usage: dynamic ? BufferUsage.STREAM_DRAW : BufferUsage.STATIC_DRAW,\r\n });\r\n}\r\n\r\nfunction updateVertexBuffer(collection) {\r\n var vertexBufferTypedArray = getVertexBufferTypedArray(collection);\r\n collection._vertexBuffer.copyFromArrayView(vertexBufferTypedArray);\r\n}\r\n\r\nfunction createPickIds(collection, context) {\r\n // PERFORMANCE_IDEA: we could skip the pick buffer completely by allocating\r\n // a continuous range of pickIds and then converting the base pickId + batchId\r\n // to RGBA in the shader. The only consider is precision issues, which might\r\n // not be an issue in WebGL 2.\r\n var instances = collection._instances;\r\n var instancesLength = instances.length;\r\n var pickIds = new Array(instancesLength);\r\n for (var i = 0; i < instancesLength; ++i) {\r\n pickIds[i] = context.createPickId(instances[i]);\r\n }\r\n return pickIds;\r\n}\r\n\r\nfunction createModel(collection, context) {\r\n var instancingSupported = collection._instancingSupported;\r\n var usesBatchTable = defined(collection._batchTable);\r\n var allowPicking = collection._allowPicking;\r\n\r\n var modelOptions = {\r\n url: collection._url,\r\n requestType: collection._requestType,\r\n gltf: collection._gltf,\r\n basePath: collection._basePath,\r\n shadows: collection._shadows,\r\n cacheKey: undefined,\r\n asynchronous: collection._asynchronous,\r\n allowPicking: allowPicking,\r\n incrementallyLoadTextures: collection._incrementallyLoadTextures,\r\n upAxis: collection._upAxis,\r\n forwardAxis: collection._forwardAxis,\r\n precreatedAttributes: undefined,\r\n vertexShaderLoaded: undefined,\r\n fragmentShaderLoaded: undefined,\r\n uniformMapLoaded: undefined,\r\n pickIdLoaded: collection._pickIdLoaded,\r\n ignoreCommands: true,\r\n opaquePass: collection._opaquePass,\r\n imageBasedLightingFactor: collection.imageBasedLightingFactor,\r\n lightColor: collection.lightColor,\r\n luminanceAtZenith: collection.luminanceAtZenith,\r\n sphericalHarmonicCoefficients: collection.sphericalHarmonicCoefficients,\r\n specularEnvironmentMaps: collection.specularEnvironmentMaps,\r\n };\r\n\r\n if (!usesBatchTable) {\r\n collection._pickIds = createPickIds(collection, context);\r\n }\r\n\r\n if (instancingSupported) {\r\n createVertexBuffer(collection, context);\r\n\r\n var vertexSizeInFloats = 12;\r\n var componentSizeInBytes = ComponentDatatype.getSizeInBytes(\r\n ComponentDatatype.FLOAT\r\n );\r\n\r\n var instancedAttributes = {\r\n czm_modelMatrixRow0: {\r\n index: 0, // updated in Model\r\n vertexBuffer: collection._vertexBuffer,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n normalize: false,\r\n offsetInBytes: 0,\r\n strideInBytes: componentSizeInBytes * vertexSizeInFloats,\r\n instanceDivisor: 1,\r\n },\r\n czm_modelMatrixRow1: {\r\n index: 0, // updated in Model\r\n vertexBuffer: collection._vertexBuffer,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n normalize: false,\r\n offsetInBytes: componentSizeInBytes * 4,\r\n strideInBytes: componentSizeInBytes * vertexSizeInFloats,\r\n instanceDivisor: 1,\r\n },\r\n czm_modelMatrixRow2: {\r\n index: 0, // updated in Model\r\n vertexBuffer: collection._vertexBuffer,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n normalize: false,\r\n offsetInBytes: componentSizeInBytes * 8,\r\n strideInBytes: componentSizeInBytes * vertexSizeInFloats,\r\n instanceDivisor: 1,\r\n },\r\n };\r\n\r\n // When using a batch table, add a batch id attribute\r\n if (usesBatchTable) {\r\n instancedAttributes.a_batchId = {\r\n index: 0, // updated in Model\r\n vertexBuffer: collection._batchIdBuffer,\r\n componentsPerAttribute: 1,\r\n componentDatatype: ComponentDatatype.UNSIGNED_SHORT,\r\n normalize: false,\r\n offsetInBytes: 0,\r\n strideInBytes: 0,\r\n instanceDivisor: 1,\r\n };\r\n }\r\n\r\n if (!usesBatchTable) {\r\n instancedAttributes.pickColor = {\r\n index: 0, // updated in Model\r\n vertexBuffer: collection._pickIdBuffer,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n normalize: true,\r\n offsetInBytes: 0,\r\n strideInBytes: 0,\r\n instanceDivisor: 1,\r\n };\r\n }\r\n\r\n modelOptions.precreatedAttributes = instancedAttributes;\r\n modelOptions.vertexShaderLoaded = getVertexShaderCallback(collection);\r\n modelOptions.fragmentShaderLoaded = getFragmentShaderCallback(collection);\r\n modelOptions.uniformMapLoaded = getUniformMapCallback(collection, context);\r\n\r\n if (defined(collection._url)) {\r\n modelOptions.cacheKey = collection._url.getUrlComponent() + \"#instanced\";\r\n }\r\n } else {\r\n modelOptions.vertexShaderLoaded = getVertexShaderNonInstancedCallback(\r\n collection\r\n );\r\n modelOptions.fragmentShaderLoaded = getFragmentShaderNonInstancedCallback(\r\n collection\r\n );\r\n modelOptions.uniformMapLoaded = getUniformMapNonInstancedCallback(\r\n collection,\r\n context\r\n );\r\n }\r\n\r\n if (defined(collection._url)) {\r\n collection._model = Model.fromGltf(modelOptions);\r\n } else {\r\n collection._model = new Model(modelOptions);\r\n }\r\n}\r\n\r\nfunction updateWireframe(collection, force) {\r\n if (collection._debugWireframe !== collection.debugWireframe || force) {\r\n collection._debugWireframe = collection.debugWireframe;\r\n\r\n // This assumes the original primitive was TRIANGLES and that the triangles\r\n // are connected for the wireframe to look perfect.\r\n var primitiveType = collection.debugWireframe\r\n ? PrimitiveType.LINES\r\n : PrimitiveType.TRIANGLES;\r\n var commands = collection._drawCommands;\r\n var length = commands.length;\r\n for (var i = 0; i < length; ++i) {\r\n commands[i].primitiveType = primitiveType;\r\n }\r\n }\r\n}\r\n\r\nfunction getDisableCullingRenderState(renderState) {\r\n var rs = clone(renderState, true);\r\n rs.cull.enabled = false;\r\n return RenderState.fromCache(rs);\r\n}\r\n\r\nfunction updateBackFaceCulling(collection, force) {\r\n if (collection._backFaceCulling !== collection.backFaceCulling || force) {\r\n collection._backFaceCulling = collection.backFaceCulling;\r\n\r\n var commands = collection._drawCommands;\r\n var length = commands.length;\r\n var i;\r\n\r\n if (!defined(collection._disableCullingRenderStates)) {\r\n collection._disableCullingRenderStates = new Array(length);\r\n collection._renderStates = new Array(length);\r\n for (i = 0; i < length; ++i) {\r\n var renderState = commands[i].renderState;\r\n var derivedRenderState = getDisableCullingRenderState(renderState);\r\n collection._disableCullingRenderStates[i] = derivedRenderState;\r\n collection._renderStates[i] = renderState;\r\n }\r\n }\r\n\r\n for (i = 0; i < length; ++i) {\r\n commands[i].renderState = collection._backFaceCulling\r\n ? collection._renderStates[i]\r\n : collection._disableCullingRenderStates[i];\r\n }\r\n }\r\n}\r\n\r\nfunction updateShowBoundingVolume(collection, force) {\r\n if (\r\n collection.debugShowBoundingVolume !==\r\n collection._debugShowBoundingVolume ||\r\n force\r\n ) {\r\n collection._debugShowBoundingVolume = collection.debugShowBoundingVolume;\r\n\r\n var commands = collection._drawCommands;\r\n var length = commands.length;\r\n for (var i = 0; i < length; ++i) {\r\n commands[i].debugShowBoundingVolume = collection.debugShowBoundingVolume;\r\n }\r\n }\r\n}\r\n\r\nfunction createCommands(collection, drawCommands) {\r\n var commandsLength = drawCommands.length;\r\n var instancesLength = collection.length;\r\n var boundingSphere = collection._boundingSphere;\r\n var cull = collection._cull;\r\n\r\n for (var i = 0; i < commandsLength; ++i) {\r\n var drawCommand = DrawCommand.shallowClone(drawCommands[i]);\r\n drawCommand.instanceCount = instancesLength;\r\n drawCommand.boundingVolume = boundingSphere;\r\n drawCommand.cull = cull;\r\n if (defined(collection._batchTable)) {\r\n drawCommand.pickId = collection._batchTable.getPickId();\r\n } else {\r\n drawCommand.pickId = \"v_pickColor\";\r\n }\r\n collection._drawCommands.push(drawCommand);\r\n }\r\n}\r\n\r\nfunction createBatchIdFunction(batchId) {\r\n return function () {\r\n return batchId;\r\n };\r\n}\r\n\r\nfunction createPickColorFunction(color) {\r\n return function () {\r\n return color;\r\n };\r\n}\r\n\r\nfunction createCommandsNonInstanced(collection, drawCommands) {\r\n // When instancing is disabled, create commands for every instance.\r\n var instances = collection._instances;\r\n var commandsLength = drawCommands.length;\r\n var instancesLength = collection.length;\r\n var batchTable = collection._batchTable;\r\n var usesBatchTable = defined(batchTable);\r\n var cull = collection._cull;\r\n\r\n for (var i = 0; i < commandsLength; ++i) {\r\n for (var j = 0; j < instancesLength; ++j) {\r\n var drawCommand = DrawCommand.shallowClone(drawCommands[i]);\r\n drawCommand.modelMatrix = new Matrix4(); // Updated in updateCommandsNonInstanced\r\n drawCommand.boundingVolume = new BoundingSphere(); // Updated in updateCommandsNonInstanced\r\n drawCommand.cull = cull;\r\n drawCommand.uniformMap = clone(drawCommand.uniformMap);\r\n if (usesBatchTable) {\r\n drawCommand.uniformMap.a_batchId = createBatchIdFunction(\r\n instances[j]._instanceId\r\n );\r\n } else {\r\n var pickId = collection._pickIds[j];\r\n drawCommand.uniformMap.czm_pickColor = createPickColorFunction(\r\n pickId.color\r\n );\r\n }\r\n collection._drawCommands.push(drawCommand);\r\n }\r\n }\r\n}\r\n\r\nfunction updateCommandsNonInstanced(collection) {\r\n var modelCommands = collection._modelCommands;\r\n var commandsLength = modelCommands.length;\r\n var instancesLength = collection.length;\r\n var collectionTransform = collection._rtcTransform;\r\n var collectionCenter = collection._center;\r\n\r\n for (var i = 0; i < commandsLength; ++i) {\r\n var modelCommand = modelCommands[i];\r\n for (var j = 0; j < instancesLength; ++j) {\r\n var commandIndex = i * instancesLength + j;\r\n var drawCommand = collection._drawCommands[commandIndex];\r\n var instanceMatrix = Matrix4.clone(\r\n collection._instances[j]._modelMatrix,\r\n scratchMatrix\r\n );\r\n instanceMatrix[12] -= collectionCenter.x;\r\n instanceMatrix[13] -= collectionCenter.y;\r\n instanceMatrix[14] -= collectionCenter.z;\r\n instanceMatrix = Matrix4.multiply(\r\n collectionTransform,\r\n instanceMatrix,\r\n scratchMatrix\r\n );\r\n var nodeMatrix = modelCommand.modelMatrix;\r\n var modelMatrix = drawCommand.modelMatrix;\r\n Matrix4.multiply(instanceMatrix, nodeMatrix, modelMatrix);\r\n\r\n var nodeBoundingSphere = modelCommand.boundingVolume;\r\n var boundingSphere = drawCommand.boundingVolume;\r\n BoundingSphere.transform(\r\n nodeBoundingSphere,\r\n instanceMatrix,\r\n boundingSphere\r\n );\r\n }\r\n }\r\n}\r\n\r\nfunction getModelCommands(model) {\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n\r\n var drawCommands = [];\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var nc = nodeCommands[i];\r\n if (nc.show) {\r\n drawCommands.push(nc.command);\r\n }\r\n }\r\n\r\n return drawCommands;\r\n}\r\n\r\nfunction commandsDirty(model) {\r\n var nodeCommands = model._nodeCommands;\r\n var length = nodeCommands.length;\r\n\r\n var commandsDirty = false;\r\n\r\n for (var i = 0; i < length; i++) {\r\n var nc = nodeCommands[i];\r\n if (nc.command.dirty) {\r\n nc.command.dirty = false;\r\n commandsDirty = true;\r\n }\r\n }\r\n return commandsDirty;\r\n}\r\n\r\nfunction generateModelCommands(modelInstanceCollection, instancingSupported) {\r\n modelInstanceCollection._drawCommands = [];\r\n\r\n var modelCommands = getModelCommands(modelInstanceCollection._model);\r\n if (instancingSupported) {\r\n createCommands(modelInstanceCollection, modelCommands);\r\n } else {\r\n createCommandsNonInstanced(modelInstanceCollection, modelCommands);\r\n updateCommandsNonInstanced(modelInstanceCollection);\r\n }\r\n}\r\n\r\nfunction updateShadows(collection, force) {\r\n if (collection.shadows !== collection._shadows || force) {\r\n collection._shadows = collection.shadows;\r\n\r\n var castShadows = ShadowMode.castShadows(collection.shadows);\r\n var receiveShadows = ShadowMode.receiveShadows(collection.shadows);\r\n\r\n var drawCommands = collection._drawCommands;\r\n var length = drawCommands.length;\r\n for (var i = 0; i < length; ++i) {\r\n var drawCommand = drawCommands[i];\r\n drawCommand.castShadows = castShadows;\r\n drawCommand.receiveShadows = receiveShadows;\r\n }\r\n }\r\n}\r\n\r\nModelInstanceCollection.prototype.update = function (frameState) {\r\n if (frameState.mode === SceneMode.MORPHING) {\r\n return;\r\n }\r\n\r\n if (!this.show) {\r\n return;\r\n }\r\n\r\n if (this.length === 0) {\r\n return;\r\n }\r\n\r\n var context = frameState.context;\r\n\r\n if (this._state === LoadState.NEEDS_LOAD) {\r\n this._state = LoadState.LOADING;\r\n this._instancingSupported = context.instancedArrays;\r\n createModel(this, context);\r\n var that = this;\r\n this._model.readyPromise.otherwise(function (error) {\r\n that._state = LoadState.FAILED;\r\n that._readyPromise.reject(error);\r\n });\r\n }\r\n\r\n var instancingSupported = this._instancingSupported;\r\n var model = this._model;\r\n\r\n model.imageBasedLightingFactor = this.imageBasedLightingFactor;\r\n model.lightColor = this.lightColor;\r\n model.luminanceAtZenith = this.luminanceAtZenith;\r\n model.sphericalHarmonicCoefficients = this.sphericalHarmonicCoefficients;\r\n model.specularEnvironmentMaps = this.specularEnvironmentMaps;\r\n\r\n model.update(frameState);\r\n\r\n if (model.ready && this._state === LoadState.LOADING) {\r\n this._state = LoadState.LOADED;\r\n this._ready = true;\r\n\r\n // Expand bounding volume to fit the radius of the loaded model including the model's offset from the center\r\n var modelRadius =\r\n model.boundingSphere.radius +\r\n Cartesian3.magnitude(model.boundingSphere.center);\r\n this._boundingSphere.radius += modelRadius;\r\n this._modelCommands = getModelCommands(model);\r\n\r\n generateModelCommands(this, instancingSupported);\r\n\r\n this._readyPromise.resolve(this);\r\n return;\r\n }\r\n\r\n if (this._state !== LoadState.LOADED) {\r\n return;\r\n }\r\n\r\n var modeChanged = frameState.mode !== this._mode;\r\n var modelMatrix = this.modelMatrix;\r\n var modelMatrixChanged = !Matrix4.equals(this._modelMatrix, modelMatrix);\r\n\r\n if (modeChanged || modelMatrixChanged) {\r\n this._mode = frameState.mode;\r\n Matrix4.clone(modelMatrix, this._modelMatrix);\r\n var rtcTransform = Matrix4.multiplyByTranslation(\r\n this._modelMatrix,\r\n this._center,\r\n this._rtcTransform\r\n );\r\n if (this._mode !== SceneMode.SCENE3D) {\r\n rtcTransform = Transforms.basisTo2D(\r\n frameState.mapProjection,\r\n rtcTransform,\r\n rtcTransform\r\n );\r\n }\r\n Matrix4.getTranslation(rtcTransform, this._boundingSphere.center);\r\n }\r\n\r\n if (instancingSupported && this._dirty) {\r\n // If at least one instance has moved assume the collection is now dynamic\r\n this._dynamic = true;\r\n this._dirty = false;\r\n\r\n // PERFORMANCE_IDEA: only update dirty sub-sections instead of the whole collection\r\n updateVertexBuffer(this);\r\n }\r\n\r\n // If the model was set to rebuild shaders during update, rebuild instanced commands.\r\n var modelCommandsDirty = commandsDirty(model);\r\n if (modelCommandsDirty) {\r\n generateModelCommands(this, instancingSupported);\r\n }\r\n\r\n // If any node changes due to an animation, update the commands. This could be inefficient if the model is\r\n // composed of many nodes and only one changes, however it is probably fine in the general use case.\r\n // Only applies when instancing is disabled. The instanced shader automatically handles node transformations.\r\n if (\r\n !instancingSupported &&\r\n (model.dirty || this._dirty || modeChanged || modelMatrixChanged)\r\n ) {\r\n updateCommandsNonInstanced(this);\r\n }\r\n\r\n updateShadows(this, modelCommandsDirty);\r\n updateWireframe(this, modelCommandsDirty);\r\n updateBackFaceCulling(this, modelCommandsDirty);\r\n updateShowBoundingVolume(this, modelCommandsDirty);\r\n\r\n var passes = frameState.passes;\r\n if (!passes.render && !passes.pick) {\r\n return;\r\n }\r\n\r\n var commandList = frameState.commandList;\r\n var commands = this._drawCommands;\r\n var commandsLength = commands.length;\r\n\r\n for (var i = 0; i < commandsLength; ++i) {\r\n commandList.push(commands[i]);\r\n }\r\n};\r\n\r\nModelInstanceCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nModelInstanceCollection.prototype.destroy = function () {\r\n this._model = this._model && this._model.destroy();\r\n\r\n var pickIds = this._pickIds;\r\n if (defined(pickIds)) {\r\n var length = pickIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n pickIds[i].destroy();\r\n }\r\n }\r\n\r\n return destroyObject(this);\r\n};\r\nexport default ModelInstanceCollection;\r\n","import AttributeCompression from \"../Core/AttributeCompression.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport deprecationWarning from \"../Core/deprecationWarning.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport getJsonFromTypedArray from \"../Core/getJsonFromTypedArray.js\";\r\nimport getStringFromTypedArray from \"../Core/getStringFromTypedArray.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Quaternion from \"../Core/Quaternion.js\";\r\nimport RequestType from \"../Core/RequestType.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport TranslationRotationScale from \"../Core/TranslationRotationScale.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport Axis from \"./Axis.js\";\r\nimport Cesium3DTileBatchTable from \"./Cesium3DTileBatchTable.js\";\r\nimport Cesium3DTileFeature from \"./Cesium3DTileFeature.js\";\r\nimport Cesium3DTileFeatureTable from \"./Cesium3DTileFeatureTable.js\";\r\nimport ModelInstanceCollection from \"./ModelInstanceCollection.js\";\r\nimport ModelAnimationLoop from \"./ModelAnimationLoop.js\";\r\n\r\n/**\r\n * Represents the contents of a\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/Instanced3DModel|Instanced 3D Model}\r\n * tile in a {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles} tileset.\r\n *

\r\n * Implements the {@link Cesium3DTileContent} interface.\r\n *

\r\n *\r\n * @alias Instanced3DModel3DTileContent\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction Instanced3DModel3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n) {\r\n this._tileset = tileset;\r\n this._tile = tile;\r\n this._resource = resource;\r\n this._modelInstanceCollection = undefined;\r\n this._batchTable = undefined;\r\n this._features = undefined;\r\n\r\n this.featurePropertiesDirty = false;\r\n\r\n initialize(this, arrayBuffer, byteOffset);\r\n}\r\n\r\n// This can be overridden for testing purposes\r\nInstanced3DModel3DTileContent._deprecationWarning = deprecationWarning;\r\n\r\nObject.defineProperties(Instanced3DModel3DTileContent.prototype, {\r\n featuresLength: {\r\n get: function () {\r\n return this._batchTable.featuresLength;\r\n },\r\n },\r\n\r\n pointsLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n trianglesLength: {\r\n get: function () {\r\n var model = this._modelInstanceCollection._model;\r\n if (defined(model)) {\r\n return model.trianglesLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n geometryByteLength: {\r\n get: function () {\r\n var model = this._modelInstanceCollection._model;\r\n if (defined(model)) {\r\n return model.geometryByteLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n texturesByteLength: {\r\n get: function () {\r\n var model = this._modelInstanceCollection._model;\r\n if (defined(model)) {\r\n return model.texturesByteLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n batchTableByteLength: {\r\n get: function () {\r\n return this._batchTable.memorySizeInBytes;\r\n },\r\n },\r\n\r\n innerContents: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return this._modelInstanceCollection.readyPromise;\r\n },\r\n },\r\n\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n tile: {\r\n get: function () {\r\n return this._tile;\r\n },\r\n },\r\n\r\n url: {\r\n get: function () {\r\n return this._resource.getUrlComponent(true);\r\n },\r\n },\r\n\r\n batchTable: {\r\n get: function () {\r\n return this._batchTable;\r\n },\r\n },\r\n});\r\n\r\nfunction getPickIdCallback(content) {\r\n return function () {\r\n return content._batchTable.getPickId();\r\n };\r\n}\r\n\r\nvar sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;\r\nvar propertyScratch1 = new Array(4);\r\nvar propertyScratch2 = new Array(4);\r\n\r\nfunction initialize(content, arrayBuffer, byteOffset) {\r\n var byteStart = defaultValue(byteOffset, 0);\r\n byteOffset = byteStart;\r\n\r\n var uint8Array = new Uint8Array(arrayBuffer);\r\n var view = new DataView(arrayBuffer);\r\n byteOffset += sizeOfUint32; // Skip magic\r\n\r\n var version = view.getUint32(byteOffset, true);\r\n if (version !== 1) {\r\n throw new RuntimeError(\r\n \"Only Instanced 3D Model version 1 is supported. Version \" +\r\n version +\r\n \" is not.\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n var byteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableJsonByteLength = view.getUint32(byteOffset, true);\r\n if (featureTableJsonByteLength === 0) {\r\n throw new RuntimeError(\r\n \"featureTableJsonByteLength is zero, the feature table must be defined.\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var batchTableJsonByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var batchTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var gltfFormat = view.getUint32(byteOffset, true);\r\n if (gltfFormat !== 1 && gltfFormat !== 0) {\r\n throw new RuntimeError(\r\n \"Only glTF format 0 (uri) or 1 (embedded) are supported. Format \" +\r\n gltfFormat +\r\n \" is not.\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n featureTableJsonByteLength\r\n );\r\n byteOffset += featureTableJsonByteLength;\r\n\r\n var featureTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n featureTableBinaryByteLength\r\n );\r\n byteOffset += featureTableBinaryByteLength;\r\n\r\n var featureTable = new Cesium3DTileFeatureTable(\r\n featureTableJson,\r\n featureTableBinary\r\n );\r\n var instancesLength = featureTable.getGlobalProperty(\"INSTANCES_LENGTH\");\r\n featureTable.featuresLength = instancesLength;\r\n\r\n if (!defined(instancesLength)) {\r\n throw new RuntimeError(\r\n \"Feature table global property: INSTANCES_LENGTH must be defined\"\r\n );\r\n }\r\n\r\n var batchTableJson;\r\n var batchTableBinary;\r\n if (batchTableJsonByteLength > 0) {\r\n batchTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n batchTableJsonByteLength\r\n );\r\n byteOffset += batchTableJsonByteLength;\r\n\r\n if (batchTableBinaryByteLength > 0) {\r\n // Has a batch table binary\r\n batchTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n batchTableBinaryByteLength\r\n );\r\n // Copy the batchTableBinary section and let the underlying ArrayBuffer be freed\r\n batchTableBinary = new Uint8Array(batchTableBinary);\r\n byteOffset += batchTableBinaryByteLength;\r\n }\r\n }\r\n\r\n content._batchTable = new Cesium3DTileBatchTable(\r\n content,\r\n instancesLength,\r\n batchTableJson,\r\n batchTableBinary\r\n );\r\n\r\n var gltfByteLength = byteStart + byteLength - byteOffset;\r\n if (gltfByteLength === 0) {\r\n throw new RuntimeError(\r\n \"glTF byte length is zero, i3dm must have a glTF to instance.\"\r\n );\r\n }\r\n\r\n var gltfView;\r\n if (byteOffset % 4 === 0) {\r\n gltfView = new Uint8Array(arrayBuffer, byteOffset, gltfByteLength);\r\n } else {\r\n // Create a copy of the glb so that it is 4-byte aligned\r\n Instanced3DModel3DTileContent._deprecationWarning(\r\n \"i3dm-glb-unaligned\",\r\n \"The embedded glb is not aligned to a 4-byte boundary.\"\r\n );\r\n gltfView = new Uint8Array(\r\n uint8Array.subarray(byteOffset, byteOffset + gltfByteLength)\r\n );\r\n }\r\n\r\n var tileset = content._tileset;\r\n\r\n // Create model instance collection\r\n var collectionOptions = {\r\n instances: new Array(instancesLength),\r\n batchTable: content._batchTable,\r\n cull: false, // Already culled by 3D Tiles\r\n url: undefined,\r\n requestType: RequestType.TILES3D,\r\n gltf: undefined,\r\n basePath: undefined,\r\n incrementallyLoadTextures: false,\r\n upAxis: tileset._gltfUpAxis,\r\n forwardAxis: Axis.X,\r\n opaquePass: Pass.CESIUM_3D_TILE, // Draw opaque portions during the 3D Tiles pass\r\n pickIdLoaded: getPickIdCallback(content),\r\n imageBasedLightingFactor: tileset.imageBasedLightingFactor,\r\n lightColor: tileset.lightColor,\r\n luminanceAtZenith: tileset.luminanceAtZenith,\r\n sphericalHarmonicCoefficients: tileset.sphericalHarmonicCoefficients,\r\n specularEnvironmentMaps: tileset.specularEnvironmentMaps,\r\n backFaceCulling: tileset.backFaceCulling,\r\n };\r\n\r\n if (gltfFormat === 0) {\r\n var gltfUrl = getStringFromTypedArray(gltfView);\r\n\r\n // We need to remove padding from the end of the model URL in case this tile was part of a composite tile.\r\n // This removes all white space and null characters from the end of the string.\r\n gltfUrl = gltfUrl.replace(/[\\s\\0]+$/, \"\");\r\n collectionOptions.url = content._resource.getDerivedResource({\r\n url: gltfUrl,\r\n });\r\n } else {\r\n collectionOptions.gltf = gltfView;\r\n collectionOptions.basePath = content._resource.clone();\r\n }\r\n\r\n var eastNorthUp = featureTable.getGlobalProperty(\"EAST_NORTH_UP\");\r\n\r\n var rtcCenter;\r\n var rtcCenterArray = featureTable.getGlobalProperty(\r\n \"RTC_CENTER\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n if (defined(rtcCenterArray)) {\r\n rtcCenter = Cartesian3.unpack(rtcCenterArray);\r\n }\r\n\r\n var instances = collectionOptions.instances;\r\n var instancePosition = new Cartesian3();\r\n var instancePositionArray = new Array(3);\r\n var instanceNormalRight = new Cartesian3();\r\n var instanceNormalUp = new Cartesian3();\r\n var instanceNormalForward = new Cartesian3();\r\n var instanceRotation = new Matrix3();\r\n var instanceQuaternion = new Quaternion();\r\n var instanceScale = new Cartesian3();\r\n var instanceTranslationRotationScale = new TranslationRotationScale();\r\n var instanceTransform = new Matrix4();\r\n for (var i = 0; i < instancesLength; i++) {\r\n // Get the instance position\r\n var position = featureTable.getProperty(\r\n \"POSITION\",\r\n ComponentDatatype.FLOAT,\r\n 3,\r\n i,\r\n propertyScratch1\r\n );\r\n if (!defined(position)) {\r\n position = instancePositionArray;\r\n var positionQuantized = featureTable.getProperty(\r\n \"POSITION_QUANTIZED\",\r\n ComponentDatatype.UNSIGNED_SHORT,\r\n 3,\r\n i,\r\n propertyScratch1\r\n );\r\n if (!defined(positionQuantized)) {\r\n throw new RuntimeError(\r\n \"Either POSITION or POSITION_QUANTIZED must be defined for each instance.\"\r\n );\r\n }\r\n var quantizedVolumeOffset = featureTable.getGlobalProperty(\r\n \"QUANTIZED_VOLUME_OFFSET\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n if (!defined(quantizedVolumeOffset)) {\r\n throw new RuntimeError(\r\n \"Global property: QUANTIZED_VOLUME_OFFSET must be defined for quantized positions.\"\r\n );\r\n }\r\n var quantizedVolumeScale = featureTable.getGlobalProperty(\r\n \"QUANTIZED_VOLUME_SCALE\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n if (!defined(quantizedVolumeScale)) {\r\n throw new RuntimeError(\r\n \"Global property: QUANTIZED_VOLUME_SCALE must be defined for quantized positions.\"\r\n );\r\n }\r\n for (var j = 0; j < 3; j++) {\r\n position[j] =\r\n (positionQuantized[j] / 65535.0) * quantizedVolumeScale[j] +\r\n quantizedVolumeOffset[j];\r\n }\r\n }\r\n Cartesian3.unpack(position, 0, instancePosition);\r\n if (defined(rtcCenter)) {\r\n Cartesian3.add(instancePosition, rtcCenter, instancePosition);\r\n }\r\n instanceTranslationRotationScale.translation = instancePosition;\r\n\r\n // Get the instance rotation\r\n var normalUp = featureTable.getProperty(\r\n \"NORMAL_UP\",\r\n ComponentDatatype.FLOAT,\r\n 3,\r\n i,\r\n propertyScratch1\r\n );\r\n var normalRight = featureTable.getProperty(\r\n \"NORMAL_RIGHT\",\r\n ComponentDatatype.FLOAT,\r\n 3,\r\n i,\r\n propertyScratch2\r\n );\r\n var hasCustomOrientation = false;\r\n if (defined(normalUp)) {\r\n if (!defined(normalRight)) {\r\n throw new RuntimeError(\r\n \"To define a custom orientation, both NORMAL_UP and NORMAL_RIGHT must be defined.\"\r\n );\r\n }\r\n Cartesian3.unpack(normalUp, 0, instanceNormalUp);\r\n Cartesian3.unpack(normalRight, 0, instanceNormalRight);\r\n hasCustomOrientation = true;\r\n } else {\r\n var octNormalUp = featureTable.getProperty(\r\n \"NORMAL_UP_OCT32P\",\r\n ComponentDatatype.UNSIGNED_SHORT,\r\n 2,\r\n i,\r\n propertyScratch1\r\n );\r\n var octNormalRight = featureTable.getProperty(\r\n \"NORMAL_RIGHT_OCT32P\",\r\n ComponentDatatype.UNSIGNED_SHORT,\r\n 2,\r\n i,\r\n propertyScratch2\r\n );\r\n if (defined(octNormalUp)) {\r\n if (!defined(octNormalRight)) {\r\n throw new RuntimeError(\r\n \"To define a custom orientation with oct-encoded vectors, both NORMAL_UP_OCT32P and NORMAL_RIGHT_OCT32P must be defined.\"\r\n );\r\n }\r\n AttributeCompression.octDecodeInRange(\r\n octNormalUp[0],\r\n octNormalUp[1],\r\n 65535,\r\n instanceNormalUp\r\n );\r\n AttributeCompression.octDecodeInRange(\r\n octNormalRight[0],\r\n octNormalRight[1],\r\n 65535,\r\n instanceNormalRight\r\n );\r\n hasCustomOrientation = true;\r\n } else if (eastNorthUp) {\r\n Transforms.eastNorthUpToFixedFrame(\r\n instancePosition,\r\n Ellipsoid.WGS84,\r\n instanceTransform\r\n );\r\n Matrix4.getMatrix3(instanceTransform, instanceRotation);\r\n } else {\r\n Matrix3.clone(Matrix3.IDENTITY, instanceRotation);\r\n }\r\n }\r\n if (hasCustomOrientation) {\r\n Cartesian3.cross(\r\n instanceNormalRight,\r\n instanceNormalUp,\r\n instanceNormalForward\r\n );\r\n Cartesian3.normalize(instanceNormalForward, instanceNormalForward);\r\n Matrix3.setColumn(\r\n instanceRotation,\r\n 0,\r\n instanceNormalRight,\r\n instanceRotation\r\n );\r\n Matrix3.setColumn(\r\n instanceRotation,\r\n 1,\r\n instanceNormalUp,\r\n instanceRotation\r\n );\r\n Matrix3.setColumn(\r\n instanceRotation,\r\n 2,\r\n instanceNormalForward,\r\n instanceRotation\r\n );\r\n }\r\n Quaternion.fromRotationMatrix(instanceRotation, instanceQuaternion);\r\n instanceTranslationRotationScale.rotation = instanceQuaternion;\r\n\r\n // Get the instance scale\r\n instanceScale = Cartesian3.fromElements(1.0, 1.0, 1.0, instanceScale);\r\n var scale = featureTable.getProperty(\r\n \"SCALE\",\r\n ComponentDatatype.FLOAT,\r\n 1,\r\n i\r\n );\r\n if (defined(scale)) {\r\n Cartesian3.multiplyByScalar(instanceScale, scale, instanceScale);\r\n }\r\n var nonUniformScale = featureTable.getProperty(\r\n \"SCALE_NON_UNIFORM\",\r\n ComponentDatatype.FLOAT,\r\n 3,\r\n i,\r\n propertyScratch1\r\n );\r\n if (defined(nonUniformScale)) {\r\n instanceScale.x *= nonUniformScale[0];\r\n instanceScale.y *= nonUniformScale[1];\r\n instanceScale.z *= nonUniformScale[2];\r\n }\r\n instanceTranslationRotationScale.scale = instanceScale;\r\n\r\n // Get the batchId\r\n var batchId = featureTable.getProperty(\r\n \"BATCH_ID\",\r\n ComponentDatatype.UNSIGNED_SHORT,\r\n 1,\r\n i\r\n );\r\n if (!defined(batchId)) {\r\n // If BATCH_ID semantic is undefined, batchId is just the instance number\r\n batchId = i;\r\n }\r\n\r\n // Create the model matrix and the instance\r\n Matrix4.fromTranslationRotationScale(\r\n instanceTranslationRotationScale,\r\n instanceTransform\r\n );\r\n var modelMatrix = instanceTransform.clone();\r\n instances[i] = {\r\n modelMatrix: modelMatrix,\r\n batchId: batchId,\r\n };\r\n }\r\n\r\n content._modelInstanceCollection = new ModelInstanceCollection(\r\n collectionOptions\r\n );\r\n content._modelInstanceCollection.readyPromise.then(function (collection) {\r\n collection.activeAnimations.addAll({\r\n loop: ModelAnimationLoop.REPEAT,\r\n });\r\n });\r\n}\r\n\r\nfunction createFeatures(content) {\r\n var featuresLength = content.featuresLength;\r\n if (!defined(content._features) && featuresLength > 0) {\r\n var features = new Array(featuresLength);\r\n for (var i = 0; i < featuresLength; ++i) {\r\n features[i] = new Cesium3DTileFeature(content, i);\r\n }\r\n content._features = features;\r\n }\r\n}\r\n\r\nInstanced3DModel3DTileContent.prototype.hasProperty = function (batchId, name) {\r\n return this._batchTable.hasProperty(batchId, name);\r\n};\r\n\r\nInstanced3DModel3DTileContent.prototype.getFeature = function (batchId) {\r\n var featuresLength = this.featuresLength;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(batchId) || batchId < 0 || batchId >= featuresLength) {\r\n throw new DeveloperError(\r\n \"batchId is required and between zero and featuresLength - 1 (\" +\r\n (featuresLength - 1) +\r\n \").\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n createFeatures(this);\r\n return this._features[batchId];\r\n};\r\n\r\nInstanced3DModel3DTileContent.prototype.applyDebugSettings = function (\r\n enabled,\r\n color\r\n) {\r\n color = enabled ? color : Color.WHITE;\r\n this._batchTable.setAllColor(color);\r\n};\r\n\r\nInstanced3DModel3DTileContent.prototype.applyStyle = function (style) {\r\n this._batchTable.applyStyle(style);\r\n};\r\n\r\nInstanced3DModel3DTileContent.prototype.update = function (\r\n tileset,\r\n frameState\r\n) {\r\n var commandStart = frameState.commandList.length;\r\n\r\n // In the PROCESSING state we may be calling update() to move forward\r\n // the content's resource loading. In the READY state, it will\r\n // actually generate commands.\r\n this._batchTable.update(tileset, frameState);\r\n this._modelInstanceCollection.modelMatrix = this._tile.computedTransform;\r\n this._modelInstanceCollection.shadows = this._tileset.shadows;\r\n this._modelInstanceCollection.lightColor = this._tileset.lightColor;\r\n this._modelInstanceCollection.luminanceAtZenith = this._tileset.luminanceAtZenith;\r\n this._modelInstanceCollection.sphericalHarmonicCoefficients = this._tileset.sphericalHarmonicCoefficients;\r\n this._modelInstanceCollection.specularEnvironmentMaps = this._tileset.specularEnvironmentMaps;\r\n this._modelInstanceCollection.backFaceCulling = this._tileset.backFaceCulling;\r\n this._modelInstanceCollection.debugWireframe = this._tileset.debugWireframe;\r\n\r\n var model = this._modelInstanceCollection._model;\r\n\r\n if (defined(model)) {\r\n // Update for clipping planes\r\n var tilesetClippingPlanes = this._tileset.clippingPlanes;\r\n model.referenceMatrix = this._tileset.clippingPlanesOriginMatrix;\r\n if (defined(tilesetClippingPlanes) && this._tile.clippingPlanesDirty) {\r\n // Dereference the clipping planes from the model if they are irrelevant - saves on shading\r\n // Link/Dereference directly to avoid ownership checks.\r\n model._clippingPlanes =\r\n tilesetClippingPlanes.enabled && this._tile._isClipped\r\n ? tilesetClippingPlanes\r\n : undefined;\r\n }\r\n\r\n // If the model references a different ClippingPlaneCollection due to the tileset's collection being replaced with a\r\n // ClippingPlaneCollection that gives this tile the same clipping status, update the model to use the new ClippingPlaneCollection.\r\n if (\r\n defined(tilesetClippingPlanes) &&\r\n defined(model._clippingPlanes) &&\r\n model._clippingPlanes !== tilesetClippingPlanes\r\n ) {\r\n model._clippingPlanes = tilesetClippingPlanes;\r\n }\r\n }\r\n\r\n this._modelInstanceCollection.update(frameState);\r\n\r\n // If any commands were pushed, add derived commands\r\n var commandEnd = frameState.commandList.length;\r\n if (\r\n commandStart < commandEnd &&\r\n (frameState.passes.render || frameState.passes.pick)\r\n ) {\r\n this._batchTable.addDerivedCommands(frameState, commandStart, false);\r\n }\r\n};\r\n\r\nInstanced3DModel3DTileContent.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nInstanced3DModel3DTileContent.prototype.destroy = function () {\r\n this._modelInstanceCollection =\r\n this._modelInstanceCollection && this._modelInstanceCollection.destroy();\r\n this._batchTable = this._batchTable && this._batchTable.destroy();\r\n\r\n return destroyObject(this);\r\n};\r\nexport default Instanced3DModel3DTileContent;\r\n","/**\r\n * The refinement approach for a tile.\r\n *

\r\n * See the {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification#refinement|Refinement}\r\n * in the 3D Tiles spec.\r\n *

\r\n *\r\n * @enum {Number}\r\n *\r\n * @private\r\n */\r\nvar Cesium3DTileRefine = {\r\n /**\r\n * Render this tile and, if it doesn't meet the screen space error, also refine to its children.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n ADD: 0,\r\n\r\n /**\r\n * Render this tile or, if it doesn't meet the screen space error, refine to its descendants instead.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n REPLACE: 1,\r\n};\r\nexport default Object.freeze(Cesium3DTileRefine);\r\n","import arraySlice from \"../Core/arraySlice.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport clone from \"../Core/clone.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport getJsonFromTypedArray from \"../Core/getJsonFromTypedArray.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport oneTimeWarning from \"../Core/oneTimeWarning.js\";\r\nimport OrthographicFrustum from \"../Core/OrthographicFrustum.js\";\r\nimport PrimitiveType from \"../Core/PrimitiveType.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport VertexArray from \"../Renderer/VertexArray.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport Cesium3DTileBatchTable from \"./Cesium3DTileBatchTable.js\";\r\nimport Cesium3DTileFeatureTable from \"./Cesium3DTileFeatureTable.js\";\r\nimport DracoLoader from \"./DracoLoader.js\";\r\nimport getClipAndStyleCode from \"./getClipAndStyleCode.js\";\r\nimport getClippingFunction from \"./getClippingFunction.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport ShadowMode from \"./ShadowMode.js\";\r\nimport StencilConstants from \"./StencilConstants.js\";\r\n\r\nvar DecodingState = {\r\n NEEDS_DECODE: 0,\r\n DECODING: 1,\r\n READY: 2,\r\n FAILED: 3,\r\n};\r\n\r\n/**\r\n * Represents the contents of a\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/PointCloud|Point Cloud}\r\n * tile. Used internally by {@link PointCloud3DTileContent} and {@link TimeDynamicPointCloud}.\r\n *\r\n * @alias PointCloud\r\n * @constructor\r\n *\r\n * @see PointCloud3DTileContent\r\n * @see TimeDynamicPointCloud\r\n *\r\n * @private\r\n */\r\nfunction PointCloud(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.object(\"options.arrayBuffer\", options.arrayBuffer);\r\n //>>includeEnd('debug');\r\n\r\n // Hold onto the payload until the render resources are created\r\n this._parsedContent = undefined;\r\n\r\n this._drawCommand = undefined;\r\n this._isTranslucent = false;\r\n this._styleTranslucent = false;\r\n this._constantColor = Color.clone(Color.DARKGRAY);\r\n this._highlightColor = Color.clone(Color.WHITE);\r\n this._pointSize = 1.0;\r\n\r\n this._rtcCenter = undefined;\r\n this._quantizedVolumeScale = undefined;\r\n this._quantizedVolumeOffset = undefined;\r\n\r\n // These values are used to regenerate the shader when the style changes\r\n this._styleableShaderAttributes = undefined;\r\n this._isQuantized = false;\r\n this._isOctEncoded16P = false;\r\n this._isRGB565 = false;\r\n this._hasColors = false;\r\n this._hasNormals = false;\r\n this._hasBatchIds = false;\r\n\r\n // Draco\r\n this._decodingState = DecodingState.READY;\r\n this._dequantizeInShader = true;\r\n this._isQuantizedDraco = false;\r\n this._isOctEncodedDraco = false;\r\n this._quantizedRange = 0.0;\r\n this._octEncodedRange = 0.0;\r\n\r\n // Use per-point normals to hide back-facing points.\r\n this.backFaceCulling = false;\r\n this._backFaceCulling = false;\r\n\r\n // Whether to enable normal shading\r\n this.normalShading = true;\r\n this._normalShading = true;\r\n\r\n this._opaqueRenderState = undefined;\r\n this._translucentRenderState = undefined;\r\n\r\n this._mode = undefined;\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n this._pointsLength = 0;\r\n this._geometryByteLength = 0;\r\n\r\n this._vertexShaderLoaded = options.vertexShaderLoaded;\r\n this._fragmentShaderLoaded = options.fragmentShaderLoaded;\r\n this._uniformMapLoaded = options.uniformMapLoaded;\r\n this._batchTableLoaded = options.batchTableLoaded;\r\n this._pickIdLoaded = options.pickIdLoaded;\r\n this._opaquePass = defaultValue(options.opaquePass, Pass.OPAQUE);\r\n this._cull = defaultValue(options.cull, true);\r\n\r\n this.style = undefined;\r\n this._style = undefined;\r\n this.styleDirty = false;\r\n\r\n this.modelMatrix = Matrix4.clone(Matrix4.IDENTITY);\r\n this._modelMatrix = Matrix4.clone(Matrix4.IDENTITY);\r\n\r\n this.time = 0.0; // For styling\r\n this.shadows = ShadowMode.ENABLED;\r\n this._boundingSphere = undefined;\r\n\r\n this.clippingPlanes = undefined;\r\n this.isClipped = false;\r\n this.clippingPlanesDirty = false;\r\n // If defined, use this matrix to position the clipping planes instead of the modelMatrix.\r\n // This is so that when point clouds are part of a tileset they all get clipped relative\r\n // to the root tile.\r\n this.clippingPlanesOriginMatrix = undefined;\r\n\r\n this.attenuation = false;\r\n this._attenuation = false;\r\n\r\n // Options for geometric error based attenuation\r\n this.geometricError = 0.0;\r\n this.geometricErrorScale = 1.0;\r\n this.maximumAttenuation = this._pointSize;\r\n\r\n initialize(this, options);\r\n}\r\n\r\nObject.defineProperties(PointCloud.prototype, {\r\n pointsLength: {\r\n get: function () {\r\n return this._pointsLength;\r\n },\r\n },\r\n\r\n geometryByteLength: {\r\n get: function () {\r\n return this._geometryByteLength;\r\n },\r\n },\r\n\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n color: {\r\n get: function () {\r\n return Color.clone(this._highlightColor);\r\n },\r\n set: function (value) {\r\n this._highlightColor = Color.clone(value, this._highlightColor);\r\n },\r\n },\r\n\r\n boundingSphere: {\r\n get: function () {\r\n if (defined(this._drawCommand)) {\r\n return this._drawCommand.boundingVolume;\r\n }\r\n return undefined;\r\n },\r\n set: function (value) {\r\n this._boundingSphere = BoundingSphere.clone(value, this._boundingSphere);\r\n },\r\n },\r\n});\r\n\r\nvar sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;\r\n\r\nfunction initialize(pointCloud, options) {\r\n var arrayBuffer = options.arrayBuffer;\r\n var byteOffset = defaultValue(options.byteOffset, 0);\r\n\r\n var uint8Array = new Uint8Array(arrayBuffer);\r\n var view = new DataView(arrayBuffer);\r\n byteOffset += sizeOfUint32; // Skip magic\r\n\r\n var version = view.getUint32(byteOffset, true);\r\n if (version !== 1) {\r\n throw new RuntimeError(\r\n \"Only Point Cloud tile version 1 is supported. Version \" +\r\n version +\r\n \" is not.\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n // Skip byteLength\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableJsonByteLength = view.getUint32(byteOffset, true);\r\n if (featureTableJsonByteLength === 0) {\r\n throw new RuntimeError(\r\n \"Feature table must have a byte length greater than zero\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var batchTableJsonByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var batchTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n featureTableJsonByteLength\r\n );\r\n byteOffset += featureTableJsonByteLength;\r\n\r\n var featureTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n featureTableBinaryByteLength\r\n );\r\n byteOffset += featureTableBinaryByteLength;\r\n\r\n // Get the batch table JSON and binary\r\n var batchTableJson;\r\n var batchTableBinary;\r\n if (batchTableJsonByteLength > 0) {\r\n // Has a batch table JSON\r\n batchTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n batchTableJsonByteLength\r\n );\r\n byteOffset += batchTableJsonByteLength;\r\n\r\n if (batchTableBinaryByteLength > 0) {\r\n // Has a batch table binary\r\n batchTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n batchTableBinaryByteLength\r\n );\r\n byteOffset += batchTableBinaryByteLength;\r\n }\r\n }\r\n\r\n var featureTable = new Cesium3DTileFeatureTable(\r\n featureTableJson,\r\n featureTableBinary\r\n );\r\n\r\n var pointsLength = featureTable.getGlobalProperty(\"POINTS_LENGTH\");\r\n featureTable.featuresLength = pointsLength;\r\n\r\n if (!defined(pointsLength)) {\r\n throw new RuntimeError(\r\n \"Feature table global property: POINTS_LENGTH must be defined\"\r\n );\r\n }\r\n\r\n var rtcCenter = featureTable.getGlobalProperty(\r\n \"RTC_CENTER\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n if (defined(rtcCenter)) {\r\n pointCloud._rtcCenter = Cartesian3.unpack(rtcCenter);\r\n }\r\n\r\n var positions;\r\n var colors;\r\n var normals;\r\n var batchIds;\r\n\r\n var hasPositions = false;\r\n var hasColors = false;\r\n var hasNormals = false;\r\n var hasBatchIds = false;\r\n\r\n var isQuantized = false;\r\n var isTranslucent = false;\r\n var isRGB565 = false;\r\n var isOctEncoded16P = false;\r\n\r\n var dracoBuffer;\r\n var dracoFeatureTableProperties;\r\n var dracoBatchTableProperties;\r\n\r\n var featureTableDraco = defined(featureTableJson.extensions)\r\n ? featureTableJson.extensions[\"3DTILES_draco_point_compression\"]\r\n : undefined;\r\n var batchTableDraco =\r\n defined(batchTableJson) && defined(batchTableJson.extensions)\r\n ? batchTableJson.extensions[\"3DTILES_draco_point_compression\"]\r\n : undefined;\r\n\r\n if (defined(batchTableDraco)) {\r\n dracoBatchTableProperties = batchTableDraco.properties;\r\n }\r\n\r\n if (defined(featureTableDraco)) {\r\n dracoFeatureTableProperties = featureTableDraco.properties;\r\n var dracoByteOffset = featureTableDraco.byteOffset;\r\n var dracoByteLength = featureTableDraco.byteLength;\r\n if (\r\n !defined(dracoFeatureTableProperties) ||\r\n !defined(dracoByteOffset) ||\r\n !defined(dracoByteLength)\r\n ) {\r\n throw new RuntimeError(\r\n \"Draco properties, byteOffset, and byteLength must be defined\"\r\n );\r\n }\r\n dracoBuffer = arraySlice(\r\n featureTableBinary,\r\n dracoByteOffset,\r\n dracoByteOffset + dracoByteLength\r\n );\r\n hasPositions = defined(dracoFeatureTableProperties.POSITION);\r\n hasColors =\r\n defined(dracoFeatureTableProperties.RGB) ||\r\n defined(dracoFeatureTableProperties.RGBA);\r\n hasNormals = defined(dracoFeatureTableProperties.NORMAL);\r\n hasBatchIds = defined(dracoFeatureTableProperties.BATCH_ID);\r\n isTranslucent = defined(dracoFeatureTableProperties.RGBA);\r\n pointCloud._decodingState = DecodingState.NEEDS_DECODE;\r\n }\r\n\r\n var draco;\r\n if (defined(dracoBuffer)) {\r\n draco = {\r\n buffer: dracoBuffer,\r\n featureTableProperties: dracoFeatureTableProperties,\r\n batchTableProperties: dracoBatchTableProperties,\r\n properties: combine(\r\n dracoFeatureTableProperties,\r\n dracoBatchTableProperties\r\n ),\r\n dequantizeInShader: pointCloud._dequantizeInShader,\r\n };\r\n }\r\n\r\n if (!hasPositions) {\r\n if (defined(featureTableJson.POSITION)) {\r\n positions = featureTable.getPropertyArray(\r\n \"POSITION\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n hasPositions = true;\r\n } else if (defined(featureTableJson.POSITION_QUANTIZED)) {\r\n positions = featureTable.getPropertyArray(\r\n \"POSITION_QUANTIZED\",\r\n ComponentDatatype.UNSIGNED_SHORT,\r\n 3\r\n );\r\n isQuantized = true;\r\n hasPositions = true;\r\n\r\n var quantizedVolumeScale = featureTable.getGlobalProperty(\r\n \"QUANTIZED_VOLUME_SCALE\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n if (!defined(quantizedVolumeScale)) {\r\n throw new RuntimeError(\r\n \"Global property: QUANTIZED_VOLUME_SCALE must be defined for quantized positions.\"\r\n );\r\n }\r\n pointCloud._quantizedVolumeScale = Cartesian3.unpack(\r\n quantizedVolumeScale\r\n );\r\n pointCloud._quantizedRange = (1 << 16) - 1;\r\n\r\n var quantizedVolumeOffset = featureTable.getGlobalProperty(\r\n \"QUANTIZED_VOLUME_OFFSET\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n if (!defined(quantizedVolumeOffset)) {\r\n throw new RuntimeError(\r\n \"Global property: QUANTIZED_VOLUME_OFFSET must be defined for quantized positions.\"\r\n );\r\n }\r\n pointCloud._quantizedVolumeOffset = Cartesian3.unpack(\r\n quantizedVolumeOffset\r\n );\r\n }\r\n }\r\n\r\n if (!hasColors) {\r\n if (defined(featureTableJson.RGBA)) {\r\n colors = featureTable.getPropertyArray(\r\n \"RGBA\",\r\n ComponentDatatype.UNSIGNED_BYTE,\r\n 4\r\n );\r\n isTranslucent = true;\r\n hasColors = true;\r\n } else if (defined(featureTableJson.RGB)) {\r\n colors = featureTable.getPropertyArray(\r\n \"RGB\",\r\n ComponentDatatype.UNSIGNED_BYTE,\r\n 3\r\n );\r\n hasColors = true;\r\n } else if (defined(featureTableJson.RGB565)) {\r\n colors = featureTable.getPropertyArray(\r\n \"RGB565\",\r\n ComponentDatatype.UNSIGNED_SHORT,\r\n 1\r\n );\r\n isRGB565 = true;\r\n hasColors = true;\r\n }\r\n }\r\n\r\n if (!hasNormals) {\r\n if (defined(featureTableJson.NORMAL)) {\r\n normals = featureTable.getPropertyArray(\r\n \"NORMAL\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n hasNormals = true;\r\n } else if (defined(featureTableJson.NORMAL_OCT16P)) {\r\n normals = featureTable.getPropertyArray(\r\n \"NORMAL_OCT16P\",\r\n ComponentDatatype.UNSIGNED_BYTE,\r\n 2\r\n );\r\n isOctEncoded16P = true;\r\n hasNormals = true;\r\n }\r\n }\r\n\r\n if (!hasBatchIds) {\r\n if (defined(featureTableJson.BATCH_ID)) {\r\n batchIds = featureTable.getPropertyArray(\r\n \"BATCH_ID\",\r\n ComponentDatatype.UNSIGNED_SHORT,\r\n 1\r\n );\r\n hasBatchIds = true;\r\n }\r\n }\r\n\r\n if (!hasPositions) {\r\n throw new RuntimeError(\r\n \"Either POSITION or POSITION_QUANTIZED must be defined.\"\r\n );\r\n }\r\n\r\n if (defined(featureTableJson.CONSTANT_RGBA)) {\r\n var constantRGBA = featureTable.getGlobalProperty(\r\n \"CONSTANT_RGBA\",\r\n ComponentDatatype.UNSIGNED_BYTE,\r\n 4\r\n );\r\n pointCloud._constantColor = Color.fromBytes(\r\n constantRGBA[0],\r\n constantRGBA[1],\r\n constantRGBA[2],\r\n constantRGBA[3],\r\n pointCloud._constantColor\r\n );\r\n }\r\n\r\n if (hasBatchIds) {\r\n var batchLength = featureTable.getGlobalProperty(\"BATCH_LENGTH\");\r\n if (!defined(batchLength)) {\r\n throw new RuntimeError(\r\n \"Global property: BATCH_LENGTH must be defined when BATCH_ID is defined.\"\r\n );\r\n }\r\n\r\n if (defined(batchTableBinary)) {\r\n // Copy the batchTableBinary section and let the underlying ArrayBuffer be freed\r\n batchTableBinary = new Uint8Array(batchTableBinary);\r\n }\r\n\r\n if (defined(pointCloud._batchTableLoaded)) {\r\n pointCloud._batchTableLoaded(\r\n batchLength,\r\n batchTableJson,\r\n batchTableBinary\r\n );\r\n }\r\n }\r\n\r\n // If points are not batched and there are per-point properties, use these properties for styling purposes\r\n var styleableProperties;\r\n if (!hasBatchIds && defined(batchTableBinary)) {\r\n styleableProperties = Cesium3DTileBatchTable.getBinaryProperties(\r\n pointsLength,\r\n batchTableJson,\r\n batchTableBinary\r\n );\r\n }\r\n\r\n pointCloud._parsedContent = {\r\n positions: positions,\r\n colors: colors,\r\n normals: normals,\r\n batchIds: batchIds,\r\n styleableProperties: styleableProperties,\r\n draco: draco,\r\n };\r\n pointCloud._pointsLength = pointsLength;\r\n pointCloud._isQuantized = isQuantized;\r\n pointCloud._isOctEncoded16P = isOctEncoded16P;\r\n pointCloud._isRGB565 = isRGB565;\r\n pointCloud._isTranslucent = isTranslucent;\r\n pointCloud._hasColors = hasColors;\r\n pointCloud._hasNormals = hasNormals;\r\n pointCloud._hasBatchIds = hasBatchIds;\r\n}\r\n\r\nvar scratchMin = new Cartesian3();\r\nvar scratchMax = new Cartesian3();\r\nvar scratchPosition = new Cartesian3();\r\nvar randomValues;\r\n\r\nfunction getRandomValues(samplesLength) {\r\n // Use same random values across all runs\r\n if (!defined(randomValues)) {\r\n CesiumMath.setRandomNumberSeed(0);\r\n randomValues = new Array(samplesLength);\r\n for (var i = 0; i < samplesLength; ++i) {\r\n randomValues[i] = CesiumMath.nextRandomNumber();\r\n }\r\n }\r\n return randomValues;\r\n}\r\n\r\nfunction computeApproximateBoundingSphereFromPositions(positions) {\r\n var maximumSamplesLength = 20;\r\n var pointsLength = positions.length / 3;\r\n var samplesLength = Math.min(pointsLength, maximumSamplesLength);\r\n var randomValues = getRandomValues(maximumSamplesLength);\r\n var maxValue = Number.MAX_VALUE;\r\n var minValue = -Number.MAX_VALUE;\r\n var min = Cartesian3.fromElements(maxValue, maxValue, maxValue, scratchMin);\r\n var max = Cartesian3.fromElements(minValue, minValue, minValue, scratchMax);\r\n for (var i = 0; i < samplesLength; ++i) {\r\n var index = Math.floor(randomValues[i] * pointsLength);\r\n var position = Cartesian3.unpack(positions, index * 3, scratchPosition);\r\n Cartesian3.minimumByComponent(min, position, min);\r\n Cartesian3.maximumByComponent(max, position, max);\r\n }\r\n\r\n var boundingSphere = BoundingSphere.fromCornerPoints(min, max);\r\n boundingSphere.radius += CesiumMath.EPSILON2; // To avoid radius of zero\r\n return boundingSphere;\r\n}\r\n\r\nfunction prepareVertexAttribute(typedArray, name) {\r\n // WebGL does not support UNSIGNED_INT, INT, or DOUBLE vertex attributes. Convert these to FLOAT.\r\n var componentDatatype = ComponentDatatype.fromTypedArray(typedArray);\r\n if (\r\n componentDatatype === ComponentDatatype.INT ||\r\n componentDatatype === ComponentDatatype.UNSIGNED_INT ||\r\n componentDatatype === ComponentDatatype.DOUBLE\r\n ) {\r\n oneTimeWarning(\r\n \"Cast pnts property to floats\",\r\n 'Point cloud property \"' +\r\n name +\r\n '\" will be casted to a float array because INT, UNSIGNED_INT, and DOUBLE are not valid WebGL vertex attribute types. Some precision may be lost.'\r\n );\r\n return new Float32Array(typedArray);\r\n }\r\n return typedArray;\r\n}\r\n\r\nvar scratchPointSizeAndTimeAndGeometricErrorAndDepthMultiplier = new Cartesian4();\r\nvar scratchQuantizedVolumeScaleAndOctEncodedRange = new Cartesian4();\r\nvar scratchColor = new Color();\r\n\r\nvar positionLocation = 0;\r\nvar colorLocation = 1;\r\nvar normalLocation = 2;\r\nvar batchIdLocation = 3;\r\nvar numberOfAttributes = 4;\r\n\r\nvar scratchClippingPlanesMatrix = new Matrix4();\r\nvar scratchInverseTransposeClippingPlanesMatrix = new Matrix4();\r\n\r\nfunction createResources(pointCloud, frameState) {\r\n var context = frameState.context;\r\n var parsedContent = pointCloud._parsedContent;\r\n var pointsLength = pointCloud._pointsLength;\r\n var positions = parsedContent.positions;\r\n var colors = parsedContent.colors;\r\n var normals = parsedContent.normals;\r\n var batchIds = parsedContent.batchIds;\r\n var styleableProperties = parsedContent.styleableProperties;\r\n var hasStyleableProperties = defined(styleableProperties);\r\n var isQuantized = pointCloud._isQuantized;\r\n var isQuantizedDraco = pointCloud._isQuantizedDraco;\r\n var isOctEncoded16P = pointCloud._isOctEncoded16P;\r\n var isOctEncodedDraco = pointCloud._isOctEncodedDraco;\r\n var quantizedRange = pointCloud._quantizedRange;\r\n var octEncodedRange = pointCloud._octEncodedRange;\r\n var isRGB565 = pointCloud._isRGB565;\r\n var isTranslucent = pointCloud._isTranslucent;\r\n var hasColors = pointCloud._hasColors;\r\n var hasNormals = pointCloud._hasNormals;\r\n var hasBatchIds = pointCloud._hasBatchIds;\r\n\r\n var componentsPerAttribute;\r\n var componentDatatype;\r\n\r\n var styleableVertexAttributes = [];\r\n var styleableShaderAttributes = {};\r\n pointCloud._styleableShaderAttributes = styleableShaderAttributes;\r\n\r\n if (hasStyleableProperties) {\r\n var attributeLocation = numberOfAttributes;\r\n\r\n for (var name in styleableProperties) {\r\n if (styleableProperties.hasOwnProperty(name)) {\r\n var property = styleableProperties[name];\r\n var typedArray = prepareVertexAttribute(property.typedArray, name);\r\n componentsPerAttribute = property.componentCount;\r\n componentDatatype = ComponentDatatype.fromTypedArray(typedArray);\r\n\r\n var vertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: typedArray,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n\r\n pointCloud._geometryByteLength += vertexBuffer.sizeInBytes;\r\n\r\n var vertexAttribute = {\r\n index: attributeLocation,\r\n vertexBuffer: vertexBuffer,\r\n componentsPerAttribute: componentsPerAttribute,\r\n componentDatatype: componentDatatype,\r\n normalize: false,\r\n offsetInBytes: 0,\r\n strideInBytes: 0,\r\n };\r\n\r\n styleableVertexAttributes.push(vertexAttribute);\r\n styleableShaderAttributes[name] = {\r\n location: attributeLocation,\r\n componentCount: componentsPerAttribute,\r\n };\r\n ++attributeLocation;\r\n }\r\n }\r\n }\r\n\r\n var positionsVertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: positions,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n pointCloud._geometryByteLength += positionsVertexBuffer.sizeInBytes;\r\n\r\n var colorsVertexBuffer;\r\n if (hasColors) {\r\n colorsVertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: colors,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n pointCloud._geometryByteLength += colorsVertexBuffer.sizeInBytes;\r\n }\r\n\r\n var normalsVertexBuffer;\r\n if (hasNormals) {\r\n normalsVertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: normals,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n pointCloud._geometryByteLength += normalsVertexBuffer.sizeInBytes;\r\n }\r\n\r\n var batchIdsVertexBuffer;\r\n if (hasBatchIds) {\r\n batchIds = prepareVertexAttribute(batchIds, \"batchIds\");\r\n batchIdsVertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: batchIds,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n pointCloud._geometryByteLength += batchIdsVertexBuffer.sizeInBytes;\r\n }\r\n\r\n var attributes = [];\r\n\r\n if (isQuantized) {\r\n componentDatatype = ComponentDatatype.UNSIGNED_SHORT;\r\n } else if (isQuantizedDraco) {\r\n componentDatatype =\r\n quantizedRange <= 255\r\n ? ComponentDatatype.UNSIGNED_BYTE\r\n : ComponentDatatype.UNSIGNED_SHORT;\r\n } else {\r\n componentDatatype = ComponentDatatype.FLOAT;\r\n }\r\n\r\n attributes.push({\r\n index: positionLocation,\r\n vertexBuffer: positionsVertexBuffer,\r\n componentsPerAttribute: 3,\r\n componentDatatype: componentDatatype,\r\n normalize: false,\r\n offsetInBytes: 0,\r\n strideInBytes: 0,\r\n });\r\n\r\n if (pointCloud._cull) {\r\n if (isQuantized || isQuantizedDraco) {\r\n pointCloud._boundingSphere = BoundingSphere.fromCornerPoints(\r\n Cartesian3.ZERO,\r\n pointCloud._quantizedVolumeScale\r\n );\r\n } else {\r\n pointCloud._boundingSphere = computeApproximateBoundingSphereFromPositions(\r\n positions\r\n );\r\n }\r\n }\r\n\r\n if (hasColors) {\r\n if (isRGB565) {\r\n attributes.push({\r\n index: colorLocation,\r\n vertexBuffer: colorsVertexBuffer,\r\n componentsPerAttribute: 1,\r\n componentDatatype: ComponentDatatype.UNSIGNED_SHORT,\r\n normalize: false,\r\n offsetInBytes: 0,\r\n strideInBytes: 0,\r\n });\r\n } else {\r\n var colorComponentsPerAttribute = isTranslucent ? 4 : 3;\r\n attributes.push({\r\n index: colorLocation,\r\n vertexBuffer: colorsVertexBuffer,\r\n componentsPerAttribute: colorComponentsPerAttribute,\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n normalize: true,\r\n offsetInBytes: 0,\r\n strideInBytes: 0,\r\n });\r\n }\r\n }\r\n\r\n if (hasNormals) {\r\n if (isOctEncoded16P) {\r\n componentsPerAttribute = 2;\r\n componentDatatype = ComponentDatatype.UNSIGNED_BYTE;\r\n } else if (isOctEncodedDraco) {\r\n componentsPerAttribute = 2;\r\n componentDatatype =\r\n octEncodedRange <= 255\r\n ? ComponentDatatype.UNSIGNED_BYTE\r\n : ComponentDatatype.UNSIGNED_SHORT;\r\n } else {\r\n componentsPerAttribute = 3;\r\n componentDatatype = ComponentDatatype.FLOAT;\r\n }\r\n attributes.push({\r\n index: normalLocation,\r\n vertexBuffer: normalsVertexBuffer,\r\n componentsPerAttribute: componentsPerAttribute,\r\n componentDatatype: componentDatatype,\r\n normalize: false,\r\n offsetInBytes: 0,\r\n strideInBytes: 0,\r\n });\r\n }\r\n\r\n if (hasBatchIds) {\r\n attributes.push({\r\n index: batchIdLocation,\r\n vertexBuffer: batchIdsVertexBuffer,\r\n componentsPerAttribute: 1,\r\n componentDatatype: ComponentDatatype.fromTypedArray(batchIds),\r\n normalize: false,\r\n offsetInBytes: 0,\r\n strideInBytes: 0,\r\n });\r\n }\r\n\r\n if (hasStyleableProperties) {\r\n attributes = attributes.concat(styleableVertexAttributes);\r\n }\r\n\r\n var vertexArray = new VertexArray({\r\n context: context,\r\n attributes: attributes,\r\n });\r\n\r\n var opaqueRenderState = {\r\n depthTest: {\r\n enabled: true,\r\n },\r\n };\r\n\r\n var translucentRenderState = {\r\n depthTest: {\r\n enabled: true,\r\n },\r\n depthMask: false,\r\n blending: BlendingState.ALPHA_BLEND,\r\n };\r\n\r\n if (pointCloud._opaquePass === Pass.CESIUM_3D_TILE) {\r\n opaqueRenderState.stencilTest = StencilConstants.setCesium3DTileBit();\r\n opaqueRenderState.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;\r\n translucentRenderState.stencilTest = StencilConstants.setCesium3DTileBit();\r\n translucentRenderState.stencilMask = StencilConstants.CESIUM_3D_TILE_MASK;\r\n }\r\n\r\n pointCloud._opaqueRenderState = RenderState.fromCache(opaqueRenderState);\r\n pointCloud._translucentRenderState = RenderState.fromCache(\r\n translucentRenderState\r\n );\r\n\r\n pointCloud._drawCommand = new DrawCommand({\r\n boundingVolume: new BoundingSphere(),\r\n cull: pointCloud._cull,\r\n modelMatrix: new Matrix4(),\r\n primitiveType: PrimitiveType.POINTS,\r\n vertexArray: vertexArray,\r\n count: pointsLength,\r\n shaderProgram: undefined, // Updated in createShaders\r\n uniformMap: undefined, // Updated in createShaders\r\n renderState: isTranslucent\r\n ? pointCloud._translucentRenderState\r\n : pointCloud._opaqueRenderState,\r\n pass: isTranslucent ? Pass.TRANSLUCENT : pointCloud._opaquePass,\r\n owner: pointCloud,\r\n castShadows: false,\r\n receiveShadows: false,\r\n pickId: pointCloud._pickIdLoaded(),\r\n });\r\n}\r\n\r\nfunction createUniformMap(pointCloud, frameState) {\r\n var context = frameState.context;\r\n var isQuantized = pointCloud._isQuantized;\r\n var isQuantizedDraco = pointCloud._isQuantizedDraco;\r\n var isOctEncodedDraco = pointCloud._isOctEncodedDraco;\r\n\r\n var uniformMap = {\r\n u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier: function () {\r\n var scratch = scratchPointSizeAndTimeAndGeometricErrorAndDepthMultiplier;\r\n scratch.x = pointCloud._attenuation\r\n ? pointCloud.maximumAttenuation\r\n : pointCloud._pointSize;\r\n scratch.x *= frameState.pixelRatio;\r\n\r\n scratch.y = pointCloud.time;\r\n\r\n if (pointCloud._attenuation) {\r\n var frustum = frameState.camera.frustum;\r\n var depthMultiplier;\r\n // Attenuation is maximumAttenuation in 2D/ortho\r\n if (\r\n frameState.mode === SceneMode.SCENE2D ||\r\n frustum instanceof OrthographicFrustum\r\n ) {\r\n depthMultiplier = Number.POSITIVE_INFINITY;\r\n } else {\r\n depthMultiplier =\r\n context.drawingBufferHeight /\r\n frameState.camera.frustum.sseDenominator;\r\n }\r\n\r\n scratch.z = pointCloud.geometricError * pointCloud.geometricErrorScale;\r\n scratch.w = depthMultiplier;\r\n }\r\n\r\n return scratch;\r\n },\r\n u_highlightColor: function () {\r\n return pointCloud._highlightColor;\r\n },\r\n u_constantColor: function () {\r\n return pointCloud._constantColor;\r\n },\r\n u_clippingPlanes: function () {\r\n var clippingPlanes = pointCloud.clippingPlanes;\r\n var isClipped = pointCloud.isClipped;\r\n return isClipped ? clippingPlanes.texture : context.defaultTexture;\r\n },\r\n u_clippingPlanesEdgeStyle: function () {\r\n var clippingPlanes = pointCloud.clippingPlanes;\r\n if (!defined(clippingPlanes)) {\r\n return Color.TRANSPARENT;\r\n }\r\n\r\n var style = Color.clone(clippingPlanes.edgeColor, scratchColor);\r\n style.alpha = clippingPlanes.edgeWidth;\r\n return style;\r\n },\r\n u_clippingPlanesMatrix: function () {\r\n var clippingPlanes = pointCloud.clippingPlanes;\r\n if (!defined(clippingPlanes)) {\r\n return Matrix4.IDENTITY;\r\n }\r\n\r\n var clippingPlanesOriginMatrix = defaultValue(\r\n pointCloud.clippingPlanesOriginMatrix,\r\n pointCloud._modelMatrix\r\n );\r\n Matrix4.multiply(\r\n context.uniformState.view3D,\r\n clippingPlanesOriginMatrix,\r\n scratchClippingPlanesMatrix\r\n );\r\n var transform = Matrix4.multiply(\r\n scratchClippingPlanesMatrix,\r\n clippingPlanes.modelMatrix,\r\n scratchClippingPlanesMatrix\r\n );\r\n\r\n return Matrix4.inverseTranspose(\r\n transform,\r\n scratchInverseTransposeClippingPlanesMatrix\r\n );\r\n },\r\n };\r\n\r\n if (isQuantized || isQuantizedDraco || isOctEncodedDraco) {\r\n uniformMap = combine(uniformMap, {\r\n u_quantizedVolumeScaleAndOctEncodedRange: function () {\r\n var scratch = scratchQuantizedVolumeScaleAndOctEncodedRange;\r\n if (defined(pointCloud._quantizedVolumeScale)) {\r\n var scale = Cartesian3.clone(\r\n pointCloud._quantizedVolumeScale,\r\n scratch\r\n );\r\n Cartesian3.divideByScalar(scale, pointCloud._quantizedRange, scratch);\r\n }\r\n scratch.w = pointCloud._octEncodedRange;\r\n return scratch;\r\n },\r\n });\r\n }\r\n\r\n if (defined(pointCloud._uniformMapLoaded)) {\r\n uniformMap = pointCloud._uniformMapLoaded(uniformMap);\r\n }\r\n\r\n pointCloud._drawCommand.uniformMap = uniformMap;\r\n}\r\n\r\nfunction getStyleablePropertyIds(source, propertyIds) {\r\n // Get all the property IDs used by this style\r\n var regex = /czm_3dtiles_property_(\\d+)/g;\r\n var matches = regex.exec(source);\r\n while (matches !== null) {\r\n var id = parseInt(matches[1]);\r\n if (propertyIds.indexOf(id) === -1) {\r\n propertyIds.push(id);\r\n }\r\n matches = regex.exec(source);\r\n }\r\n}\r\n\r\nfunction getBuiltinPropertyNames(source, propertyNames) {\r\n // Get all the builtin property names used by this style\r\n var regex = /czm_3dtiles_builtin_property_(\\w+)/g;\r\n var matches = regex.exec(source);\r\n while (matches !== null) {\r\n var name = matches[1];\r\n if (propertyNames.indexOf(name) === -1) {\r\n propertyNames.push(name);\r\n }\r\n matches = regex.exec(source);\r\n }\r\n}\r\n\r\nfunction getVertexAttribute(vertexArray, index) {\r\n var numberOfAttributes = vertexArray.numberOfAttributes;\r\n for (var i = 0; i < numberOfAttributes; ++i) {\r\n var attribute = vertexArray.getAttribute(i);\r\n if (attribute.index === index) {\r\n return attribute;\r\n }\r\n }\r\n}\r\n\r\nvar builtinPropertyNameMap = {\r\n POSITION: \"czm_3dtiles_builtin_property_POSITION\",\r\n POSITION_ABSOLUTE: \"czm_3dtiles_builtin_property_POSITION_ABSOLUTE\",\r\n COLOR: \"czm_3dtiles_builtin_property_COLOR\",\r\n NORMAL: \"czm_3dtiles_builtin_property_NORMAL\",\r\n};\r\n\r\nfunction modifyStyleFunction(source) {\r\n // Edit the function header to accept the point position, color, and normal\r\n var functionHeader =\r\n \"(\" +\r\n \"vec3 czm_3dtiles_builtin_property_POSITION, \" +\r\n \"vec3 czm_3dtiles_builtin_property_POSITION_ABSOLUTE, \" +\r\n \"vec4 czm_3dtiles_builtin_property_COLOR, \" +\r\n \"vec3 czm_3dtiles_builtin_property_NORMAL\" +\r\n \")\";\r\n\r\n return source.replace(\"()\", functionHeader);\r\n}\r\n\r\nfunction createShaders(pointCloud, frameState, style) {\r\n var i;\r\n var name;\r\n var attribute;\r\n\r\n var context = frameState.context;\r\n var hasStyle = defined(style);\r\n var isQuantized = pointCloud._isQuantized;\r\n var isQuantizedDraco = pointCloud._isQuantizedDraco;\r\n var isOctEncoded16P = pointCloud._isOctEncoded16P;\r\n var isOctEncodedDraco = pointCloud._isOctEncodedDraco;\r\n var isRGB565 = pointCloud._isRGB565;\r\n var isTranslucent = pointCloud._isTranslucent;\r\n var hasColors = pointCloud._hasColors;\r\n var hasNormals = pointCloud._hasNormals;\r\n var hasBatchIds = pointCloud._hasBatchIds;\r\n var backFaceCulling = pointCloud._backFaceCulling;\r\n var normalShading = pointCloud._normalShading;\r\n var vertexArray = pointCloud._drawCommand.vertexArray;\r\n var clippingPlanes = pointCloud.clippingPlanes;\r\n var attenuation = pointCloud._attenuation;\r\n\r\n var colorStyleFunction;\r\n var showStyleFunction;\r\n var pointSizeStyleFunction;\r\n var styleTranslucent = isTranslucent;\r\n\r\n var propertyNameMap = clone(builtinPropertyNameMap);\r\n var propertyIdToAttributeMap = {};\r\n var styleableShaderAttributes = pointCloud._styleableShaderAttributes;\r\n for (name in styleableShaderAttributes) {\r\n if (styleableShaderAttributes.hasOwnProperty(name)) {\r\n attribute = styleableShaderAttributes[name];\r\n propertyNameMap[name] = \"czm_3dtiles_property_\" + attribute.location;\r\n propertyIdToAttributeMap[attribute.location] = attribute;\r\n }\r\n }\r\n\r\n if (hasStyle) {\r\n var shaderState = {\r\n translucent: false,\r\n };\r\n colorStyleFunction = style.getColorShaderFunction(\r\n \"getColorFromStyle\",\r\n propertyNameMap,\r\n shaderState\r\n );\r\n showStyleFunction = style.getShowShaderFunction(\r\n \"getShowFromStyle\",\r\n propertyNameMap,\r\n shaderState\r\n );\r\n pointSizeStyleFunction = style.getPointSizeShaderFunction(\r\n \"getPointSizeFromStyle\",\r\n propertyNameMap,\r\n shaderState\r\n );\r\n if (defined(colorStyleFunction) && shaderState.translucent) {\r\n styleTranslucent = true;\r\n }\r\n }\r\n\r\n pointCloud._styleTranslucent = styleTranslucent;\r\n\r\n var hasColorStyle = defined(colorStyleFunction);\r\n var hasShowStyle = defined(showStyleFunction);\r\n var hasPointSizeStyle = defined(pointSizeStyleFunction);\r\n var hasClippedContent = pointCloud.isClipped;\r\n\r\n // Get the properties in use by the style\r\n var styleablePropertyIds = [];\r\n var builtinPropertyNames = [];\r\n\r\n if (hasColorStyle) {\r\n getStyleablePropertyIds(colorStyleFunction, styleablePropertyIds);\r\n getBuiltinPropertyNames(colorStyleFunction, builtinPropertyNames);\r\n colorStyleFunction = modifyStyleFunction(colorStyleFunction);\r\n }\r\n if (hasShowStyle) {\r\n getStyleablePropertyIds(showStyleFunction, styleablePropertyIds);\r\n getBuiltinPropertyNames(showStyleFunction, builtinPropertyNames);\r\n showStyleFunction = modifyStyleFunction(showStyleFunction);\r\n }\r\n if (hasPointSizeStyle) {\r\n getStyleablePropertyIds(pointSizeStyleFunction, styleablePropertyIds);\r\n getBuiltinPropertyNames(pointSizeStyleFunction, builtinPropertyNames);\r\n pointSizeStyleFunction = modifyStyleFunction(pointSizeStyleFunction);\r\n }\r\n\r\n var usesColorSemantic = builtinPropertyNames.indexOf(\"COLOR\") >= 0;\r\n var usesNormalSemantic = builtinPropertyNames.indexOf(\"NORMAL\") >= 0;\r\n\r\n if (usesNormalSemantic && !hasNormals) {\r\n throw new RuntimeError(\r\n \"Style references the NORMAL semantic but the point cloud does not have normals\"\r\n );\r\n }\r\n\r\n // Disable vertex attributes that aren't used in the style, enable attributes that are\r\n for (name in styleableShaderAttributes) {\r\n if (styleableShaderAttributes.hasOwnProperty(name)) {\r\n attribute = styleableShaderAttributes[name];\r\n var enabled = styleablePropertyIds.indexOf(attribute.location) >= 0;\r\n var vertexAttribute = getVertexAttribute(vertexArray, attribute.location);\r\n vertexAttribute.enabled = enabled;\r\n }\r\n }\r\n\r\n var usesColors = hasColors && (!hasColorStyle || usesColorSemantic);\r\n if (hasColors) {\r\n // Disable the color vertex attribute if the color style does not reference the color semantic\r\n var colorVertexAttribute = getVertexAttribute(vertexArray, colorLocation);\r\n colorVertexAttribute.enabled = usesColors;\r\n }\r\n\r\n var usesNormals =\r\n hasNormals && (normalShading || backFaceCulling || usesNormalSemantic);\r\n if (hasNormals) {\r\n // Disable the normal vertex attribute if normals are not used\r\n var normalVertexAttribute = getVertexAttribute(vertexArray, normalLocation);\r\n normalVertexAttribute.enabled = usesNormals;\r\n }\r\n\r\n var attributeLocations = {\r\n a_position: positionLocation,\r\n };\r\n if (usesColors) {\r\n attributeLocations.a_color = colorLocation;\r\n }\r\n if (usesNormals) {\r\n attributeLocations.a_normal = normalLocation;\r\n }\r\n if (hasBatchIds) {\r\n attributeLocations.a_batchId = batchIdLocation;\r\n }\r\n\r\n var attributeDeclarations = \"\";\r\n\r\n var length = styleablePropertyIds.length;\r\n for (i = 0; i < length; ++i) {\r\n var propertyId = styleablePropertyIds[i];\r\n attribute = propertyIdToAttributeMap[propertyId];\r\n var componentCount = attribute.componentCount;\r\n var attributeName = \"czm_3dtiles_property_\" + propertyId;\r\n var attributeType;\r\n if (componentCount === 1) {\r\n attributeType = \"float\";\r\n } else {\r\n attributeType = \"vec\" + componentCount;\r\n }\r\n\r\n attributeDeclarations +=\r\n \"attribute \" + attributeType + \" \" + attributeName + \"; \\n\";\r\n attributeLocations[attributeName] = attribute.location;\r\n }\r\n\r\n createUniformMap(pointCloud, frameState);\r\n\r\n var vs =\r\n \"attribute vec3 a_position; \\n\" +\r\n \"varying vec4 v_color; \\n\" +\r\n \"uniform vec4 u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier; \\n\" +\r\n \"uniform vec4 u_constantColor; \\n\" +\r\n \"uniform vec4 u_highlightColor; \\n\";\r\n vs += \"float u_pointSize; \\n\" + \"float u_time; \\n\";\r\n\r\n if (attenuation) {\r\n vs += \"float u_geometricError; \\n\" + \"float u_depthMultiplier; \\n\";\r\n }\r\n\r\n vs += attributeDeclarations;\r\n\r\n if (usesColors) {\r\n if (isTranslucent) {\r\n vs += \"attribute vec4 a_color; \\n\";\r\n } else if (isRGB565) {\r\n vs +=\r\n \"attribute float a_color; \\n\" +\r\n \"const float SHIFT_RIGHT_11 = 1.0 / 2048.0; \\n\" +\r\n \"const float SHIFT_RIGHT_5 = 1.0 / 32.0; \\n\" +\r\n \"const float SHIFT_LEFT_11 = 2048.0; \\n\" +\r\n \"const float SHIFT_LEFT_5 = 32.0; \\n\" +\r\n \"const float NORMALIZE_6 = 1.0 / 64.0; \\n\" +\r\n \"const float NORMALIZE_5 = 1.0 / 32.0; \\n\";\r\n } else {\r\n vs += \"attribute vec3 a_color; \\n\";\r\n }\r\n }\r\n if (usesNormals) {\r\n if (isOctEncoded16P || isOctEncodedDraco) {\r\n vs += \"attribute vec2 a_normal; \\n\";\r\n } else {\r\n vs += \"attribute vec3 a_normal; \\n\";\r\n }\r\n }\r\n\r\n if (hasBatchIds) {\r\n vs += \"attribute float a_batchId; \\n\";\r\n }\r\n\r\n if (isQuantized || isQuantizedDraco || isOctEncodedDraco) {\r\n vs += \"uniform vec4 u_quantizedVolumeScaleAndOctEncodedRange; \\n\";\r\n }\r\n\r\n if (hasColorStyle) {\r\n vs += colorStyleFunction;\r\n }\r\n\r\n if (hasShowStyle) {\r\n vs += showStyleFunction;\r\n }\r\n\r\n if (hasPointSizeStyle) {\r\n vs += pointSizeStyleFunction;\r\n }\r\n\r\n vs +=\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" u_pointSize = u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier.x; \\n\" +\r\n \" u_time = u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier.y; \\n\";\r\n\r\n if (attenuation) {\r\n vs +=\r\n \" u_geometricError = u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier.z; \\n\" +\r\n \" u_depthMultiplier = u_pointSizeAndTimeAndGeometricErrorAndDepthMultiplier.w; \\n\";\r\n }\r\n\r\n if (usesColors) {\r\n if (isTranslucent) {\r\n vs += \" vec4 color = a_color; \\n\";\r\n } else if (isRGB565) {\r\n vs +=\r\n \" float compressed = a_color; \\n\" +\r\n \" float r = floor(compressed * SHIFT_RIGHT_11); \\n\" +\r\n \" compressed -= r * SHIFT_LEFT_11; \\n\" +\r\n \" float g = floor(compressed * SHIFT_RIGHT_5); \\n\" +\r\n \" compressed -= g * SHIFT_LEFT_5; \\n\" +\r\n \" float b = compressed; \\n\" +\r\n \" vec3 rgb = vec3(r * NORMALIZE_5, g * NORMALIZE_6, b * NORMALIZE_5); \\n\" +\r\n \" vec4 color = vec4(rgb, 1.0); \\n\";\r\n } else {\r\n vs += \" vec4 color = vec4(a_color, 1.0); \\n\";\r\n }\r\n } else {\r\n vs += \" vec4 color = u_constantColor; \\n\";\r\n }\r\n\r\n if (isQuantized || isQuantizedDraco) {\r\n vs +=\r\n \" vec3 position = a_position * u_quantizedVolumeScaleAndOctEncodedRange.xyz; \\n\";\r\n } else {\r\n vs += \" vec3 position = a_position; \\n\";\r\n }\r\n vs +=\r\n \" vec3 position_absolute = vec3(czm_model * vec4(position, 1.0)); \\n\";\r\n\r\n if (usesNormals) {\r\n if (isOctEncoded16P) {\r\n vs += \" vec3 normal = czm_octDecode(a_normal); \\n\";\r\n } else if (isOctEncodedDraco) {\r\n // Draco oct-encoding decodes to zxy order\r\n vs +=\r\n \" vec3 normal = czm_octDecode(a_normal, u_quantizedVolumeScaleAndOctEncodedRange.w).zxy; \\n\";\r\n } else {\r\n vs += \" vec3 normal = a_normal; \\n\";\r\n }\r\n vs += \" vec3 normalEC = czm_normal * normal; \\n\";\r\n } else {\r\n vs += \" vec3 normal = vec3(1.0); \\n\";\r\n }\r\n\r\n if (hasColorStyle) {\r\n vs +=\r\n \" color = getColorFromStyle(position, position_absolute, color, normal); \\n\";\r\n }\r\n\r\n if (hasShowStyle) {\r\n vs +=\r\n \" float show = float(getShowFromStyle(position, position_absolute, color, normal)); \\n\";\r\n }\r\n\r\n if (hasPointSizeStyle) {\r\n vs +=\r\n \" gl_PointSize = getPointSizeFromStyle(position, position_absolute, color, normal) * czm_pixelRatio; \\n\";\r\n } else if (attenuation) {\r\n vs +=\r\n \" vec4 positionEC = czm_modelView * vec4(position, 1.0); \\n\" +\r\n \" float depth = -positionEC.z; \\n\" +\r\n // compute SSE for this point\r\n \" gl_PointSize = min((u_geometricError / depth) * u_depthMultiplier, u_pointSize); \\n\";\r\n } else {\r\n vs += \" gl_PointSize = u_pointSize; \\n\";\r\n }\r\n\r\n vs += \" color = color * u_highlightColor; \\n\";\r\n\r\n if (usesNormals && normalShading) {\r\n vs +=\r\n \" float diffuseStrength = czm_getLambertDiffuse(czm_lightDirectionEC, normalEC); \\n\" +\r\n \" diffuseStrength = max(diffuseStrength, 0.4); \\n\" + // Apply some ambient lighting\r\n \" color.xyz *= diffuseStrength * czm_lightColor; \\n\";\r\n }\r\n\r\n vs +=\r\n \" v_color = color; \\n\" +\r\n \" gl_Position = czm_modelViewProjection * vec4(position, 1.0); \\n\";\r\n\r\n if (usesNormals && backFaceCulling) {\r\n vs +=\r\n \" float visible = step(-normalEC.z, 0.0); \\n\" +\r\n \" gl_Position *= visible; \\n\" +\r\n \" gl_PointSize *= visible; \\n\";\r\n }\r\n\r\n if (hasShowStyle) {\r\n vs +=\r\n \" gl_Position.w *= float(show); \\n\" +\r\n \" gl_PointSize *= float(show); \\n\";\r\n }\r\n\r\n vs += \"} \\n\";\r\n\r\n var fs = \"varying vec4 v_color; \\n\";\r\n\r\n if (hasClippedContent) {\r\n fs +=\r\n \"uniform highp sampler2D u_clippingPlanes; \\n\" +\r\n \"uniform mat4 u_clippingPlanesMatrix; \\n\" +\r\n \"uniform vec4 u_clippingPlanesEdgeStyle; \\n\";\r\n fs += \"\\n\";\r\n fs += getClippingFunction(clippingPlanes, context);\r\n fs += \"\\n\";\r\n }\r\n\r\n fs +=\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" gl_FragColor = czm_gammaCorrect(v_color); \\n\";\r\n\r\n if (hasClippedContent) {\r\n fs += getClipAndStyleCode(\r\n \"u_clippingPlanes\",\r\n \"u_clippingPlanesMatrix\",\r\n \"u_clippingPlanesEdgeStyle\"\r\n );\r\n }\r\n\r\n fs += \"} \\n\";\r\n\r\n if (defined(pointCloud._vertexShaderLoaded)) {\r\n vs = pointCloud._vertexShaderLoaded(vs);\r\n }\r\n\r\n if (defined(pointCloud._fragmentShaderLoaded)) {\r\n fs = pointCloud._fragmentShaderLoaded(fs);\r\n }\r\n\r\n var drawCommand = pointCloud._drawCommand;\r\n if (defined(drawCommand.shaderProgram)) {\r\n // Destroy the old shader\r\n drawCommand.shaderProgram.destroy();\r\n }\r\n drawCommand.shaderProgram = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n try {\r\n // Check if the shader compiles correctly. If not there is likely a syntax error with the style.\r\n drawCommand.shaderProgram._bind();\r\n } catch (error) {\r\n // Rephrase the error.\r\n throw new RuntimeError(\r\n \"Error generating style shader: this may be caused by a type mismatch, index out-of-bounds, or other syntax error.\"\r\n );\r\n }\r\n}\r\n\r\nfunction decodeDraco(pointCloud, context) {\r\n if (pointCloud._decodingState === DecodingState.READY) {\r\n return false;\r\n }\r\n if (pointCloud._decodingState === DecodingState.NEEDS_DECODE) {\r\n var parsedContent = pointCloud._parsedContent;\r\n var draco = parsedContent.draco;\r\n var decodePromise = DracoLoader.decodePointCloud(draco, context);\r\n if (defined(decodePromise)) {\r\n pointCloud._decodingState = DecodingState.DECODING;\r\n decodePromise\r\n .then(function (result) {\r\n pointCloud._decodingState = DecodingState.READY;\r\n var decodedPositions = defined(result.POSITION)\r\n ? result.POSITION.array\r\n : undefined;\r\n var decodedRgb = defined(result.RGB) ? result.RGB.array : undefined;\r\n var decodedRgba = defined(result.RGBA)\r\n ? result.RGBA.array\r\n : undefined;\r\n var decodedNormals = defined(result.NORMAL)\r\n ? result.NORMAL.array\r\n : undefined;\r\n var decodedBatchIds = defined(result.BATCH_ID)\r\n ? result.BATCH_ID.array\r\n : undefined;\r\n var isQuantizedDraco =\r\n defined(decodedPositions) &&\r\n defined(result.POSITION.data.quantization);\r\n var isOctEncodedDraco =\r\n defined(decodedNormals) && defined(result.NORMAL.data.quantization);\r\n if (isQuantizedDraco) {\r\n // Draco quantization range == quantized volume scale - size in meters of the quantized volume\r\n // Internal quantized range is the range of values of the quantized data, e.g. 255 for 8-bit, 1023 for 10-bit, etc\r\n var quantization = result.POSITION.data.quantization;\r\n var range = quantization.range;\r\n pointCloud._quantizedVolumeScale = Cartesian3.fromElements(\r\n range,\r\n range,\r\n range\r\n );\r\n pointCloud._quantizedVolumeOffset = Cartesian3.unpack(\r\n quantization.minValues\r\n );\r\n pointCloud._quantizedRange =\r\n (1 << quantization.quantizationBits) - 1.0;\r\n pointCloud._isQuantizedDraco = true;\r\n }\r\n if (isOctEncodedDraco) {\r\n pointCloud._octEncodedRange =\r\n (1 << result.NORMAL.data.quantization.quantizationBits) - 1.0;\r\n pointCloud._isOctEncodedDraco = true;\r\n }\r\n var styleableProperties = parsedContent.styleableProperties;\r\n var batchTableProperties = draco.batchTableProperties;\r\n for (var name in batchTableProperties) {\r\n if (batchTableProperties.hasOwnProperty(name)) {\r\n var property = result[name];\r\n if (!defined(styleableProperties)) {\r\n styleableProperties = {};\r\n }\r\n styleableProperties[name] = {\r\n typedArray: property.array,\r\n componentCount: property.data.componentsPerAttribute,\r\n };\r\n }\r\n }\r\n parsedContent.positions = defaultValue(\r\n decodedPositions,\r\n parsedContent.positions\r\n );\r\n parsedContent.colors = defaultValue(\r\n defaultValue(decodedRgba, decodedRgb),\r\n parsedContent.colors\r\n );\r\n parsedContent.normals = defaultValue(\r\n decodedNormals,\r\n parsedContent.normals\r\n );\r\n parsedContent.batchIds = defaultValue(\r\n decodedBatchIds,\r\n parsedContent.batchIds\r\n );\r\n parsedContent.styleableProperties = styleableProperties;\r\n })\r\n .otherwise(function (error) {\r\n pointCloud._decodingState = DecodingState.FAILED;\r\n pointCloud._readyPromise.reject(error);\r\n });\r\n }\r\n }\r\n return true;\r\n}\r\n\r\nvar scratchComputedTranslation = new Cartesian4();\r\nvar scratchScale = new Cartesian3();\r\n\r\nPointCloud.prototype.update = function (frameState) {\r\n var context = frameState.context;\r\n var decoding = decodeDraco(this, context);\r\n if (decoding) {\r\n return;\r\n }\r\n\r\n var shadersDirty = false;\r\n var modelMatrixDirty = !Matrix4.equals(this._modelMatrix, this.modelMatrix);\r\n\r\n if (this._mode !== frameState.mode) {\r\n this._mode = frameState.mode;\r\n modelMatrixDirty = true;\r\n }\r\n\r\n if (!defined(this._drawCommand)) {\r\n createResources(this, frameState);\r\n modelMatrixDirty = true;\r\n shadersDirty = true;\r\n this._ready = true;\r\n this._readyPromise.resolve(this);\r\n this._parsedContent = undefined; // Unload\r\n }\r\n\r\n if (modelMatrixDirty) {\r\n Matrix4.clone(this.modelMatrix, this._modelMatrix);\r\n var modelMatrix = this._drawCommand.modelMatrix;\r\n Matrix4.clone(this._modelMatrix, modelMatrix);\r\n\r\n if (defined(this._rtcCenter)) {\r\n Matrix4.multiplyByTranslation(modelMatrix, this._rtcCenter, modelMatrix);\r\n }\r\n if (defined(this._quantizedVolumeOffset)) {\r\n Matrix4.multiplyByTranslation(\r\n modelMatrix,\r\n this._quantizedVolumeOffset,\r\n modelMatrix\r\n );\r\n }\r\n\r\n if (frameState.mode !== SceneMode.SCENE3D) {\r\n var projection = frameState.mapProjection;\r\n var translation = Matrix4.getColumn(\r\n modelMatrix,\r\n 3,\r\n scratchComputedTranslation\r\n );\r\n if (!Cartesian4.equals(translation, Cartesian4.UNIT_W)) {\r\n Transforms.basisTo2D(projection, modelMatrix, modelMatrix);\r\n }\r\n }\r\n\r\n var boundingSphere = this._drawCommand.boundingVolume;\r\n BoundingSphere.clone(this._boundingSphere, boundingSphere);\r\n\r\n if (this._cull) {\r\n var center = boundingSphere.center;\r\n Matrix4.multiplyByPoint(modelMatrix, center, center);\r\n var scale = Matrix4.getScale(modelMatrix, scratchScale);\r\n boundingSphere.radius *= Cartesian3.maximumComponent(scale);\r\n }\r\n }\r\n\r\n if (this.clippingPlanesDirty) {\r\n this.clippingPlanesDirty = false;\r\n shadersDirty = true;\r\n }\r\n\r\n if (this._attenuation !== this.attenuation) {\r\n this._attenuation = this.attenuation;\r\n shadersDirty = true;\r\n }\r\n\r\n if (this.backFaceCulling !== this._backFaceCulling) {\r\n this._backFaceCulling = this.backFaceCulling;\r\n shadersDirty = true;\r\n }\r\n\r\n if (this.normalShading !== this._normalShading) {\r\n this._normalShading = this.normalShading;\r\n shadersDirty = true;\r\n }\r\n\r\n if (this._style !== this.style || this.styleDirty) {\r\n this._style = this.style;\r\n this.styleDirty = false;\r\n shadersDirty = true;\r\n }\r\n\r\n if (shadersDirty) {\r\n createShaders(this, frameState, this._style);\r\n }\r\n\r\n this._drawCommand.castShadows = ShadowMode.castShadows(this.shadows);\r\n this._drawCommand.receiveShadows = ShadowMode.receiveShadows(this.shadows);\r\n\r\n // Update the render state\r\n var isTranslucent =\r\n this._highlightColor.alpha < 1.0 ||\r\n this._constantColor.alpha < 1.0 ||\r\n this._styleTranslucent;\r\n this._drawCommand.renderState = isTranslucent\r\n ? this._translucentRenderState\r\n : this._opaqueRenderState;\r\n this._drawCommand.pass = isTranslucent ? Pass.TRANSLUCENT : this._opaquePass;\r\n\r\n var commandList = frameState.commandList;\r\n\r\n var passes = frameState.passes;\r\n if (passes.render || passes.pick) {\r\n commandList.push(this._drawCommand);\r\n }\r\n};\r\n\r\nPointCloud.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nPointCloud.prototype.destroy = function () {\r\n var command = this._drawCommand;\r\n if (defined(command)) {\r\n command.vertexArray = command.vertexArray && command.vertexArray.destroy();\r\n command.shaderProgram =\r\n command.shaderProgram && command.shaderProgram.destroy();\r\n }\r\n return destroyObject(this);\r\n};\r\nexport default PointCloud;\r\n","import Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport ContextLimits from \"./ContextLimits.js\";\r\nimport PixelDatatype from \"./PixelDatatype.js\";\r\n\r\nfunction attachTexture(framebuffer, attachment, texture) {\r\n var gl = framebuffer._gl;\r\n gl.framebufferTexture2D(\r\n gl.FRAMEBUFFER,\r\n attachment,\r\n texture._target,\r\n texture._texture,\r\n 0\r\n );\r\n}\r\n\r\nfunction attachRenderbuffer(framebuffer, attachment, renderbuffer) {\r\n var gl = framebuffer._gl;\r\n gl.framebufferRenderbuffer(\r\n gl.FRAMEBUFFER,\r\n attachment,\r\n gl.RENDERBUFFER,\r\n renderbuffer._getRenderbuffer()\r\n );\r\n}\r\n\r\n/**\r\n * Creates a framebuffer with optional initial color, depth, and stencil attachments.\r\n * Framebuffers are used for render-to-texture effects; they allow us to render to\r\n * textures in one pass, and read from it in a later pass.\r\n *\r\n * @param {Object} options The initial framebuffer attachments as shown in the example below. context is required. The possible properties are colorTextures, colorRenderbuffers, depthTexture, depthRenderbuffer, stencilRenderbuffer, depthStencilTexture, and depthStencilRenderbuffer.\r\n *\r\n * @exception {DeveloperError} Cannot have both color texture and color renderbuffer attachments.\r\n * @exception {DeveloperError} Cannot have both a depth texture and depth renderbuffer attachment.\r\n * @exception {DeveloperError} Cannot have both a depth-stencil texture and depth-stencil renderbuffer attachment.\r\n * @exception {DeveloperError} Cannot have both a depth and depth-stencil renderbuffer.\r\n * @exception {DeveloperError} Cannot have both a stencil and depth-stencil renderbuffer.\r\n * @exception {DeveloperError} Cannot have both a depth and stencil renderbuffer.\r\n * @exception {DeveloperError} The color-texture pixel-format must be a color format.\r\n * @exception {DeveloperError} The depth-texture pixel-format must be DEPTH_COMPONENT.\r\n * @exception {DeveloperError} The depth-stencil-texture pixel-format must be DEPTH_STENCIL.\r\n * @exception {DeveloperError} The number of color attachments exceeds the number supported.\r\n * @exception {DeveloperError} The color-texture pixel datatype is HALF_FLOAT and the WebGL implementation does not support the EXT_color_buffer_half_float extension.\r\n * @exception {DeveloperError} The color-texture pixel datatype is FLOAT and the WebGL implementation does not support the EXT_color_buffer_float or WEBGL_color_buffer_float extensions.\r\n *\r\n * @example\r\n * // Create a framebuffer with color and depth texture attachments.\r\n * var width = context.canvas.clientWidth;\r\n * var height = context.canvas.clientHeight;\r\n * var framebuffer = new Framebuffer({\r\n * context : context,\r\n * colorTextures : [new Texture({\r\n * context : context,\r\n * width : width,\r\n * height : height,\r\n * pixelFormat : PixelFormat.RGBA\r\n * })],\r\n * depthTexture : new Texture({\r\n * context : context,\r\n * width : width,\r\n * height : height,\r\n * pixelFormat : PixelFormat.DEPTH_COMPONENT,\r\n * pixelDatatype : PixelDatatype.UNSIGNED_SHORT\r\n * })\r\n * });\r\n *\r\n * @private\r\n * @constructor\r\n */\r\nfunction Framebuffer(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var context = options.context;\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.context\", context);\r\n //>>includeEnd('debug');\r\n\r\n var gl = context._gl;\r\n var maximumColorAttachments = ContextLimits.maximumColorAttachments;\r\n\r\n this._gl = gl;\r\n this._framebuffer = gl.createFramebuffer();\r\n\r\n this._colorTextures = [];\r\n this._colorRenderbuffers = [];\r\n this._activeColorAttachments = [];\r\n\r\n this._depthTexture = undefined;\r\n this._depthRenderbuffer = undefined;\r\n this._stencilRenderbuffer = undefined;\r\n this._depthStencilTexture = undefined;\r\n this._depthStencilRenderbuffer = undefined;\r\n\r\n /**\r\n * When true, the framebuffer owns its attachments so they will be destroyed when\r\n * {@link Framebuffer#destroy} is called or when a new attachment is assigned\r\n * to an attachment point.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n *\r\n * @see Framebuffer#destroy\r\n */\r\n this.destroyAttachments = defaultValue(options.destroyAttachments, true);\r\n\r\n // Throw if a texture and renderbuffer are attached to the same point. This won't\r\n // cause a WebGL error (because only one will be attached), but is likely a developer error.\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(options.colorTextures) && defined(options.colorRenderbuffers)) {\r\n throw new DeveloperError(\r\n \"Cannot have both color texture and color renderbuffer attachments.\"\r\n );\r\n }\r\n if (defined(options.depthTexture) && defined(options.depthRenderbuffer)) {\r\n throw new DeveloperError(\r\n \"Cannot have both a depth texture and depth renderbuffer attachment.\"\r\n );\r\n }\r\n if (\r\n defined(options.depthStencilTexture) &&\r\n defined(options.depthStencilRenderbuffer)\r\n ) {\r\n throw new DeveloperError(\r\n \"Cannot have both a depth-stencil texture and depth-stencil renderbuffer attachment.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Avoid errors defined in Section 6.5 of the WebGL spec\r\n var depthAttachment =\r\n defined(options.depthTexture) || defined(options.depthRenderbuffer);\r\n var depthStencilAttachment =\r\n defined(options.depthStencilTexture) ||\r\n defined(options.depthStencilRenderbuffer);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (depthAttachment && depthStencilAttachment) {\r\n throw new DeveloperError(\r\n \"Cannot have both a depth and depth-stencil attachment.\"\r\n );\r\n }\r\n if (defined(options.stencilRenderbuffer) && depthStencilAttachment) {\r\n throw new DeveloperError(\r\n \"Cannot have both a stencil and depth-stencil attachment.\"\r\n );\r\n }\r\n if (depthAttachment && defined(options.stencilRenderbuffer)) {\r\n throw new DeveloperError(\r\n \"Cannot have both a depth and stencil attachment.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n ///////////////////////////////////////////////////////////////////\r\n\r\n this._bind();\r\n\r\n var texture;\r\n var renderbuffer;\r\n var i;\r\n var length;\r\n var attachmentEnum;\r\n\r\n if (defined(options.colorTextures)) {\r\n var textures = options.colorTextures;\r\n length = this._colorTextures.length = this._activeColorAttachments.length =\r\n textures.length;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (length > maximumColorAttachments) {\r\n throw new DeveloperError(\r\n \"The number of color attachments exceeds the number supported.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n for (i = 0; i < length; ++i) {\r\n texture = textures[i];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!PixelFormat.isColorFormat(texture.pixelFormat)) {\r\n throw new DeveloperError(\r\n \"The color-texture pixel-format must be a color format.\"\r\n );\r\n }\r\n if (\r\n texture.pixelDatatype === PixelDatatype.FLOAT &&\r\n !context.colorBufferFloat\r\n ) {\r\n throw new DeveloperError(\r\n \"The color texture pixel datatype is FLOAT and the WebGL implementation does not support the EXT_color_buffer_float or WEBGL_color_buffer_float extensions. See Context.colorBufferFloat.\"\r\n );\r\n }\r\n if (\r\n texture.pixelDatatype === PixelDatatype.HALF_FLOAT &&\r\n !context.colorBufferHalfFloat\r\n ) {\r\n throw new DeveloperError(\r\n \"The color texture pixel datatype is HALF_FLOAT and the WebGL implementation does not support the EXT_color_buffer_half_float extension. See Context.colorBufferHalfFloat.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n attachmentEnum = this._gl.COLOR_ATTACHMENT0 + i;\r\n attachTexture(this, attachmentEnum, texture);\r\n this._activeColorAttachments[i] = attachmentEnum;\r\n this._colorTextures[i] = texture;\r\n }\r\n }\r\n\r\n if (defined(options.colorRenderbuffers)) {\r\n var renderbuffers = options.colorRenderbuffers;\r\n length = this._colorRenderbuffers.length = this._activeColorAttachments.length =\r\n renderbuffers.length;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (length > maximumColorAttachments) {\r\n throw new DeveloperError(\r\n \"The number of color attachments exceeds the number supported.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n for (i = 0; i < length; ++i) {\r\n renderbuffer = renderbuffers[i];\r\n attachmentEnum = this._gl.COLOR_ATTACHMENT0 + i;\r\n attachRenderbuffer(this, attachmentEnum, renderbuffer);\r\n this._activeColorAttachments[i] = attachmentEnum;\r\n this._colorRenderbuffers[i] = renderbuffer;\r\n }\r\n }\r\n\r\n if (defined(options.depthTexture)) {\r\n texture = options.depthTexture;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (texture.pixelFormat !== PixelFormat.DEPTH_COMPONENT) {\r\n throw new DeveloperError(\r\n \"The depth-texture pixel-format must be DEPTH_COMPONENT.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n attachTexture(this, this._gl.DEPTH_ATTACHMENT, texture);\r\n this._depthTexture = texture;\r\n }\r\n\r\n if (defined(options.depthRenderbuffer)) {\r\n renderbuffer = options.depthRenderbuffer;\r\n attachRenderbuffer(this, this._gl.DEPTH_ATTACHMENT, renderbuffer);\r\n this._depthRenderbuffer = renderbuffer;\r\n }\r\n\r\n if (defined(options.stencilRenderbuffer)) {\r\n renderbuffer = options.stencilRenderbuffer;\r\n attachRenderbuffer(this, this._gl.STENCIL_ATTACHMENT, renderbuffer);\r\n this._stencilRenderbuffer = renderbuffer;\r\n }\r\n\r\n if (defined(options.depthStencilTexture)) {\r\n texture = options.depthStencilTexture;\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (texture.pixelFormat !== PixelFormat.DEPTH_STENCIL) {\r\n throw new DeveloperError(\r\n \"The depth-stencil pixel-format must be DEPTH_STENCIL.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n attachTexture(this, this._gl.DEPTH_STENCIL_ATTACHMENT, texture);\r\n this._depthStencilTexture = texture;\r\n }\r\n\r\n if (defined(options.depthStencilRenderbuffer)) {\r\n renderbuffer = options.depthStencilRenderbuffer;\r\n attachRenderbuffer(this, this._gl.DEPTH_STENCIL_ATTACHMENT, renderbuffer);\r\n this._depthStencilRenderbuffer = renderbuffer;\r\n }\r\n\r\n this._unBind();\r\n}\r\n\r\nObject.defineProperties(Framebuffer.prototype, {\r\n /**\r\n * The status of the framebuffer. If the status is not WebGLConstants.FRAMEBUFFER_COMPLETE,\r\n * a {@link DeveloperError} will be thrown when attempting to render to the framebuffer.\r\n * @memberof Framebuffer.prototype\r\n * @type {Number}\r\n */\r\n status: {\r\n get: function () {\r\n this._bind();\r\n var status = this._gl.checkFramebufferStatus(this._gl.FRAMEBUFFER);\r\n this._unBind();\r\n return status;\r\n },\r\n },\r\n numberOfColorAttachments: {\r\n get: function () {\r\n return this._activeColorAttachments.length;\r\n },\r\n },\r\n depthTexture: {\r\n get: function () {\r\n return this._depthTexture;\r\n },\r\n },\r\n depthRenderbuffer: {\r\n get: function () {\r\n return this._depthRenderbuffer;\r\n },\r\n },\r\n stencilRenderbuffer: {\r\n get: function () {\r\n return this._stencilRenderbuffer;\r\n },\r\n },\r\n depthStencilTexture: {\r\n get: function () {\r\n return this._depthStencilTexture;\r\n },\r\n },\r\n depthStencilRenderbuffer: {\r\n get: function () {\r\n return this._depthStencilRenderbuffer;\r\n },\r\n },\r\n\r\n /**\r\n * True if the framebuffer has a depth attachment. Depth attachments include\r\n * depth and depth-stencil textures, and depth and depth-stencil renderbuffers. When\r\n * rendering to a framebuffer, a depth attachment is required for the depth test to have effect.\r\n * @memberof Framebuffer.prototype\r\n * @type {Boolean}\r\n */\r\n hasDepthAttachment: {\r\n get: function () {\r\n return !!(\r\n this.depthTexture ||\r\n this.depthRenderbuffer ||\r\n this.depthStencilTexture ||\r\n this.depthStencilRenderbuffer\r\n );\r\n },\r\n },\r\n});\r\n\r\nFramebuffer.prototype._bind = function () {\r\n var gl = this._gl;\r\n gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffer);\r\n};\r\n\r\nFramebuffer.prototype._unBind = function () {\r\n var gl = this._gl;\r\n gl.bindFramebuffer(gl.FRAMEBUFFER, null);\r\n};\r\n\r\nFramebuffer.prototype._getActiveColorAttachments = function () {\r\n return this._activeColorAttachments;\r\n};\r\n\r\nFramebuffer.prototype.getColorTexture = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index) || index < 0 || index >= this._colorTextures.length) {\r\n throw new DeveloperError(\r\n \"index is required, must be greater than or equal to zero and must be less than the number of color attachments.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._colorTextures[index];\r\n};\r\n\r\nFramebuffer.prototype.getColorRenderbuffer = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n !defined(index) ||\r\n index < 0 ||\r\n index >= this._colorRenderbuffers.length\r\n ) {\r\n throw new DeveloperError(\r\n \"index is required, must be greater than or equal to zero and must be less than the number of color attachments.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._colorRenderbuffers[index];\r\n};\r\n\r\nFramebuffer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nFramebuffer.prototype.destroy = function () {\r\n if (this.destroyAttachments) {\r\n // If the color texture is a cube map face, it is owned by the cube map, and will not be destroyed.\r\n var i = 0;\r\n var textures = this._colorTextures;\r\n var length = textures.length;\r\n for (; i < length; ++i) {\r\n var texture = textures[i];\r\n if (defined(texture)) {\r\n texture.destroy();\r\n }\r\n }\r\n\r\n var renderbuffers = this._colorRenderbuffers;\r\n length = renderbuffers.length;\r\n for (i = 0; i < length; ++i) {\r\n var renderbuffer = renderbuffers[i];\r\n if (defined(renderbuffer)) {\r\n renderbuffer.destroy();\r\n }\r\n }\r\n\r\n this._depthTexture = this._depthTexture && this._depthTexture.destroy();\r\n this._depthRenderbuffer =\r\n this._depthRenderbuffer && this._depthRenderbuffer.destroy();\r\n this._stencilRenderbuffer =\r\n this._stencilRenderbuffer && this._stencilRenderbuffer.destroy();\r\n this._depthStencilTexture =\r\n this._depthStencilTexture && this._depthStencilTexture.destroy();\r\n this._depthStencilRenderbuffer =\r\n this._depthStencilRenderbuffer &&\r\n this._depthStencilRenderbuffer.destroy();\r\n }\r\n\r\n this._gl.deleteFramebuffer(this._framebuffer);\r\n return destroyObject(this);\r\n};\r\nexport default Framebuffer;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#extension GL_EXT_frag_depth : enable\\n\\\nuniform sampler2D u_pointCloud_colorGBuffer;\\n\\\nuniform sampler2D u_pointCloud_depthGBuffer;\\n\\\nuniform vec2 u_distanceAndEdlStrength;\\n\\\nvarying vec2 v_textureCoordinates;\\n\\\nvec2 neighborContribution(float log2Depth, vec2 offset)\\n\\\n{\\n\\\nfloat dist = u_distanceAndEdlStrength.x;\\n\\\nvec2 texCoordOrig = v_textureCoordinates + offset * dist;\\n\\\nvec2 texCoord0 = v_textureCoordinates + offset * floor(dist);\\n\\\nvec2 texCoord1 = v_textureCoordinates + offset * ceil(dist);\\n\\\nfloat depthOrLogDepth0 = czm_unpackDepth(texture2D(u_pointCloud_depthGBuffer, texCoord0));\\n\\\nfloat depthOrLogDepth1 = czm_unpackDepth(texture2D(u_pointCloud_depthGBuffer, texCoord1));\\n\\\nif (depthOrLogDepth0 == 0.0 || depthOrLogDepth1 == 0.0) {\\n\\\nreturn vec2(0.0);\\n\\\n}\\n\\\nfloat depthMix = mix(depthOrLogDepth0, depthOrLogDepth1, fract(dist));\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(texCoordOrig, depthMix);\\n\\\nreturn vec2(max(0.0, log2Depth - log2(-eyeCoordinate.z / eyeCoordinate.w)), 1.0);\\n\\\n}\\n\\\nvoid main()\\n\\\n{\\n\\\nfloat depthOrLogDepth = czm_unpackDepth(texture2D(u_pointCloud_depthGBuffer, v_textureCoordinates));\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, depthOrLogDepth);\\n\\\neyeCoordinate /= eyeCoordinate.w;\\n\\\nfloat log2Depth = log2(-eyeCoordinate.z);\\n\\\nif (depthOrLogDepth == 0.0)\\n\\\n{\\n\\\ndiscard;\\n\\\n}\\n\\\nvec4 color = texture2D(u_pointCloud_colorGBuffer, v_textureCoordinates);\\n\\\nvec2 texelSize = 1.0 / czm_viewport.zw;\\n\\\nvec2 responseAndCount = vec2(0.0);\\n\\\nresponseAndCount += neighborContribution(log2Depth, vec2(-texelSize.x, 0.0));\\n\\\nresponseAndCount += neighborContribution(log2Depth, vec2(+texelSize.x, 0.0));\\n\\\nresponseAndCount += neighborContribution(log2Depth, vec2(0.0, -texelSize.y));\\n\\\nresponseAndCount += neighborContribution(log2Depth, vec2(0.0, +texelSize.y));\\n\\\nfloat response = responseAndCount.x / responseAndCount.y;\\n\\\nfloat strength = u_distanceAndEdlStrength.y;\\n\\\nfloat shade = exp(-response * 300.0 * strength);\\n\\\ncolor.rgb *= shade;\\n\\\ngl_FragColor = vec4(color);\\n\\\ngl_FragDepthEXT = depthOrLogDepth;\\n\\\n}\\n\\\n\";\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport PrimitiveType from \"../Core/PrimitiveType.js\";\r\nimport ClearCommand from \"../Renderer/ClearCommand.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Framebuffer from \"../Renderer/Framebuffer.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport PixelDatatype from \"../Renderer/PixelDatatype.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport Sampler from \"../Renderer/Sampler.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport BlendingState from \"../Scene/BlendingState.js\";\r\nimport StencilConstants from \"../Scene/StencilConstants.js\";\r\nimport PointCloudEyeDomeLightingShader from \"../Shaders/PostProcessStages/PointCloudEyeDomeLighting.js\";\r\n\r\n/**\r\n * Eye dome lighting. Does not support points with per-point translucency, but does allow translucent styling against the globe.\r\n * Requires support for EXT_frag_depth and WEBGL_draw_buffers extensions in WebGL 1.0.\r\n *\r\n * @private\r\n */\r\nfunction PointCloudEyeDomeLighting() {\r\n this._framebuffer = undefined;\r\n this._colorGBuffer = undefined; // color gbuffer\r\n this._depthGBuffer = undefined; // depth gbuffer\r\n this._depthTexture = undefined; // needed to write depth so camera based on depth works\r\n this._drawCommand = undefined;\r\n this._clearCommand = undefined;\r\n\r\n this._strength = 1.0;\r\n this._radius = 1.0;\r\n}\r\n\r\nfunction destroyFramebuffer(processor) {\r\n var framebuffer = processor._framebuffer;\r\n if (!defined(framebuffer)) {\r\n return;\r\n }\r\n\r\n processor._colorGBuffer.destroy();\r\n processor._depthGBuffer.destroy();\r\n processor._depthTexture.destroy();\r\n framebuffer.destroy();\r\n\r\n processor._framebuffer = undefined;\r\n processor._colorGBuffer = undefined;\r\n processor._depthGBuffer = undefined;\r\n processor._depthTexture = undefined;\r\n processor._drawCommand = undefined;\r\n processor._clearCommand = undefined;\r\n}\r\n\r\nfunction createFramebuffer(processor, context) {\r\n var screenWidth = context.drawingBufferWidth;\r\n var screenHeight = context.drawingBufferHeight;\r\n\r\n var colorGBuffer = new Texture({\r\n context: context,\r\n width: screenWidth,\r\n height: screenHeight,\r\n pixelFormat: PixelFormat.RGBA,\r\n pixelDatatype: PixelDatatype.UNSIGNED_BYTE,\r\n sampler: Sampler.NEAREST,\r\n });\r\n\r\n var depthGBuffer = new Texture({\r\n context: context,\r\n width: screenWidth,\r\n height: screenHeight,\r\n pixelFormat: PixelFormat.RGBA,\r\n pixelDatatype: PixelDatatype.UNSIGNED_BYTE,\r\n sampler: Sampler.NEAREST,\r\n });\r\n\r\n var depthTexture = new Texture({\r\n context: context,\r\n width: screenWidth,\r\n height: screenHeight,\r\n pixelFormat: PixelFormat.DEPTH_COMPONENT,\r\n pixelDatatype: PixelDatatype.UNSIGNED_INT,\r\n sampler: Sampler.NEAREST,\r\n });\r\n\r\n processor._framebuffer = new Framebuffer({\r\n context: context,\r\n colorTextures: [colorGBuffer, depthGBuffer],\r\n depthTexture: depthTexture,\r\n destroyAttachments: false,\r\n });\r\n processor._colorGBuffer = colorGBuffer;\r\n processor._depthGBuffer = depthGBuffer;\r\n processor._depthTexture = depthTexture;\r\n}\r\n\r\nvar distanceAndEdlStrengthScratch = new Cartesian2();\r\n\r\nfunction createCommands(processor, context) {\r\n var blendFS = new ShaderSource({\r\n defines: [\"LOG_DEPTH_WRITE\"],\r\n sources: [PointCloudEyeDomeLightingShader],\r\n });\r\n\r\n var blendUniformMap = {\r\n u_pointCloud_colorGBuffer: function () {\r\n return processor._colorGBuffer;\r\n },\r\n u_pointCloud_depthGBuffer: function () {\r\n return processor._depthGBuffer;\r\n },\r\n u_distanceAndEdlStrength: function () {\r\n distanceAndEdlStrengthScratch.x = processor._radius;\r\n distanceAndEdlStrengthScratch.y = processor._strength;\r\n return distanceAndEdlStrengthScratch;\r\n },\r\n };\r\n\r\n var blendRenderState = RenderState.fromCache({\r\n blending: BlendingState.ALPHA_BLEND,\r\n depthMask: true,\r\n depthTest: {\r\n enabled: true,\r\n },\r\n stencilTest: StencilConstants.setCesium3DTileBit(),\r\n stencilMask: StencilConstants.CESIUM_3D_TILE_MASK,\r\n });\r\n\r\n processor._drawCommand = context.createViewportQuadCommand(blendFS, {\r\n uniformMap: blendUniformMap,\r\n renderState: blendRenderState,\r\n pass: Pass.CESIUM_3D_TILE,\r\n owner: processor,\r\n });\r\n\r\n processor._clearCommand = new ClearCommand({\r\n framebuffer: processor._framebuffer,\r\n color: new Color(0.0, 0.0, 0.0, 0.0),\r\n depth: 1.0,\r\n renderState: RenderState.fromCache(),\r\n pass: Pass.CESIUM_3D_TILE,\r\n owner: processor,\r\n });\r\n}\r\n\r\nfunction createResources(processor, context) {\r\n var screenWidth = context.drawingBufferWidth;\r\n var screenHeight = context.drawingBufferHeight;\r\n var colorGBuffer = processor._colorGBuffer;\r\n var nowDirty = false;\r\n var resized =\r\n defined(colorGBuffer) &&\r\n (colorGBuffer.width !== screenWidth ||\r\n colorGBuffer.height !== screenHeight);\r\n\r\n if (!defined(colorGBuffer) || resized) {\r\n destroyFramebuffer(processor);\r\n createFramebuffer(processor, context);\r\n createCommands(processor, context);\r\n nowDirty = true;\r\n }\r\n return nowDirty;\r\n}\r\n\r\nfunction isSupported(context) {\r\n return context.drawBuffers && context.fragmentDepth;\r\n}\r\n\r\nPointCloudEyeDomeLighting.isSupported = isSupported;\r\n\r\nfunction getECShaderProgram(context, shaderProgram) {\r\n var shader = context.shaderCache.getDerivedShaderProgram(shaderProgram, \"EC\");\r\n if (!defined(shader)) {\r\n var attributeLocations = shaderProgram._attributeLocations;\r\n\r\n var fs = shaderProgram.fragmentShaderSource.clone();\r\n\r\n fs.sources = fs.sources.map(function (source) {\r\n source = ShaderSource.replaceMain(\r\n source,\r\n \"czm_point_cloud_post_process_main\"\r\n );\r\n source = source.replace(/gl_FragColor/g, \"gl_FragData[0]\");\r\n return source;\r\n });\r\n\r\n fs.sources.unshift(\"#extension GL_EXT_draw_buffers : enable \\n\");\r\n fs.sources.push(\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" czm_point_cloud_post_process_main(); \\n\" +\r\n \"#ifdef LOG_DEPTH\\n\" +\r\n \" czm_writeLogDepth();\\n\" +\r\n \" gl_FragData[1] = czm_packDepth(gl_FragDepthEXT); \\n\" +\r\n \"#else\\n\" +\r\n \" gl_FragData[1] = czm_packDepth(gl_FragCoord.z);\\n\" +\r\n \"#endif\\n\" +\r\n \"}\"\r\n );\r\n\r\n shader = context.shaderCache.createDerivedShaderProgram(\r\n shaderProgram,\r\n \"EC\",\r\n {\r\n vertexShaderSource: shaderProgram.vertexShaderSource,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n }\r\n );\r\n }\r\n\r\n return shader;\r\n}\r\n\r\nPointCloudEyeDomeLighting.prototype.update = function (\r\n frameState,\r\n commandStart,\r\n pointCloudShading,\r\n boundingVolume\r\n) {\r\n if (!isSupported(frameState.context)) {\r\n return;\r\n }\r\n\r\n this._strength = pointCloudShading.eyeDomeLightingStrength;\r\n this._radius =\r\n pointCloudShading.eyeDomeLightingRadius * frameState.pixelRatio;\r\n\r\n var dirty = createResources(this, frameState.context);\r\n\r\n // Hijack existing point commands to render into an offscreen FBO.\r\n var i;\r\n var commandList = frameState.commandList;\r\n var commandEnd = commandList.length;\r\n\r\n for (i = commandStart; i < commandEnd; ++i) {\r\n var command = commandList[i];\r\n if (\r\n command.primitiveType !== PrimitiveType.POINTS ||\r\n command.pass === Pass.TRANSLUCENT\r\n ) {\r\n continue;\r\n }\r\n var derivedCommand = command.derivedCommands.pointCloudProcessor;\r\n if (\r\n !defined(derivedCommand) ||\r\n command.dirty ||\r\n dirty ||\r\n derivedCommand.framebuffer !== this._framebuffer\r\n ) {\r\n // Prevent crash when tiles out-of-view come in-view during context size change\r\n derivedCommand = DrawCommand.shallowClone(command);\r\n command.derivedCommands.pointCloudProcessor = derivedCommand;\r\n\r\n derivedCommand.framebuffer = this._framebuffer;\r\n derivedCommand.shaderProgram = getECShaderProgram(\r\n frameState.context,\r\n command.shaderProgram\r\n );\r\n derivedCommand.castShadows = false;\r\n derivedCommand.receiveShadows = false;\r\n }\r\n\r\n commandList[i] = derivedCommand;\r\n }\r\n\r\n var clearCommand = this._clearCommand;\r\n var blendCommand = this._drawCommand;\r\n\r\n blendCommand.boundingVolume = boundingVolume;\r\n\r\n // Blend EDL into the main FBO\r\n commandList.push(blendCommand);\r\n commandList.push(clearCommand);\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see PointCloudEyeDomeLighting#destroy\r\n */\r\nPointCloudEyeDomeLighting.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * processor = processor && processor.destroy();\r\n *\r\n * @see PointCloudEyeDomeLighting#isDestroyed\r\n */\r\nPointCloudEyeDomeLighting.prototype.destroy = function () {\r\n destroyFramebuffer(this);\r\n return destroyObject(this);\r\n};\r\nexport default PointCloudEyeDomeLighting;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport PointCloudEyeDomeLighting from \"./PointCloudEyeDomeLighting.js\";\r\n\r\n/**\r\n * Options for performing point attenuation based on geometric error when rendering\r\n * point clouds using 3D Tiles.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.attenuation=false] Perform point attenuation based on geometric error.\r\n * @param {Number} [options.geometricErrorScale=1.0] Scale to be applied to each tile's geometric error.\r\n * @param {Number} [options.maximumAttenuation] Maximum attenuation in pixels. Defaults to the Cesium3DTileset's maximumScreenSpaceError.\r\n * @param {Number} [options.baseResolution] Average base resolution for the dataset in meters. Substitute for Geometric Error when not available.\r\n * @param {Boolean} [options.eyeDomeLighting=true] When true, use eye dome lighting when drawing with point attenuation.\r\n * @param {Number} [options.eyeDomeLightingStrength=1.0] Increasing this value increases contrast on slopes and edges.\r\n * @param {Number} [options.eyeDomeLightingRadius=1.0] Increase the thickness of contours from eye dome lighting.\r\n * @param {Boolean} [options.backFaceCulling=false] Determines whether back-facing points are hidden. This option works only if data has normals included.\r\n * @param {Boolean} [options.normalShading=true] Determines whether a point cloud that contains normals is shaded by the scene's light source.\r\n *\r\n * @alias PointCloudShading\r\n * @constructor\r\n */\r\nfunction PointCloudShading(options) {\r\n var pointCloudShading = defaultValue(options, {});\r\n\r\n /**\r\n * Perform point attenuation based on geometric error.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.attenuation = defaultValue(pointCloudShading.attenuation, false);\r\n\r\n /**\r\n * Scale to be applied to the geometric error before computing attenuation.\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.geometricErrorScale = defaultValue(\r\n pointCloudShading.geometricErrorScale,\r\n 1.0\r\n );\r\n\r\n /**\r\n * Maximum point attenuation in pixels. If undefined, the Cesium3DTileset's maximumScreenSpaceError will be used.\r\n * @type {Number}\r\n */\r\n this.maximumAttenuation = pointCloudShading.maximumAttenuation;\r\n\r\n /**\r\n * Average base resolution for the dataset in meters.\r\n * Used in place of geometric error when geometric error is 0.\r\n * If undefined, an approximation will be computed for each tile that has geometric error of 0.\r\n * @type {Number}\r\n */\r\n this.baseResolution = pointCloudShading.baseResolution;\r\n\r\n /**\r\n * Use eye dome lighting when drawing with point attenuation\r\n * Requires support for EXT_frag_depth, OES_texture_float, and WEBGL_draw_buffers extensions in WebGL 1.0,\r\n * otherwise eye dome lighting is ignored.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.eyeDomeLighting = defaultValue(pointCloudShading.eyeDomeLighting, true);\r\n\r\n /**\r\n * Eye dome lighting strength (apparent contrast)\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.eyeDomeLightingStrength = defaultValue(\r\n pointCloudShading.eyeDomeLightingStrength,\r\n 1.0\r\n );\r\n\r\n /**\r\n * Thickness of contours from eye dome lighting\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n this.eyeDomeLightingRadius = defaultValue(\r\n pointCloudShading.eyeDomeLightingRadius,\r\n 1.0\r\n );\r\n\r\n /**\r\n * Determines whether back-facing points are hidden.\r\n * This option works only if data has normals included.\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.backFaceCulling = defaultValue(pointCloudShading.backFaceCulling, false);\r\n\r\n /**\r\n * Determines whether a point cloud that contains normals is shaded by the scene's light source.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.normalShading = defaultValue(pointCloudShading.normalShading, true);\r\n}\r\n\r\n/**\r\n * Determines if point cloud shading is supported.\r\n *\r\n * @param {Scene} scene The scene.\r\n * @returns {Boolean} true if point cloud shading is supported; otherwise, returns false\r\n */\r\nPointCloudShading.isSupported = function (scene) {\r\n return PointCloudEyeDomeLighting.isSupported(scene.context);\r\n};\r\nexport default PointCloudShading;\r\n","import Color from \"../Core/Color.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport Cesium3DTileBatchTable from \"./Cesium3DTileBatchTable.js\";\r\nimport Cesium3DTileFeature from \"./Cesium3DTileFeature.js\";\r\nimport Cesium3DTileRefine from \"./Cesium3DTileRefine.js\";\r\nimport PointCloud from \"./PointCloud.js\";\r\nimport PointCloudShading from \"./PointCloudShading.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\n\r\n/**\r\n * Represents the contents of a\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/TileFormats/PointCloud|Point Cloud}\r\n * tile in a {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles} tileset.\r\n *

\r\n * Implements the {@link Cesium3DTileContent} interface.\r\n *

\r\n *\r\n * @alias PointCloud3DTileContent\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction PointCloud3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n) {\r\n this._tileset = tileset;\r\n this._tile = tile;\r\n this._resource = resource;\r\n this._pickId = undefined; // Only defined when batchTable is undefined\r\n this._batchTable = undefined; // Used when feature table contains BATCH_ID semantic\r\n this._styleDirty = false;\r\n this._features = undefined;\r\n this.featurePropertiesDirty = false;\r\n\r\n this._pointCloud = new PointCloud({\r\n arrayBuffer: arrayBuffer,\r\n byteOffset: byteOffset,\r\n cull: false,\r\n opaquePass: Pass.CESIUM_3D_TILE,\r\n vertexShaderLoaded: getVertexShaderLoaded(this),\r\n fragmentShaderLoaded: getFragmentShaderLoaded(this),\r\n uniformMapLoaded: getUniformMapLoaded(this),\r\n batchTableLoaded: getBatchTableLoaded(this),\r\n pickIdLoaded: getPickIdLoaded(this),\r\n });\r\n}\r\n\r\nObject.defineProperties(PointCloud3DTileContent.prototype, {\r\n featuresLength: {\r\n get: function () {\r\n if (defined(this._batchTable)) {\r\n return this._batchTable.featuresLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n pointsLength: {\r\n get: function () {\r\n return this._pointCloud.pointsLength;\r\n },\r\n },\r\n\r\n trianglesLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n geometryByteLength: {\r\n get: function () {\r\n return this._pointCloud.geometryByteLength;\r\n },\r\n },\r\n\r\n texturesByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n batchTableByteLength: {\r\n get: function () {\r\n if (defined(this._batchTable)) {\r\n return this._batchTable.memorySizeInBytes;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n innerContents: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return this._pointCloud.readyPromise;\r\n },\r\n },\r\n\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n tile: {\r\n get: function () {\r\n return this._tile;\r\n },\r\n },\r\n\r\n url: {\r\n get: function () {\r\n return this._resource.getUrlComponent(true);\r\n },\r\n },\r\n\r\n batchTable: {\r\n get: function () {\r\n return this._batchTable;\r\n },\r\n },\r\n});\r\n\r\nfunction getVertexShaderLoaded(content) {\r\n return function (vs) {\r\n if (defined(content._batchTable)) {\r\n return content._batchTable.getVertexShaderCallback(\r\n false,\r\n \"a_batchId\",\r\n undefined\r\n )(vs);\r\n }\r\n return vs;\r\n };\r\n}\r\n\r\nfunction getFragmentShaderLoaded(content) {\r\n return function (fs) {\r\n if (defined(content._batchTable)) {\r\n return content._batchTable.getFragmentShaderCallback(\r\n false,\r\n undefined,\r\n false\r\n )(fs);\r\n }\r\n return \"uniform vec4 czm_pickColor;\\n\" + fs;\r\n };\r\n}\r\n\r\nfunction getUniformMapLoaded(content) {\r\n return function (uniformMap) {\r\n if (defined(content._batchTable)) {\r\n return content._batchTable.getUniformMapCallback()(uniformMap);\r\n }\r\n return combine(uniformMap, {\r\n czm_pickColor: function () {\r\n return content._pickId.color;\r\n },\r\n });\r\n };\r\n}\r\n\r\nfunction getBatchTableLoaded(content) {\r\n return function (batchLength, batchTableJson, batchTableBinary) {\r\n content._batchTable = new Cesium3DTileBatchTable(\r\n content,\r\n batchLength,\r\n batchTableJson,\r\n batchTableBinary\r\n );\r\n };\r\n}\r\n\r\nfunction getPickIdLoaded(content) {\r\n return function () {\r\n return defined(content._batchTable)\r\n ? content._batchTable.getPickId()\r\n : \"czm_pickColor\";\r\n };\r\n}\r\n\r\nfunction getGeometricError(content) {\r\n var pointCloudShading = content._tileset.pointCloudShading;\r\n var sphereVolume = content._tile.contentBoundingVolume.boundingSphere.volume();\r\n var baseResolutionApproximation = CesiumMath.cbrt(\r\n sphereVolume / content.pointsLength\r\n );\r\n\r\n var geometricError = content._tile.geometricError;\r\n if (geometricError === 0) {\r\n if (\r\n defined(pointCloudShading) &&\r\n defined(pointCloudShading.baseResolution)\r\n ) {\r\n geometricError = pointCloudShading.baseResolution;\r\n } else {\r\n geometricError = baseResolutionApproximation;\r\n }\r\n }\r\n return geometricError;\r\n}\r\n\r\nfunction createFeatures(content) {\r\n var featuresLength = content.featuresLength;\r\n if (!defined(content._features) && featuresLength > 0) {\r\n var features = new Array(featuresLength);\r\n for (var i = 0; i < featuresLength; ++i) {\r\n features[i] = new Cesium3DTileFeature(content, i);\r\n }\r\n content._features = features;\r\n }\r\n}\r\n\r\nPointCloud3DTileContent.prototype.hasProperty = function (batchId, name) {\r\n if (defined(this._batchTable)) {\r\n return this._batchTable.hasProperty(batchId, name);\r\n }\r\n return false;\r\n};\r\n\r\n/**\r\n * Part of the {@link Cesium3DTileContent} interface.\r\n *\r\n * In this context a feature refers to a group of points that share the same BATCH_ID.\r\n * For example all the points that represent a door in a house point cloud would be a feature.\r\n *\r\n * Features are backed by a batch table and can be colored, shown/hidden, picked, etc like features\r\n * in b3dm and i3dm.\r\n *\r\n * When the BATCH_ID semantic is omitted and the point cloud stores per-point properties, they\r\n * are not accessible by getFeature. They are only used for dynamic styling.\r\n */\r\nPointCloud3DTileContent.prototype.getFeature = function (batchId) {\r\n if (!defined(this._batchTable)) {\r\n return undefined;\r\n }\r\n var featuresLength = this.featuresLength;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(batchId) || batchId < 0 || batchId >= featuresLength) {\r\n throw new DeveloperError(\r\n \"batchId is required and between zero and featuresLength - 1 (\" +\r\n (featuresLength - 1) +\r\n \").\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n createFeatures(this);\r\n return this._features[batchId];\r\n};\r\n\r\nPointCloud3DTileContent.prototype.applyDebugSettings = function (\r\n enabled,\r\n color\r\n) {\r\n this._pointCloud.color = enabled ? color : Color.WHITE;\r\n};\r\n\r\nPointCloud3DTileContent.prototype.applyStyle = function (style) {\r\n if (defined(this._batchTable)) {\r\n this._batchTable.applyStyle(style);\r\n } else {\r\n this._styleDirty = true;\r\n }\r\n};\r\n\r\nvar defaultShading = new PointCloudShading();\r\n\r\nPointCloud3DTileContent.prototype.update = function (tileset, frameState) {\r\n var pointCloud = this._pointCloud;\r\n var pointCloudShading = defaultValue(\r\n tileset.pointCloudShading,\r\n defaultShading\r\n );\r\n var tile = this._tile;\r\n var batchTable = this._batchTable;\r\n var mode = frameState.mode;\r\n var clippingPlanes = tileset.clippingPlanes;\r\n\r\n if (!defined(this._pickId) && !defined(batchTable)) {\r\n this._pickId = frameState.context.createPickId({\r\n primitive: tileset,\r\n content: this,\r\n });\r\n }\r\n\r\n if (defined(batchTable)) {\r\n batchTable.update(tileset, frameState);\r\n }\r\n\r\n var boundingSphere;\r\n if (defined(tile._contentBoundingVolume)) {\r\n boundingSphere =\r\n mode === SceneMode.SCENE3D\r\n ? tile._contentBoundingVolume.boundingSphere\r\n : tile._contentBoundingVolume2D.boundingSphere;\r\n } else {\r\n boundingSphere =\r\n mode === SceneMode.SCENE3D\r\n ? tile._boundingVolume.boundingSphere\r\n : tile._boundingVolume2D.boundingSphere;\r\n }\r\n\r\n var styleDirty = this._styleDirty;\r\n this._styleDirty = false;\r\n\r\n pointCloud.clippingPlanesOriginMatrix = tileset.clippingPlanesOriginMatrix;\r\n pointCloud.style = defined(batchTable) ? undefined : tileset.style;\r\n pointCloud.styleDirty = styleDirty;\r\n pointCloud.modelMatrix = tile.computedTransform;\r\n pointCloud.time = tileset.timeSinceLoad;\r\n pointCloud.shadows = tileset.shadows;\r\n pointCloud.boundingSphere = boundingSphere;\r\n pointCloud.clippingPlanes = clippingPlanes;\r\n pointCloud.isClipped =\r\n defined(clippingPlanes) && clippingPlanes.enabled && tile._isClipped;\r\n pointCloud.clippingPlanesDirty = tile.clippingPlanesDirty;\r\n pointCloud.attenuation = pointCloudShading.attenuation;\r\n pointCloud.backFaceCulling = pointCloudShading.backFaceCulling;\r\n pointCloud.normalShading = pointCloudShading.normalShading;\r\n pointCloud.geometricError = getGeometricError(this);\r\n pointCloud.geometricErrorScale = pointCloudShading.geometricErrorScale;\r\n if (\r\n defined(pointCloudShading) &&\r\n defined(pointCloudShading.maximumAttenuation)\r\n ) {\r\n pointCloud.maximumAttenuation = pointCloudShading.maximumAttenuation;\r\n } else if (tile.refine === Cesium3DTileRefine.ADD) {\r\n pointCloud.maximumAttenuation = 5.0;\r\n } else {\r\n pointCloud.maximumAttenuation = tileset.maximumScreenSpaceError;\r\n }\r\n\r\n pointCloud.update(frameState);\r\n};\r\n\r\nPointCloud3DTileContent.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nPointCloud3DTileContent.prototype.destroy = function () {\r\n this._pickId = this._pickId && this._pickId.destroy();\r\n this._pointCloud = this._pointCloud && this._pointCloud.destroy();\r\n this._batchTable = this._batchTable && this._batchTable.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default PointCloud3DTileContent;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport getJsonFromTypedArray from \"../Core/getJsonFromTypedArray.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\n\r\n/**\r\n * Represents content for a tile in a\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles} tileset whose\r\n * content points to another 3D Tiles tileset.\r\n *

\r\n * Implements the {@link Cesium3DTileContent} interface.\r\n *

\r\n *\r\n * @alias Tileset3DTileContent\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction Tileset3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n) {\r\n this._tileset = tileset;\r\n this._tile = tile;\r\n this._resource = resource;\r\n this._readyPromise = when.defer();\r\n\r\n this.featurePropertiesDirty = false;\r\n\r\n initialize(this, arrayBuffer, byteOffset);\r\n}\r\n\r\nObject.defineProperties(Tileset3DTileContent.prototype, {\r\n featuresLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n pointsLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n trianglesLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n geometryByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n texturesByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n batchTableByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n innerContents: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n tile: {\r\n get: function () {\r\n return this._tile;\r\n },\r\n },\r\n\r\n url: {\r\n get: function () {\r\n return this._resource.getUrlComponent(true);\r\n },\r\n },\r\n\r\n batchTable: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n});\r\n\r\nfunction initialize(content, arrayBuffer, byteOffset) {\r\n byteOffset = defaultValue(byteOffset, 0);\r\n var uint8Array = new Uint8Array(arrayBuffer);\r\n var tilesetJson;\r\n\r\n try {\r\n tilesetJson = getJsonFromTypedArray(uint8Array, byteOffset);\r\n } catch (error) {\r\n content._readyPromise.reject(new RuntimeError(\"Invalid tile content.\"));\r\n return;\r\n }\r\n\r\n content._tileset.loadTileset(content._resource, tilesetJson, content._tile);\r\n content._readyPromise.resolve(content);\r\n}\r\n\r\n/**\r\n * Part of the {@link Cesium3DTileContent} interface. Tileset3DTileContent\r\n * always returns false since a tile of this type does not have any features.\r\n */\r\nTileset3DTileContent.prototype.hasProperty = function (batchId, name) {\r\n return false;\r\n};\r\n\r\n/**\r\n * Part of the {@link Cesium3DTileContent} interface. Tileset3DTileContent\r\n * always returns undefined since a tile of this type does not have any features.\r\n */\r\nTileset3DTileContent.prototype.getFeature = function (batchId) {\r\n return undefined;\r\n};\r\n\r\nTileset3DTileContent.prototype.applyDebugSettings = function (\r\n enabled,\r\n color\r\n) {};\r\n\r\nTileset3DTileContent.prototype.applyStyle = function (style) {};\r\n\r\nTileset3DTileContent.prototype.update = function (tileset, frameState) {};\r\n\r\nTileset3DTileContent.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nTileset3DTileContent.prototype.destroy = function () {\r\n return destroyObject(this);\r\n};\r\nexport default Tileset3DTileContent;\r\n","import Check from \"../Core/Check.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Buffer from \"./Buffer.js\";\r\nimport BufferUsage from \"./BufferUsage.js\";\r\nimport VertexArray from \"./VertexArray.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction VertexArrayFacade(context, attributes, sizeInVertices, instanced) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"context\", context);\r\n if (!attributes || attributes.length === 0) {\r\n throw new DeveloperError(\"At least one attribute is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var attrs = VertexArrayFacade._verifyAttributes(attributes);\r\n sizeInVertices = defaultValue(sizeInVertices, 0);\r\n var precreatedAttributes = [];\r\n var attributesByUsage = {};\r\n var attributesForUsage;\r\n var usage;\r\n\r\n // Bucket the attributes by usage.\r\n var length = attrs.length;\r\n for (var i = 0; i < length; ++i) {\r\n var attribute = attrs[i];\r\n\r\n // If the attribute already has a vertex buffer, we do not need\r\n // to manage a vertex buffer or typed array for it.\r\n if (attribute.vertexBuffer) {\r\n precreatedAttributes.push(attribute);\r\n continue;\r\n }\r\n\r\n usage = attribute.usage;\r\n attributesForUsage = attributesByUsage[usage];\r\n if (!defined(attributesForUsage)) {\r\n attributesForUsage = attributesByUsage[usage] = [];\r\n }\r\n\r\n attributesForUsage.push(attribute);\r\n }\r\n\r\n // A function to sort attributes by the size of their components. From left to right, a vertex\r\n // stores floats, shorts, and then bytes.\r\n function compare(left, right) {\r\n return (\r\n ComponentDatatype.getSizeInBytes(right.componentDatatype) -\r\n ComponentDatatype.getSizeInBytes(left.componentDatatype)\r\n );\r\n }\r\n\r\n this._allBuffers = [];\r\n\r\n for (usage in attributesByUsage) {\r\n if (attributesByUsage.hasOwnProperty(usage)) {\r\n attributesForUsage = attributesByUsage[usage];\r\n\r\n attributesForUsage.sort(compare);\r\n var vertexSizeInBytes = VertexArrayFacade._vertexSizeInBytes(\r\n attributesForUsage\r\n );\r\n\r\n var bufferUsage = attributesForUsage[0].usage;\r\n\r\n var buffer = {\r\n vertexSizeInBytes: vertexSizeInBytes,\r\n vertexBuffer: undefined,\r\n usage: bufferUsage,\r\n needsCommit: false,\r\n arrayBuffer: undefined,\r\n arrayViews: VertexArrayFacade._createArrayViews(\r\n attributesForUsage,\r\n vertexSizeInBytes\r\n ),\r\n };\r\n\r\n this._allBuffers.push(buffer);\r\n }\r\n }\r\n\r\n this._size = 0;\r\n this._instanced = defaultValue(instanced, false);\r\n\r\n this._precreated = precreatedAttributes;\r\n this._context = context;\r\n\r\n this.writers = undefined;\r\n this.va = undefined;\r\n\r\n this.resize(sizeInVertices);\r\n}\r\nVertexArrayFacade._verifyAttributes = function (attributes) {\r\n var attrs = [];\r\n\r\n for (var i = 0; i < attributes.length; ++i) {\r\n var attribute = attributes[i];\r\n\r\n var attr = {\r\n index: defaultValue(attribute.index, i),\r\n enabled: defaultValue(attribute.enabled, true),\r\n componentsPerAttribute: attribute.componentsPerAttribute,\r\n componentDatatype: defaultValue(\r\n attribute.componentDatatype,\r\n ComponentDatatype.FLOAT\r\n ),\r\n normalize: defaultValue(attribute.normalize, false),\r\n\r\n // There will be either a vertexBuffer or an [optional] usage.\r\n vertexBuffer: attribute.vertexBuffer,\r\n usage: defaultValue(attribute.usage, BufferUsage.STATIC_DRAW),\r\n };\r\n attrs.push(attr);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n attr.componentsPerAttribute !== 1 &&\r\n attr.componentsPerAttribute !== 2 &&\r\n attr.componentsPerAttribute !== 3 &&\r\n attr.componentsPerAttribute !== 4\r\n ) {\r\n throw new DeveloperError(\r\n \"attribute.componentsPerAttribute must be in the range [1, 4].\"\r\n );\r\n }\r\n\r\n var datatype = attr.componentDatatype;\r\n if (!ComponentDatatype.validate(datatype)) {\r\n throw new DeveloperError(\r\n \"Attribute must have a valid componentDatatype or not specify it.\"\r\n );\r\n }\r\n\r\n if (!BufferUsage.validate(attr.usage)) {\r\n throw new DeveloperError(\r\n \"Attribute must have a valid usage or not specify it.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n }\r\n\r\n // Verify all attribute names are unique.\r\n var uniqueIndices = new Array(attrs.length);\r\n for (var j = 0; j < attrs.length; ++j) {\r\n var currentAttr = attrs[j];\r\n var index = currentAttr.index;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (uniqueIndices[index]) {\r\n throw new DeveloperError(\r\n \"Index \" + index + \" is used by more than one attribute.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n uniqueIndices[index] = true;\r\n }\r\n\r\n return attrs;\r\n};\r\n\r\nVertexArrayFacade._vertexSizeInBytes = function (attributes) {\r\n var sizeInBytes = 0;\r\n\r\n var length = attributes.length;\r\n for (var i = 0; i < length; ++i) {\r\n var attribute = attributes[i];\r\n sizeInBytes +=\r\n attribute.componentsPerAttribute *\r\n ComponentDatatype.getSizeInBytes(attribute.componentDatatype);\r\n }\r\n\r\n var maxComponentSizeInBytes =\r\n length > 0\r\n ? ComponentDatatype.getSizeInBytes(attributes[0].componentDatatype)\r\n : 0; // Sorted by size\r\n var remainder =\r\n maxComponentSizeInBytes > 0 ? sizeInBytes % maxComponentSizeInBytes : 0;\r\n var padding = remainder === 0 ? 0 : maxComponentSizeInBytes - remainder;\r\n sizeInBytes += padding;\r\n\r\n return sizeInBytes;\r\n};\r\n\r\nVertexArrayFacade._createArrayViews = function (attributes, vertexSizeInBytes) {\r\n var views = [];\r\n var offsetInBytes = 0;\r\n\r\n var length = attributes.length;\r\n for (var i = 0; i < length; ++i) {\r\n var attribute = attributes[i];\r\n var componentDatatype = attribute.componentDatatype;\r\n\r\n views.push({\r\n index: attribute.index,\r\n enabled: attribute.enabled,\r\n componentsPerAttribute: attribute.componentsPerAttribute,\r\n componentDatatype: componentDatatype,\r\n normalize: attribute.normalize,\r\n\r\n offsetInBytes: offsetInBytes,\r\n vertexSizeInComponentType:\r\n vertexSizeInBytes / ComponentDatatype.getSizeInBytes(componentDatatype),\r\n\r\n view: undefined,\r\n });\r\n\r\n offsetInBytes +=\r\n attribute.componentsPerAttribute *\r\n ComponentDatatype.getSizeInBytes(componentDatatype);\r\n }\r\n\r\n return views;\r\n};\r\n\r\n/**\r\n * Invalidates writers. Can't render again until commit is called.\r\n */\r\nVertexArrayFacade.prototype.resize = function (sizeInVertices) {\r\n this._size = sizeInVertices;\r\n\r\n var allBuffers = this._allBuffers;\r\n this.writers = [];\r\n\r\n for (var i = 0, len = allBuffers.length; i < len; ++i) {\r\n var buffer = allBuffers[i];\r\n\r\n VertexArrayFacade._resize(buffer, this._size);\r\n\r\n // Reserving invalidates the writers, so if client's cache them, they need to invalidate their cache.\r\n VertexArrayFacade._appendWriters(this.writers, buffer);\r\n }\r\n\r\n // VAs are recreated next time commit is called.\r\n destroyVA(this);\r\n};\r\n\r\nVertexArrayFacade._resize = function (buffer, size) {\r\n if (buffer.vertexSizeInBytes > 0) {\r\n // Create larger array buffer\r\n var arrayBuffer = new ArrayBuffer(size * buffer.vertexSizeInBytes);\r\n\r\n // Copy contents from previous array buffer\r\n if (defined(buffer.arrayBuffer)) {\r\n var destView = new Uint8Array(arrayBuffer);\r\n var sourceView = new Uint8Array(buffer.arrayBuffer);\r\n var sourceLength = sourceView.length;\r\n for (var j = 0; j < sourceLength; ++j) {\r\n destView[j] = sourceView[j];\r\n }\r\n }\r\n\r\n // Create typed views into the new array buffer\r\n var views = buffer.arrayViews;\r\n var length = views.length;\r\n for (var i = 0; i < length; ++i) {\r\n var view = views[i];\r\n view.view = ComponentDatatype.createArrayBufferView(\r\n view.componentDatatype,\r\n arrayBuffer,\r\n view.offsetInBytes\r\n );\r\n }\r\n\r\n buffer.arrayBuffer = arrayBuffer;\r\n }\r\n};\r\n\r\nvar createWriters = [\r\n // 1 component per attribute\r\n function (buffer, view, vertexSizeInComponentType) {\r\n return function (index, attribute) {\r\n view[index * vertexSizeInComponentType] = attribute;\r\n buffer.needsCommit = true;\r\n };\r\n },\r\n\r\n // 2 component per attribute\r\n function (buffer, view, vertexSizeInComponentType) {\r\n return function (index, component0, component1) {\r\n var i = index * vertexSizeInComponentType;\r\n view[i] = component0;\r\n view[i + 1] = component1;\r\n buffer.needsCommit = true;\r\n };\r\n },\r\n\r\n // 3 component per attribute\r\n function (buffer, view, vertexSizeInComponentType) {\r\n return function (index, component0, component1, component2) {\r\n var i = index * vertexSizeInComponentType;\r\n view[i] = component0;\r\n view[i + 1] = component1;\r\n view[i + 2] = component2;\r\n buffer.needsCommit = true;\r\n };\r\n },\r\n\r\n // 4 component per attribute\r\n function (buffer, view, vertexSizeInComponentType) {\r\n return function (index, component0, component1, component2, component3) {\r\n var i = index * vertexSizeInComponentType;\r\n view[i] = component0;\r\n view[i + 1] = component1;\r\n view[i + 2] = component2;\r\n view[i + 3] = component3;\r\n buffer.needsCommit = true;\r\n };\r\n },\r\n];\r\n\r\nVertexArrayFacade._appendWriters = function (writers, buffer) {\r\n var arrayViews = buffer.arrayViews;\r\n var length = arrayViews.length;\r\n for (var i = 0; i < length; ++i) {\r\n var arrayView = arrayViews[i];\r\n writers[arrayView.index] = createWriters[\r\n arrayView.componentsPerAttribute - 1\r\n ](buffer, arrayView.view, arrayView.vertexSizeInComponentType);\r\n }\r\n};\r\n\r\nVertexArrayFacade.prototype.commit = function (indexBuffer) {\r\n var recreateVA = false;\r\n\r\n var allBuffers = this._allBuffers;\r\n var buffer;\r\n var i;\r\n var length;\r\n\r\n for (i = 0, length = allBuffers.length; i < length; ++i) {\r\n buffer = allBuffers[i];\r\n recreateVA = commit(this, buffer) || recreateVA;\r\n }\r\n\r\n ///////////////////////////////////////////////////////////////////////\r\n\r\n if (recreateVA || !defined(this.va)) {\r\n destroyVA(this);\r\n var va = (this.va = []);\r\n\r\n var chunkSize = CesiumMath.SIXTY_FOUR_KILOBYTES - 4; // The 65535 index is reserved for primitive restart. Reserve the last 4 indices so that billboard quads are not broken up.\r\n var numberOfVertexArrays =\r\n defined(indexBuffer) && !this._instanced\r\n ? Math.ceil(this._size / chunkSize)\r\n : 1;\r\n for (var k = 0; k < numberOfVertexArrays; ++k) {\r\n var attributes = [];\r\n for (i = 0, length = allBuffers.length; i < length; ++i) {\r\n buffer = allBuffers[i];\r\n var offset = k * (buffer.vertexSizeInBytes * chunkSize);\r\n VertexArrayFacade._appendAttributes(\r\n attributes,\r\n buffer,\r\n offset,\r\n this._instanced\r\n );\r\n }\r\n\r\n attributes = attributes.concat(this._precreated);\r\n\r\n va.push({\r\n va: new VertexArray({\r\n context: this._context,\r\n attributes: attributes,\r\n indexBuffer: indexBuffer,\r\n }),\r\n indicesCount:\r\n 1.5 *\r\n (k !== numberOfVertexArrays - 1 ? chunkSize : this._size % chunkSize),\r\n // TODO: not hardcode 1.5, this assumes 6 indices per 4 vertices (as for Billboard quads).\r\n });\r\n }\r\n }\r\n};\r\n\r\nfunction commit(vertexArrayFacade, buffer) {\r\n if (buffer.needsCommit && buffer.vertexSizeInBytes > 0) {\r\n buffer.needsCommit = false;\r\n\r\n var vertexBuffer = buffer.vertexBuffer;\r\n var vertexBufferSizeInBytes =\r\n vertexArrayFacade._size * buffer.vertexSizeInBytes;\r\n var vertexBufferDefined = defined(vertexBuffer);\r\n if (\r\n !vertexBufferDefined ||\r\n vertexBuffer.sizeInBytes < vertexBufferSizeInBytes\r\n ) {\r\n if (vertexBufferDefined) {\r\n vertexBuffer.destroy();\r\n }\r\n buffer.vertexBuffer = Buffer.createVertexBuffer({\r\n context: vertexArrayFacade._context,\r\n typedArray: buffer.arrayBuffer,\r\n usage: buffer.usage,\r\n });\r\n buffer.vertexBuffer.vertexArrayDestroyable = false;\r\n\r\n return true; // Created new vertex buffer\r\n }\r\n\r\n buffer.vertexBuffer.copyFromArrayView(buffer.arrayBuffer);\r\n }\r\n\r\n return false; // Did not create new vertex buffer\r\n}\r\n\r\nVertexArrayFacade._appendAttributes = function (\r\n attributes,\r\n buffer,\r\n vertexBufferOffset,\r\n instanced\r\n) {\r\n var arrayViews = buffer.arrayViews;\r\n var length = arrayViews.length;\r\n for (var i = 0; i < length; ++i) {\r\n var view = arrayViews[i];\r\n\r\n attributes.push({\r\n index: view.index,\r\n enabled: view.enabled,\r\n componentsPerAttribute: view.componentsPerAttribute,\r\n componentDatatype: view.componentDatatype,\r\n normalize: view.normalize,\r\n vertexBuffer: buffer.vertexBuffer,\r\n offsetInBytes: vertexBufferOffset + view.offsetInBytes,\r\n strideInBytes: buffer.vertexSizeInBytes,\r\n instanceDivisor: instanced ? 1 : 0,\r\n });\r\n }\r\n};\r\n\r\nVertexArrayFacade.prototype.subCommit = function (\r\n offsetInVertices,\r\n lengthInVertices\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (offsetInVertices < 0 || offsetInVertices >= this._size) {\r\n throw new DeveloperError(\r\n \"offsetInVertices must be greater than or equal to zero and less than the vertex array size.\"\r\n );\r\n }\r\n if (offsetInVertices + lengthInVertices > this._size) {\r\n throw new DeveloperError(\r\n \"offsetInVertices + lengthInVertices cannot exceed the vertex array size.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var allBuffers = this._allBuffers;\r\n for (var i = 0, len = allBuffers.length; i < len; ++i) {\r\n subCommit(allBuffers[i], offsetInVertices, lengthInVertices);\r\n }\r\n};\r\n\r\nfunction subCommit(buffer, offsetInVertices, lengthInVertices) {\r\n if (buffer.needsCommit && buffer.vertexSizeInBytes > 0) {\r\n var byteOffset = buffer.vertexSizeInBytes * offsetInVertices;\r\n var byteLength = buffer.vertexSizeInBytes * lengthInVertices;\r\n\r\n // PERFORMANCE_IDEA: If we want to get really crazy, we could consider updating\r\n // individual attributes instead of the entire (sub-)vertex.\r\n //\r\n // PERFORMANCE_IDEA: Does creating the typed view add too much GC overhead?\r\n buffer.vertexBuffer.copyFromArrayView(\r\n new Uint8Array(buffer.arrayBuffer, byteOffset, byteLength),\r\n byteOffset\r\n );\r\n }\r\n}\r\n\r\nVertexArrayFacade.prototype.endSubCommits = function () {\r\n var allBuffers = this._allBuffers;\r\n\r\n for (var i = 0, len = allBuffers.length; i < len; ++i) {\r\n allBuffers[i].needsCommit = false;\r\n }\r\n};\r\n\r\nfunction destroyVA(vertexArrayFacade) {\r\n var va = vertexArrayFacade.va;\r\n if (!defined(va)) {\r\n return;\r\n }\r\n\r\n var length = va.length;\r\n for (var i = 0; i < length; ++i) {\r\n va[i].va.destroy();\r\n }\r\n\r\n vertexArrayFacade.va = undefined;\r\n}\r\n\r\nVertexArrayFacade.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nVertexArrayFacade.prototype.destroy = function () {\r\n var allBuffers = this._allBuffers;\r\n for (var i = 0, len = allBuffers.length; i < len; ++i) {\r\n var buffer = allBuffers[i];\r\n buffer.vertexBuffer = buffer.vertexBuffer && buffer.vertexBuffer.destroy();\r\n }\r\n\r\n destroyVA(this);\r\n\r\n return destroyObject(this);\r\n};\r\nexport default VertexArrayFacade;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef GL_OES_standard_derivatives\\n\\\n#extension GL_OES_standard_derivatives : enable\\n\\\n#endif\\n\\\nuniform sampler2D u_atlas;\\n\\\n#ifdef VECTOR_TILE\\n\\\nuniform vec4 u_highlightColor;\\n\\\n#endif\\n\\\nvarying vec2 v_textureCoordinates;\\n\\\nvarying vec4 v_pickColor;\\n\\\nvarying vec4 v_color;\\n\\\n#ifdef SDF\\n\\\nvarying vec4 v_outlineColor;\\n\\\nvarying float v_outlineWidth;\\n\\\n#endif\\n\\\n#ifdef FRAGMENT_DEPTH_CHECK\\n\\\nvarying vec4 v_textureCoordinateBounds;\\n\\\nvarying vec4 v_originTextureCoordinateAndTranslate;\\n\\\nvarying vec4 v_compressed;\\n\\\nvarying mat2 v_rotationMatrix;\\n\\\nconst float SHIFT_LEFT12 = 4096.0;\\n\\\nconst float SHIFT_LEFT1 = 2.0;\\n\\\nconst float SHIFT_RIGHT12 = 1.0 / 4096.0;\\n\\\nconst float SHIFT_RIGHT1 = 1.0 / 2.0;\\n\\\nfloat getGlobeDepth(vec2 adjustedST, vec2 depthLookupST, bool applyTranslate, vec2 dimensions, vec2 imageSize)\\n\\\n{\\n\\\nvec2 lookupVector = imageSize * (depthLookupST - adjustedST);\\n\\\nlookupVector = v_rotationMatrix * lookupVector;\\n\\\nvec2 labelOffset = (dimensions - imageSize) * (depthLookupST - vec2(0.0, v_originTextureCoordinateAndTranslate.y));\\n\\\nvec2 translation = v_originTextureCoordinateAndTranslate.zw;\\n\\\nif (applyTranslate)\\n\\\n{\\n\\\ntranslation += (dimensions * v_originTextureCoordinateAndTranslate.xy * vec2(1.0, 0.0));\\n\\\n}\\n\\\nvec2 st = ((lookupVector - translation + labelOffset) + gl_FragCoord.xy) / czm_viewport.zw;\\n\\\nfloat logDepthOrDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, st));\\n\\\nif (logDepthOrDepth == 0.0)\\n\\\n{\\n\\\nreturn 0.0;\\n\\\n}\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);\\n\\\nreturn eyeCoordinate.z / eyeCoordinate.w;\\n\\\n}\\n\\\n#endif\\n\\\n#ifdef SDF\\n\\\nfloat getDistance(vec2 position)\\n\\\n{\\n\\\nreturn texture2D(u_atlas, position).r;\\n\\\n}\\n\\\nvec4 getSDFColor(vec2 position, float outlineWidth, vec4 outlineColor, float smoothing)\\n\\\n{\\n\\\nfloat distance = getDistance(position);\\n\\\nif (outlineWidth > 0.0)\\n\\\n{\\n\\\nfloat outlineEdge = clamp(SDF_EDGE - outlineWidth, 0.0, SDF_EDGE);\\n\\\nfloat outlineFactor = smoothstep(SDF_EDGE - smoothing, SDF_EDGE + smoothing, distance);\\n\\\nvec4 sdfColor = mix(outlineColor, v_color, outlineFactor);\\n\\\nfloat alpha = smoothstep(outlineEdge - smoothing, outlineEdge + smoothing, distance);\\n\\\nreturn vec4(sdfColor.rgb, sdfColor.a * alpha);\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nfloat alpha = smoothstep(SDF_EDGE - smoothing, SDF_EDGE + smoothing, distance);\\n\\\nreturn vec4(v_color.rgb, v_color.a * alpha);\\n\\\n}\\n\\\n}\\n\\\n#endif\\n\\\nvoid main()\\n\\\n{\\n\\\nvec4 color = texture2D(u_atlas, v_textureCoordinates);\\n\\\n#ifdef SDF\\n\\\nfloat outlineWidth = v_outlineWidth;\\n\\\nvec4 outlineColor = v_outlineColor;\\n\\\nfloat distance = getDistance(v_textureCoordinates);\\n\\\n#ifdef GL_OES_standard_derivatives\\n\\\nfloat smoothing = fwidth(distance);\\n\\\nvec2 sampleOffset = 0.354 * vec2(dFdx(v_textureCoordinates) + dFdy(v_textureCoordinates));\\n\\\nvec4 center = getSDFColor(v_textureCoordinates, outlineWidth, outlineColor, smoothing);\\n\\\nvec4 color1 = getSDFColor(v_textureCoordinates + vec2(sampleOffset.x, sampleOffset.y), outlineWidth, outlineColor, smoothing);\\n\\\nvec4 color2 = getSDFColor(v_textureCoordinates + vec2(-sampleOffset.x, sampleOffset.y), outlineWidth, outlineColor, smoothing);\\n\\\nvec4 color3 = getSDFColor(v_textureCoordinates + vec2(-sampleOffset.x, -sampleOffset.y), outlineWidth, outlineColor, smoothing);\\n\\\nvec4 color4 = getSDFColor(v_textureCoordinates + vec2(sampleOffset.x, -sampleOffset.y), outlineWidth, outlineColor, smoothing);\\n\\\ncolor = (center + color1 + color2 + color3 + color4)/5.0;\\n\\\n#else\\n\\\nfloat smoothing = 1.0/32.0;\\n\\\ncolor = getSDFColor(v_textureCoordinates, outlineWidth, outlineColor, smoothing);\\n\\\n#endif\\n\\\ncolor = czm_gammaCorrect(color);\\n\\\n#else\\n\\\ncolor = czm_gammaCorrect(color);\\n\\\ncolor *= czm_gammaCorrect(v_color);\\n\\\n#endif\\n\\\n#if !defined(OPAQUE) && !defined(TRANSLUCENT)\\n\\\nif (color.a < 0.005)\\n\\\n{\\n\\\ndiscard;\\n\\\n}\\n\\\n#else\\n\\\n#ifdef OPAQUE\\n\\\nif (color.a < 0.995)\\n\\\n{\\n\\\ndiscard;\\n\\\n}\\n\\\n#else\\n\\\nif (color.a >= 0.995)\\n\\\n{\\n\\\ndiscard;\\n\\\n}\\n\\\n#endif\\n\\\n#endif\\n\\\n#ifdef VECTOR_TILE\\n\\\ncolor *= u_highlightColor;\\n\\\n#endif\\n\\\ngl_FragColor = color;\\n\\\n#ifdef LOG_DEPTH\\n\\\nczm_writeLogDepth();\\n\\\n#endif\\n\\\n#ifdef FRAGMENT_DEPTH_CHECK\\n\\\nfloat temp = v_compressed.y;\\n\\\ntemp = temp * SHIFT_RIGHT1;\\n\\\nfloat temp2 = (temp - floor(temp)) * SHIFT_LEFT1;\\n\\\nbool enableDepthTest = temp2 != 0.0;\\n\\\nbool applyTranslate = floor(temp) != 0.0;\\n\\\nif (enableDepthTest) {\\n\\\ntemp = v_compressed.z;\\n\\\ntemp = temp * SHIFT_RIGHT12;\\n\\\nvec2 dimensions;\\n\\\ndimensions.y = (temp - floor(temp)) * SHIFT_LEFT12;\\n\\\ndimensions.x = floor(temp);\\n\\\ntemp = v_compressed.w;\\n\\\ntemp = temp * SHIFT_RIGHT12;\\n\\\nvec2 imageSize;\\n\\\nimageSize.y = (temp - floor(temp)) * SHIFT_LEFT12;\\n\\\nimageSize.x = floor(temp);\\n\\\nvec2 adjustedST = v_textureCoordinates - v_textureCoordinateBounds.xy;\\n\\\nadjustedST = adjustedST / vec2(v_textureCoordinateBounds.z - v_textureCoordinateBounds.x, v_textureCoordinateBounds.w - v_textureCoordinateBounds.y);\\n\\\nfloat epsilonEyeDepth = v_compressed.x + czm_epsilon1;\\n\\\nfloat globeDepth1 = getGlobeDepth(adjustedST, v_originTextureCoordinateAndTranslate.xy, applyTranslate, dimensions, imageSize);\\n\\\nif (globeDepth1 != 0.0 && globeDepth1 > epsilonEyeDepth)\\n\\\n{\\n\\\nfloat globeDepth2 = getGlobeDepth(adjustedST, vec2(0.0, 1.0), applyTranslate, dimensions, imageSize);\\n\\\nif (globeDepth2 != 0.0 && globeDepth2 > epsilonEyeDepth)\\n\\\n{\\n\\\nfloat globeDepth3 = getGlobeDepth(adjustedST, vec2(1.0, 1.0), applyTranslate, dimensions, imageSize);\\n\\\nif (globeDepth3 != 0.0 && globeDepth3 > epsilonEyeDepth)\\n\\\n{\\n\\\ndiscard;\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\n#endif\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef INSTANCED\\n\\\nattribute vec2 direction;\\n\\\n#endif\\n\\\nattribute vec4 positionHighAndScale;\\n\\\nattribute vec4 positionLowAndRotation;\\n\\\nattribute vec4 compressedAttribute0;\\n\\\nattribute vec4 compressedAttribute1;\\n\\\nattribute vec4 compressedAttribute2;\\n\\\nattribute vec4 eyeOffset;\\n\\\nattribute vec4 scaleByDistance;\\n\\\nattribute vec4 pixelOffsetScaleByDistance;\\n\\\nattribute vec4 compressedAttribute3;\\n\\\nattribute vec2 sdf;\\n\\\n#if defined(VERTEX_DEPTH_CHECK) || defined(FRAGMENT_DEPTH_CHECK)\\n\\\nattribute vec4 textureCoordinateBoundsOrLabelTranslate;\\n\\\n#endif\\n\\\n#ifdef VECTOR_TILE\\n\\\nattribute float a_batchId;\\n\\\n#endif\\n\\\nvarying vec2 v_textureCoordinates;\\n\\\n#ifdef FRAGMENT_DEPTH_CHECK\\n\\\nvarying vec4 v_textureCoordinateBounds;\\n\\\nvarying vec4 v_originTextureCoordinateAndTranslate;\\n\\\nvarying vec4 v_compressed;\\n\\\nvarying mat2 v_rotationMatrix;\\n\\\n#endif\\n\\\nvarying vec4 v_pickColor;\\n\\\nvarying vec4 v_color;\\n\\\n#ifdef SDF\\n\\\nvarying vec4 v_outlineColor;\\n\\\nvarying float v_outlineWidth;\\n\\\n#endif\\n\\\nconst float UPPER_BOUND = 32768.0;\\n\\\nconst float SHIFT_LEFT16 = 65536.0;\\n\\\nconst float SHIFT_LEFT12 = 4096.0;\\n\\\nconst float SHIFT_LEFT8 = 256.0;\\n\\\nconst float SHIFT_LEFT7 = 128.0;\\n\\\nconst float SHIFT_LEFT5 = 32.0;\\n\\\nconst float SHIFT_LEFT3 = 8.0;\\n\\\nconst float SHIFT_LEFT2 = 4.0;\\n\\\nconst float SHIFT_LEFT1 = 2.0;\\n\\\nconst float SHIFT_RIGHT12 = 1.0 / 4096.0;\\n\\\nconst float SHIFT_RIGHT8 = 1.0 / 256.0;\\n\\\nconst float SHIFT_RIGHT7 = 1.0 / 128.0;\\n\\\nconst float SHIFT_RIGHT5 = 1.0 / 32.0;\\n\\\nconst float SHIFT_RIGHT3 = 1.0 / 8.0;\\n\\\nconst float SHIFT_RIGHT2 = 1.0 / 4.0;\\n\\\nconst float SHIFT_RIGHT1 = 1.0 / 2.0;\\n\\\nvec4 addScreenSpaceOffset(vec4 positionEC, vec2 imageSize, float scale, vec2 direction, vec2 origin, vec2 translate, vec2 pixelOffset, vec3 alignedAxis, bool validAlignedAxis, float rotation, bool sizeInMeters, out mat2 rotationMatrix, out float mpp)\\n\\\n{\\n\\\nvec2 halfSize = imageSize * scale * 0.5;\\n\\\nhalfSize *= ((direction * 2.0) - 1.0);\\n\\\nvec2 originTranslate = origin * abs(halfSize);\\n\\\n#if defined(ROTATION) || defined(ALIGNED_AXIS)\\n\\\nif (validAlignedAxis || rotation != 0.0)\\n\\\n{\\n\\\nfloat angle = rotation;\\n\\\nif (validAlignedAxis)\\n\\\n{\\n\\\nvec4 projectedAlignedAxis = czm_modelViewProjection * vec4(alignedAxis, 0.0);\\n\\\nangle += sign(-projectedAlignedAxis.x) * acos(sign(projectedAlignedAxis.y) * (projectedAlignedAxis.y * projectedAlignedAxis.y) /\\n\\\n(projectedAlignedAxis.x * projectedAlignedAxis.x + projectedAlignedAxis.y * projectedAlignedAxis.y));\\n\\\n}\\n\\\nfloat cosTheta = cos(angle);\\n\\\nfloat sinTheta = sin(angle);\\n\\\nrotationMatrix = mat2(cosTheta, sinTheta, -sinTheta, cosTheta);\\n\\\nhalfSize = rotationMatrix * halfSize;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nrotationMatrix = mat2(1.0, 0.0, 0.0, 1.0);\\n\\\n}\\n\\\n#endif\\n\\\nmpp = czm_metersPerPixel(positionEC);\\n\\\npositionEC.xy += (originTranslate + halfSize) * czm_branchFreeTernary(sizeInMeters, 1.0, mpp);\\n\\\npositionEC.xy += (translate + pixelOffset) * mpp;\\n\\\nreturn positionEC;\\n\\\n}\\n\\\n#ifdef VERTEX_DEPTH_CHECK\\n\\\nfloat getGlobeDepth(vec4 positionEC)\\n\\\n{\\n\\\nvec4 posWC = czm_eyeToWindowCoordinates(positionEC);\\n\\\nfloat globeDepth = czm_unpackDepth(texture2D(czm_globeDepthTexture, posWC.xy / czm_viewport.zw));\\n\\\nif (globeDepth == 0.0)\\n\\\n{\\n\\\nreturn 0.0;\\n\\\n}\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(posWC.xy, globeDepth);\\n\\\nreturn eyeCoordinate.z / eyeCoordinate.w;\\n\\\n}\\n\\\n#endif\\n\\\nvoid main()\\n\\\n{\\n\\\nvec3 positionHigh = positionHighAndScale.xyz;\\n\\\nvec3 positionLow = positionLowAndRotation.xyz;\\n\\\nfloat scale = positionHighAndScale.w;\\n\\\n#if defined(ROTATION) || defined(ALIGNED_AXIS)\\n\\\nfloat rotation = positionLowAndRotation.w;\\n\\\n#else\\n\\\nfloat rotation = 0.0;\\n\\\n#endif\\n\\\nfloat compressed = compressedAttribute0.x;\\n\\\nvec2 pixelOffset;\\n\\\npixelOffset.x = floor(compressed * SHIFT_RIGHT7);\\n\\\ncompressed -= pixelOffset.x * SHIFT_LEFT7;\\n\\\npixelOffset.x -= UPPER_BOUND;\\n\\\nvec2 origin;\\n\\\norigin.x = floor(compressed * SHIFT_RIGHT5);\\n\\\ncompressed -= origin.x * SHIFT_LEFT5;\\n\\\norigin.y = floor(compressed * SHIFT_RIGHT3);\\n\\\ncompressed -= origin.y * SHIFT_LEFT3;\\n\\\n#ifdef FRAGMENT_DEPTH_CHECK\\n\\\nvec2 depthOrigin = origin.xy;\\n\\\n#endif\\n\\\norigin -= vec2(1.0);\\n\\\nfloat show = floor(compressed * SHIFT_RIGHT2);\\n\\\ncompressed -= show * SHIFT_LEFT2;\\n\\\n#ifdef INSTANCED\\n\\\nvec2 textureCoordinatesBottomLeft = czm_decompressTextureCoordinates(compressedAttribute0.w);\\n\\\nvec2 textureCoordinatesRange = czm_decompressTextureCoordinates(eyeOffset.w);\\n\\\nvec2 textureCoordinates = textureCoordinatesBottomLeft + direction * textureCoordinatesRange;\\n\\\n#else\\n\\\nvec2 direction;\\n\\\ndirection.x = floor(compressed * SHIFT_RIGHT1);\\n\\\ndirection.y = compressed - direction.x * SHIFT_LEFT1;\\n\\\nvec2 textureCoordinates = czm_decompressTextureCoordinates(compressedAttribute0.w);\\n\\\n#endif\\n\\\nfloat temp = compressedAttribute0.y * SHIFT_RIGHT8;\\n\\\npixelOffset.y = -(floor(temp) - UPPER_BOUND);\\n\\\nvec2 translate;\\n\\\ntranslate.y = (temp - floor(temp)) * SHIFT_LEFT16;\\n\\\ntemp = compressedAttribute0.z * SHIFT_RIGHT8;\\n\\\ntranslate.x = floor(temp) - UPPER_BOUND;\\n\\\ntranslate.y += (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ntranslate.y -= UPPER_BOUND;\\n\\\ntemp = compressedAttribute1.x * SHIFT_RIGHT8;\\n\\\nfloat temp2 = floor(compressedAttribute2.w * SHIFT_RIGHT2);\\n\\\nvec2 imageSize = vec2(floor(temp), temp2);\\n\\\n#ifdef FRAGMENT_DEPTH_CHECK\\n\\\nfloat labelHorizontalOrigin = floor(compressedAttribute2.w - (temp2 * SHIFT_LEFT2));\\n\\\nfloat applyTranslate = 0.0;\\n\\\nif (labelHorizontalOrigin != 0.0)\\n\\\n{\\n\\\napplyTranslate = 1.0;\\n\\\nlabelHorizontalOrigin -= 2.0;\\n\\\ndepthOrigin.x = labelHorizontalOrigin + 1.0;\\n\\\n}\\n\\\ndepthOrigin = vec2(1.0) - (depthOrigin * 0.5);\\n\\\n#endif\\n\\\n#ifdef EYE_DISTANCE_TRANSLUCENCY\\n\\\nvec4 translucencyByDistance;\\n\\\ntranslucencyByDistance.x = compressedAttribute1.z;\\n\\\ntranslucencyByDistance.z = compressedAttribute1.w;\\n\\\ntranslucencyByDistance.y = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;\\n\\\ntemp = compressedAttribute1.y * SHIFT_RIGHT8;\\n\\\ntranslucencyByDistance.w = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;\\n\\\n#endif\\n\\\n#if defined(VERTEX_DEPTH_CHECK) || defined(FRAGMENT_DEPTH_CHECK)\\n\\\ntemp = compressedAttribute3.w;\\n\\\ntemp = temp * SHIFT_RIGHT12;\\n\\\nvec2 dimensions;\\n\\\ndimensions.y = (temp - floor(temp)) * SHIFT_LEFT12;\\n\\\ndimensions.x = floor(temp);\\n\\\n#endif\\n\\\n#ifdef ALIGNED_AXIS\\n\\\nvec3 alignedAxis = czm_octDecode(floor(compressedAttribute1.y * SHIFT_RIGHT8));\\n\\\ntemp = compressedAttribute2.z * SHIFT_RIGHT5;\\n\\\nbool validAlignedAxis = (temp - floor(temp)) * SHIFT_LEFT1 > 0.0;\\n\\\n#else\\n\\\nvec3 alignedAxis = vec3(0.0);\\n\\\nbool validAlignedAxis = false;\\n\\\n#endif\\n\\\nvec4 pickColor;\\n\\\nvec4 color;\\n\\\ntemp = compressedAttribute2.y;\\n\\\ntemp = temp * SHIFT_RIGHT8;\\n\\\npickColor.b = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\npickColor.g = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\npickColor.r = floor(temp);\\n\\\ntemp = compressedAttribute2.x;\\n\\\ntemp = temp * SHIFT_RIGHT8;\\n\\\ncolor.b = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\ncolor.g = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ncolor.r = floor(temp);\\n\\\ntemp = compressedAttribute2.z * SHIFT_RIGHT8;\\n\\\nbool sizeInMeters = floor((temp - floor(temp)) * SHIFT_LEFT7) > 0.0;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\npickColor.a = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\npickColor /= 255.0;\\n\\\ncolor.a = floor(temp);\\n\\\ncolor /= 255.0;\\n\\\nvec4 p = czm_translateRelativeToEye(positionHigh, positionLow);\\n\\\nvec4 positionEC = czm_modelViewRelativeToEye * p;\\n\\\n#if defined(FRAGMENT_DEPTH_CHECK) || defined(VERTEX_DEPTH_CHECK)\\n\\\nfloat eyeDepth = positionEC.z;\\n\\\n#endif\\n\\\npositionEC = czm_eyeOffset(positionEC, eyeOffset.xyz);\\n\\\npositionEC.xyz *= show;\\n\\\n#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(EYE_DISTANCE_PIXEL_OFFSET) || defined(DISTANCE_DISPLAY_CONDITION) || defined(DISABLE_DEPTH_DISTANCE)\\n\\\nfloat lengthSq;\\n\\\nif (czm_sceneMode == czm_sceneMode2D)\\n\\\n{\\n\\\nlengthSq = czm_eyeHeight2D.y;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nlengthSq = dot(positionEC.xyz, positionEC.xyz);\\n\\\n}\\n\\\n#endif\\n\\\n#ifdef EYE_DISTANCE_SCALING\\n\\\nfloat distanceScale = czm_nearFarScalar(scaleByDistance, lengthSq);\\n\\\nscale *= distanceScale;\\n\\\ntranslate *= distanceScale;\\n\\\nif (scale == 0.0)\\n\\\n{\\n\\\npositionEC.xyz = vec3(0.0);\\n\\\n}\\n\\\n#endif\\n\\\nfloat translucency = 1.0;\\n\\\n#ifdef EYE_DISTANCE_TRANSLUCENCY\\n\\\ntranslucency = czm_nearFarScalar(translucencyByDistance, lengthSq);\\n\\\nif (translucency == 0.0)\\n\\\n{\\n\\\npositionEC.xyz = vec3(0.0);\\n\\\n}\\n\\\n#endif\\n\\\n#ifdef EYE_DISTANCE_PIXEL_OFFSET\\n\\\nfloat pixelOffsetScale = czm_nearFarScalar(pixelOffsetScaleByDistance, lengthSq);\\n\\\npixelOffset *= pixelOffsetScale;\\n\\\n#endif\\n\\\n#ifdef DISTANCE_DISPLAY_CONDITION\\n\\\nfloat nearSq = compressedAttribute3.x;\\n\\\nfloat farSq = compressedAttribute3.y;\\n\\\nif (lengthSq < nearSq || lengthSq > farSq)\\n\\\n{\\n\\\npositionEC.xyz = vec3(0.0);\\n\\\n}\\n\\\n#endif\\n\\\nmat2 rotationMatrix;\\n\\\nfloat mpp;\\n\\\n#ifdef DISABLE_DEPTH_DISTANCE\\n\\\nfloat disableDepthTestDistance = compressedAttribute3.z;\\n\\\n#endif\\n\\\n#ifdef VERTEX_DEPTH_CHECK\\n\\\nif (lengthSq < disableDepthTestDistance) {\\n\\\nfloat depthsilon = 10.0;\\n\\\nvec2 labelTranslate = textureCoordinateBoundsOrLabelTranslate.xy;\\n\\\nvec4 pEC1 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp);\\n\\\nfloat globeDepth1 = getGlobeDepth(pEC1);\\n\\\nif (globeDepth1 != 0.0 && pEC1.z + depthsilon < globeDepth1)\\n\\\n{\\n\\\nvec4 pEC2 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(0.0, 1.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp);\\n\\\nfloat globeDepth2 = getGlobeDepth(pEC2);\\n\\\nif (globeDepth2 != 0.0 && pEC2.z + depthsilon < globeDepth2)\\n\\\n{\\n\\\nvec4 pEC3 = addScreenSpaceOffset(positionEC, dimensions, scale, vec2(1.0), origin, labelTranslate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp);\\n\\\nfloat globeDepth3 = getGlobeDepth(pEC3);\\n\\\nif (globeDepth3 != 0.0 && pEC3.z + depthsilon < globeDepth3)\\n\\\n{\\n\\\npositionEC.xyz = vec3(0.0);\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\n}\\n\\\n#endif\\n\\\npositionEC = addScreenSpaceOffset(positionEC, imageSize, scale, direction, origin, translate, pixelOffset, alignedAxis, validAlignedAxis, rotation, sizeInMeters, rotationMatrix, mpp);\\n\\\ngl_Position = czm_projection * positionEC;\\n\\\nv_textureCoordinates = textureCoordinates;\\n\\\n#ifdef LOG_DEPTH\\n\\\nczm_vertexLogDepth();\\n\\\n#endif\\n\\\n#ifdef DISABLE_DEPTH_DISTANCE\\n\\\nif (disableDepthTestDistance == 0.0 && czm_minimumDisableDepthTestDistance != 0.0)\\n\\\n{\\n\\\ndisableDepthTestDistance = czm_minimumDisableDepthTestDistance;\\n\\\n}\\n\\\nif (disableDepthTestDistance != 0.0)\\n\\\n{\\n\\\nfloat zclip = gl_Position.z / gl_Position.w;\\n\\\nbool clipped = (zclip < -1.0 || zclip > 1.0);\\n\\\nif (!clipped && (disableDepthTestDistance < 0.0 || (lengthSq > 0.0 && lengthSq < disableDepthTestDistance)))\\n\\\n{\\n\\\ngl_Position.z = -gl_Position.w;\\n\\\n#ifdef LOG_DEPTH\\n\\\nv_depthFromNearPlusOne = 1.0;\\n\\\n#endif\\n\\\n}\\n\\\n}\\n\\\n#endif\\n\\\n#ifdef FRAGMENT_DEPTH_CHECK\\n\\\nif (sizeInMeters) {\\n\\\ntranslate /= mpp;\\n\\\ndimensions /= mpp;\\n\\\nimageSize /= mpp;\\n\\\n}\\n\\\n#if defined(ROTATION) || defined(ALIGNED_AXIS)\\n\\\nv_rotationMatrix = rotationMatrix;\\n\\\n#else\\n\\\nv_rotationMatrix = mat2(1.0, 0.0, 0.0, 1.0);\\n\\\n#endif\\n\\\nfloat enableDepthCheck = 0.0;\\n\\\nif (lengthSq < disableDepthTestDistance)\\n\\\n{\\n\\\nenableDepthCheck = 1.0;\\n\\\n}\\n\\\nfloat dw = floor(clamp(dimensions.x, 0.0, SHIFT_LEFT12));\\n\\\nfloat dh = floor(clamp(dimensions.y, 0.0, SHIFT_LEFT12));\\n\\\nfloat iw = floor(clamp(imageSize.x, 0.0, SHIFT_LEFT12));\\n\\\nfloat ih = floor(clamp(imageSize.y, 0.0, SHIFT_LEFT12));\\n\\\nv_compressed.x = eyeDepth;\\n\\\nv_compressed.y = applyTranslate * SHIFT_LEFT1 + enableDepthCheck;\\n\\\nv_compressed.z = dw * SHIFT_LEFT12 + dh;\\n\\\nv_compressed.w = iw * SHIFT_LEFT12 + ih;\\n\\\nv_originTextureCoordinateAndTranslate.xy = depthOrigin;\\n\\\nv_originTextureCoordinateAndTranslate.zw = translate;\\n\\\nv_textureCoordinateBounds = textureCoordinateBoundsOrLabelTranslate;\\n\\\n#endif\\n\\\n#ifdef SDF\\n\\\nvec4 outlineColor;\\n\\\nfloat outlineWidth;\\n\\\ntemp = sdf.x;\\n\\\ntemp = temp * SHIFT_RIGHT8;\\n\\\noutlineColor.b = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\noutlineColor.g = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\noutlineColor.r = floor(temp);\\n\\\ntemp = sdf.y;\\n\\\ntemp = temp * SHIFT_RIGHT8;\\n\\\nfloat temp3 = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\noutlineWidth = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\noutlineColor.a = floor(temp);\\n\\\noutlineColor /= 255.0;\\n\\\nv_outlineWidth = outlineWidth / 255.0;\\n\\\nv_outlineColor = outlineColor;\\n\\\nv_outlineColor.a *= translucency;\\n\\\n#endif\\n\\\nv_pickColor = pickColor;\\n\\\nv_color = color;\\n\\\nv_color.a *= translucency;\\n\\\n}\\n\\\n\";\n","import BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport OrthographicFrustum from \"../Core/OrthographicFrustum.js\";\r\nimport OrthographicOffCenterFrustum from \"../Core/OrthographicOffCenterFrustum.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\n\r\n/**\r\n * Functions that do scene-dependent transforms between rendering-related coordinate systems.\r\n *\r\n * @namespace SceneTransforms\r\n */\r\nvar SceneTransforms = {};\r\n\r\nvar actualPositionScratch = new Cartesian4(0, 0, 0, 1);\r\nvar positionCC = new Cartesian4();\r\nvar scratchViewport = new BoundingRectangle();\r\n\r\nvar scratchWindowCoord0 = new Cartesian2();\r\nvar scratchWindowCoord1 = new Cartesian2();\r\n\r\n/**\r\n * Transforms a position in WGS84 coordinates to window coordinates. This is commonly used to place an\r\n * HTML element at the same screen position as an object in the scene.\r\n *\r\n * @param {Scene} scene The scene.\r\n * @param {Cartesian3} position The position in WGS84 (world) coordinates.\r\n * @param {Cartesian2} [result] An optional object to return the input position transformed to window coordinates.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. This may be undefined if the input position is near the center of the ellipsoid.\r\n *\r\n * @example\r\n * // Output the window position of longitude/latitude (0, 0) every time the mouse moves.\r\n * var scene = widget.scene;\r\n * var ellipsoid = scene.globe.ellipsoid;\r\n * var position = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);\r\n * handler.setInputAction(function(movement) {\r\n * console.log(Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, position));\r\n * }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);\r\n */\r\nSceneTransforms.wgs84ToWindowCoordinates = function (scene, position, result) {\r\n return SceneTransforms.wgs84WithEyeOffsetToWindowCoordinates(\r\n scene,\r\n position,\r\n Cartesian3.ZERO,\r\n result\r\n );\r\n};\r\n\r\nvar scratchCartesian4 = new Cartesian4();\r\nvar scratchEyeOffset = new Cartesian3();\r\n\r\nfunction worldToClip(position, eyeOffset, camera, result) {\r\n var viewMatrix = camera.viewMatrix;\r\n\r\n var positionEC = Matrix4.multiplyByVector(\r\n viewMatrix,\r\n Cartesian4.fromElements(\r\n position.x,\r\n position.y,\r\n position.z,\r\n 1,\r\n scratchCartesian4\r\n ),\r\n scratchCartesian4\r\n );\r\n\r\n var zEyeOffset = Cartesian3.multiplyComponents(\r\n eyeOffset,\r\n Cartesian3.normalize(positionEC, scratchEyeOffset),\r\n scratchEyeOffset\r\n );\r\n positionEC.x += eyeOffset.x + zEyeOffset.x;\r\n positionEC.y += eyeOffset.y + zEyeOffset.y;\r\n positionEC.z += zEyeOffset.z;\r\n\r\n return Matrix4.multiplyByVector(\r\n camera.frustum.projectionMatrix,\r\n positionEC,\r\n result\r\n );\r\n}\r\n\r\nvar scratchMaxCartographic = new Cartographic(Math.PI, CesiumMath.PI_OVER_TWO);\r\nvar scratchProjectedCartesian = new Cartesian3();\r\nvar scratchCameraPosition = new Cartesian3();\r\n\r\n/**\r\n * @private\r\n */\r\nSceneTransforms.wgs84WithEyeOffsetToWindowCoordinates = function (\r\n scene,\r\n position,\r\n eyeOffset,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(scene)) {\r\n throw new DeveloperError(\"scene is required.\");\r\n }\r\n if (!defined(position)) {\r\n throw new DeveloperError(\"position is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Transform for 3D, 2D, or Columbus view\r\n var frameState = scene.frameState;\r\n var actualPosition = SceneTransforms.computeActualWgs84Position(\r\n frameState,\r\n position,\r\n actualPositionScratch\r\n );\r\n\r\n if (!defined(actualPosition)) {\r\n return undefined;\r\n }\r\n\r\n // Assuming viewport takes up the entire canvas...\r\n var canvas = scene.canvas;\r\n var viewport = scratchViewport;\r\n viewport.x = 0;\r\n viewport.y = 0;\r\n viewport.width = canvas.clientWidth;\r\n viewport.height = canvas.clientHeight;\r\n\r\n var camera = scene.camera;\r\n var cameraCentered = false;\r\n\r\n if (frameState.mode === SceneMode.SCENE2D) {\r\n var projection = scene.mapProjection;\r\n var maxCartographic = scratchMaxCartographic;\r\n var maxCoord = projection.project(\r\n maxCartographic,\r\n scratchProjectedCartesian\r\n );\r\n\r\n var cameraPosition = Cartesian3.clone(\r\n camera.position,\r\n scratchCameraPosition\r\n );\r\n var frustum = camera.frustum.clone();\r\n\r\n var viewportTransformation = Matrix4.computeViewportTransformation(\r\n viewport,\r\n 0.0,\r\n 1.0,\r\n new Matrix4()\r\n );\r\n var projectionMatrix = camera.frustum.projectionMatrix;\r\n\r\n var x = camera.positionWC.y;\r\n var eyePoint = Cartesian3.fromElements(\r\n CesiumMath.sign(x) * maxCoord.x - x,\r\n 0.0,\r\n -camera.positionWC.x\r\n );\r\n var windowCoordinates = Transforms.pointToGLWindowCoordinates(\r\n projectionMatrix,\r\n viewportTransformation,\r\n eyePoint\r\n );\r\n\r\n if (\r\n x === 0.0 ||\r\n windowCoordinates.x <= 0.0 ||\r\n windowCoordinates.x >= canvas.clientWidth\r\n ) {\r\n cameraCentered = true;\r\n } else {\r\n if (windowCoordinates.x > canvas.clientWidth * 0.5) {\r\n viewport.width = windowCoordinates.x;\r\n\r\n camera.frustum.right = maxCoord.x - x;\r\n\r\n positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);\r\n SceneTransforms.clipToGLWindowCoordinates(\r\n viewport,\r\n positionCC,\r\n scratchWindowCoord0\r\n );\r\n\r\n viewport.x += windowCoordinates.x;\r\n\r\n camera.position.x = -camera.position.x;\r\n\r\n var right = camera.frustum.right;\r\n camera.frustum.right = -camera.frustum.left;\r\n camera.frustum.left = -right;\r\n\r\n positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);\r\n SceneTransforms.clipToGLWindowCoordinates(\r\n viewport,\r\n positionCC,\r\n scratchWindowCoord1\r\n );\r\n } else {\r\n viewport.x += windowCoordinates.x;\r\n viewport.width -= windowCoordinates.x;\r\n\r\n camera.frustum.left = -maxCoord.x - x;\r\n\r\n positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);\r\n SceneTransforms.clipToGLWindowCoordinates(\r\n viewport,\r\n positionCC,\r\n scratchWindowCoord0\r\n );\r\n\r\n viewport.x = viewport.x - viewport.width;\r\n\r\n camera.position.x = -camera.position.x;\r\n\r\n var left = camera.frustum.left;\r\n camera.frustum.left = -camera.frustum.right;\r\n camera.frustum.right = -left;\r\n\r\n positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);\r\n SceneTransforms.clipToGLWindowCoordinates(\r\n viewport,\r\n positionCC,\r\n scratchWindowCoord1\r\n );\r\n }\r\n\r\n Cartesian3.clone(cameraPosition, camera.position);\r\n camera.frustum = frustum.clone();\r\n\r\n result = Cartesian2.clone(scratchWindowCoord0, result);\r\n if (result.x < 0.0 || result.x > canvas.clientWidth) {\r\n result.x = scratchWindowCoord1.x;\r\n }\r\n }\r\n }\r\n\r\n if (frameState.mode !== SceneMode.SCENE2D || cameraCentered) {\r\n // View-projection matrix to transform from world coordinates to clip coordinates\r\n positionCC = worldToClip(actualPosition, eyeOffset, camera, positionCC);\r\n if (\r\n positionCC.z < 0 &&\r\n !(camera.frustum instanceof OrthographicFrustum) &&\r\n !(camera.frustum instanceof OrthographicOffCenterFrustum)\r\n ) {\r\n return undefined;\r\n }\r\n\r\n result = SceneTransforms.clipToGLWindowCoordinates(\r\n viewport,\r\n positionCC,\r\n result\r\n );\r\n }\r\n\r\n result.y = canvas.clientHeight - result.y;\r\n return result;\r\n};\r\n\r\n/**\r\n * Transforms a position in WGS84 coordinates to drawing buffer coordinates. This may produce different\r\n * results from SceneTransforms.wgs84ToWindowCoordinates when the browser zoom is not 100%, or on high-DPI displays.\r\n *\r\n * @param {Scene} scene The scene.\r\n * @param {Cartesian3} position The position in WGS84 (world) coordinates.\r\n * @param {Cartesian2} [result] An optional object to return the input position transformed to window coordinates.\r\n * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. This may be undefined if the input position is near the center of the ellipsoid.\r\n *\r\n * @example\r\n * // Output the window position of longitude/latitude (0, 0) every time the mouse moves.\r\n * var scene = widget.scene;\r\n * var ellipsoid = scene.globe.ellipsoid;\r\n * var position = Cesium.Cartesian3.fromDegrees(0.0, 0.0);\r\n * var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);\r\n * handler.setInputAction(function(movement) {\r\n * console.log(Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, position));\r\n * }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);\r\n */\r\nSceneTransforms.wgs84ToDrawingBufferCoordinates = function (\r\n scene,\r\n position,\r\n result\r\n) {\r\n result = SceneTransforms.wgs84ToWindowCoordinates(scene, position, result);\r\n if (!defined(result)) {\r\n return undefined;\r\n }\r\n\r\n return SceneTransforms.transformWindowToDrawingBuffer(scene, result, result);\r\n};\r\n\r\nvar projectedPosition = new Cartesian3();\r\nvar positionInCartographic = new Cartographic();\r\n\r\n/**\r\n * @private\r\n */\r\nSceneTransforms.computeActualWgs84Position = function (\r\n frameState,\r\n position,\r\n result\r\n) {\r\n var mode = frameState.mode;\r\n\r\n if (mode === SceneMode.SCENE3D) {\r\n return Cartesian3.clone(position, result);\r\n }\r\n\r\n var projection = frameState.mapProjection;\r\n var cartographic = projection.ellipsoid.cartesianToCartographic(\r\n position,\r\n positionInCartographic\r\n );\r\n if (!defined(cartographic)) {\r\n return undefined;\r\n }\r\n\r\n projection.project(cartographic, projectedPosition);\r\n\r\n if (mode === SceneMode.COLUMBUS_VIEW) {\r\n return Cartesian3.fromElements(\r\n projectedPosition.z,\r\n projectedPosition.x,\r\n projectedPosition.y,\r\n result\r\n );\r\n }\r\n\r\n if (mode === SceneMode.SCENE2D) {\r\n return Cartesian3.fromElements(\r\n 0.0,\r\n projectedPosition.x,\r\n projectedPosition.y,\r\n result\r\n );\r\n }\r\n\r\n // mode === SceneMode.MORPHING\r\n var morphTime = frameState.morphTime;\r\n return Cartesian3.fromElements(\r\n CesiumMath.lerp(projectedPosition.z, position.x, morphTime),\r\n CesiumMath.lerp(projectedPosition.x, position.y, morphTime),\r\n CesiumMath.lerp(projectedPosition.y, position.z, morphTime),\r\n result\r\n );\r\n};\r\n\r\nvar positionNDC = new Cartesian3();\r\nvar positionWC = new Cartesian3();\r\nvar viewportTransform = new Matrix4();\r\n\r\n/**\r\n * @private\r\n */\r\nSceneTransforms.clipToGLWindowCoordinates = function (\r\n viewport,\r\n position,\r\n result\r\n) {\r\n // Perspective divide to transform from clip coordinates to normalized device coordinates\r\n Cartesian3.divideByScalar(position, position.w, positionNDC);\r\n\r\n // Viewport transform to transform from clip coordinates to window coordinates\r\n Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, viewportTransform);\r\n Matrix4.multiplyByPoint(viewportTransform, positionNDC, positionWC);\r\n\r\n return Cartesian2.fromCartesian3(positionWC, result);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nSceneTransforms.transformWindowToDrawingBuffer = function (\r\n scene,\r\n windowPosition,\r\n result\r\n) {\r\n var canvas = scene.canvas;\r\n var xScale = scene.drawingBufferWidth / canvas.clientWidth;\r\n var yScale = scene.drawingBufferHeight / canvas.clientHeight;\r\n return Cartesian2.fromElements(\r\n windowPosition.x * xScale,\r\n windowPosition.y * yScale,\r\n result\r\n );\r\n};\r\n\r\nvar scratchNDC = new Cartesian4();\r\nvar scratchWorldCoords = new Cartesian4();\r\n\r\n/**\r\n * @private\r\n */\r\nSceneTransforms.drawingBufferToWgs84Coordinates = function (\r\n scene,\r\n drawingBufferPosition,\r\n depth,\r\n result\r\n) {\r\n var context = scene.context;\r\n var uniformState = context.uniformState;\r\n\r\n var currentFrustum = uniformState.currentFrustum;\r\n var near = currentFrustum.x;\r\n var far = currentFrustum.y;\r\n\r\n if (scene.frameState.useLogDepth) {\r\n // transforming logarithmic depth of form\r\n // log2(z + 1) / log2( far + 1);\r\n // to perspective form\r\n // (far - far * near / z) / (far - near)\r\n var log2Depth = depth * uniformState.log2FarDepthFromNearPlusOne;\r\n var depthFromNear = Math.pow(2.0, log2Depth) - 1.0;\r\n depth = (far * (1.0 - near / (depthFromNear + near))) / (far - near);\r\n }\r\n\r\n var viewport = scene.view.passState.viewport;\r\n var ndc = Cartesian4.clone(Cartesian4.UNIT_W, scratchNDC);\r\n ndc.x = ((drawingBufferPosition.x - viewport.x) / viewport.width) * 2.0 - 1.0;\r\n ndc.y =\r\n ((drawingBufferPosition.y - viewport.y) / viewport.height) * 2.0 - 1.0;\r\n ndc.z = depth * 2.0 - 1.0;\r\n ndc.w = 1.0;\r\n\r\n var worldCoords;\r\n var frustum = scene.camera.frustum;\r\n if (!defined(frustum.fovy)) {\r\n if (defined(frustum._offCenterFrustum)) {\r\n frustum = frustum._offCenterFrustum;\r\n }\r\n worldCoords = scratchWorldCoords;\r\n worldCoords.x =\r\n (ndc.x * (frustum.right - frustum.left) + frustum.left + frustum.right) *\r\n 0.5;\r\n worldCoords.y =\r\n (ndc.y * (frustum.top - frustum.bottom) + frustum.bottom + frustum.top) *\r\n 0.5;\r\n worldCoords.z = (ndc.z * (near - far) - near - far) * 0.5;\r\n worldCoords.w = 1.0;\r\n\r\n worldCoords = Matrix4.multiplyByVector(\r\n uniformState.inverseView,\r\n worldCoords,\r\n worldCoords\r\n );\r\n } else {\r\n worldCoords = Matrix4.multiplyByVector(\r\n uniformState.inverseViewProjection,\r\n ndc,\r\n scratchWorldCoords\r\n );\r\n\r\n // Reverse perspective divide\r\n var w = 1.0 / worldCoords.w;\r\n Cartesian3.multiplyByScalar(worldCoords, w, worldCoords);\r\n }\r\n return Cartesian3.fromCartesian4(worldCoords, result);\r\n};\r\nexport default SceneTransforms;\r\n","import BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport NearFarScalar from \"../Core/NearFarScalar.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport HeightReference from \"./HeightReference.js\";\r\nimport HorizontalOrigin from \"./HorizontalOrigin.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport SceneTransforms from \"./SceneTransforms.js\";\r\nimport VerticalOrigin from \"./VerticalOrigin.js\";\r\n\r\n/**\r\n * A viewport-aligned image positioned in the 3D scene, that is created\r\n * and rendered using a {@link BillboardCollection}. A billboard is created and its initial\r\n * properties are set by calling {@link BillboardCollection#add}.\r\n *

\r\n *
\r\n *
\r\n * Example billboards\r\n *
\r\n *\r\n * @alias Billboard\r\n *\r\n * @performance Reading a property, e.g., {@link Billboard#show}, is constant time.\r\n * Assigning to a property is constant time but results in\r\n * CPU to GPU traffic when {@link BillboardCollection#update} is called. The per-billboard traffic is\r\n * the same regardless of how many properties were updated. If most billboards in a collection need to be\r\n * updated, it may be more efficient to clear the collection with {@link BillboardCollection#removeAll}\r\n * and add new billboards instead of modifying each one.\r\n *\r\n * @exception {DeveloperError} scaleByDistance.far must be greater than scaleByDistance.near\r\n * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near\r\n * @exception {DeveloperError} pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near\r\n * @exception {DeveloperError} distanceDisplayCondition.far must be greater than distanceDisplayCondition.near\r\n *\r\n * @see BillboardCollection\r\n * @see BillboardCollection#add\r\n * @see Label\r\n *\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Billboards.html|Cesium Sandcastle Billboard Demo}\r\n */\r\nfunction Billboard(options, billboardCollection) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n defined(options.disableDepthTestDistance) &&\r\n options.disableDepthTestDistance < 0.0\r\n ) {\r\n throw new DeveloperError(\r\n \"disableDepthTestDistance must be greater than or equal to 0.0.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var translucencyByDistance = options.translucencyByDistance;\r\n var pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance;\r\n var scaleByDistance = options.scaleByDistance;\r\n var distanceDisplayCondition = options.distanceDisplayCondition;\r\n if (defined(translucencyByDistance)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (translucencyByDistance.far <= translucencyByDistance.near) {\r\n throw new DeveloperError(\r\n \"translucencyByDistance.far must be greater than translucencyByDistance.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n translucencyByDistance = NearFarScalar.clone(translucencyByDistance);\r\n }\r\n if (defined(pixelOffsetScaleByDistance)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (pixelOffsetScaleByDistance.far <= pixelOffsetScaleByDistance.near) {\r\n throw new DeveloperError(\r\n \"pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n pixelOffsetScaleByDistance = NearFarScalar.clone(\r\n pixelOffsetScaleByDistance\r\n );\r\n }\r\n if (defined(scaleByDistance)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (scaleByDistance.far <= scaleByDistance.near) {\r\n throw new DeveloperError(\r\n \"scaleByDistance.far must be greater than scaleByDistance.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n scaleByDistance = NearFarScalar.clone(scaleByDistance);\r\n }\r\n if (defined(distanceDisplayCondition)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (distanceDisplayCondition.far <= distanceDisplayCondition.near) {\r\n throw new DeveloperError(\r\n \"distanceDisplayCondition.far must be greater than distanceDisplayCondition.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n distanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition\r\n );\r\n }\r\n\r\n this._show = defaultValue(options.show, true);\r\n this._position = Cartesian3.clone(\r\n defaultValue(options.position, Cartesian3.ZERO)\r\n );\r\n this._actualPosition = Cartesian3.clone(this._position); // For columbus view and 2D\r\n this._pixelOffset = Cartesian2.clone(\r\n defaultValue(options.pixelOffset, Cartesian2.ZERO)\r\n );\r\n this._translate = new Cartesian2(0.0, 0.0); // used by labels for glyph vertex translation\r\n this._eyeOffset = Cartesian3.clone(\r\n defaultValue(options.eyeOffset, Cartesian3.ZERO)\r\n );\r\n this._heightReference = defaultValue(\r\n options.heightReference,\r\n HeightReference.NONE\r\n );\r\n this._verticalOrigin = defaultValue(\r\n options.verticalOrigin,\r\n VerticalOrigin.CENTER\r\n );\r\n this._horizontalOrigin = defaultValue(\r\n options.horizontalOrigin,\r\n HorizontalOrigin.CENTER\r\n );\r\n this._scale = defaultValue(options.scale, 1.0);\r\n this._color = Color.clone(defaultValue(options.color, Color.WHITE));\r\n this._rotation = defaultValue(options.rotation, 0.0);\r\n this._alignedAxis = Cartesian3.clone(\r\n defaultValue(options.alignedAxis, Cartesian3.ZERO)\r\n );\r\n this._width = options.width;\r\n this._height = options.height;\r\n this._scaleByDistance = scaleByDistance;\r\n this._translucencyByDistance = translucencyByDistance;\r\n this._pixelOffsetScaleByDistance = pixelOffsetScaleByDistance;\r\n this._sizeInMeters = defaultValue(options.sizeInMeters, false);\r\n this._distanceDisplayCondition = distanceDisplayCondition;\r\n this._disableDepthTestDistance = options.disableDepthTestDistance;\r\n this._id = options.id;\r\n this._collection = defaultValue(options.collection, billboardCollection);\r\n\r\n this._pickId = undefined;\r\n this._pickPrimitive = defaultValue(options._pickPrimitive, this);\r\n this._billboardCollection = billboardCollection;\r\n this._dirty = false;\r\n this._index = -1; //Used only by BillboardCollection\r\n this._batchIndex = undefined; // Used only by Vector3DTilePoints and BillboardCollection\r\n\r\n this._imageIndex = -1;\r\n this._imageIndexPromise = undefined;\r\n this._imageId = undefined;\r\n this._image = undefined;\r\n this._imageSubRegion = undefined;\r\n this._imageWidth = undefined;\r\n this._imageHeight = undefined;\r\n\r\n this._labelDimensions = undefined;\r\n this._labelHorizontalOrigin = undefined;\r\n this._labelTranslate = undefined;\r\n\r\n var image = options.image;\r\n var imageId = options.imageId;\r\n if (defined(image)) {\r\n if (!defined(imageId)) {\r\n if (typeof image === \"string\") {\r\n imageId = image;\r\n } else if (defined(image.src)) {\r\n imageId = image.src;\r\n } else {\r\n imageId = createGuid();\r\n }\r\n }\r\n\r\n this._imageId = imageId;\r\n this._image = image;\r\n }\r\n\r\n if (defined(options.imageSubRegion)) {\r\n this._imageId = imageId;\r\n this._imageSubRegion = options.imageSubRegion;\r\n }\r\n\r\n if (defined(this._billboardCollection._textureAtlas)) {\r\n this._loadImage();\r\n }\r\n\r\n this._actualClampedPosition = undefined;\r\n this._removeCallbackFunc = undefined;\r\n this._mode = SceneMode.SCENE3D;\r\n\r\n this._clusterShow = true;\r\n this._outlineColor = Color.clone(\r\n defaultValue(options.outlineColor, Color.BLACK)\r\n );\r\n this._outlineWidth = defaultValue(options.outlineWidth, 0.0);\r\n\r\n this._updateClamping();\r\n}\r\n\r\nvar SHOW_INDEX = (Billboard.SHOW_INDEX = 0);\r\nvar POSITION_INDEX = (Billboard.POSITION_INDEX = 1);\r\nvar PIXEL_OFFSET_INDEX = (Billboard.PIXEL_OFFSET_INDEX = 2);\r\nvar EYE_OFFSET_INDEX = (Billboard.EYE_OFFSET_INDEX = 3);\r\nvar HORIZONTAL_ORIGIN_INDEX = (Billboard.HORIZONTAL_ORIGIN_INDEX = 4);\r\nvar VERTICAL_ORIGIN_INDEX = (Billboard.VERTICAL_ORIGIN_INDEX = 5);\r\nvar SCALE_INDEX = (Billboard.SCALE_INDEX = 6);\r\nvar IMAGE_INDEX_INDEX = (Billboard.IMAGE_INDEX_INDEX = 7);\r\nvar COLOR_INDEX = (Billboard.COLOR_INDEX = 8);\r\nvar ROTATION_INDEX = (Billboard.ROTATION_INDEX = 9);\r\nvar ALIGNED_AXIS_INDEX = (Billboard.ALIGNED_AXIS_INDEX = 10);\r\nvar SCALE_BY_DISTANCE_INDEX = (Billboard.SCALE_BY_DISTANCE_INDEX = 11);\r\nvar TRANSLUCENCY_BY_DISTANCE_INDEX = (Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX = 12);\r\nvar PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = (Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX = 13);\r\nvar DISTANCE_DISPLAY_CONDITION = (Billboard.DISTANCE_DISPLAY_CONDITION = 14);\r\nvar DISABLE_DEPTH_DISTANCE = (Billboard.DISABLE_DEPTH_DISTANCE = 15);\r\nBillboard.TEXTURE_COORDINATE_BOUNDS = 16;\r\nvar SDF_INDEX = (Billboard.SDF_INDEX = 17);\r\nBillboard.NUMBER_OF_PROPERTIES = 18;\r\n\r\nfunction makeDirty(billboard, propertyChanged) {\r\n var billboardCollection = billboard._billboardCollection;\r\n if (defined(billboardCollection)) {\r\n billboardCollection._updateBillboard(billboard, propertyChanged);\r\n billboard._dirty = true;\r\n }\r\n}\r\n\r\nObject.defineProperties(Billboard.prototype, {\r\n /**\r\n * Determines if this billboard will be shown. Use this to hide or show a billboard, instead\r\n * of removing it and re-adding it to the collection.\r\n * @memberof Billboard.prototype\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n show: {\r\n get: function () {\r\n return this._show;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._show !== value) {\r\n this._show = value;\r\n makeDirty(this, SHOW_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the Cartesian position of this billboard.\r\n * @memberof Billboard.prototype\r\n * @type {Cartesian3}\r\n */\r\n position: {\r\n get: function () {\r\n return this._position;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var position = this._position;\r\n if (!Cartesian3.equals(position, value)) {\r\n Cartesian3.clone(value, position);\r\n Cartesian3.clone(value, this._actualPosition);\r\n this._updateClamping();\r\n makeDirty(this, POSITION_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the height reference of this billboard.\r\n * @memberof Billboard.prototype\r\n * @type {HeightReference}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: {\r\n get: function () {\r\n return this._heightReference;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var heightReference = this._heightReference;\r\n if (value !== heightReference) {\r\n this._heightReference = value;\r\n this._updateClamping();\r\n makeDirty(this, POSITION_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the pixel offset in screen space from the origin of this billboard. This is commonly used\r\n * to align multiple billboards and labels at the same position, e.g., an image and text. The\r\n * screen space origin is the top, left corner of the canvas; x increases from\r\n * left to right, and y increases from top to bottom.\r\n *

\r\n *
\r\n * \r\n * \r\n * \r\n *
default
b.pixeloffset = new Cartesian2(50, 25);
\r\n * The billboard's origin is indicated by the yellow point.\r\n *
\r\n * @memberof Billboard.prototype\r\n * @type {Cartesian2}\r\n */\r\n pixelOffset: {\r\n get: function () {\r\n return this._pixelOffset;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var pixelOffset = this._pixelOffset;\r\n if (!Cartesian2.equals(pixelOffset, value)) {\r\n Cartesian2.clone(value, pixelOffset);\r\n makeDirty(this, PIXEL_OFFSET_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets near and far scaling properties of a Billboard based on the billboard's distance from the camera.\r\n * A billboard's scale will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the billboard's scale remains clamped to the nearest bound. If undefined,\r\n * scaleByDistance will be disabled.\r\n * @memberof Billboard.prototype\r\n * @type {NearFarScalar}\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a billboard's scaleByDistance to scale by 1.5 when the\r\n * // camera is 1500 meters from the billboard and disappear as\r\n * // the camera distance approaches 8.0e6 meters.\r\n * b.scaleByDistance = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.0);\r\n *\r\n * @example\r\n * // Example 2.\r\n * // disable scaling by distance\r\n * b.scaleByDistance = undefined;\r\n */\r\n scaleByDistance: {\r\n get: function () {\r\n return this._scaleByDistance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var scaleByDistance = this._scaleByDistance;\r\n if (!NearFarScalar.equals(scaleByDistance, value)) {\r\n this._scaleByDistance = NearFarScalar.clone(value, scaleByDistance);\r\n makeDirty(this, SCALE_BY_DISTANCE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets near and far translucency properties of a Billboard based on the billboard's distance from the camera.\r\n * A billboard's translucency will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the billboard's translucency remains clamped to the nearest bound. If undefined,\r\n * translucencyByDistance will be disabled.\r\n * @memberof Billboard.prototype\r\n * @type {NearFarScalar}\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a billboard's translucency to 1.0 when the\r\n * // camera is 1500 meters from the billboard and disappear as\r\n * // the camera distance approaches 8.0e6 meters.\r\n * b.translucencyByDistance = new Cesium.NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0);\r\n *\r\n * @example\r\n * // Example 2.\r\n * // disable translucency by distance\r\n * b.translucencyByDistance = undefined;\r\n */\r\n translucencyByDistance: {\r\n get: function () {\r\n return this._translucencyByDistance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var translucencyByDistance = this._translucencyByDistance;\r\n if (!NearFarScalar.equals(translucencyByDistance, value)) {\r\n this._translucencyByDistance = NearFarScalar.clone(\r\n value,\r\n translucencyByDistance\r\n );\r\n makeDirty(this, TRANSLUCENCY_BY_DISTANCE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets near and far pixel offset scaling properties of a Billboard based on the billboard's distance from the camera.\r\n * A billboard's pixel offset will be scaled between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the billboard's pixel offset scale remains clamped to the nearest bound. If undefined,\r\n * pixelOffsetScaleByDistance will be disabled.\r\n * @memberof Billboard.prototype\r\n * @type {NearFarScalar}\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a billboard's pixel offset scale to 0.0 when the\r\n * // camera is 1500 meters from the billboard and scale pixel offset to 10.0 pixels\r\n * // in the y direction the camera distance approaches 8.0e6 meters.\r\n * b.pixelOffset = new Cesium.Cartesian2(0.0, 1.0);\r\n * b.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(1.5e2, 0.0, 8.0e6, 10.0);\r\n *\r\n * @example\r\n * // Example 2.\r\n * // disable pixel offset by distance\r\n * b.pixelOffsetScaleByDistance = undefined;\r\n */\r\n pixelOffsetScaleByDistance: {\r\n get: function () {\r\n return this._pixelOffsetScaleByDistance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance;\r\n if (!NearFarScalar.equals(pixelOffsetScaleByDistance, value)) {\r\n this._pixelOffsetScaleByDistance = NearFarScalar.clone(\r\n value,\r\n pixelOffsetScaleByDistance\r\n );\r\n makeDirty(this, PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the 3D Cartesian offset applied to this billboard in eye coordinates. Eye coordinates is a left-handed\r\n * coordinate system, where x points towards the viewer's right, y points up, and\r\n * z points into the screen. Eye coordinates use the same scale as world and model coordinates,\r\n * which is typically meters.\r\n *

\r\n * An eye offset is commonly used to arrange multiple billboards or objects at the same position, e.g., to\r\n * arrange a billboard above its corresponding 3D model.\r\n *

\r\n * Below, the billboard is positioned at the center of the Earth but an eye offset makes it always\r\n * appear on top of the Earth regardless of the viewer's or Earth's orientation.\r\n *

\r\n *
\r\n * \r\n * \r\n * \r\n *
\r\n * b.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);

\r\n *
\r\n * @memberof Billboard.prototype\r\n * @type {Cartesian3}\r\n */\r\n eyeOffset: {\r\n get: function () {\r\n return this._eyeOffset;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var eyeOffset = this._eyeOffset;\r\n if (!Cartesian3.equals(eyeOffset, value)) {\r\n Cartesian3.clone(value, eyeOffset);\r\n makeDirty(this, EYE_OFFSET_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the horizontal origin of this billboard, which determines if the billboard is\r\n * to the left, center, or right of its anchor position.\r\n *

\r\n *
\r\n *
\r\n *
\r\n * @memberof Billboard.prototype\r\n * @type {HorizontalOrigin}\r\n * @example\r\n * // Use a bottom, left origin\r\n * b.horizontalOrigin = Cesium.HorizontalOrigin.LEFT;\r\n * b.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;\r\n */\r\n horizontalOrigin: {\r\n get: function () {\r\n return this._horizontalOrigin;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._horizontalOrigin !== value) {\r\n this._horizontalOrigin = value;\r\n makeDirty(this, HORIZONTAL_ORIGIN_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the vertical origin of this billboard, which determines if the billboard is\r\n * to the above, below, or at the center of its anchor position.\r\n *

\r\n *
\r\n *
\r\n *
\r\n * @memberof Billboard.prototype\r\n * @type {VerticalOrigin}\r\n * @example\r\n * // Use a bottom, left origin\r\n * b.horizontalOrigin = Cesium.HorizontalOrigin.LEFT;\r\n * b.verticalOrigin = Cesium.VerticalOrigin.BOTTOM;\r\n */\r\n verticalOrigin: {\r\n get: function () {\r\n return this._verticalOrigin;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._verticalOrigin !== value) {\r\n this._verticalOrigin = value;\r\n makeDirty(this, VERTICAL_ORIGIN_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the uniform scale that is multiplied with the billboard's image size in pixels.\r\n * A scale of 1.0 does not change the size of the billboard; a scale greater than\r\n * 1.0 enlarges the billboard; a positive scale less than 1.0 shrinks\r\n * the billboard.\r\n *

\r\n *
\r\n *
\r\n * From left to right in the above image, the scales are 0.5, 1.0,\r\n * and 2.0.\r\n *
\r\n * @memberof Billboard.prototype\r\n * @type {Number}\r\n */\r\n scale: {\r\n get: function () {\r\n return this._scale;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._scale !== value) {\r\n this._scale = value;\r\n makeDirty(this, SCALE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the color that is multiplied with the billboard's texture. This has two common use cases. First,\r\n * the same white texture may be used by many different billboards, each with a different color, to create\r\n * colored billboards. Second, the color's alpha component can be used to make the billboard translucent as shown below.\r\n * An alpha of 0.0 makes the billboard transparent, and 1.0 makes the billboard opaque.\r\n *

\r\n *
\r\n * \r\n * \r\n * \r\n *
default
alpha : 0.5
\r\n *
\r\n *
\r\n * The red, green, blue, and alpha values are indicated by value's red, green,\r\n * blue, and alpha properties as shown in Example 1. These components range from 0.0\r\n * (no intensity) to 1.0 (full intensity).\r\n * @memberof Billboard.prototype\r\n * @type {Color}\r\n *\r\n * @example\r\n * // Example 1. Assign yellow.\r\n * b.color = Cesium.Color.YELLOW;\r\n *\r\n * @example\r\n * // Example 2. Make a billboard 50% translucent.\r\n * b.color = new Cesium.Color(1.0, 1.0, 1.0, 0.5);\r\n */\r\n color: {\r\n get: function () {\r\n return this._color;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var color = this._color;\r\n if (!Color.equals(color, value)) {\r\n Color.clone(value, color);\r\n makeDirty(this, COLOR_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the rotation angle in radians.\r\n * @memberof Billboard.prototype\r\n * @type {Number}\r\n */\r\n rotation: {\r\n get: function () {\r\n return this._rotation;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._rotation !== value) {\r\n this._rotation = value;\r\n makeDirty(this, ROTATION_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the aligned axis in world space. The aligned axis is the unit vector that the billboard up vector points towards.\r\n * The default is the zero vector, which means the billboard is aligned to the screen up vector.\r\n * @memberof Billboard.prototype\r\n * @type {Cartesian3}\r\n * @example\r\n * // Example 1.\r\n * // Have the billboard up vector point north\r\n * billboard.alignedAxis = Cesium.Cartesian3.UNIT_Z;\r\n *\r\n * @example\r\n * // Example 2.\r\n * // Have the billboard point east.\r\n * billboard.alignedAxis = Cesium.Cartesian3.UNIT_Z;\r\n * billboard.rotation = -Cesium.Math.PI_OVER_TWO;\r\n *\r\n * @example\r\n * // Example 3.\r\n * // Reset the aligned axis\r\n * billboard.alignedAxis = Cesium.Cartesian3.ZERO;\r\n */\r\n alignedAxis: {\r\n get: function () {\r\n return this._alignedAxis;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var alignedAxis = this._alignedAxis;\r\n if (!Cartesian3.equals(alignedAxis, value)) {\r\n Cartesian3.clone(value, alignedAxis);\r\n makeDirty(this, ALIGNED_AXIS_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets a width for the billboard. If undefined, the image width will be used.\r\n * @memberof Billboard.prototype\r\n * @type {Number}\r\n */\r\n width: {\r\n get: function () {\r\n return defaultValue(this._width, this._imageWidth);\r\n },\r\n set: function (value) {\r\n if (this._width !== value) {\r\n this._width = value;\r\n makeDirty(this, IMAGE_INDEX_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets a height for the billboard. If undefined, the image height will be used.\r\n * @memberof Billboard.prototype\r\n * @type {Number}\r\n */\r\n height: {\r\n get: function () {\r\n return defaultValue(this._height, this._imageHeight);\r\n },\r\n set: function (value) {\r\n if (this._height !== value) {\r\n this._height = value;\r\n makeDirty(this, IMAGE_INDEX_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets if the billboard size is in meters or pixels. true to size the billboard in meters;\r\n * otherwise, the size is in pixels.\r\n * @memberof Billboard.prototype\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n sizeInMeters: {\r\n get: function () {\r\n return this._sizeInMeters;\r\n },\r\n set: function (value) {\r\n if (this._sizeInMeters !== value) {\r\n this._sizeInMeters = value;\r\n makeDirty(this, COLOR_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the condition specifying at what distance from the camera that this billboard will be displayed.\r\n * @memberof Billboard.prototype\r\n * @type {DistanceDisplayCondition}\r\n * @default undefined\r\n */\r\n distanceDisplayCondition: {\r\n get: function () {\r\n return this._distanceDisplayCondition;\r\n },\r\n set: function (value) {\r\n if (\r\n !DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n this._distanceDisplayCondition = DistanceDisplayCondition.clone(\r\n value,\r\n this._distanceDisplayCondition\r\n );\r\n makeDirty(this, DISTANCE_DISPLAY_CONDITION);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.\r\n * When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.\r\n * @memberof Billboard.prototype\r\n * @type {Number}\r\n */\r\n disableDepthTestDistance: {\r\n get: function () {\r\n return this._disableDepthTestDistance;\r\n },\r\n set: function (value) {\r\n if (this._disableDepthTestDistance !== value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value < 0.0) {\r\n throw new DeveloperError(\r\n \"disableDepthTestDistance must be greater than or equal to 0.0.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n this._disableDepthTestDistance = value;\r\n makeDirty(this, DISABLE_DEPTH_DISTANCE);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the user-defined object returned when the billboard is picked.\r\n * @memberof Billboard.prototype\r\n * @type {Object}\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n set: function (value) {\r\n this._id = value;\r\n if (defined(this._pickId)) {\r\n this._pickId.object.id = value;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The primitive to return when picking this billboard.\r\n * @memberof Billboard.prototype\r\n * @private\r\n */\r\n pickPrimitive: {\r\n get: function () {\r\n return this._pickPrimitive;\r\n },\r\n set: function (value) {\r\n this._pickPrimitive = value;\r\n if (defined(this._pickId)) {\r\n this._pickId.object.primitive = value;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n pickId: {\r\n get: function () {\r\n return this._pickId;\r\n },\r\n },\r\n\r\n /**\r\n *

\r\n * Gets or sets the image to be used for this billboard. If a texture has already been created for the\r\n * given image, the existing texture is used.\r\n *

\r\n *

\r\n * This property can be set to a loaded Image, a URL which will be loaded as an Image automatically,\r\n * a canvas, or another billboard's image property (from the same billboard collection).\r\n *

\r\n *\r\n * @memberof Billboard.prototype\r\n * @type {String}\r\n * @example\r\n * // load an image from a URL\r\n * b.image = 'some/image/url.png';\r\n *\r\n * // assuming b1 and b2 are billboards in the same billboard collection,\r\n * // use the same image for both billboards.\r\n * b2.image = b1.image;\r\n */\r\n image: {\r\n get: function () {\r\n return this._imageId;\r\n },\r\n set: function (value) {\r\n if (!defined(value)) {\r\n this._imageIndex = -1;\r\n this._imageSubRegion = undefined;\r\n this._imageId = undefined;\r\n this._image = undefined;\r\n this._imageIndexPromise = undefined;\r\n makeDirty(this, IMAGE_INDEX_INDEX);\r\n } else if (typeof value === \"string\") {\r\n this.setImage(value, value);\r\n } else if (value instanceof Resource) {\r\n this.setImage(value.url, value);\r\n } else if (defined(value.src)) {\r\n this.setImage(value.src, value);\r\n } else {\r\n this.setImage(createGuid(), value);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * When true, this billboard is ready to render, i.e., the image\r\n * has been downloaded and the WebGL resources are created.\r\n *\r\n * @memberof Billboard.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n ready: {\r\n get: function () {\r\n return this._imageIndex !== -1;\r\n },\r\n },\r\n\r\n /**\r\n * Keeps track of the position of the billboard based on the height reference.\r\n * @memberof Billboard.prototype\r\n * @type {Cartesian3}\r\n * @private\r\n */\r\n _clampedPosition: {\r\n get: function () {\r\n return this._actualClampedPosition;\r\n },\r\n set: function (value) {\r\n this._actualClampedPosition = Cartesian3.clone(\r\n value,\r\n this._actualClampedPosition\r\n );\r\n makeDirty(this, POSITION_INDEX);\r\n },\r\n },\r\n\r\n /**\r\n * Determines whether or not this billboard will be shown or hidden because it was clustered.\r\n * @memberof Billboard.prototype\r\n * @type {Boolean}\r\n * @private\r\n */\r\n clusterShow: {\r\n get: function () {\r\n return this._clusterShow;\r\n },\r\n set: function (value) {\r\n if (this._clusterShow !== value) {\r\n this._clusterShow = value;\r\n makeDirty(this, SHOW_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The outline color of this Billboard. Effective only for SDF billboards like Label glyphs.\r\n * @memberof Billboard.prototype\r\n * @type {Color}\r\n * @private\r\n */\r\n outlineColor: {\r\n get: function () {\r\n return this._outlineColor;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var outlineColor = this._outlineColor;\r\n if (!Color.equals(outlineColor, value)) {\r\n Color.clone(value, outlineColor);\r\n makeDirty(this, SDF_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * The outline width of this Billboard in pixels. Effective only for SDF billboards like Label glyphs.\r\n * @memberof Billboard.prototype\r\n * @type {Number}\r\n * @private\r\n */\r\n outlineWidth: {\r\n get: function () {\r\n return this._outlineWidth;\r\n },\r\n set: function (value) {\r\n if (this._outlineWidth !== value) {\r\n this._outlineWidth = value;\r\n makeDirty(this, SDF_INDEX);\r\n }\r\n },\r\n },\r\n});\r\n\r\nBillboard.prototype.getPickId = function (context) {\r\n if (!defined(this._pickId)) {\r\n this._pickId = context.createPickId({\r\n primitive: this._pickPrimitive,\r\n collection: this._collection,\r\n id: this._id,\r\n });\r\n }\r\n\r\n return this._pickId;\r\n};\r\n\r\nBillboard.prototype._updateClamping = function () {\r\n Billboard._updateClamping(this._billboardCollection, this);\r\n};\r\n\r\nvar scratchCartographic = new Cartographic();\r\nvar scratchPosition = new Cartesian3();\r\n\r\nBillboard._updateClamping = function (collection, owner) {\r\n var scene = collection._scene;\r\n if (!defined(scene) || !defined(scene.globe)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (owner._heightReference !== HeightReference.NONE) {\r\n throw new DeveloperError(\r\n \"Height reference is not supported without a scene and globe.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n return;\r\n }\r\n\r\n var globe = scene.globe;\r\n var ellipsoid = globe.ellipsoid;\r\n var surface = globe._surface;\r\n\r\n var mode = scene.frameState.mode;\r\n\r\n var modeChanged = mode !== owner._mode;\r\n owner._mode = mode;\r\n\r\n if (\r\n (owner._heightReference === HeightReference.NONE || modeChanged) &&\r\n defined(owner._removeCallbackFunc)\r\n ) {\r\n owner._removeCallbackFunc();\r\n owner._removeCallbackFunc = undefined;\r\n owner._clampedPosition = undefined;\r\n }\r\n\r\n if (\r\n owner._heightReference === HeightReference.NONE ||\r\n !defined(owner._position)\r\n ) {\r\n return;\r\n }\r\n\r\n var position = ellipsoid.cartesianToCartographic(owner._position);\r\n if (!defined(position)) {\r\n owner._actualClampedPosition = undefined;\r\n return;\r\n }\r\n\r\n if (defined(owner._removeCallbackFunc)) {\r\n owner._removeCallbackFunc();\r\n }\r\n\r\n function updateFunction(clampedPosition) {\r\n if (owner._heightReference === HeightReference.RELATIVE_TO_GROUND) {\r\n if (owner._mode === SceneMode.SCENE3D) {\r\n var clampedCart = ellipsoid.cartesianToCartographic(\r\n clampedPosition,\r\n scratchCartographic\r\n );\r\n clampedCart.height += position.height;\r\n ellipsoid.cartographicToCartesian(clampedCart, clampedPosition);\r\n } else {\r\n clampedPosition.x += position.height;\r\n }\r\n }\r\n owner._clampedPosition = Cartesian3.clone(\r\n clampedPosition,\r\n owner._clampedPosition\r\n );\r\n }\r\n owner._removeCallbackFunc = surface.updateHeight(position, updateFunction);\r\n\r\n Cartographic.clone(position, scratchCartographic);\r\n var height = globe.getHeight(position);\r\n if (defined(height)) {\r\n scratchCartographic.height = height;\r\n }\r\n\r\n ellipsoid.cartographicToCartesian(scratchCartographic, scratchPosition);\r\n\r\n updateFunction(scratchPosition);\r\n};\r\n\r\nBillboard.prototype._loadImage = function () {\r\n var atlas = this._billboardCollection._textureAtlas;\r\n\r\n var imageId = this._imageId;\r\n var image = this._image;\r\n var imageSubRegion = this._imageSubRegion;\r\n var imageIndexPromise;\r\n\r\n if (defined(image)) {\r\n imageIndexPromise = atlas.addImage(imageId, image);\r\n }\r\n if (defined(imageSubRegion)) {\r\n imageIndexPromise = atlas.addSubRegion(imageId, imageSubRegion);\r\n }\r\n\r\n this._imageIndexPromise = imageIndexPromise;\r\n\r\n if (!defined(imageIndexPromise)) {\r\n return;\r\n }\r\n\r\n var that = this;\r\n imageIndexPromise\r\n .then(function (index) {\r\n if (\r\n that._imageId !== imageId ||\r\n that._image !== image ||\r\n !BoundingRectangle.equals(that._imageSubRegion, imageSubRegion)\r\n ) {\r\n // another load occurred before this one finished, ignore the index\r\n return;\r\n }\r\n\r\n // fill in imageWidth and imageHeight\r\n var textureCoordinates = atlas.textureCoordinates[index];\r\n that._imageWidth = atlas.texture.width * textureCoordinates.width;\r\n that._imageHeight = atlas.texture.height * textureCoordinates.height;\r\n\r\n that._imageIndex = index;\r\n that._ready = true;\r\n that._image = undefined;\r\n that._imageIndexPromise = undefined;\r\n makeDirty(that, IMAGE_INDEX_INDEX);\r\n })\r\n .otherwise(function (error) {\r\n console.error(\"Error loading image for billboard: \" + error);\r\n that._imageIndexPromise = undefined;\r\n });\r\n};\r\n\r\n/**\r\n *

\r\n * Sets the image to be used for this billboard. If a texture has already been created for the\r\n * given id, the existing texture is used.\r\n *

\r\n *

\r\n * This function is useful for dynamically creating textures that are shared across many billboards.\r\n * Only the first billboard will actually call the function and create the texture, while subsequent\r\n * billboards created with the same id will simply re-use the existing texture.\r\n *

\r\n *

\r\n * To load an image from a URL, setting the {@link Billboard#image} property is more convenient.\r\n *

\r\n *\r\n * @param {String} id The id of the image. This can be any string that uniquely identifies the image.\r\n * @param {HTMLImageElement|HTMLCanvasElement|String|Resource|Billboard.CreateImageCallback} image The image to load. This parameter\r\n * can either be a loaded Image or Canvas, a URL which will be loaded as an Image automatically,\r\n * or a function which will be called to create the image if it hasn't been loaded already.\r\n * @example\r\n * // create a billboard image dynamically\r\n * function drawImage(id) {\r\n * // create and draw an image using a canvas\r\n * var canvas = document.createElement('canvas');\r\n * var context2D = canvas.getContext('2d');\r\n * // ... draw image\r\n * return canvas;\r\n * }\r\n * // drawImage will be called to create the texture\r\n * b.setImage('myImage', drawImage);\r\n *\r\n * // subsequent billboards created in the same collection using the same id will use the existing\r\n * // texture, without the need to create the canvas or draw the image\r\n * b2.setImage('myImage', drawImage);\r\n */\r\nBillboard.prototype.setImage = function (id, image) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(id)) {\r\n throw new DeveloperError(\"id is required.\");\r\n }\r\n if (!defined(image)) {\r\n throw new DeveloperError(\"image is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._imageId === id) {\r\n return;\r\n }\r\n\r\n this._imageIndex = -1;\r\n this._imageSubRegion = undefined;\r\n this._imageId = id;\r\n this._image = image;\r\n\r\n if (defined(this._billboardCollection._textureAtlas)) {\r\n this._loadImage();\r\n }\r\n};\r\n\r\n/**\r\n * Uses a sub-region of the image with the given id as the image for this billboard,\r\n * measured in pixels from the bottom-left.\r\n *\r\n * @param {String} id The id of the image to use.\r\n * @param {BoundingRectangle} subRegion The sub-region of the image.\r\n *\r\n * @exception {RuntimeError} image with id must be in the atlas\r\n */\r\nBillboard.prototype.setImageSubRegion = function (id, subRegion) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(id)) {\r\n throw new DeveloperError(\"id is required.\");\r\n }\r\n if (!defined(subRegion)) {\r\n throw new DeveloperError(\"subRegion is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (\r\n this._imageId === id &&\r\n BoundingRectangle.equals(this._imageSubRegion, subRegion)\r\n ) {\r\n return;\r\n }\r\n\r\n this._imageIndex = -1;\r\n this._imageId = id;\r\n this._imageSubRegion = BoundingRectangle.clone(subRegion);\r\n\r\n if (defined(this._billboardCollection._textureAtlas)) {\r\n this._loadImage();\r\n }\r\n};\r\n\r\nBillboard.prototype._setTranslate = function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var translate = this._translate;\r\n if (!Cartesian2.equals(translate, value)) {\r\n Cartesian2.clone(value, translate);\r\n makeDirty(this, PIXEL_OFFSET_INDEX);\r\n }\r\n};\r\n\r\nBillboard.prototype._getActualPosition = function () {\r\n return defined(this._clampedPosition)\r\n ? this._clampedPosition\r\n : this._actualPosition;\r\n};\r\n\r\nBillboard.prototype._setActualPosition = function (value) {\r\n if (!defined(this._clampedPosition)) {\r\n Cartesian3.clone(value, this._actualPosition);\r\n }\r\n makeDirty(this, POSITION_INDEX);\r\n};\r\n\r\nvar tempCartesian3 = new Cartesian4();\r\nBillboard._computeActualPosition = function (\r\n billboard,\r\n position,\r\n frameState,\r\n modelMatrix\r\n) {\r\n if (defined(billboard._clampedPosition)) {\r\n if (frameState.mode !== billboard._mode) {\r\n billboard._updateClamping();\r\n }\r\n return billboard._clampedPosition;\r\n } else if (frameState.mode === SceneMode.SCENE3D) {\r\n return position;\r\n }\r\n\r\n Matrix4.multiplyByPoint(modelMatrix, position, tempCartesian3);\r\n return SceneTransforms.computeActualWgs84Position(frameState, tempCartesian3);\r\n};\r\n\r\nvar scratchCartesian3 = new Cartesian3();\r\n\r\n// This function is basically a stripped-down JavaScript version of BillboardCollectionVS.glsl\r\nBillboard._computeScreenSpacePosition = function (\r\n modelMatrix,\r\n position,\r\n eyeOffset,\r\n pixelOffset,\r\n scene,\r\n result\r\n) {\r\n // Model to world coordinates\r\n var positionWorld = Matrix4.multiplyByPoint(\r\n modelMatrix,\r\n position,\r\n scratchCartesian3\r\n );\r\n\r\n // World to window coordinates\r\n var positionWC = SceneTransforms.wgs84WithEyeOffsetToWindowCoordinates(\r\n scene,\r\n positionWorld,\r\n eyeOffset,\r\n result\r\n );\r\n if (!defined(positionWC)) {\r\n return undefined;\r\n }\r\n\r\n // Apply pixel offset\r\n Cartesian2.add(positionWC, pixelOffset, positionWC);\r\n\r\n return positionWC;\r\n};\r\n\r\nvar scratchPixelOffset = new Cartesian2(0.0, 0.0);\r\n\r\n/**\r\n * Computes the screen-space position of the billboard's origin, taking into account eye and pixel offsets.\r\n * The screen space origin is the top, left corner of the canvas; x increases from\r\n * left to right, and y increases from top to bottom.\r\n *\r\n * @param {Scene} scene The scene.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The screen-space position of the billboard.\r\n *\r\n * @exception {DeveloperError} Billboard must be in a collection.\r\n *\r\n * @example\r\n * console.log(b.computeScreenSpacePosition(scene).toString());\r\n *\r\n * @see Billboard#eyeOffset\r\n * @see Billboard#pixelOffset\r\n */\r\nBillboard.prototype.computeScreenSpacePosition = function (scene, result) {\r\n var billboardCollection = this._billboardCollection;\r\n if (!defined(result)) {\r\n result = new Cartesian2();\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(billboardCollection)) {\r\n throw new DeveloperError(\r\n \"Billboard must be in a collection. Was it removed?\"\r\n );\r\n }\r\n if (!defined(scene)) {\r\n throw new DeveloperError(\"scene is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // pixel offset for screen space computation is the pixelOffset + screen space translate\r\n Cartesian2.clone(this._pixelOffset, scratchPixelOffset);\r\n Cartesian2.add(scratchPixelOffset, this._translate, scratchPixelOffset);\r\n\r\n var modelMatrix = billboardCollection.modelMatrix;\r\n var position = this._position;\r\n if (defined(this._clampedPosition)) {\r\n position = this._clampedPosition;\r\n if (scene.mode !== SceneMode.SCENE3D) {\r\n // position needs to be in world coordinates\r\n var projection = scene.mapProjection;\r\n var ellipsoid = projection.ellipsoid;\r\n var cart = projection.unproject(position, scratchCartographic);\r\n position = ellipsoid.cartographicToCartesian(cart, scratchCartesian3);\r\n modelMatrix = Matrix4.IDENTITY;\r\n }\r\n }\r\n\r\n var windowCoordinates = Billboard._computeScreenSpacePosition(\r\n modelMatrix,\r\n position,\r\n this._eyeOffset,\r\n scratchPixelOffset,\r\n scene,\r\n result\r\n );\r\n return windowCoordinates;\r\n};\r\n\r\n/**\r\n * Gets a billboard's screen space bounding box centered around screenSpacePosition.\r\n * @param {Billboard} billboard The billboard to get the screen space bounding box for.\r\n * @param {Cartesian2} screenSpacePosition The screen space center of the label.\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The screen space bounding box.\r\n *\r\n * @private\r\n */\r\nBillboard.getScreenSpaceBoundingBox = function (\r\n billboard,\r\n screenSpacePosition,\r\n result\r\n) {\r\n var width = billboard.width;\r\n var height = billboard.height;\r\n\r\n var scale = billboard.scale;\r\n width *= scale;\r\n height *= scale;\r\n\r\n var x = screenSpacePosition.x;\r\n if (billboard.horizontalOrigin === HorizontalOrigin.RIGHT) {\r\n x -= width;\r\n } else if (billboard.horizontalOrigin === HorizontalOrigin.CENTER) {\r\n x -= width * 0.5;\r\n }\r\n\r\n var y = screenSpacePosition.y;\r\n if (\r\n billboard.verticalOrigin === VerticalOrigin.BOTTOM ||\r\n billboard.verticalOrigin === VerticalOrigin.BASELINE\r\n ) {\r\n y -= height;\r\n } else if (billboard.verticalOrigin === VerticalOrigin.CENTER) {\r\n y -= height * 0.5;\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new BoundingRectangle();\r\n }\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.width = width;\r\n result.height = height;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines if this billboard equals another billboard. Billboards are equal if all their properties\r\n * are equal. Billboards in different collections can be equal.\r\n *\r\n * @param {Billboard} other The billboard to compare for equality.\r\n * @returns {Boolean} true if the billboards are equal; otherwise, false.\r\n */\r\nBillboard.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (defined(other) &&\r\n this._id === other._id &&\r\n Cartesian3.equals(this._position, other._position) &&\r\n this._imageId === other._imageId &&\r\n this._show === other._show &&\r\n this._scale === other._scale &&\r\n this._verticalOrigin === other._verticalOrigin &&\r\n this._horizontalOrigin === other._horizontalOrigin &&\r\n this._heightReference === other._heightReference &&\r\n BoundingRectangle.equals(this._imageSubRegion, other._imageSubRegion) &&\r\n Color.equals(this._color, other._color) &&\r\n Cartesian2.equals(this._pixelOffset, other._pixelOffset) &&\r\n Cartesian2.equals(this._translate, other._translate) &&\r\n Cartesian3.equals(this._eyeOffset, other._eyeOffset) &&\r\n NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance) &&\r\n NearFarScalar.equals(\r\n this._translucencyByDistance,\r\n other._translucencyByDistance\r\n ) &&\r\n NearFarScalar.equals(\r\n this._pixelOffsetScaleByDistance,\r\n other._pixelOffsetScaleByDistance\r\n ) &&\r\n DistanceDisplayCondition.equals(\r\n this._distanceDisplayCondition,\r\n other._distanceDisplayCondition\r\n ) &&\r\n this._disableDepthTestDistance === other._disableDepthTestDistance)\r\n );\r\n};\r\n\r\nBillboard.prototype._destroy = function () {\r\n if (defined(this._customData)) {\r\n this._billboardCollection._scene.globe._surface.removeTileCustomData(\r\n this._customData\r\n );\r\n this._customData = undefined;\r\n }\r\n\r\n if (defined(this._removeCallbackFunc)) {\r\n this._removeCallbackFunc();\r\n this._removeCallbackFunc = undefined;\r\n }\r\n\r\n this.image = undefined;\r\n this._pickId = this._pickId && this._pickId.destroy();\r\n this._billboardCollection = undefined;\r\n};\r\n\r\n/**\r\n * A function that creates an image.\r\n * @callback Billboard.CreateImageCallback\r\n * @param {String} id The identifier of the image to load.\r\n * @returns {HTMLImageElement|HTMLCanvasElement|Promise} The image, or a promise that will resolve to an image.\r\n */\r\nexport default Billboard;\r\n","/**\r\n * Determines how opaque and translucent parts of billboards, points, and labels are blended with the scene.\r\n *\r\n * @enum {Number}\r\n */\r\nvar BlendOption = {\r\n /**\r\n * The billboards, points, or labels in the collection are completely opaque.\r\n * @type {Number}\r\n * @constant\r\n */\r\n OPAQUE: 0,\r\n\r\n /**\r\n * The billboards, points, or labels in the collection are completely translucent.\r\n * @type {Number}\r\n * @constant\r\n */\r\n TRANSLUCENT: 1,\r\n\r\n /**\r\n * The billboards, points, or labels in the collection are both opaque and translucent.\r\n * @type {Number}\r\n * @constant\r\n */\r\n OPAQUE_AND_TRANSLUCENT: 2,\r\n};\r\nexport default Object.freeze(BlendOption);\r\n","/**\r\n * Settings for the generation of signed distance field glyphs\r\n *\r\n * @private\r\n */\r\nvar SDFSettings = {\r\n /**\r\n * The font size in pixels\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n FONT_SIZE: 48.0,\r\n\r\n /**\r\n * Whitespace padding around glyphs.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n PADDING: 10.0,\r\n\r\n /**\r\n * How many pixels around the glyph shape to use for encoding distance\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n RADIUS: 8.0,\r\n\r\n /**\r\n * How much of the radius (relative) is used for the inside part the glyph.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n CUTOFF: 0.25,\r\n};\r\nexport default Object.freeze(SDFSettings);\r\n","import BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport PixelFormat from \"../Core/PixelFormat.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Framebuffer from \"../Renderer/Framebuffer.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\n\r\n// The atlas is made up of regions of space called nodes that contain images or child nodes.\r\nfunction TextureAtlasNode(\r\n bottomLeft,\r\n topRight,\r\n childNode1,\r\n childNode2,\r\n imageIndex\r\n) {\r\n this.bottomLeft = defaultValue(bottomLeft, Cartesian2.ZERO);\r\n this.topRight = defaultValue(topRight, Cartesian2.ZERO);\r\n this.childNode1 = childNode1;\r\n this.childNode2 = childNode2;\r\n this.imageIndex = imageIndex;\r\n}\r\n\r\nvar defaultInitialSize = new Cartesian2(16.0, 16.0);\r\n\r\n/**\r\n * A TextureAtlas stores multiple images in one square texture and keeps\r\n * track of the texture coordinates for each image. TextureAtlas is dynamic,\r\n * meaning new images can be added at any point in time.\r\n * Texture coordinates are subject to change if the texture atlas resizes, so it is\r\n * important to check {@link TextureAtlas#getGUID} before using old values.\r\n *\r\n * @alias TextureAtlas\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Scene} options.context The context in which the texture gets created.\r\n * @param {PixelFormat} [options.pixelFormat=PixelFormat.RGBA] The pixel format of the texture.\r\n * @param {Number} [options.borderWidthInPixels=1] The amount of spacing between adjacent images in pixels.\r\n * @param {Cartesian2} [options.initialSize=new Cartesian2(16.0, 16.0)] The initial side lengths of the texture.\r\n *\r\n * @exception {DeveloperError} borderWidthInPixels must be greater than or equal to zero.\r\n * @exception {DeveloperError} initialSize must be greater than zero.\r\n *\r\n * @private\r\n */\r\nfunction TextureAtlas(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var borderWidthInPixels = defaultValue(options.borderWidthInPixels, 1.0);\r\n var initialSize = defaultValue(options.initialSize, defaultInitialSize);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(options.context)) {\r\n throw new DeveloperError(\"context is required.\");\r\n }\r\n if (borderWidthInPixels < 0) {\r\n throw new DeveloperError(\r\n \"borderWidthInPixels must be greater than or equal to zero.\"\r\n );\r\n }\r\n if (initialSize.x < 1 || initialSize.y < 1) {\r\n throw new DeveloperError(\"initialSize must be greater than zero.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._context = options.context;\r\n this._pixelFormat = defaultValue(options.pixelFormat, PixelFormat.RGBA);\r\n this._borderWidthInPixels = borderWidthInPixels;\r\n this._textureCoordinates = [];\r\n this._guid = createGuid();\r\n this._idHash = {};\r\n this._initialSize = initialSize;\r\n\r\n this._root = undefined;\r\n}\r\n\r\nObject.defineProperties(TextureAtlas.prototype, {\r\n /**\r\n * The amount of spacing between adjacent images in pixels.\r\n * @memberof TextureAtlas.prototype\r\n * @type {Number}\r\n */\r\n borderWidthInPixels: {\r\n get: function () {\r\n return this._borderWidthInPixels;\r\n },\r\n },\r\n\r\n /**\r\n * An array of {@link BoundingRectangle} texture coordinate regions for all the images in the texture atlas.\r\n * The x and y values of the rectangle correspond to the bottom-left corner of the texture coordinate.\r\n * The coordinates are in the order that the corresponding images were added to the atlas.\r\n * @memberof TextureAtlas.prototype\r\n * @type {BoundingRectangle[]}\r\n */\r\n textureCoordinates: {\r\n get: function () {\r\n return this._textureCoordinates;\r\n },\r\n },\r\n\r\n /**\r\n * The texture that all of the images are being written to.\r\n * @memberof TextureAtlas.prototype\r\n * @type {Texture}\r\n */\r\n texture: {\r\n get: function () {\r\n if (!defined(this._texture)) {\r\n this._texture = new Texture({\r\n context: this._context,\r\n width: this._initialSize.x,\r\n height: this._initialSize.y,\r\n pixelFormat: this._pixelFormat,\r\n });\r\n }\r\n return this._texture;\r\n },\r\n },\r\n\r\n /**\r\n * The number of images in the texture atlas. This value increases\r\n * every time addImage or addImages is called.\r\n * Texture coordinates are subject to change if the texture atlas resizes, so it is\r\n * important to check {@link TextureAtlas#getGUID} before using old values.\r\n * @memberof TextureAtlas.prototype\r\n * @type {Number}\r\n */\r\n numberOfImages: {\r\n get: function () {\r\n return this._textureCoordinates.length;\r\n },\r\n },\r\n\r\n /**\r\n * The atlas' globally unique identifier (GUID).\r\n * The GUID changes whenever the texture atlas is modified.\r\n * Classes that use a texture atlas should check if the GUID\r\n * has changed before processing the atlas data.\r\n * @memberof TextureAtlas.prototype\r\n * @type {String}\r\n */\r\n guid: {\r\n get: function () {\r\n return this._guid;\r\n },\r\n },\r\n});\r\n\r\n// Builds a larger texture and copies the old texture into the new one.\r\nfunction resizeAtlas(textureAtlas, image) {\r\n var context = textureAtlas._context;\r\n var numImages = textureAtlas.numberOfImages;\r\n var scalingFactor = 2.0;\r\n var borderWidthInPixels = textureAtlas._borderWidthInPixels;\r\n if (numImages > 0) {\r\n var oldAtlasWidth = textureAtlas._texture.width;\r\n var oldAtlasHeight = textureAtlas._texture.height;\r\n var atlasWidth =\r\n scalingFactor * (oldAtlasWidth + image.width + borderWidthInPixels);\r\n var atlasHeight =\r\n scalingFactor * (oldAtlasHeight + image.height + borderWidthInPixels);\r\n var widthRatio = oldAtlasWidth / atlasWidth;\r\n var heightRatio = oldAtlasHeight / atlasHeight;\r\n\r\n // Create new node structure, putting the old root node in the bottom left.\r\n var nodeBottomRight = new TextureAtlasNode(\r\n new Cartesian2(oldAtlasWidth + borderWidthInPixels, borderWidthInPixels),\r\n new Cartesian2(atlasWidth, oldAtlasHeight)\r\n );\r\n var nodeBottomHalf = new TextureAtlasNode(\r\n new Cartesian2(),\r\n new Cartesian2(atlasWidth, oldAtlasHeight),\r\n textureAtlas._root,\r\n nodeBottomRight\r\n );\r\n var nodeTopHalf = new TextureAtlasNode(\r\n new Cartesian2(borderWidthInPixels, oldAtlasHeight + borderWidthInPixels),\r\n new Cartesian2(atlasWidth, atlasHeight)\r\n );\r\n var nodeMain = new TextureAtlasNode(\r\n new Cartesian2(),\r\n new Cartesian2(atlasWidth, atlasHeight),\r\n nodeBottomHalf,\r\n nodeTopHalf\r\n );\r\n\r\n // Resize texture coordinates.\r\n for (var i = 0; i < textureAtlas._textureCoordinates.length; i++) {\r\n var texCoord = textureAtlas._textureCoordinates[i];\r\n if (defined(texCoord)) {\r\n texCoord.x *= widthRatio;\r\n texCoord.y *= heightRatio;\r\n texCoord.width *= widthRatio;\r\n texCoord.height *= heightRatio;\r\n }\r\n }\r\n\r\n // Copy larger texture.\r\n var newTexture = new Texture({\r\n context: textureAtlas._context,\r\n width: atlasWidth,\r\n height: atlasHeight,\r\n pixelFormat: textureAtlas._pixelFormat,\r\n });\r\n\r\n var framebuffer = new Framebuffer({\r\n context: context,\r\n colorTextures: [textureAtlas._texture],\r\n destroyAttachments: false,\r\n });\r\n\r\n framebuffer._bind();\r\n newTexture.copyFromFramebuffer(0, 0, 0, 0, atlasWidth, atlasHeight);\r\n framebuffer._unBind();\r\n framebuffer.destroy();\r\n textureAtlas._texture =\r\n textureAtlas._texture && textureAtlas._texture.destroy();\r\n textureAtlas._texture = newTexture;\r\n textureAtlas._root = nodeMain;\r\n } else {\r\n // First image exceeds initialSize\r\n var initialWidth = scalingFactor * (image.width + 2 * borderWidthInPixels);\r\n var initialHeight =\r\n scalingFactor * (image.height + 2 * borderWidthInPixels);\r\n if (initialWidth < textureAtlas._initialSize.x) {\r\n initialWidth = textureAtlas._initialSize.x;\r\n }\r\n if (initialHeight < textureAtlas._initialSize.y) {\r\n initialHeight = textureAtlas._initialSize.y;\r\n }\r\n textureAtlas._texture =\r\n textureAtlas._texture && textureAtlas._texture.destroy();\r\n textureAtlas._texture = new Texture({\r\n context: textureAtlas._context,\r\n width: initialWidth,\r\n height: initialHeight,\r\n pixelFormat: textureAtlas._pixelFormat,\r\n });\r\n textureAtlas._root = new TextureAtlasNode(\r\n new Cartesian2(borderWidthInPixels, borderWidthInPixels),\r\n new Cartesian2(initialWidth, initialHeight)\r\n );\r\n }\r\n}\r\n\r\n// A recursive function that finds the best place to insert\r\n// a new image based on existing image 'nodes'.\r\n// Inspired by: http://blackpawn.com/texts/lightmaps/default.html\r\nfunction findNode(textureAtlas, node, image) {\r\n if (!defined(node)) {\r\n return undefined;\r\n }\r\n\r\n // If a leaf node\r\n if (!defined(node.childNode1) && !defined(node.childNode2)) {\r\n // Node already contains an image, don't add to it.\r\n if (defined(node.imageIndex)) {\r\n return undefined;\r\n }\r\n\r\n var nodeWidth = node.topRight.x - node.bottomLeft.x;\r\n var nodeHeight = node.topRight.y - node.bottomLeft.y;\r\n var widthDifference = nodeWidth - image.width;\r\n var heightDifference = nodeHeight - image.height;\r\n\r\n // Node is smaller than the image.\r\n if (widthDifference < 0 || heightDifference < 0) {\r\n return undefined;\r\n }\r\n\r\n // If the node is the same size as the image, return the node\r\n if (widthDifference === 0 && heightDifference === 0) {\r\n return node;\r\n }\r\n\r\n // Vertical split (childNode1 = left half, childNode2 = right half).\r\n if (widthDifference > heightDifference) {\r\n node.childNode1 = new TextureAtlasNode(\r\n new Cartesian2(node.bottomLeft.x, node.bottomLeft.y),\r\n new Cartesian2(node.bottomLeft.x + image.width, node.topRight.y)\r\n );\r\n // Only make a second child if the border gives enough space.\r\n var childNode2BottomLeftX =\r\n node.bottomLeft.x + image.width + textureAtlas._borderWidthInPixels;\r\n if (childNode2BottomLeftX < node.topRight.x) {\r\n node.childNode2 = new TextureAtlasNode(\r\n new Cartesian2(childNode2BottomLeftX, node.bottomLeft.y),\r\n new Cartesian2(node.topRight.x, node.topRight.y)\r\n );\r\n }\r\n }\r\n // Horizontal split (childNode1 = bottom half, childNode2 = top half).\r\n else {\r\n node.childNode1 = new TextureAtlasNode(\r\n new Cartesian2(node.bottomLeft.x, node.bottomLeft.y),\r\n new Cartesian2(node.topRight.x, node.bottomLeft.y + image.height)\r\n );\r\n // Only make a second child if the border gives enough space.\r\n var childNode2BottomLeftY =\r\n node.bottomLeft.y + image.height + textureAtlas._borderWidthInPixels;\r\n if (childNode2BottomLeftY < node.topRight.y) {\r\n node.childNode2 = new TextureAtlasNode(\r\n new Cartesian2(node.bottomLeft.x, childNode2BottomLeftY),\r\n new Cartesian2(node.topRight.x, node.topRight.y)\r\n );\r\n }\r\n }\r\n return findNode(textureAtlas, node.childNode1, image);\r\n }\r\n\r\n // If not a leaf node\r\n return (\r\n findNode(textureAtlas, node.childNode1, image) ||\r\n findNode(textureAtlas, node.childNode2, image)\r\n );\r\n}\r\n\r\n// Adds image of given index to the texture atlas. Called from addImage and addImages.\r\nfunction addImage(textureAtlas, image, index) {\r\n var node = findNode(textureAtlas, textureAtlas._root, image);\r\n if (defined(node)) {\r\n // Found a node that can hold the image.\r\n node.imageIndex = index;\r\n\r\n // Add texture coordinate and write to texture\r\n var atlasWidth = textureAtlas._texture.width;\r\n var atlasHeight = textureAtlas._texture.height;\r\n var nodeWidth = node.topRight.x - node.bottomLeft.x;\r\n var nodeHeight = node.topRight.y - node.bottomLeft.y;\r\n var x = node.bottomLeft.x / atlasWidth;\r\n var y = node.bottomLeft.y / atlasHeight;\r\n var w = nodeWidth / atlasWidth;\r\n var h = nodeHeight / atlasHeight;\r\n textureAtlas._textureCoordinates[index] = new BoundingRectangle(x, y, w, h);\r\n textureAtlas._texture.copyFrom(image, node.bottomLeft.x, node.bottomLeft.y);\r\n } else {\r\n // No node found, must resize the texture atlas.\r\n resizeAtlas(textureAtlas, image);\r\n addImage(textureAtlas, image, index);\r\n }\r\n\r\n textureAtlas._guid = createGuid();\r\n}\r\n\r\n/**\r\n * Adds an image to the atlas. If the image is already in the atlas, the atlas is unchanged and\r\n * the existing index is used.\r\n *\r\n * @param {String} id An identifier to detect whether the image already exists in the atlas.\r\n * @param {HTMLImageElement|HTMLCanvasElement|String|Resource|Promise|TextureAtlas.CreateImageCallback} image An image or canvas to add to the texture atlas,\r\n * or a URL to an Image, or a Promise for an image, or a function that creates an image.\r\n * @returns {Promise.} A Promise for the image index.\r\n */\r\nTextureAtlas.prototype.addImage = function (id, image) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(id)) {\r\n throw new DeveloperError(\"id is required.\");\r\n }\r\n if (!defined(image)) {\r\n throw new DeveloperError(\"image is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indexPromise = this._idHash[id];\r\n if (defined(indexPromise)) {\r\n // we're already aware of this source\r\n return indexPromise;\r\n }\r\n\r\n // not in atlas, create the promise for the index\r\n\r\n if (typeof image === \"function\") {\r\n // if image is a function, call it\r\n image = image(id);\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(image)) {\r\n throw new DeveloperError(\"image is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n } else if (typeof image === \"string\" || image instanceof Resource) {\r\n // Get a resource\r\n var resource = Resource.createIfNeeded(image);\r\n image = resource.fetchImage();\r\n }\r\n\r\n var that = this;\r\n\r\n indexPromise = when(image, function (image) {\r\n if (that.isDestroyed()) {\r\n return -1;\r\n }\r\n\r\n var index = that.numberOfImages;\r\n\r\n addImage(that, image, index);\r\n\r\n return index;\r\n });\r\n\r\n // store the promise\r\n this._idHash[id] = indexPromise;\r\n\r\n return indexPromise;\r\n};\r\n\r\n/**\r\n * Add a sub-region of an existing atlas image as additional image indices.\r\n *\r\n * @param {String} id The identifier of the existing image.\r\n * @param {BoundingRectangle} subRegion An {@link BoundingRectangle} sub-region measured in pixels from the bottom-left.\r\n *\r\n * @returns {Promise.} A Promise for the image index.\r\n */\r\nTextureAtlas.prototype.addSubRegion = function (id, subRegion) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(id)) {\r\n throw new DeveloperError(\"id is required.\");\r\n }\r\n if (!defined(subRegion)) {\r\n throw new DeveloperError(\"subRegion is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var indexPromise = this._idHash[id];\r\n if (!defined(indexPromise)) {\r\n throw new RuntimeError(\r\n 'image with id \"' + id + '\" not found in the atlas.'\r\n );\r\n }\r\n\r\n var that = this;\r\n return when(indexPromise, function (index) {\r\n if (index === -1) {\r\n // the atlas is destroyed\r\n return -1;\r\n }\r\n var atlasWidth = that._texture.width;\r\n var atlasHeight = that._texture.height;\r\n var numImages = that.numberOfImages;\r\n\r\n var baseRegion = that._textureCoordinates[index];\r\n var x = baseRegion.x + subRegion.x / atlasWidth;\r\n var y = baseRegion.y + subRegion.y / atlasHeight;\r\n var w = subRegion.width / atlasWidth;\r\n var h = subRegion.height / atlasHeight;\r\n that._textureCoordinates.push(new BoundingRectangle(x, y, w, h));\r\n that._guid = createGuid();\r\n\r\n return numImages;\r\n });\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n *\r\n * @see TextureAtlas#destroy\r\n */\r\nTextureAtlas.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * atlas = atlas && atlas.destroy();\r\n *\r\n * @see TextureAtlas#isDestroyed\r\n */\r\nTextureAtlas.prototype.destroy = function () {\r\n this._texture = this._texture && this._texture.destroy();\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * A function that creates an image.\r\n * @callback TextureAtlas.CreateImageCallback\r\n * @param {String} id The identifier of the image to load.\r\n * @returns {HTMLImageElement|Promise} The image, or a promise that will resolve to an image.\r\n */\r\nexport default TextureAtlas;\r\n","import AttributeCompression from \"../Core/AttributeCompression.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport EncodedCartesian3 from \"../Core/EncodedCartesian3.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport ContextLimits from \"../Renderer/ContextLimits.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport VertexArrayFacade from \"../Renderer/VertexArrayFacade.js\";\r\nimport BillboardCollectionFS from \"../Shaders/BillboardCollectionFS.js\";\r\nimport BillboardCollectionVS from \"../Shaders/BillboardCollectionVS.js\";\r\nimport Billboard from \"./Billboard.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport BlendOption from \"./BlendOption.js\";\r\nimport HeightReference from \"./HeightReference.js\";\r\nimport HorizontalOrigin from \"./HorizontalOrigin.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport SDFSettings from \"./SDFSettings.js\";\r\nimport TextureAtlas from \"./TextureAtlas.js\";\r\nimport VerticalOrigin from \"./VerticalOrigin.js\";\r\n\r\nvar SHOW_INDEX = Billboard.SHOW_INDEX;\r\nvar POSITION_INDEX = Billboard.POSITION_INDEX;\r\nvar PIXEL_OFFSET_INDEX = Billboard.PIXEL_OFFSET_INDEX;\r\nvar EYE_OFFSET_INDEX = Billboard.EYE_OFFSET_INDEX;\r\nvar HORIZONTAL_ORIGIN_INDEX = Billboard.HORIZONTAL_ORIGIN_INDEX;\r\nvar VERTICAL_ORIGIN_INDEX = Billboard.VERTICAL_ORIGIN_INDEX;\r\nvar SCALE_INDEX = Billboard.SCALE_INDEX;\r\nvar IMAGE_INDEX_INDEX = Billboard.IMAGE_INDEX_INDEX;\r\nvar COLOR_INDEX = Billboard.COLOR_INDEX;\r\nvar ROTATION_INDEX = Billboard.ROTATION_INDEX;\r\nvar ALIGNED_AXIS_INDEX = Billboard.ALIGNED_AXIS_INDEX;\r\nvar SCALE_BY_DISTANCE_INDEX = Billboard.SCALE_BY_DISTANCE_INDEX;\r\nvar TRANSLUCENCY_BY_DISTANCE_INDEX = Billboard.TRANSLUCENCY_BY_DISTANCE_INDEX;\r\nvar PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX =\r\n Billboard.PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX;\r\nvar DISTANCE_DISPLAY_CONDITION_INDEX = Billboard.DISTANCE_DISPLAY_CONDITION;\r\nvar DISABLE_DEPTH_DISTANCE = Billboard.DISABLE_DEPTH_DISTANCE;\r\nvar TEXTURE_COORDINATE_BOUNDS = Billboard.TEXTURE_COORDINATE_BOUNDS;\r\nvar SDF_INDEX = Billboard.SDF_INDEX;\r\nvar NUMBER_OF_PROPERTIES = Billboard.NUMBER_OF_PROPERTIES;\r\n\r\nvar attributeLocations;\r\n\r\nvar attributeLocationsBatched = {\r\n positionHighAndScale: 0,\r\n positionLowAndRotation: 1,\r\n compressedAttribute0: 2, // pixel offset, translate, horizontal origin, vertical origin, show, direction, texture coordinates\r\n compressedAttribute1: 3, // aligned axis, translucency by distance, image width\r\n compressedAttribute2: 4, // image height, color, pick color, size in meters, valid aligned axis, 13 bits free\r\n eyeOffset: 5, // 4 bytes free\r\n scaleByDistance: 6,\r\n pixelOffsetScaleByDistance: 7,\r\n compressedAttribute3: 8,\r\n textureCoordinateBoundsOrLabelTranslate: 9,\r\n a_batchId: 10,\r\n sdf: 11,\r\n};\r\n\r\nvar attributeLocationsInstanced = {\r\n direction: 0,\r\n positionHighAndScale: 1,\r\n positionLowAndRotation: 2, // texture offset in w\r\n compressedAttribute0: 3,\r\n compressedAttribute1: 4,\r\n compressedAttribute2: 5,\r\n eyeOffset: 6, // texture range in w\r\n scaleByDistance: 7,\r\n pixelOffsetScaleByDistance: 8,\r\n compressedAttribute3: 9,\r\n textureCoordinateBoundsOrLabelTranslate: 10,\r\n a_batchId: 11,\r\n sdf: 12,\r\n};\r\n\r\n/**\r\n * A renderable collection of billboards. Billboards are viewport-aligned\r\n * images positioned in the 3D scene.\r\n *

\r\n *
\r\n *
\r\n * Example billboards\r\n *
\r\n *

\r\n * Billboards are added and removed from the collection using {@link BillboardCollection#add}\r\n * and {@link BillboardCollection#remove}. Billboards in a collection automatically share textures\r\n * for images with the same identifier.\r\n *\r\n * @alias BillboardCollection\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms each billboard from model to world coordinates.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.\r\n * @param {Scene} [options.scene] Must be passed in for billboards that use the height reference property or will be depth tested against the globe.\r\n * @param {BlendOption} [options.blendOption=BlendOption.OPAQUE_AND_TRANSLUCENT] The billboard blending option. The default\r\n * is used for rendering both opaque and translucent billboards. However, if either all of the billboards are completely opaque or all are completely translucent,\r\n * setting the technique to BlendOption.OPAQUE or BlendOption.TRANSLUCENT can improve performance by up to 2x.\r\n * @param {Boolean} [options.show=true] Determines if the billboards in the collection will be shown.\r\n *\r\n * @performance For best performance, prefer a few collections, each with many billboards, to\r\n * many collections with only a few billboards each. Organize collections so that billboards\r\n * with the same update frequency are in the same collection, i.e., billboards that do not\r\n * change should be in one collection; billboards that change every frame should be in another\r\n * collection; and so on.\r\n *\r\n * @see BillboardCollection#add\r\n * @see BillboardCollection#remove\r\n * @see Billboard\r\n * @see LabelCollection\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Billboards.html|Cesium Sandcastle Billboard Demo}\r\n *\r\n * @example\r\n * // Create a billboard collection with two billboards\r\n * var billboards = scene.primitives.add(new Cesium.BillboardCollection());\r\n * billboards.add({\r\n * position : new Cesium.Cartesian3(1.0, 2.0, 3.0),\r\n * image : 'url/to/image'\r\n * });\r\n * billboards.add({\r\n * position : new Cesium.Cartesian3(4.0, 5.0, 6.0),\r\n * image : 'url/to/another/image'\r\n * });\r\n */\r\nfunction BillboardCollection(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._scene = options.scene;\r\n this._batchTable = options.batchTable;\r\n\r\n this._textureAtlas = undefined;\r\n this._textureAtlasGUID = undefined;\r\n this._destroyTextureAtlas = true;\r\n this._sp = undefined;\r\n this._spTranslucent = undefined;\r\n this._rsOpaque = undefined;\r\n this._rsTranslucent = undefined;\r\n this._vaf = undefined;\r\n\r\n this._billboards = [];\r\n this._billboardsToUpdate = [];\r\n this._billboardsToUpdateIndex = 0;\r\n this._billboardsRemoved = false;\r\n this._createVertexArray = false;\r\n\r\n this._shaderRotation = false;\r\n this._compiledShaderRotation = false;\r\n\r\n this._shaderAlignedAxis = false;\r\n this._compiledShaderAlignedAxis = false;\r\n\r\n this._shaderScaleByDistance = false;\r\n this._compiledShaderScaleByDistance = false;\r\n\r\n this._shaderTranslucencyByDistance = false;\r\n this._compiledShaderTranslucencyByDistance = false;\r\n\r\n this._shaderPixelOffsetScaleByDistance = false;\r\n this._compiledShaderPixelOffsetScaleByDistance = false;\r\n\r\n this._shaderDistanceDisplayCondition = false;\r\n this._compiledShaderDistanceDisplayCondition = false;\r\n\r\n this._shaderDisableDepthDistance = false;\r\n this._compiledShaderDisableDepthDistance = false;\r\n\r\n this._shaderClampToGround = false;\r\n this._compiledShaderClampToGround = false;\r\n\r\n this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES);\r\n\r\n this._maxSize = 0.0;\r\n this._maxEyeOffset = 0.0;\r\n this._maxScale = 1.0;\r\n this._maxPixelOffset = 0.0;\r\n this._allHorizontalCenter = true;\r\n this._allVerticalCenter = true;\r\n this._allSizedInMeters = true;\r\n\r\n this._baseVolume = new BoundingSphere();\r\n this._baseVolumeWC = new BoundingSphere();\r\n this._baseVolume2D = new BoundingSphere();\r\n this._boundingVolume = new BoundingSphere();\r\n this._boundingVolumeDirty = false;\r\n\r\n this._colorCommands = [];\r\n\r\n /**\r\n * Determines if billboards in this collection will be shown.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * The 4x4 transformation matrix that transforms each billboard in this collection from model to world coordinates.\r\n * When this is the identity matrix, the billboards are drawn in world coordinates, i.e., Earth's WGS84 coordinates.\r\n * Local reference frames can be used by providing a different transformation matrix, like that returned\r\n * by {@link Transforms.eastNorthUpToFixedFrame}.\r\n *\r\n * @type {Matrix4}\r\n * @default {@link Matrix4.IDENTITY}\r\n *\r\n *\r\n * @example\r\n * var center = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);\r\n * billboards.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);\r\n * billboards.add({\r\n * image : 'url/to/image',\r\n * position : new Cesium.Cartesian3(0.0, 0.0, 0.0) // center\r\n * });\r\n * billboards.add({\r\n * image : 'url/to/image',\r\n * position : new Cesium.Cartesian3(1000000.0, 0.0, 0.0) // east\r\n * });\r\n * billboards.add({\r\n * image : 'url/to/image',\r\n * position : new Cesium.Cartesian3(0.0, 1000000.0, 0.0) // north\r\n * });\r\n * billboards.add({\r\n * image : 'url/to/image',\r\n * position : new Cesium.Cartesian3(0.0, 0.0, 1000000.0) // up\r\n * });\r\n *\r\n * @see Transforms.eastNorthUpToFixedFrame\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n this._modelMatrix = Matrix4.clone(Matrix4.IDENTITY);\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the texture atlas for this BillboardCollection as a fullscreen quad.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowTextureAtlas = defaultValue(\r\n options.debugShowTextureAtlas,\r\n false\r\n );\r\n\r\n /**\r\n * The billboard blending option. The default is used for rendering both opaque and translucent billboards.\r\n * However, if either all of the billboards are completely opaque or all are completely translucent,\r\n * setting the technique to BlendOption.OPAQUE or BlendOption.TRANSLUCENT can improve\r\n * performance by up to 2x.\r\n * @type {BlendOption}\r\n * @default BlendOption.OPAQUE_AND_TRANSLUCENT\r\n */\r\n this.blendOption = defaultValue(\r\n options.blendOption,\r\n BlendOption.OPAQUE_AND_TRANSLUCENT\r\n );\r\n this._blendOption = undefined;\r\n\r\n this._mode = SceneMode.SCENE3D;\r\n\r\n // The buffer usage for each attribute is determined based on the usage of the attribute over time.\r\n this._buffersUsage = [\r\n BufferUsage.STATIC_DRAW, // SHOW_INDEX\r\n BufferUsage.STATIC_DRAW, // POSITION_INDEX\r\n BufferUsage.STATIC_DRAW, // PIXEL_OFFSET_INDEX\r\n BufferUsage.STATIC_DRAW, // EYE_OFFSET_INDEX\r\n BufferUsage.STATIC_DRAW, // HORIZONTAL_ORIGIN_INDEX\r\n BufferUsage.STATIC_DRAW, // VERTICAL_ORIGIN_INDEX\r\n BufferUsage.STATIC_DRAW, // SCALE_INDEX\r\n BufferUsage.STATIC_DRAW, // IMAGE_INDEX_INDEX\r\n BufferUsage.STATIC_DRAW, // COLOR_INDEX\r\n BufferUsage.STATIC_DRAW, // ROTATION_INDEX\r\n BufferUsage.STATIC_DRAW, // ALIGNED_AXIS_INDEX\r\n BufferUsage.STATIC_DRAW, // SCALE_BY_DISTANCE_INDEX\r\n BufferUsage.STATIC_DRAW, // TRANSLUCENCY_BY_DISTANCE_INDEX\r\n BufferUsage.STATIC_DRAW, // PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX\r\n BufferUsage.STATIC_DRAW, // DISTANCE_DISPLAY_CONDITION_INDEX\r\n BufferUsage.STATIC_DRAW, // TEXTURE_COORDINATE_BOUNDS\r\n ];\r\n\r\n this._highlightColor = Color.clone(Color.WHITE); // Only used by Vector3DTilePoints\r\n\r\n var that = this;\r\n this._uniforms = {\r\n u_atlas: function () {\r\n return that._textureAtlas.texture;\r\n },\r\n u_highlightColor: function () {\r\n return that._highlightColor;\r\n },\r\n };\r\n\r\n var scene = this._scene;\r\n if (defined(scene) && defined(scene.terrainProviderChanged)) {\r\n this._removeCallbackFunc = scene.terrainProviderChanged.addEventListener(\r\n function () {\r\n var billboards = this._billboards;\r\n var length = billboards.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (defined(billboards[i])) {\r\n billboards[i]._updateClamping();\r\n }\r\n }\r\n },\r\n this\r\n );\r\n }\r\n}\r\n\r\nObject.defineProperties(BillboardCollection.prototype, {\r\n /**\r\n * Returns the number of billboards in this collection. This is commonly used with\r\n * {@link BillboardCollection#get} to iterate over all the billboards\r\n * in the collection.\r\n * @memberof BillboardCollection.prototype\r\n * @type {Number}\r\n */\r\n length: {\r\n get: function () {\r\n removeBillboards(this);\r\n return this._billboards.length;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the textureAtlas.\r\n * @memberof BillboardCollection.prototype\r\n * @type {TextureAtlas}\r\n * @private\r\n */\r\n textureAtlas: {\r\n get: function () {\r\n return this._textureAtlas;\r\n },\r\n set: function (value) {\r\n if (this._textureAtlas !== value) {\r\n this._textureAtlas =\r\n this._destroyTextureAtlas &&\r\n this._textureAtlas &&\r\n this._textureAtlas.destroy();\r\n this._textureAtlas = value;\r\n this._createVertexArray = true; // New per-billboard texture coordinates\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets a value which determines if the texture atlas is\r\n * destroyed when the collection is destroyed.\r\n *\r\n * If the texture atlas is used by more than one collection, set this to false,\r\n * and explicitly destroy the atlas to avoid attempting to destroy it multiple times.\r\n *\r\n * @memberof BillboardCollection.prototype\r\n * @type {Boolean}\r\n * @private\r\n *\r\n * @example\r\n * // Set destroyTextureAtlas\r\n * // Destroy a billboard collection but not its texture atlas.\r\n *\r\n * var atlas = new TextureAtlas({\r\n * scene : scene,\r\n * images : images\r\n * });\r\n * billboards.textureAtlas = atlas;\r\n * billboards.destroyTextureAtlas = false;\r\n * billboards = billboards.destroy();\r\n * console.log(atlas.isDestroyed()); // False\r\n */\r\n destroyTextureAtlas: {\r\n get: function () {\r\n return this._destroyTextureAtlas;\r\n },\r\n set: function (value) {\r\n this._destroyTextureAtlas = value;\r\n },\r\n },\r\n});\r\n\r\nfunction destroyBillboards(billboards) {\r\n var length = billboards.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (billboards[i]) {\r\n billboards[i]._destroy();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Creates and adds a billboard with the specified initial properties to the collection.\r\n * The added billboard is returned so it can be modified or removed from the collection later.\r\n *\r\n * @param {Object}[options] A template describing the billboard's properties as shown in Example 1.\r\n * @returns {Billboard} The billboard that was added to the collection.\r\n *\r\n * @performance Calling add is expected constant time. However, the collection's vertex buffer\r\n * is rewritten - an O(n) operation that also incurs CPU to GPU overhead. For\r\n * best performance, add as many billboards as possible before calling update.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * // Example 1: Add a billboard, specifying all the default values.\r\n * var b = billboards.add({\r\n * show : true,\r\n * position : Cesium.Cartesian3.ZERO,\r\n * pixelOffset : Cesium.Cartesian2.ZERO,\r\n * eyeOffset : Cesium.Cartesian3.ZERO,\r\n * heightReference : Cesium.HeightReference.NONE,\r\n * horizontalOrigin : Cesium.HorizontalOrigin.CENTER,\r\n * verticalOrigin : Cesium.VerticalOrigin.CENTER,\r\n * scale : 1.0,\r\n * image : 'url/to/image',\r\n * imageSubRegion : undefined,\r\n * color : Cesium.Color.WHITE,\r\n * id : undefined,\r\n * rotation : 0.0,\r\n * alignedAxis : Cesium.Cartesian3.ZERO,\r\n * width : undefined,\r\n * height : undefined,\r\n * scaleByDistance : undefined,\r\n * translucencyByDistance : undefined,\r\n * pixelOffsetScaleByDistance : undefined,\r\n * sizeInMeters : false,\r\n * distanceDisplayCondition : undefined\r\n * });\r\n *\r\n * @example\r\n * // Example 2: Specify only the billboard's cartographic position.\r\n * var b = billboards.add({\r\n * position : Cesium.Cartesian3.fromDegrees(longitude, latitude, height)\r\n * });\r\n *\r\n * @see BillboardCollection#remove\r\n * @see BillboardCollection#removeAll\r\n */\r\nBillboardCollection.prototype.add = function (options) {\r\n var b = new Billboard(options, this);\r\n b._index = this._billboards.length;\r\n\r\n this._billboards.push(b);\r\n this._createVertexArray = true;\r\n\r\n return b;\r\n};\r\n\r\n/**\r\n * Removes a billboard from the collection.\r\n *\r\n * @param {Billboard} billboard The billboard to remove.\r\n * @returns {Boolean} true if the billboard was removed; false if the billboard was not found in the collection.\r\n *\r\n * @performance Calling remove is expected constant time. However, the collection's vertex buffer\r\n * is rewritten - an O(n) operation that also incurs CPU to GPU overhead. For\r\n * best performance, remove as many billboards as possible before calling update.\r\n * If you intend to temporarily hide a billboard, it is usually more efficient to call\r\n * {@link Billboard#show} instead of removing and re-adding the billboard.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * var b = billboards.add(...);\r\n * billboards.remove(b); // Returns true\r\n *\r\n * @see BillboardCollection#add\r\n * @see BillboardCollection#removeAll\r\n * @see Billboard#show\r\n */\r\nBillboardCollection.prototype.remove = function (billboard) {\r\n if (this.contains(billboard)) {\r\n this._billboards[billboard._index] = null; // Removed later\r\n this._billboardsRemoved = true;\r\n this._createVertexArray = true;\r\n billboard._destroy();\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes all billboards from the collection.\r\n *\r\n * @performance O(n). It is more efficient to remove all the billboards\r\n * from a collection and then add new ones than to create a new collection entirely.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * billboards.add(...);\r\n * billboards.add(...);\r\n * billboards.removeAll();\r\n *\r\n * @see BillboardCollection#add\r\n * @see BillboardCollection#remove\r\n */\r\nBillboardCollection.prototype.removeAll = function () {\r\n destroyBillboards(this._billboards);\r\n this._billboards = [];\r\n this._billboardsToUpdate = [];\r\n this._billboardsToUpdateIndex = 0;\r\n this._billboardsRemoved = false;\r\n\r\n this._createVertexArray = true;\r\n};\r\n\r\nfunction removeBillboards(billboardCollection) {\r\n if (billboardCollection._billboardsRemoved) {\r\n billboardCollection._billboardsRemoved = false;\r\n\r\n var newBillboards = [];\r\n var billboards = billboardCollection._billboards;\r\n var length = billboards.length;\r\n for (var i = 0, j = 0; i < length; ++i) {\r\n var billboard = billboards[i];\r\n if (billboard) {\r\n billboard._index = j++;\r\n newBillboards.push(billboard);\r\n }\r\n }\r\n\r\n billboardCollection._billboards = newBillboards;\r\n }\r\n}\r\n\r\nBillboardCollection.prototype._updateBillboard = function (\r\n billboard,\r\n propertyChanged\r\n) {\r\n if (!billboard._dirty) {\r\n this._billboardsToUpdate[this._billboardsToUpdateIndex++] = billboard;\r\n }\r\n\r\n ++this._propertiesChanged[propertyChanged];\r\n};\r\n\r\n/**\r\n * Check whether this collection contains a given billboard.\r\n *\r\n * @param {Billboard} [billboard] The billboard to check for.\r\n * @returns {Boolean} true if this collection contains the billboard, false otherwise.\r\n *\r\n * @see BillboardCollection#get\r\n */\r\nBillboardCollection.prototype.contains = function (billboard) {\r\n return defined(billboard) && billboard._billboardCollection === this;\r\n};\r\n\r\n/**\r\n * Returns the billboard in the collection at the specified index. Indices are zero-based\r\n * and increase as billboards are added. Removing a billboard shifts all billboards after\r\n * it to the left, changing their indices. This function is commonly used with\r\n * {@link BillboardCollection#length} to iterate over all the billboards\r\n * in the collection.\r\n *\r\n * @param {Number} index The zero-based index of the billboard.\r\n * @returns {Billboard} The billboard at the specified index.\r\n *\r\n * @performance Expected constant time. If billboards were removed from the collection and\r\n * {@link BillboardCollection#update} was not called, an implicit O(n)\r\n * operation is performed.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * // Toggle the show property of every billboard in the collection\r\n * var len = billboards.length;\r\n * for (var i = 0; i < len; ++i) {\r\n * var b = billboards.get(i);\r\n * b.show = !b.show;\r\n * }\r\n *\r\n * @see BillboardCollection#length\r\n */\r\nBillboardCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n removeBillboards(this);\r\n return this._billboards[index];\r\n};\r\n\r\nvar getIndexBuffer;\r\n\r\nfunction getIndexBufferBatched(context) {\r\n var sixteenK = 16 * 1024;\r\n\r\n var indexBuffer = context.cache.billboardCollection_indexBufferBatched;\r\n if (defined(indexBuffer)) {\r\n return indexBuffer;\r\n }\r\n\r\n // Subtract 6 because the last index is reserverd for primitive restart.\r\n // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.18\r\n var length = sixteenK * 6 - 6;\r\n var indices = new Uint16Array(length);\r\n for (var i = 0, j = 0; i < length; i += 6, j += 4) {\r\n indices[i] = j;\r\n indices[i + 1] = j + 1;\r\n indices[i + 2] = j + 2;\r\n\r\n indices[i + 3] = j + 0;\r\n indices[i + 4] = j + 2;\r\n indices[i + 5] = j + 3;\r\n }\r\n\r\n // PERFORMANCE_IDEA: Should we reference count billboard collections, and eventually delete this?\r\n // Is this too much memory to allocate up front? Should we dynamically grow it?\r\n indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: indices,\r\n usage: BufferUsage.STATIC_DRAW,\r\n indexDatatype: IndexDatatype.UNSIGNED_SHORT,\r\n });\r\n indexBuffer.vertexArrayDestroyable = false;\r\n context.cache.billboardCollection_indexBufferBatched = indexBuffer;\r\n return indexBuffer;\r\n}\r\n\r\nfunction getIndexBufferInstanced(context) {\r\n var indexBuffer = context.cache.billboardCollection_indexBufferInstanced;\r\n if (defined(indexBuffer)) {\r\n return indexBuffer;\r\n }\r\n\r\n indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: new Uint16Array([0, 1, 2, 0, 2, 3]),\r\n usage: BufferUsage.STATIC_DRAW,\r\n indexDatatype: IndexDatatype.UNSIGNED_SHORT,\r\n });\r\n\r\n indexBuffer.vertexArrayDestroyable = false;\r\n context.cache.billboardCollection_indexBufferInstanced = indexBuffer;\r\n return indexBuffer;\r\n}\r\n\r\nfunction getVertexBufferInstanced(context) {\r\n var vertexBuffer = context.cache.billboardCollection_vertexBufferInstanced;\r\n if (defined(vertexBuffer)) {\r\n return vertexBuffer;\r\n }\r\n\r\n vertexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: new Float32Array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]),\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n\r\n vertexBuffer.vertexArrayDestroyable = false;\r\n context.cache.billboardCollection_vertexBufferInstanced = vertexBuffer;\r\n return vertexBuffer;\r\n}\r\n\r\nBillboardCollection.prototype.computeNewBuffersUsage = function () {\r\n var buffersUsage = this._buffersUsage;\r\n var usageChanged = false;\r\n\r\n var properties = this._propertiesChanged;\r\n for (var k = 0; k < NUMBER_OF_PROPERTIES; ++k) {\r\n var newUsage =\r\n properties[k] === 0 ? BufferUsage.STATIC_DRAW : BufferUsage.STREAM_DRAW;\r\n usageChanged = usageChanged || buffersUsage[k] !== newUsage;\r\n buffersUsage[k] = newUsage;\r\n }\r\n\r\n return usageChanged;\r\n};\r\n\r\nfunction createVAF(\r\n context,\r\n numberOfBillboards,\r\n buffersUsage,\r\n instanced,\r\n batchTable,\r\n sdf\r\n) {\r\n var attributes = [\r\n {\r\n index: attributeLocations.positionHighAndScale,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[POSITION_INDEX],\r\n },\r\n {\r\n index: attributeLocations.positionLowAndRotation,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[POSITION_INDEX],\r\n },\r\n {\r\n index: attributeLocations.compressedAttribute0,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[PIXEL_OFFSET_INDEX],\r\n },\r\n {\r\n index: attributeLocations.compressedAttribute1,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[TRANSLUCENCY_BY_DISTANCE_INDEX],\r\n },\r\n {\r\n index: attributeLocations.compressedAttribute2,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[COLOR_INDEX],\r\n },\r\n {\r\n index: attributeLocations.eyeOffset,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[EYE_OFFSET_INDEX],\r\n },\r\n {\r\n index: attributeLocations.scaleByDistance,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[SCALE_BY_DISTANCE_INDEX],\r\n },\r\n {\r\n index: attributeLocations.pixelOffsetScaleByDistance,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX],\r\n },\r\n {\r\n index: attributeLocations.compressedAttribute3,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX],\r\n },\r\n {\r\n index: attributeLocations.textureCoordinateBoundsOrLabelTranslate,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[TEXTURE_COORDINATE_BOUNDS],\r\n },\r\n ];\r\n\r\n // Instancing requires one non-instanced attribute.\r\n if (instanced) {\r\n attributes.push({\r\n index: attributeLocations.direction,\r\n componentsPerAttribute: 2,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n vertexBuffer: getVertexBufferInstanced(context),\r\n });\r\n }\r\n\r\n if (defined(batchTable)) {\r\n attributes.push({\r\n index: attributeLocations.a_batchId,\r\n componentsPerAttribute: 1,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n bufferUsage: BufferUsage.STATIC_DRAW,\r\n });\r\n }\r\n\r\n if (sdf) {\r\n attributes.push({\r\n index: attributeLocations.sdf,\r\n componentsPerAttribute: 2,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[SDF_INDEX],\r\n });\r\n }\r\n\r\n // When instancing is enabled, only one vertex is needed for each billboard.\r\n var sizeInVertices = instanced ? numberOfBillboards : 4 * numberOfBillboards;\r\n return new VertexArrayFacade(context, attributes, sizeInVertices, instanced);\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n// Four vertices per billboard. Each has the same position, etc., but a different screen-space direction vector.\r\n\r\n// PERFORMANCE_IDEA: Save memory if a property is the same for all billboards, use a latched attribute state,\r\n// instead of storing it in a vertex buffer.\r\n\r\nvar writePositionScratch = new EncodedCartesian3();\r\n\r\nfunction writePositionScaleAndRotation(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n var i;\r\n var positionHighWriter = vafWriters[attributeLocations.positionHighAndScale];\r\n var positionLowWriter = vafWriters[attributeLocations.positionLowAndRotation];\r\n var position = billboard._getActualPosition();\r\n\r\n if (billboardCollection._mode === SceneMode.SCENE3D) {\r\n BoundingSphere.expand(\r\n billboardCollection._baseVolume,\r\n position,\r\n billboardCollection._baseVolume\r\n );\r\n billboardCollection._boundingVolumeDirty = true;\r\n }\r\n\r\n EncodedCartesian3.fromCartesian(position, writePositionScratch);\r\n var scale = billboard.scale;\r\n var rotation = billboard.rotation;\r\n\r\n if (rotation !== 0.0) {\r\n billboardCollection._shaderRotation = true;\r\n }\r\n\r\n billboardCollection._maxScale = Math.max(\r\n billboardCollection._maxScale,\r\n scale\r\n );\r\n\r\n var high = writePositionScratch.high;\r\n var low = writePositionScratch.low;\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n positionHighWriter(i, high.x, high.y, high.z, scale);\r\n positionLowWriter(i, low.x, low.y, low.z, rotation);\r\n } else {\r\n i = billboard._index * 4;\r\n positionHighWriter(i + 0, high.x, high.y, high.z, scale);\r\n positionHighWriter(i + 1, high.x, high.y, high.z, scale);\r\n positionHighWriter(i + 2, high.x, high.y, high.z, scale);\r\n positionHighWriter(i + 3, high.x, high.y, high.z, scale);\r\n\r\n positionLowWriter(i + 0, low.x, low.y, low.z, rotation);\r\n positionLowWriter(i + 1, low.x, low.y, low.z, rotation);\r\n positionLowWriter(i + 2, low.x, low.y, low.z, rotation);\r\n positionLowWriter(i + 3, low.x, low.y, low.z, rotation);\r\n }\r\n}\r\n\r\nvar scratchCartesian2 = new Cartesian2();\r\n\r\nvar UPPER_BOUND = 32768.0; // 2^15\r\n\r\nvar LEFT_SHIFT16 = 65536.0; // 2^16\r\nvar LEFT_SHIFT12 = 4096.0; // 2^12\r\nvar LEFT_SHIFT8 = 256.0; // 2^8\r\nvar LEFT_SHIFT7 = 128.0;\r\nvar LEFT_SHIFT5 = 32.0;\r\nvar LEFT_SHIFT3 = 8.0;\r\nvar LEFT_SHIFT2 = 4.0;\r\n\r\nvar RIGHT_SHIFT8 = 1.0 / 256.0;\r\n\r\nvar LOWER_LEFT = 0.0;\r\nvar LOWER_RIGHT = 2.0;\r\nvar UPPER_RIGHT = 3.0;\r\nvar UPPER_LEFT = 1.0;\r\n\r\nfunction writeCompressedAttrib0(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n var i;\r\n var writer = vafWriters[attributeLocations.compressedAttribute0];\r\n var pixelOffset = billboard.pixelOffset;\r\n var pixelOffsetX = pixelOffset.x;\r\n var pixelOffsetY = pixelOffset.y;\r\n\r\n var translate = billboard._translate;\r\n var translateX = translate.x;\r\n var translateY = translate.y;\r\n\r\n billboardCollection._maxPixelOffset = Math.max(\r\n billboardCollection._maxPixelOffset,\r\n Math.abs(pixelOffsetX + translateX),\r\n Math.abs(-pixelOffsetY + translateY)\r\n );\r\n\r\n var horizontalOrigin = billboard.horizontalOrigin;\r\n var verticalOrigin = billboard._verticalOrigin;\r\n var show = billboard.show && billboard.clusterShow;\r\n\r\n // If the color alpha is zero, do not show this billboard. This lets us avoid providing\r\n // color during the pick pass and also eliminates a discard in the fragment shader.\r\n if (billboard.color.alpha === 0.0) {\r\n show = false;\r\n }\r\n\r\n // Raw billboards don't distinguish between BASELINE and BOTTOM, only LabelCollection does that.\r\n if (verticalOrigin === VerticalOrigin.BASELINE) {\r\n verticalOrigin = VerticalOrigin.BOTTOM;\r\n }\r\n\r\n billboardCollection._allHorizontalCenter =\r\n billboardCollection._allHorizontalCenter &&\r\n horizontalOrigin === HorizontalOrigin.CENTER;\r\n billboardCollection._allVerticalCenter =\r\n billboardCollection._allVerticalCenter &&\r\n verticalOrigin === VerticalOrigin.CENTER;\r\n\r\n var bottomLeftX = 0;\r\n var bottomLeftY = 0;\r\n var width = 0;\r\n var height = 0;\r\n var index = billboard._imageIndex;\r\n if (index !== -1) {\r\n var imageRectangle = textureAtlasCoordinates[index];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(imageRectangle)) {\r\n throw new DeveloperError(\"Invalid billboard image index: \" + index);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n bottomLeftX = imageRectangle.x;\r\n bottomLeftY = imageRectangle.y;\r\n width = imageRectangle.width;\r\n height = imageRectangle.height;\r\n }\r\n var topRightX = bottomLeftX + width;\r\n var topRightY = bottomLeftY + height;\r\n\r\n var compressed0 =\r\n Math.floor(\r\n CesiumMath.clamp(pixelOffsetX, -UPPER_BOUND, UPPER_BOUND) + UPPER_BOUND\r\n ) * LEFT_SHIFT7;\r\n compressed0 += (horizontalOrigin + 1.0) * LEFT_SHIFT5;\r\n compressed0 += (verticalOrigin + 1.0) * LEFT_SHIFT3;\r\n compressed0 += (show ? 1.0 : 0.0) * LEFT_SHIFT2;\r\n\r\n var compressed1 =\r\n Math.floor(\r\n CesiumMath.clamp(pixelOffsetY, -UPPER_BOUND, UPPER_BOUND) + UPPER_BOUND\r\n ) * LEFT_SHIFT8;\r\n var compressed2 =\r\n Math.floor(\r\n CesiumMath.clamp(translateX, -UPPER_BOUND, UPPER_BOUND) + UPPER_BOUND\r\n ) * LEFT_SHIFT8;\r\n\r\n var tempTanslateY =\r\n (CesiumMath.clamp(translateY, -UPPER_BOUND, UPPER_BOUND) + UPPER_BOUND) *\r\n RIGHT_SHIFT8;\r\n var upperTranslateY = Math.floor(tempTanslateY);\r\n var lowerTranslateY = Math.floor(\r\n (tempTanslateY - upperTranslateY) * LEFT_SHIFT8\r\n );\r\n\r\n compressed1 += upperTranslateY;\r\n compressed2 += lowerTranslateY;\r\n\r\n scratchCartesian2.x = bottomLeftX;\r\n scratchCartesian2.y = bottomLeftY;\r\n var compressedTexCoordsLL = AttributeCompression.compressTextureCoordinates(\r\n scratchCartesian2\r\n );\r\n scratchCartesian2.x = topRightX;\r\n var compressedTexCoordsLR = AttributeCompression.compressTextureCoordinates(\r\n scratchCartesian2\r\n );\r\n scratchCartesian2.y = topRightY;\r\n var compressedTexCoordsUR = AttributeCompression.compressTextureCoordinates(\r\n scratchCartesian2\r\n );\r\n scratchCartesian2.x = bottomLeftX;\r\n var compressedTexCoordsUL = AttributeCompression.compressTextureCoordinates(\r\n scratchCartesian2\r\n );\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, compressed0, compressed1, compressed2, compressedTexCoordsLL);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(\r\n i + 0,\r\n compressed0 + LOWER_LEFT,\r\n compressed1,\r\n compressed2,\r\n compressedTexCoordsLL\r\n );\r\n writer(\r\n i + 1,\r\n compressed0 + LOWER_RIGHT,\r\n compressed1,\r\n compressed2,\r\n compressedTexCoordsLR\r\n );\r\n writer(\r\n i + 2,\r\n compressed0 + UPPER_RIGHT,\r\n compressed1,\r\n compressed2,\r\n compressedTexCoordsUR\r\n );\r\n writer(\r\n i + 3,\r\n compressed0 + UPPER_LEFT,\r\n compressed1,\r\n compressed2,\r\n compressedTexCoordsUL\r\n );\r\n }\r\n}\r\n\r\nfunction writeCompressedAttrib1(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n var i;\r\n var writer = vafWriters[attributeLocations.compressedAttribute1];\r\n var alignedAxis = billboard.alignedAxis;\r\n if (!Cartesian3.equals(alignedAxis, Cartesian3.ZERO)) {\r\n billboardCollection._shaderAlignedAxis = true;\r\n }\r\n\r\n var near = 0.0;\r\n var nearValue = 1.0;\r\n var far = 1.0;\r\n var farValue = 1.0;\r\n\r\n var translucency = billboard.translucencyByDistance;\r\n if (defined(translucency)) {\r\n near = translucency.near;\r\n nearValue = translucency.nearValue;\r\n far = translucency.far;\r\n farValue = translucency.farValue;\r\n\r\n if (nearValue !== 1.0 || farValue !== 1.0) {\r\n // translucency by distance calculation in shader need not be enabled\r\n // until a billboard with near and far !== 1.0 is found\r\n billboardCollection._shaderTranslucencyByDistance = true;\r\n }\r\n }\r\n\r\n var width = 0;\r\n var index = billboard._imageIndex;\r\n if (index !== -1) {\r\n var imageRectangle = textureAtlasCoordinates[index];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(imageRectangle)) {\r\n throw new DeveloperError(\"Invalid billboard image index: \" + index);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n width = imageRectangle.width;\r\n }\r\n\r\n var textureWidth = billboardCollection._textureAtlas.texture.width;\r\n var imageWidth = Math.round(\r\n defaultValue(billboard.width, textureWidth * width)\r\n );\r\n billboardCollection._maxSize = Math.max(\r\n billboardCollection._maxSize,\r\n imageWidth\r\n );\r\n\r\n var compressed0 = CesiumMath.clamp(imageWidth, 0.0, LEFT_SHIFT16);\r\n var compressed1 = 0.0;\r\n\r\n if (\r\n Math.abs(Cartesian3.magnitudeSquared(alignedAxis) - 1.0) <\r\n CesiumMath.EPSILON6\r\n ) {\r\n compressed1 = AttributeCompression.octEncodeFloat(alignedAxis);\r\n }\r\n\r\n nearValue = CesiumMath.clamp(nearValue, 0.0, 1.0);\r\n nearValue = nearValue === 1.0 ? 255.0 : (nearValue * 255.0) | 0;\r\n compressed0 = compressed0 * LEFT_SHIFT8 + nearValue;\r\n\r\n farValue = CesiumMath.clamp(farValue, 0.0, 1.0);\r\n farValue = farValue === 1.0 ? 255.0 : (farValue * 255.0) | 0;\r\n compressed1 = compressed1 * LEFT_SHIFT8 + farValue;\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, compressed0, compressed1, near, far);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, compressed0, compressed1, near, far);\r\n writer(i + 1, compressed0, compressed1, near, far);\r\n writer(i + 2, compressed0, compressed1, near, far);\r\n writer(i + 3, compressed0, compressed1, near, far);\r\n }\r\n}\r\n\r\nfunction writeCompressedAttrib2(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n var i;\r\n var writer = vafWriters[attributeLocations.compressedAttribute2];\r\n var color = billboard.color;\r\n var pickColor = !defined(billboardCollection._batchTable)\r\n ? billboard.getPickId(frameState.context).color\r\n : Color.WHITE;\r\n var sizeInMeters = billboard.sizeInMeters ? 1.0 : 0.0;\r\n var validAlignedAxis =\r\n Math.abs(Cartesian3.magnitudeSquared(billboard.alignedAxis) - 1.0) <\r\n CesiumMath.EPSILON6\r\n ? 1.0\r\n : 0.0;\r\n\r\n billboardCollection._allSizedInMeters =\r\n billboardCollection._allSizedInMeters && sizeInMeters === 1.0;\r\n\r\n var height = 0;\r\n var index = billboard._imageIndex;\r\n if (index !== -1) {\r\n var imageRectangle = textureAtlasCoordinates[index];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(imageRectangle)) {\r\n throw new DeveloperError(\"Invalid billboard image index: \" + index);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n height = imageRectangle.height;\r\n }\r\n\r\n var dimensions = billboardCollection._textureAtlas.texture.dimensions;\r\n var imageHeight = Math.round(\r\n defaultValue(billboard.height, dimensions.y * height)\r\n );\r\n billboardCollection._maxSize = Math.max(\r\n billboardCollection._maxSize,\r\n imageHeight\r\n );\r\n var labelHorizontalOrigin = defaultValue(\r\n billboard._labelHorizontalOrigin,\r\n -2\r\n );\r\n labelHorizontalOrigin += 2;\r\n var compressed3 = imageHeight * LEFT_SHIFT2 + labelHorizontalOrigin;\r\n\r\n var red = Color.floatToByte(color.red);\r\n var green = Color.floatToByte(color.green);\r\n var blue = Color.floatToByte(color.blue);\r\n var compressed0 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;\r\n\r\n red = Color.floatToByte(pickColor.red);\r\n green = Color.floatToByte(pickColor.green);\r\n blue = Color.floatToByte(pickColor.blue);\r\n var compressed1 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;\r\n\r\n var compressed2 =\r\n Color.floatToByte(color.alpha) * LEFT_SHIFT16 +\r\n Color.floatToByte(pickColor.alpha) * LEFT_SHIFT8;\r\n compressed2 += sizeInMeters * 2.0 + validAlignedAxis;\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, compressed0, compressed1, compressed2, compressed3);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, compressed0, compressed1, compressed2, compressed3);\r\n writer(i + 1, compressed0, compressed1, compressed2, compressed3);\r\n writer(i + 2, compressed0, compressed1, compressed2, compressed3);\r\n writer(i + 3, compressed0, compressed1, compressed2, compressed3);\r\n }\r\n}\r\n\r\nfunction writeEyeOffset(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n var i;\r\n var writer = vafWriters[attributeLocations.eyeOffset];\r\n var eyeOffset = billboard.eyeOffset;\r\n\r\n // For billboards that are clamped to ground, move it slightly closer to the camera\r\n var eyeOffsetZ = eyeOffset.z;\r\n if (billboard._heightReference !== HeightReference.NONE) {\r\n eyeOffsetZ *= 1.005;\r\n }\r\n billboardCollection._maxEyeOffset = Math.max(\r\n billboardCollection._maxEyeOffset,\r\n Math.abs(eyeOffset.x),\r\n Math.abs(eyeOffset.y),\r\n Math.abs(eyeOffsetZ)\r\n );\r\n\r\n if (billboardCollection._instanced) {\r\n var width = 0;\r\n var height = 0;\r\n var index = billboard._imageIndex;\r\n if (index !== -1) {\r\n var imageRectangle = textureAtlasCoordinates[index];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(imageRectangle)) {\r\n throw new DeveloperError(\"Invalid billboard image index: \" + index);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n width = imageRectangle.width;\r\n height = imageRectangle.height;\r\n }\r\n\r\n scratchCartesian2.x = width;\r\n scratchCartesian2.y = height;\r\n var compressedTexCoordsRange = AttributeCompression.compressTextureCoordinates(\r\n scratchCartesian2\r\n );\r\n\r\n i = billboard._index;\r\n writer(i, eyeOffset.x, eyeOffset.y, eyeOffsetZ, compressedTexCoordsRange);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0.0);\r\n writer(i + 1, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0.0);\r\n writer(i + 2, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0.0);\r\n writer(i + 3, eyeOffset.x, eyeOffset.y, eyeOffsetZ, 0.0);\r\n }\r\n}\r\n\r\nfunction writeScaleByDistance(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n var i;\r\n var writer = vafWriters[attributeLocations.scaleByDistance];\r\n var near = 0.0;\r\n var nearValue = 1.0;\r\n var far = 1.0;\r\n var farValue = 1.0;\r\n\r\n var scale = billboard.scaleByDistance;\r\n if (defined(scale)) {\r\n near = scale.near;\r\n nearValue = scale.nearValue;\r\n far = scale.far;\r\n farValue = scale.farValue;\r\n\r\n if (nearValue !== 1.0 || farValue !== 1.0) {\r\n // scale by distance calculation in shader need not be enabled\r\n // until a billboard with near and far !== 1.0 is found\r\n billboardCollection._shaderScaleByDistance = true;\r\n }\r\n }\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, near, nearValue, far, farValue);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, near, nearValue, far, farValue);\r\n writer(i + 1, near, nearValue, far, farValue);\r\n writer(i + 2, near, nearValue, far, farValue);\r\n writer(i + 3, near, nearValue, far, farValue);\r\n }\r\n}\r\n\r\nfunction writePixelOffsetScaleByDistance(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n var i;\r\n var writer = vafWriters[attributeLocations.pixelOffsetScaleByDistance];\r\n var near = 0.0;\r\n var nearValue = 1.0;\r\n var far = 1.0;\r\n var farValue = 1.0;\r\n\r\n var pixelOffsetScale = billboard.pixelOffsetScaleByDistance;\r\n if (defined(pixelOffsetScale)) {\r\n near = pixelOffsetScale.near;\r\n nearValue = pixelOffsetScale.nearValue;\r\n far = pixelOffsetScale.far;\r\n farValue = pixelOffsetScale.farValue;\r\n\r\n if (nearValue !== 1.0 || farValue !== 1.0) {\r\n // pixelOffsetScale by distance calculation in shader need not be enabled\r\n // until a billboard with near and far !== 1.0 is found\r\n billboardCollection._shaderPixelOffsetScaleByDistance = true;\r\n }\r\n }\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, near, nearValue, far, farValue);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, near, nearValue, far, farValue);\r\n writer(i + 1, near, nearValue, far, farValue);\r\n writer(i + 2, near, nearValue, far, farValue);\r\n writer(i + 3, near, nearValue, far, farValue);\r\n }\r\n}\r\n\r\nfunction writeCompressedAttribute3(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n var i;\r\n var writer = vafWriters[attributeLocations.compressedAttribute3];\r\n var near = 0.0;\r\n var far = Number.MAX_VALUE;\r\n\r\n var distanceDisplayCondition = billboard.distanceDisplayCondition;\r\n if (defined(distanceDisplayCondition)) {\r\n near = distanceDisplayCondition.near;\r\n far = distanceDisplayCondition.far;\r\n\r\n near *= near;\r\n far *= far;\r\n\r\n billboardCollection._shaderDistanceDisplayCondition = true;\r\n }\r\n\r\n var disableDepthTestDistance = billboard.disableDepthTestDistance;\r\n var clampToGround =\r\n billboard.heightReference === HeightReference.CLAMP_TO_GROUND &&\r\n frameState.context.depthTexture;\r\n if (!defined(disableDepthTestDistance)) {\r\n disableDepthTestDistance = clampToGround ? 5000.0 : 0.0;\r\n }\r\n\r\n disableDepthTestDistance *= disableDepthTestDistance;\r\n if (clampToGround || disableDepthTestDistance > 0.0) {\r\n billboardCollection._shaderDisableDepthDistance = true;\r\n if (disableDepthTestDistance === Number.POSITIVE_INFINITY) {\r\n disableDepthTestDistance = -1.0;\r\n }\r\n }\r\n\r\n var imageHeight;\r\n var imageWidth;\r\n\r\n if (!defined(billboard._labelDimensions)) {\r\n var height = 0;\r\n var width = 0;\r\n var index = billboard._imageIndex;\r\n if (index !== -1) {\r\n var imageRectangle = textureAtlasCoordinates[index];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(imageRectangle)) {\r\n throw new DeveloperError(\"Invalid billboard image index: \" + index);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n height = imageRectangle.height;\r\n width = imageRectangle.width;\r\n }\r\n\r\n imageHeight = Math.round(\r\n defaultValue(\r\n billboard.height,\r\n billboardCollection._textureAtlas.texture.dimensions.y * height\r\n )\r\n );\r\n\r\n var textureWidth = billboardCollection._textureAtlas.texture.width;\r\n imageWidth = Math.round(\r\n defaultValue(billboard.width, textureWidth * width)\r\n );\r\n } else {\r\n imageWidth = billboard._labelDimensions.x;\r\n imageHeight = billboard._labelDimensions.y;\r\n }\r\n\r\n var w = Math.floor(CesiumMath.clamp(imageWidth, 0.0, LEFT_SHIFT12));\r\n var h = Math.floor(CesiumMath.clamp(imageHeight, 0.0, LEFT_SHIFT12));\r\n var dimensions = w * LEFT_SHIFT12 + h;\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, near, far, disableDepthTestDistance, dimensions);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, near, far, disableDepthTestDistance, dimensions);\r\n writer(i + 1, near, far, disableDepthTestDistance, dimensions);\r\n writer(i + 2, near, far, disableDepthTestDistance, dimensions);\r\n writer(i + 3, near, far, disableDepthTestDistance, dimensions);\r\n }\r\n}\r\n\r\nfunction writeTextureCoordinateBoundsOrLabelTranslate(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n if (billboard.heightReference === HeightReference.CLAMP_TO_GROUND) {\r\n var scene = billboardCollection._scene;\r\n var context = frameState.context;\r\n var globeTranslucent = frameState.globeTranslucencyState.translucent;\r\n var depthTestAgainstTerrain =\r\n defined(scene.globe) && scene.globe.depthTestAgainstTerrain;\r\n\r\n // Only do manual depth test if the globe is opaque and writes depth\r\n billboardCollection._shaderClampToGround =\r\n context.depthTexture && !globeTranslucent && depthTestAgainstTerrain;\r\n }\r\n var i;\r\n var writer =\r\n vafWriters[attributeLocations.textureCoordinateBoundsOrLabelTranslate];\r\n\r\n if (ContextLimits.maximumVertexTextureImageUnits > 0) {\r\n //write _labelTranslate, used by depth testing in the vertex shader\r\n var translateX = 0;\r\n var translateY = 0;\r\n if (defined(billboard._labelTranslate)) {\r\n translateX = billboard._labelTranslate.x;\r\n translateY = billboard._labelTranslate.y;\r\n }\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, translateX, translateY, 0.0, 0.0);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, translateX, translateY, 0.0, 0.0);\r\n writer(i + 1, translateX, translateY, 0.0, 0.0);\r\n writer(i + 2, translateX, translateY, 0.0, 0.0);\r\n writer(i + 3, translateX, translateY, 0.0, 0.0);\r\n }\r\n return;\r\n }\r\n\r\n //write texture coordinate bounds, used by depth testing in fragment shader\r\n var minX = 0;\r\n var minY = 0;\r\n var width = 0;\r\n var height = 0;\r\n var index = billboard._imageIndex;\r\n if (index !== -1) {\r\n var imageRectangle = textureAtlasCoordinates[index];\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(imageRectangle)) {\r\n throw new DeveloperError(\"Invalid billboard image index: \" + index);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n minX = imageRectangle.x;\r\n minY = imageRectangle.y;\r\n width = imageRectangle.width;\r\n height = imageRectangle.height;\r\n }\r\n var maxX = minX + width;\r\n var maxY = minY + height;\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, minX, minY, maxX, maxY);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, minX, minY, maxX, maxY);\r\n writer(i + 1, minX, minY, maxX, maxY);\r\n writer(i + 2, minX, minY, maxX, maxY);\r\n writer(i + 3, minX, minY, maxX, maxY);\r\n }\r\n}\r\n\r\nfunction writeBatchId(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n if (!defined(billboardCollection._batchTable)) {\r\n return;\r\n }\r\n\r\n var writer = vafWriters[attributeLocations.a_batchId];\r\n var id = billboard._batchIndex;\r\n\r\n var i;\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, id);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, id);\r\n writer(i + 1, id);\r\n writer(i + 2, id);\r\n writer(i + 3, id);\r\n }\r\n}\r\n\r\nfunction writeSDF(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n if (!billboardCollection._sdf) {\r\n return;\r\n }\r\n\r\n var i;\r\n var writer = vafWriters[attributeLocations.sdf];\r\n\r\n var outlineColor = billboard.outlineColor;\r\n var outlineWidth = billboard.outlineWidth;\r\n\r\n var red = Color.floatToByte(outlineColor.red);\r\n var green = Color.floatToByte(outlineColor.green);\r\n var blue = Color.floatToByte(outlineColor.blue);\r\n var compressed0 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;\r\n\r\n // Compute the relative outline distance\r\n var outlineDistance = outlineWidth / SDFSettings.RADIUS;\r\n var compressed1 =\r\n Color.floatToByte(outlineColor.alpha) * LEFT_SHIFT16 +\r\n Color.floatToByte(outlineDistance) * LEFT_SHIFT8;\r\n\r\n if (billboardCollection._instanced) {\r\n i = billboard._index;\r\n writer(i, compressed0, compressed1);\r\n } else {\r\n i = billboard._index * 4;\r\n writer(i + 0, compressed0 + LOWER_LEFT, compressed1);\r\n writer(i + 1, compressed0 + LOWER_RIGHT, compressed1);\r\n writer(i + 2, compressed0 + UPPER_RIGHT, compressed1);\r\n writer(i + 3, compressed0 + UPPER_LEFT, compressed1);\r\n }\r\n}\r\n\r\nfunction writeBillboard(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n) {\r\n writePositionScaleAndRotation(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeCompressedAttrib0(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeCompressedAttrib1(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeCompressedAttrib2(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeEyeOffset(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeScaleByDistance(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writePixelOffsetScaleByDistance(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeCompressedAttribute3(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeTextureCoordinateBoundsOrLabelTranslate(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeBatchId(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n writeSDF(\r\n billboardCollection,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n}\r\n\r\nfunction recomputeActualPositions(\r\n billboardCollection,\r\n billboards,\r\n length,\r\n frameState,\r\n modelMatrix,\r\n recomputeBoundingVolume\r\n) {\r\n var boundingVolume;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n boundingVolume = billboardCollection._baseVolume;\r\n billboardCollection._boundingVolumeDirty = true;\r\n } else {\r\n boundingVolume = billboardCollection._baseVolume2D;\r\n }\r\n\r\n var positions = [];\r\n for (var i = 0; i < length; ++i) {\r\n var billboard = billboards[i];\r\n var position = billboard.position;\r\n var actualPosition = Billboard._computeActualPosition(\r\n billboard,\r\n position,\r\n frameState,\r\n modelMatrix\r\n );\r\n if (defined(actualPosition)) {\r\n billboard._setActualPosition(actualPosition);\r\n\r\n if (recomputeBoundingVolume) {\r\n positions.push(actualPosition);\r\n } else {\r\n BoundingSphere.expand(boundingVolume, actualPosition, boundingVolume);\r\n }\r\n }\r\n }\r\n\r\n if (recomputeBoundingVolume) {\r\n BoundingSphere.fromPoints(positions, boundingVolume);\r\n }\r\n}\r\n\r\nfunction updateMode(billboardCollection, frameState) {\r\n var mode = frameState.mode;\r\n\r\n var billboards = billboardCollection._billboards;\r\n var billboardsToUpdate = billboardCollection._billboardsToUpdate;\r\n var modelMatrix = billboardCollection._modelMatrix;\r\n\r\n if (\r\n billboardCollection._createVertexArray ||\r\n billboardCollection._mode !== mode ||\r\n (mode !== SceneMode.SCENE3D &&\r\n !Matrix4.equals(modelMatrix, billboardCollection.modelMatrix))\r\n ) {\r\n billboardCollection._mode = mode;\r\n Matrix4.clone(billboardCollection.modelMatrix, modelMatrix);\r\n billboardCollection._createVertexArray = true;\r\n\r\n if (\r\n mode === SceneMode.SCENE3D ||\r\n mode === SceneMode.SCENE2D ||\r\n mode === SceneMode.COLUMBUS_VIEW\r\n ) {\r\n recomputeActualPositions(\r\n billboardCollection,\r\n billboards,\r\n billboards.length,\r\n frameState,\r\n modelMatrix,\r\n true\r\n );\r\n }\r\n } else if (mode === SceneMode.MORPHING) {\r\n recomputeActualPositions(\r\n billboardCollection,\r\n billboards,\r\n billboards.length,\r\n frameState,\r\n modelMatrix,\r\n true\r\n );\r\n } else if (mode === SceneMode.SCENE2D || mode === SceneMode.COLUMBUS_VIEW) {\r\n recomputeActualPositions(\r\n billboardCollection,\r\n billboardsToUpdate,\r\n billboardCollection._billboardsToUpdateIndex,\r\n frameState,\r\n modelMatrix,\r\n false\r\n );\r\n }\r\n}\r\n\r\nfunction updateBoundingVolume(collection, frameState, boundingVolume) {\r\n var pixelScale = 1.0;\r\n if (!collection._allSizedInMeters || collection._maxPixelOffset !== 0.0) {\r\n pixelScale = frameState.camera.getPixelSize(\r\n boundingVolume,\r\n frameState.context.drawingBufferWidth,\r\n frameState.context.drawingBufferHeight\r\n );\r\n }\r\n\r\n var size = pixelScale * collection._maxScale * collection._maxSize * 2.0;\r\n if (collection._allHorizontalCenter && collection._allVerticalCenter) {\r\n size *= 0.5;\r\n }\r\n\r\n var offset =\r\n pixelScale * collection._maxPixelOffset + collection._maxEyeOffset;\r\n boundingVolume.radius += size + offset;\r\n}\r\n\r\nfunction createDebugCommand(billboardCollection, context) {\r\n var fs;\r\n fs =\r\n \"uniform sampler2D billboard_texture; \\n\" +\r\n \"varying vec2 v_textureCoordinates; \\n\" +\r\n \"void main() \\n\" +\r\n \"{ \\n\" +\r\n \" gl_FragColor = texture2D(billboard_texture, v_textureCoordinates); \\n\" +\r\n \"} \\n\";\r\n\r\n var drawCommand = context.createViewportQuadCommand(fs, {\r\n uniformMap: {\r\n billboard_texture: function () {\r\n return billboardCollection._textureAtlas.texture;\r\n },\r\n },\r\n });\r\n drawCommand.pass = Pass.OVERLAY;\r\n return drawCommand;\r\n}\r\n\r\nvar scratchWriterArray = [];\r\n\r\n/**\r\n * Called when {@link Viewer} or {@link CesiumWidget} render the scene to\r\n * get the draw commands needed to render this primitive.\r\n *

\r\n * Do not call this function directly. This is documented just to\r\n * list the exceptions that may be propagated when the scene is rendered:\r\n *

\r\n *\r\n * @exception {RuntimeError} image with id must be in the atlas.\r\n */\r\nBillboardCollection.prototype.update = function (frameState) {\r\n removeBillboards(this);\r\n\r\n if (!this.show) {\r\n return;\r\n }\r\n\r\n var billboards = this._billboards;\r\n var billboardsLength = billboards.length;\r\n\r\n var context = frameState.context;\r\n this._instanced = context.instancedArrays;\r\n attributeLocations = this._instanced\r\n ? attributeLocationsInstanced\r\n : attributeLocationsBatched;\r\n getIndexBuffer = this._instanced\r\n ? getIndexBufferInstanced\r\n : getIndexBufferBatched;\r\n\r\n var textureAtlas = this._textureAtlas;\r\n if (!defined(textureAtlas)) {\r\n textureAtlas = this._textureAtlas = new TextureAtlas({\r\n context: context,\r\n });\r\n\r\n for (var ii = 0; ii < billboardsLength; ++ii) {\r\n billboards[ii]._loadImage();\r\n }\r\n }\r\n\r\n var textureAtlasCoordinates = textureAtlas.textureCoordinates;\r\n if (textureAtlasCoordinates.length === 0) {\r\n // Can't write billboard vertices until we have texture coordinates\r\n // provided by a texture atlas\r\n return;\r\n }\r\n\r\n updateMode(this, frameState);\r\n\r\n billboards = this._billboards;\r\n billboardsLength = billboards.length;\r\n var billboardsToUpdate = this._billboardsToUpdate;\r\n var billboardsToUpdateLength = this._billboardsToUpdateIndex;\r\n\r\n var properties = this._propertiesChanged;\r\n\r\n var textureAtlasGUID = textureAtlas.guid;\r\n var createVertexArray =\r\n this._createVertexArray || this._textureAtlasGUID !== textureAtlasGUID;\r\n this._textureAtlasGUID = textureAtlasGUID;\r\n\r\n var vafWriters;\r\n var pass = frameState.passes;\r\n var picking = pass.pick;\r\n\r\n // PERFORMANCE_IDEA: Round robin multiple buffers.\r\n if (createVertexArray || (!picking && this.computeNewBuffersUsage())) {\r\n this._createVertexArray = false;\r\n\r\n for (var k = 0; k < NUMBER_OF_PROPERTIES; ++k) {\r\n properties[k] = 0;\r\n }\r\n\r\n this._vaf = this._vaf && this._vaf.destroy();\r\n\r\n if (billboardsLength > 0) {\r\n // PERFORMANCE_IDEA: Instead of creating a new one, resize like std::vector.\r\n this._vaf = createVAF(\r\n context,\r\n billboardsLength,\r\n this._buffersUsage,\r\n this._instanced,\r\n this._batchTable,\r\n this._sdf\r\n );\r\n vafWriters = this._vaf.writers;\r\n\r\n // Rewrite entire buffer if billboards were added or removed.\r\n for (var i = 0; i < billboardsLength; ++i) {\r\n var billboard = this._billboards[i];\r\n billboard._dirty = false; // In case it needed an update.\r\n writeBillboard(\r\n this,\r\n frameState,\r\n textureAtlasCoordinates,\r\n vafWriters,\r\n billboard\r\n );\r\n }\r\n\r\n // Different billboard collections share the same index buffer.\r\n this._vaf.commit(getIndexBuffer(context));\r\n }\r\n\r\n this._billboardsToUpdateIndex = 0;\r\n } else if (billboardsToUpdateLength > 0) {\r\n // Billboards were modified, but none were added or removed.\r\n var writers = scratchWriterArray;\r\n writers.length = 0;\r\n\r\n if (\r\n properties[POSITION_INDEX] ||\r\n properties[ROTATION_INDEX] ||\r\n properties[SCALE_INDEX]\r\n ) {\r\n writers.push(writePositionScaleAndRotation);\r\n }\r\n\r\n if (\r\n properties[IMAGE_INDEX_INDEX] ||\r\n properties[PIXEL_OFFSET_INDEX] ||\r\n properties[HORIZONTAL_ORIGIN_INDEX] ||\r\n properties[VERTICAL_ORIGIN_INDEX] ||\r\n properties[SHOW_INDEX]\r\n ) {\r\n writers.push(writeCompressedAttrib0);\r\n if (this._instanced) {\r\n writers.push(writeEyeOffset);\r\n }\r\n }\r\n\r\n if (\r\n properties[IMAGE_INDEX_INDEX] ||\r\n properties[ALIGNED_AXIS_INDEX] ||\r\n properties[TRANSLUCENCY_BY_DISTANCE_INDEX]\r\n ) {\r\n writers.push(writeCompressedAttrib1);\r\n writers.push(writeCompressedAttrib2);\r\n }\r\n\r\n if (properties[IMAGE_INDEX_INDEX] || properties[COLOR_INDEX]) {\r\n writers.push(writeCompressedAttrib2);\r\n }\r\n\r\n if (properties[EYE_OFFSET_INDEX]) {\r\n writers.push(writeEyeOffset);\r\n }\r\n\r\n if (properties[SCALE_BY_DISTANCE_INDEX]) {\r\n writers.push(writeScaleByDistance);\r\n }\r\n\r\n if (properties[PIXEL_OFFSET_SCALE_BY_DISTANCE_INDEX]) {\r\n writers.push(writePixelOffsetScaleByDistance);\r\n }\r\n\r\n if (\r\n properties[DISTANCE_DISPLAY_CONDITION_INDEX] ||\r\n properties[DISABLE_DEPTH_DISTANCE] ||\r\n properties[IMAGE_INDEX_INDEX] ||\r\n properties[POSITION_INDEX]\r\n ) {\r\n writers.push(writeCompressedAttribute3);\r\n }\r\n\r\n if (properties[IMAGE_INDEX_INDEX] || properties[POSITION_INDEX]) {\r\n writers.push(writeTextureCoordinateBoundsOrLabelTranslate);\r\n }\r\n\r\n if (properties[SDF_INDEX]) {\r\n writers.push(writeSDF);\r\n }\r\n\r\n var numWriters = writers.length;\r\n vafWriters = this._vaf.writers;\r\n\r\n if (billboardsToUpdateLength / billboardsLength > 0.1) {\r\n // If more than 10% of billboard change, rewrite the entire buffer.\r\n\r\n // PERFORMANCE_IDEA: I totally made up 10% :).\r\n\r\n for (var m = 0; m < billboardsToUpdateLength; ++m) {\r\n var b = billboardsToUpdate[m];\r\n b._dirty = false;\r\n\r\n for (var n = 0; n < numWriters; ++n) {\r\n writers[n](this, frameState, textureAtlasCoordinates, vafWriters, b);\r\n }\r\n }\r\n this._vaf.commit(getIndexBuffer(context));\r\n } else {\r\n for (var h = 0; h < billboardsToUpdateLength; ++h) {\r\n var bb = billboardsToUpdate[h];\r\n bb._dirty = false;\r\n\r\n for (var o = 0; o < numWriters; ++o) {\r\n writers[o](this, frameState, textureAtlasCoordinates, vafWriters, bb);\r\n }\r\n\r\n if (this._instanced) {\r\n this._vaf.subCommit(bb._index, 1);\r\n } else {\r\n this._vaf.subCommit(bb._index * 4, 4);\r\n }\r\n }\r\n this._vaf.endSubCommits();\r\n }\r\n\r\n this._billboardsToUpdateIndex = 0;\r\n }\r\n\r\n // If the number of total billboards ever shrinks considerably\r\n // Truncate billboardsToUpdate so that we free memory that we're\r\n // not going to be using.\r\n if (billboardsToUpdateLength > billboardsLength * 1.5) {\r\n billboardsToUpdate.length = billboardsLength;\r\n }\r\n\r\n if (!defined(this._vaf) || !defined(this._vaf.va)) {\r\n return;\r\n }\r\n\r\n if (this._boundingVolumeDirty) {\r\n this._boundingVolumeDirty = false;\r\n BoundingSphere.transform(\r\n this._baseVolume,\r\n this.modelMatrix,\r\n this._baseVolumeWC\r\n );\r\n }\r\n\r\n var boundingVolume;\r\n var modelMatrix = Matrix4.IDENTITY;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n modelMatrix = this.modelMatrix;\r\n boundingVolume = BoundingSphere.clone(\r\n this._baseVolumeWC,\r\n this._boundingVolume\r\n );\r\n } else {\r\n boundingVolume = BoundingSphere.clone(\r\n this._baseVolume2D,\r\n this._boundingVolume\r\n );\r\n }\r\n updateBoundingVolume(this, frameState, boundingVolume);\r\n\r\n var blendOptionChanged = this._blendOption !== this.blendOption;\r\n this._blendOption = this.blendOption;\r\n\r\n if (blendOptionChanged) {\r\n if (\r\n this._blendOption === BlendOption.OPAQUE ||\r\n this._blendOption === BlendOption.OPAQUE_AND_TRANSLUCENT\r\n ) {\r\n this._rsOpaque = RenderState.fromCache({\r\n depthTest: {\r\n enabled: true,\r\n func: WebGLConstants.LESS,\r\n },\r\n depthMask: true,\r\n });\r\n } else {\r\n this._rsOpaque = undefined;\r\n }\r\n\r\n // If OPAQUE_AND_TRANSLUCENT is in use, only the opaque pass gets the benefit of the depth buffer,\r\n // not the translucent pass. Otherwise, if the TRANSLUCENT pass is on its own, it turns on\r\n // a depthMask in lieu of full depth sorting (because it has opaque-ish fragments that look bad in OIT).\r\n // When the TRANSLUCENT depth mask is in use, label backgrounds require the depth func to be LEQUAL.\r\n var useTranslucentDepthMask = this._blendOption === BlendOption.TRANSLUCENT;\r\n\r\n if (\r\n this._blendOption === BlendOption.TRANSLUCENT ||\r\n this._blendOption === BlendOption.OPAQUE_AND_TRANSLUCENT\r\n ) {\r\n this._rsTranslucent = RenderState.fromCache({\r\n depthTest: {\r\n enabled: true,\r\n func: useTranslucentDepthMask\r\n ? WebGLConstants.LEQUAL\r\n : WebGLConstants.LESS,\r\n },\r\n depthMask: useTranslucentDepthMask,\r\n blending: BlendingState.ALPHA_BLEND,\r\n });\r\n } else {\r\n this._rsTranslucent = undefined;\r\n }\r\n }\r\n\r\n this._shaderDisableDepthDistance =\r\n this._shaderDisableDepthDistance ||\r\n frameState.minimumDisableDepthTestDistance !== 0.0;\r\n\r\n var vsSource;\r\n var fsSource;\r\n var vs;\r\n var fs;\r\n var vertDefines;\r\n\r\n var supportVSTextureReads = ContextLimits.maximumVertexTextureImageUnits > 0;\r\n\r\n if (\r\n blendOptionChanged ||\r\n this._shaderRotation !== this._compiledShaderRotation ||\r\n this._shaderAlignedAxis !== this._compiledShaderAlignedAxis ||\r\n this._shaderScaleByDistance !== this._compiledShaderScaleByDistance ||\r\n this._shaderTranslucencyByDistance !==\r\n this._compiledShaderTranslucencyByDistance ||\r\n this._shaderPixelOffsetScaleByDistance !==\r\n this._compiledShaderPixelOffsetScaleByDistance ||\r\n this._shaderDistanceDisplayCondition !==\r\n this._compiledShaderDistanceDisplayCondition ||\r\n this._shaderDisableDepthDistance !==\r\n this._compiledShaderDisableDepthDistance ||\r\n this._shaderClampToGround !== this._compiledShaderClampToGround ||\r\n this._sdf !== this._compiledSDF\r\n ) {\r\n vsSource = BillboardCollectionVS;\r\n fsSource = BillboardCollectionFS;\r\n\r\n vertDefines = [];\r\n if (defined(this._batchTable)) {\r\n vertDefines.push(\"VECTOR_TILE\");\r\n vsSource = this._batchTable.getVertexShaderCallback(\r\n false,\r\n \"a_batchId\",\r\n undefined\r\n )(vsSource);\r\n fsSource = this._batchTable.getFragmentShaderCallback(\r\n false,\r\n undefined\r\n )(fsSource);\r\n }\r\n\r\n vs = new ShaderSource({\r\n defines: vertDefines,\r\n sources: [vsSource],\r\n });\r\n if (this._instanced) {\r\n vs.defines.push(\"INSTANCED\");\r\n }\r\n if (this._shaderRotation) {\r\n vs.defines.push(\"ROTATION\");\r\n }\r\n if (this._shaderAlignedAxis) {\r\n vs.defines.push(\"ALIGNED_AXIS\");\r\n }\r\n if (this._shaderScaleByDistance) {\r\n vs.defines.push(\"EYE_DISTANCE_SCALING\");\r\n }\r\n if (this._shaderTranslucencyByDistance) {\r\n vs.defines.push(\"EYE_DISTANCE_TRANSLUCENCY\");\r\n }\r\n if (this._shaderPixelOffsetScaleByDistance) {\r\n vs.defines.push(\"EYE_DISTANCE_PIXEL_OFFSET\");\r\n }\r\n if (this._shaderDistanceDisplayCondition) {\r\n vs.defines.push(\"DISTANCE_DISPLAY_CONDITION\");\r\n }\r\n if (this._shaderDisableDepthDistance) {\r\n vs.defines.push(\"DISABLE_DEPTH_DISTANCE\");\r\n }\r\n if (this._shaderClampToGround) {\r\n if (supportVSTextureReads) {\r\n vs.defines.push(\"VERTEX_DEPTH_CHECK\");\r\n } else {\r\n vs.defines.push(\"FRAGMENT_DEPTH_CHECK\");\r\n }\r\n }\r\n\r\n var sdfEdge = 1.0 - SDFSettings.CUTOFF;\r\n\r\n if (this._sdf) {\r\n vs.defines.push(\"SDF\");\r\n }\r\n\r\n var vectorFragDefine = defined(this._batchTable) ? \"VECTOR_TILE\" : \"\";\r\n\r\n if (this._blendOption === BlendOption.OPAQUE_AND_TRANSLUCENT) {\r\n fs = new ShaderSource({\r\n defines: [\"OPAQUE\", vectorFragDefine],\r\n sources: [fsSource],\r\n });\r\n if (this._shaderClampToGround) {\r\n if (supportVSTextureReads) {\r\n fs.defines.push(\"VERTEX_DEPTH_CHECK\");\r\n } else {\r\n fs.defines.push(\"FRAGMENT_DEPTH_CHECK\");\r\n }\r\n }\r\n\r\n if (this._sdf) {\r\n fs.defines.push(\"SDF\");\r\n fs.defines.push(\"SDF_EDGE \" + sdfEdge);\r\n }\r\n\r\n this._sp = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: this._sp,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n fs = new ShaderSource({\r\n defines: [\"TRANSLUCENT\", vectorFragDefine],\r\n sources: [fsSource],\r\n });\r\n if (this._shaderClampToGround) {\r\n if (supportVSTextureReads) {\r\n fs.defines.push(\"VERTEX_DEPTH_CHECK\");\r\n } else {\r\n fs.defines.push(\"FRAGMENT_DEPTH_CHECK\");\r\n }\r\n }\r\n if (this._sdf) {\r\n fs.defines.push(\"SDF\");\r\n fs.defines.push(\"SDF_EDGE \" + sdfEdge);\r\n }\r\n this._spTranslucent = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: this._spTranslucent,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n }\r\n\r\n if (this._blendOption === BlendOption.OPAQUE) {\r\n fs = new ShaderSource({\r\n defines: [vectorFragDefine],\r\n sources: [fsSource],\r\n });\r\n if (this._shaderClampToGround) {\r\n if (supportVSTextureReads) {\r\n fs.defines.push(\"VERTEX_DEPTH_CHECK\");\r\n } else {\r\n fs.defines.push(\"FRAGMENT_DEPTH_CHECK\");\r\n }\r\n }\r\n if (this._sdf) {\r\n fs.defines.push(\"SDF\");\r\n fs.defines.push(\"SDF_EDGE \" + sdfEdge);\r\n }\r\n this._sp = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: this._sp,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n }\r\n\r\n if (this._blendOption === BlendOption.TRANSLUCENT) {\r\n fs = new ShaderSource({\r\n defines: [vectorFragDefine],\r\n sources: [fsSource],\r\n });\r\n if (this._shaderClampToGround) {\r\n if (supportVSTextureReads) {\r\n fs.defines.push(\"VERTEX_DEPTH_CHECK\");\r\n } else {\r\n fs.defines.push(\"FRAGMENT_DEPTH_CHECK\");\r\n }\r\n }\r\n if (this._sdf) {\r\n fs.defines.push(\"SDF\");\r\n fs.defines.push(\"SDF_EDGE \" + sdfEdge);\r\n }\r\n this._spTranslucent = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: this._spTranslucent,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n }\r\n\r\n this._compiledShaderRotation = this._shaderRotation;\r\n this._compiledShaderAlignedAxis = this._shaderAlignedAxis;\r\n this._compiledShaderScaleByDistance = this._shaderScaleByDistance;\r\n this._compiledShaderTranslucencyByDistance = this._shaderTranslucencyByDistance;\r\n this._compiledShaderPixelOffsetScaleByDistance = this._shaderPixelOffsetScaleByDistance;\r\n this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition;\r\n this._compiledShaderDisableDepthDistance = this._shaderDisableDepthDistance;\r\n this._compiledShaderClampToGround = this._shaderClampToGround;\r\n this._compiledSDF = this._sdf;\r\n }\r\n\r\n var commandList = frameState.commandList;\r\n\r\n if (pass.render || pass.pick) {\r\n var colorList = this._colorCommands;\r\n\r\n var opaque = this._blendOption === BlendOption.OPAQUE;\r\n var opaqueAndTranslucent =\r\n this._blendOption === BlendOption.OPAQUE_AND_TRANSLUCENT;\r\n\r\n var va = this._vaf.va;\r\n var vaLength = va.length;\r\n\r\n var uniforms = this._uniforms;\r\n var pickId;\r\n if (defined(this._batchTable)) {\r\n uniforms = this._batchTable.getUniformMapCallback()(uniforms);\r\n pickId = this._batchTable.getPickId();\r\n } else {\r\n pickId = \"v_pickColor\";\r\n }\r\n\r\n colorList.length = vaLength;\r\n var totalLength = opaqueAndTranslucent ? vaLength * 2 : vaLength;\r\n for (var j = 0; j < totalLength; ++j) {\r\n var command = colorList[j];\r\n if (!defined(command)) {\r\n command = colorList[j] = new DrawCommand();\r\n }\r\n\r\n var opaqueCommand = opaque || (opaqueAndTranslucent && j % 2 === 0);\r\n\r\n command.pass =\r\n opaqueCommand || !opaqueAndTranslucent ? Pass.OPAQUE : Pass.TRANSLUCENT;\r\n command.owner = this;\r\n\r\n var index = opaqueAndTranslucent ? Math.floor(j / 2.0) : j;\r\n command.boundingVolume = boundingVolume;\r\n command.modelMatrix = modelMatrix;\r\n command.count = va[index].indicesCount;\r\n command.shaderProgram = opaqueCommand ? this._sp : this._spTranslucent;\r\n command.uniformMap = uniforms;\r\n command.vertexArray = va[index].va;\r\n command.renderState = opaqueCommand\r\n ? this._rsOpaque\r\n : this._rsTranslucent;\r\n command.debugShowBoundingVolume = this.debugShowBoundingVolume;\r\n command.pickId = pickId;\r\n\r\n if (this._instanced) {\r\n command.count = 6;\r\n command.instanceCount = billboardsLength;\r\n }\r\n\r\n commandList.push(command);\r\n }\r\n\r\n if (this.debugShowTextureAtlas) {\r\n if (!defined(this.debugCommand)) {\r\n this.debugCommand = createDebugCommand(this, frameState.context);\r\n }\r\n\r\n commandList.push(this.debugCommand);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see BillboardCollection#destroy\r\n */\r\nBillboardCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * billboards = billboards && billboards.destroy();\r\n *\r\n * @see BillboardCollection#isDestroyed\r\n */\r\nBillboardCollection.prototype.destroy = function () {\r\n if (defined(this._removeCallbackFunc)) {\r\n this._removeCallbackFunc();\r\n this._removeCallbackFunc = undefined;\r\n }\r\n\r\n this._textureAtlas =\r\n this._destroyTextureAtlas &&\r\n this._textureAtlas &&\r\n this._textureAtlas.destroy();\r\n this._sp = this._sp && this._sp.destroy();\r\n this._spTranslucent = this._spTranslucent && this._spTranslucent.destroy();\r\n this._vaf = this._vaf && this._vaf.destroy();\r\n destroyBillboards(this._billboards);\r\n\r\n return destroyObject(this);\r\n};\r\nexport default BillboardCollection;\r\n","/**\r\n * Creates a {@link createBillboardPointCallback.CanvasFunction} that will create a canvas with a point.\r\n *\r\n * @param {Number} centerAlpha The alpha of the center of the point. The value must be in the range [0.0, 1.0].\r\n * @param {String} cssColor The CSS color string.\r\n * @param {String} cssOutlineColor The CSS color of the point outline.\r\n * @param {Number} cssOutlineWidth The width of the outline in pixels.\r\n * @param {Number} pixelSize The size of the point in pixels.\r\n * @return {createBillboardPointCallback.CanvasFunction} The function that will return a canvas with the point drawn on it.\r\n *\r\n * @private\r\n */\r\nfunction createBillboardPointCallback(\r\n centerAlpha,\r\n cssColor,\r\n cssOutlineColor,\r\n cssOutlineWidth,\r\n pixelSize\r\n) {\r\n return function () {\r\n var canvas = document.createElement(\"canvas\");\r\n\r\n var length = pixelSize + 2 * cssOutlineWidth;\r\n canvas.height = canvas.width = length;\r\n\r\n var context2D = canvas.getContext(\"2d\");\r\n context2D.clearRect(0, 0, length, length);\r\n\r\n if (cssOutlineWidth !== 0) {\r\n context2D.beginPath();\r\n context2D.arc(length / 2, length / 2, length / 2, 0, 2 * Math.PI, true);\r\n context2D.closePath();\r\n context2D.fillStyle = cssOutlineColor;\r\n context2D.fill();\r\n // Punch a hole in the center if needed.\r\n if (centerAlpha < 1.0) {\r\n context2D.save();\r\n context2D.globalCompositeOperation = \"destination-out\";\r\n context2D.beginPath();\r\n context2D.arc(\r\n length / 2,\r\n length / 2,\r\n pixelSize / 2,\r\n 0,\r\n 2 * Math.PI,\r\n true\r\n );\r\n context2D.closePath();\r\n context2D.fillStyle = \"black\";\r\n context2D.fill();\r\n context2D.restore();\r\n }\r\n }\r\n\r\n context2D.beginPath();\r\n context2D.arc(length / 2, length / 2, pixelSize / 2, 0, 2 * Math.PI, true);\r\n context2D.closePath();\r\n context2D.fillStyle = cssColor;\r\n context2D.fill();\r\n\r\n return canvas;\r\n };\r\n}\r\n\r\n/**\r\n * A function that returns a canvas containing an image of a point.\r\n * @callback createBillboardPointCallback.CanvasFunction\r\n * @returns {HTMLCanvasElement} The result of the calculation.\r\n */\r\nexport default createBillboardPointCallback;\r\n","import Cartographic from \"../Core/Cartographic.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport createBillboardPointCallback from \"./createBillboardPointCallback.js\";\r\n\r\n/**\r\n * A point feature of a {@link Cesium3DTileset}.\r\n *

\r\n * Provides access to a feature's properties stored in the tile's batch table, as well\r\n * as the ability to show/hide a feature and change its point properties\r\n *

\r\n *

\r\n * Modifications to a Cesium3DTilePointFeature object have the lifetime of the tile's\r\n * content. If the tile's content is unloaded, e.g., due to it going out of view and needing\r\n * to free space in the cache for visible tiles, listen to the {@link Cesium3DTileset#tileUnload} event to save any\r\n * modifications. Also listen to the {@link Cesium3DTileset#tileVisible} event to reapply any modifications.\r\n *

\r\n *

\r\n * Do not construct this directly. Access it through {@link Cesium3DTileContent#getFeature}\r\n * or picking using {@link Scene#pick} and {@link Scene#pickPosition}.\r\n *

\r\n *\r\n * @alias Cesium3DTilePointFeature\r\n * @constructor\r\n *\r\n * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.\r\n *\r\n * @example\r\n * // On mouse over, display all the properties for a feature in the console log.\r\n * handler.setInputAction(function(movement) {\r\n * var feature = scene.pick(movement.endPosition);\r\n * if (feature instanceof Cesium.Cesium3DTilePointFeature) {\r\n * var propertyNames = feature.getPropertyNames();\r\n * var length = propertyNames.length;\r\n * for (var i = 0; i < length; ++i) {\r\n * var propertyName = propertyNames[i];\r\n * console.log(propertyName + ': ' + feature.getProperty(propertyName));\r\n * }\r\n * }\r\n * }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);\r\n */\r\nfunction Cesium3DTilePointFeature(\r\n content,\r\n batchId,\r\n billboard,\r\n label,\r\n polyline\r\n) {\r\n this._content = content;\r\n this._billboard = billboard;\r\n this._label = label;\r\n this._polyline = polyline;\r\n\r\n this._batchId = batchId;\r\n this._billboardImage = undefined;\r\n this._billboardColor = undefined;\r\n this._billboardOutlineColor = undefined;\r\n this._billboardOutlineWidth = undefined;\r\n this._billboardSize = undefined;\r\n this._pointSize = undefined;\r\n this._color = undefined;\r\n this._pointSize = undefined;\r\n this._pointOutlineColor = undefined;\r\n this._pointOutlineWidth = undefined;\r\n this._heightOffset = undefined;\r\n\r\n this._pickIds = new Array(3);\r\n\r\n setBillboardImage(this);\r\n}\r\n\r\nvar scratchCartographic = new Cartographic();\r\n\r\nObject.defineProperties(Cesium3DTilePointFeature.prototype, {\r\n /**\r\n * Gets or sets if the feature will be shown. This is set for all features\r\n * when a style's show is evaluated.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default true\r\n */\r\n show: {\r\n get: function () {\r\n return this._label.show;\r\n },\r\n set: function (value) {\r\n this._label.show = value;\r\n this._billboard.show = value;\r\n this._polyline.show = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the color of the point of this feature.\r\n *

\r\n * Only applied when image is undefined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Color}\r\n */\r\n color: {\r\n get: function () {\r\n return this._color;\r\n },\r\n set: function (value) {\r\n this._color = Color.clone(value, this._color);\r\n setBillboardImage(this);\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the point size of this feature.\r\n *

\r\n * Only applied when image is undefined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Number}\r\n */\r\n pointSize: {\r\n get: function () {\r\n return this._pointSize;\r\n },\r\n set: function (value) {\r\n this._pointSize = value;\r\n setBillboardImage(this);\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the point outline color of this feature.\r\n *

\r\n * Only applied when image is undefined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Color}\r\n */\r\n pointOutlineColor: {\r\n get: function () {\r\n return this._pointOutlineColor;\r\n },\r\n set: function (value) {\r\n this._pointOutlineColor = Color.clone(value, this._pointOutlineColor);\r\n setBillboardImage(this);\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the point outline width in pixels of this feature.\r\n *

\r\n * Only applied when image is undefined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Number}\r\n */\r\n pointOutlineWidth: {\r\n get: function () {\r\n return this._pointOutlineWidth;\r\n },\r\n set: function (value) {\r\n this._pointOutlineWidth = value;\r\n setBillboardImage(this);\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the label color of this feature.\r\n *

\r\n * The color will be applied to the label if labelText is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Color}\r\n */\r\n labelColor: {\r\n get: function () {\r\n return this._label.fillColor;\r\n },\r\n set: function (value) {\r\n this._label.fillColor = value;\r\n this._polyline.show = this._label.show && value.alpha > 0.0;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the label outline color of this feature.\r\n *

\r\n * The outline color will be applied to the label if labelText is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Color}\r\n */\r\n labelOutlineColor: {\r\n get: function () {\r\n return this._label.outlineColor;\r\n },\r\n set: function (value) {\r\n this._label.outlineColor = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the outline width in pixels of this feature.\r\n *

\r\n * The outline width will be applied to the point if labelText is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Number}\r\n */\r\n labelOutlineWidth: {\r\n get: function () {\r\n return this._label.outlineWidth;\r\n },\r\n set: function (value) {\r\n this._label.outlineWidth = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the font of this feature.\r\n *

\r\n * Only applied when the labelText is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {String}\r\n */\r\n font: {\r\n get: function () {\r\n return this._label.font;\r\n },\r\n set: function (value) {\r\n this._label.font = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the fill and outline style of this feature.\r\n *

\r\n * Only applied when labelText is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {LabelStyle}\r\n */\r\n labelStyle: {\r\n get: function () {\r\n return this._label.style;\r\n },\r\n set: function (value) {\r\n this._label.style = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the text for this feature.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {String}\r\n */\r\n labelText: {\r\n get: function () {\r\n return this._label.text;\r\n },\r\n set: function (value) {\r\n if (!defined(value)) {\r\n value = \"\";\r\n }\r\n this._label.text = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the background color of the text for this feature.\r\n *

\r\n * Only applied when labelText is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Color}\r\n */\r\n backgroundColor: {\r\n get: function () {\r\n return this._label.backgroundColor;\r\n },\r\n set: function (value) {\r\n this._label.backgroundColor = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the background padding of the text for this feature.\r\n *

\r\n * Only applied when labelText is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Cartesian2}\r\n */\r\n backgroundPadding: {\r\n get: function () {\r\n return this._label.backgroundPadding;\r\n },\r\n set: function (value) {\r\n this._label.backgroundPadding = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets whether to display the background of the text for this feature.\r\n *

\r\n * Only applied when labelText is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Boolean}\r\n */\r\n backgroundEnabled: {\r\n get: function () {\r\n return this._label.showBackground;\r\n },\r\n set: function (value) {\r\n this._label.showBackground = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the near and far scaling properties for this feature.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {NearFarScalar}\r\n */\r\n scaleByDistance: {\r\n get: function () {\r\n return this._label.scaleByDistance;\r\n },\r\n set: function (value) {\r\n this._label.scaleByDistance = value;\r\n this._billboard.scaleByDistance = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the near and far translucency properties for this feature.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {NearFarScalar}\r\n */\r\n translucencyByDistance: {\r\n get: function () {\r\n return this._label.translucencyByDistance;\r\n },\r\n set: function (value) {\r\n this._label.translucencyByDistance = value;\r\n this._billboard.translucencyByDistance = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the condition specifying at what distance from the camera that this feature will be displayed.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {DistanceDisplayCondition}\r\n */\r\n distanceDisplayCondition: {\r\n get: function () {\r\n return this._label.distanceDisplayCondition;\r\n },\r\n set: function (value) {\r\n this._label.distanceDisplayCondition = value;\r\n this._polyline.distanceDisplayCondition = value;\r\n this._billboard.distanceDisplayCondition = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the height offset in meters of this feature.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Number}\r\n */\r\n heightOffset: {\r\n get: function () {\r\n return this._heightOffset;\r\n },\r\n set: function (value) {\r\n var offset = defaultValue(this._heightOffset, 0.0);\r\n\r\n var ellipsoid = this._content.tileset.ellipsoid;\r\n var cart = ellipsoid.cartesianToCartographic(\r\n this._billboard.position,\r\n scratchCartographic\r\n );\r\n cart.height = cart.height - offset + value;\r\n var newPosition = ellipsoid.cartographicToCartesian(cart);\r\n\r\n this._billboard.position = newPosition;\r\n this._label.position = this._billboard.position;\r\n this._polyline.positions = [this._polyline.positions[0], newPosition];\r\n\r\n this._heightOffset = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets whether the anchor line is displayed.\r\n *

\r\n * Only applied when heightOffset is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Boolean}\r\n */\r\n anchorLineEnabled: {\r\n get: function () {\r\n return this._polyline.show;\r\n },\r\n set: function (value) {\r\n this._polyline.show = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the color for the anchor line.\r\n *

\r\n * Only applied when heightOffset is defined.\r\n *

\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Color}\r\n */\r\n anchorLineColor: {\r\n get: function () {\r\n return this._polyline.material.uniforms.color;\r\n },\r\n set: function (value) {\r\n this._polyline.material.uniforms.color = Color.clone(\r\n value,\r\n this._polyline.material.uniforms.color\r\n );\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the image of this feature.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {String}\r\n */\r\n image: {\r\n get: function () {\r\n return this._billboardImage;\r\n },\r\n set: function (value) {\r\n var imageChanged = this._billboardImage !== value;\r\n this._billboardImage = value;\r\n if (imageChanged) {\r\n setBillboardImage(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the distance where depth testing will be disabled.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Number}\r\n */\r\n disableDepthTestDistance: {\r\n get: function () {\r\n return this._label.disableDepthTestDistance;\r\n },\r\n set: function (value) {\r\n this._label.disableDepthTestDistance = value;\r\n this._billboard.disableDepthTestDistance = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the horizontal origin of this point, which determines if the point is\r\n * to the left, center, or right of its anchor position.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {HorizontalOrigin}\r\n */\r\n horizontalOrigin: {\r\n get: function () {\r\n return this._billboard.horizontalOrigin;\r\n },\r\n set: function (value) {\r\n this._billboard.horizontalOrigin = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the vertical origin of this point, which determines if the point is\r\n * to the bottom, center, or top of its anchor position.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {VerticalOrigin}\r\n */\r\n verticalOrigin: {\r\n get: function () {\r\n return this._billboard.verticalOrigin;\r\n },\r\n set: function (value) {\r\n this._billboard.verticalOrigin = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the horizontal origin of this point's text, which determines if the point's text is\r\n * to the left, center, or right of its anchor position.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {HorizontalOrigin}\r\n */\r\n labelHorizontalOrigin: {\r\n get: function () {\r\n return this._label.horizontalOrigin;\r\n },\r\n set: function (value) {\r\n this._label.horizontalOrigin = value;\r\n },\r\n },\r\n\r\n /**\r\n * Get or sets the vertical origin of this point's text, which determines if the point's text is\r\n * to the bottom, center, top, or baseline of it's anchor point.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {VerticalOrigin}\r\n */\r\n labelVerticalOrigin: {\r\n get: function () {\r\n return this._label.verticalOrigin;\r\n },\r\n set: function (value) {\r\n this._label.verticalOrigin = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the content of the tile containing the feature.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Cesium3DTileContent}\r\n *\r\n * @readonly\r\n * @private\r\n */\r\n content: {\r\n get: function () {\r\n return this._content;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tileset containing the feature.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Cesium3DTileset}\r\n *\r\n * @readonly\r\n */\r\n tileset: {\r\n get: function () {\r\n return this._content.tileset;\r\n },\r\n },\r\n\r\n /**\r\n * All objects returned by {@link Scene#pick} have a primitive property. This returns\r\n * the tileset containing the feature.\r\n *\r\n * @memberof Cesium3DTilePointFeature.prototype\r\n *\r\n * @type {Cesium3DTileset}\r\n *\r\n * @readonly\r\n */\r\n primitive: {\r\n get: function () {\r\n return this._content.tileset;\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n pickIds: {\r\n get: function () {\r\n var ids = this._pickIds;\r\n ids[0] = this._billboard.pickId;\r\n ids[1] = this._label.pickId;\r\n ids[2] = this._polyline.pickId;\r\n return ids;\r\n },\r\n },\r\n});\r\n\r\nCesium3DTilePointFeature.defaultColor = Color.WHITE;\r\nCesium3DTilePointFeature.defaultPointOutlineColor = Color.BLACK;\r\nCesium3DTilePointFeature.defaultPointOutlineWidth = 0.0;\r\nCesium3DTilePointFeature.defaultPointSize = 8.0;\r\n\r\nfunction setBillboardImage(feature) {\r\n var b = feature._billboard;\r\n if (defined(feature._billboardImage) && feature._billboardImage !== b.image) {\r\n b.image = feature._billboardImage;\r\n return;\r\n }\r\n\r\n if (defined(feature._billboardImage)) {\r\n return;\r\n }\r\n\r\n var newColor = defaultValue(\r\n feature._color,\r\n Cesium3DTilePointFeature.defaultColor\r\n );\r\n var newOutlineColor = defaultValue(\r\n feature._pointOutlineColor,\r\n Cesium3DTilePointFeature.defaultPointOutlineColor\r\n );\r\n var newOutlineWidth = defaultValue(\r\n feature._pointOutlineWidth,\r\n Cesium3DTilePointFeature.defaultPointOutlineWidth\r\n );\r\n var newPointSize = defaultValue(\r\n feature._pointSize,\r\n Cesium3DTilePointFeature.defaultPointSize\r\n );\r\n\r\n var currentColor = feature._billboardColor;\r\n var currentOutlineColor = feature._billboardOutlineColor;\r\n var currentOutlineWidth = feature._billboardOutlineWidth;\r\n var currentPointSize = feature._billboardSize;\r\n\r\n if (\r\n Color.equals(newColor, currentColor) &&\r\n Color.equals(newOutlineColor, currentOutlineColor) &&\r\n newOutlineWidth === currentOutlineWidth &&\r\n newPointSize === currentPointSize\r\n ) {\r\n return;\r\n }\r\n\r\n feature._billboardColor = Color.clone(newColor, feature._billboardColor);\r\n feature._billboardOutlineColor = Color.clone(\r\n newOutlineColor,\r\n feature._billboardOutlineColor\r\n );\r\n feature._billboardOutlineWidth = newOutlineWidth;\r\n feature._billboardSize = newPointSize;\r\n\r\n var centerAlpha = newColor.alpha;\r\n var cssColor = newColor.toCssColorString();\r\n var cssOutlineColor = newOutlineColor.toCssColorString();\r\n var textureId = JSON.stringify([\r\n cssColor,\r\n newPointSize,\r\n cssOutlineColor,\r\n newOutlineWidth,\r\n ]);\r\n\r\n b.setImage(\r\n textureId,\r\n createBillboardPointCallback(\r\n centerAlpha,\r\n cssColor,\r\n cssOutlineColor,\r\n newOutlineWidth,\r\n newPointSize\r\n )\r\n );\r\n}\r\n\r\n/**\r\n * Returns whether the feature contains this property. This includes properties from this feature's\r\n * class and inherited classes when using a batch table hierarchy.\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy}\r\n *\r\n * @param {String} name The case-sensitive name of the property.\r\n * @returns {Boolean} Whether the feature contains this property.\r\n */\r\nCesium3DTilePointFeature.prototype.hasProperty = function (name) {\r\n return this._content.batchTable.hasProperty(this._batchId, name);\r\n};\r\n\r\n/**\r\n * Returns an array of property names for the feature. This includes properties from this feature's\r\n * class and inherited classes when using a batch table hierarchy.\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy}\r\n *\r\n * @param {String[]} [results] An array into which to store the results.\r\n * @returns {String[]} The names of the feature's properties.\r\n */\r\nCesium3DTilePointFeature.prototype.getPropertyNames = function (results) {\r\n return this._content.batchTable.getPropertyNames(this._batchId, results);\r\n};\r\n\r\n/**\r\n * Returns a copy of the value of the feature's property with the given name. This includes properties from this feature's\r\n * class and inherited classes when using a batch table hierarchy.\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/extensions/3DTILES_batch_table_hierarchy}\r\n *\r\n * @param {String} name The case-sensitive name of the property.\r\n * @returns {*} The value of the property or undefined if the property does not exist.\r\n *\r\n * @example\r\n * // Display all the properties for a feature in the console log.\r\n * var propertyNames = feature.getPropertyNames();\r\n * var length = propertyNames.length;\r\n * for (var i = 0; i < length; ++i) {\r\n * var propertyName = propertyNames[i];\r\n * console.log(propertyName + ': ' + feature.getProperty(propertyName));\r\n * }\r\n */\r\nCesium3DTilePointFeature.prototype.getProperty = function (name) {\r\n return this._content.batchTable.getProperty(this._batchId, name);\r\n};\r\n\r\n/**\r\n * Sets the value of the feature's property with the given name.\r\n *

\r\n * If a property with the given name doesn't exist, it is created.\r\n *

\r\n *\r\n * @param {String} name The case-sensitive name of the property.\r\n * @param {*} value The value of the property that will be copied.\r\n *\r\n * @exception {DeveloperError} Inherited batch table hierarchy property is read only.\r\n *\r\n * @example\r\n * var height = feature.getProperty('Height'); // e.g., the height of a building\r\n *\r\n * @example\r\n * var name = 'clicked';\r\n * if (feature.getProperty(name)) {\r\n * console.log('already clicked');\r\n * } else {\r\n * feature.setProperty(name, true);\r\n * console.log('first click');\r\n * }\r\n */\r\nCesium3DTilePointFeature.prototype.setProperty = function (name, value) {\r\n this._content.batchTable.setProperty(this._batchId, name, value);\r\n\r\n // PERFORMANCE_IDEA: Probably overkill, but maybe only mark the tile dirty if the\r\n // property is in one of the style's expressions or - if it can be done quickly -\r\n // if the new property value changed the result of an expression.\r\n this._content.featurePropertiesDirty = true;\r\n};\r\n\r\n/**\r\n * Returns whether the feature's class name equals className. Unlike {@link Cesium3DTileFeature#isClass}\r\n * this function only checks the feature's exact class and not inherited classes.\r\n *

\r\n * This function returns false if no batch table hierarchy is present.\r\n *

\r\n *\r\n * @param {String} className The name to check against.\r\n * @returns {Boolean} Whether the feature's class name equals className\r\n *\r\n * @private\r\n */\r\nCesium3DTilePointFeature.prototype.isExactClass = function (className) {\r\n return this._content.batchTable.isExactClass(this._batchId, className);\r\n};\r\n\r\n/**\r\n * Returns whether the feature's class or any inherited classes are named className.\r\n *

\r\n * This function returns false if no batch table hierarchy is present.\r\n *

\r\n *\r\n * @param {String} className The name to check against.\r\n * @returns {Boolean} Whether the feature's class or inherited classes are named className\r\n *\r\n * @private\r\n */\r\nCesium3DTilePointFeature.prototype.isClass = function (className) {\r\n return this._content.batchTable.isClass(this._batchId, className);\r\n};\r\n\r\n/**\r\n * Returns the feature's class name.\r\n *

\r\n * This function returns undefined if no batch table hierarchy is present.\r\n *

\r\n *\r\n * @returns {String} The feature's class name.\r\n *\r\n * @private\r\n */\r\nCesium3DTilePointFeature.prototype.getExactClassName = function () {\r\n return this._content.batchTable.getExactClassName(this._batchId);\r\n};\r\nexport default Cesium3DTilePointFeature;\r\n","/*\r\n* https://github.com/dy/bitmap-sdf\r\n* Calculate SDF for image/bitmap/bw data\r\n* This project is a fork of MapBox's TinySDF that works directly on an input Canvas instead of generating the glyphs themselves.\r\n*/\r\n\r\n var INF = 1e20;\r\n\r\n function clamp(value, min, max) {\r\n return min < max\r\n ? (value < min ? min : value > max ? max : value)\r\n : (value < max ? max : value > min ? min : value)\r\n }\r\n\r\n function calcSDF(src, options) {\r\n if (!options) options = {}\r\n\r\n var cutoff = options.cutoff == null ? 0.25 : options.cutoff\r\n var radius = options.radius == null ? 8 : options.radius\r\n var channel = options.channel || 0\r\n var w, h, size, data, intData, stride, ctx, canvas, imgData, i, l\r\n\r\n // handle image container\r\n if (ArrayBuffer.isView(src) || Array.isArray(src)) {\r\n if (!options.width || !options.height) throw Error('For raw data width and height should be provided by options')\r\n w = options.width, h = options.height\r\n data = src\r\n\r\n if (!options.stride) stride = Math.floor(src.length / w / h)\r\n else stride = options.stride\r\n }\r\n else {\r\n if (window.HTMLCanvasElement && src instanceof window.HTMLCanvasElement) {\r\n canvas = src\r\n ctx = canvas.getContext('2d')\r\n w = canvas.width, h = canvas.height\r\n imgData = ctx.getImageData(0, 0, w, h)\r\n data = imgData.data\r\n stride = 4\r\n }\r\n else if (window.CanvasRenderingContext2D && src instanceof window.CanvasRenderingContext2D) {\r\n canvas = src.canvas\r\n ctx = src\r\n w = canvas.width, h = canvas.height\r\n imgData = ctx.getImageData(0, 0, w, h)\r\n data = imgData.data\r\n stride = 4\r\n }\r\n else if (window.ImageData && src instanceof window.ImageData) {\r\n imgData = src\r\n w = src.width, h = src.height\r\n data = imgData.data\r\n stride = 4\r\n }\r\n }\r\n\r\n size = Math.max(w, h)\r\n\r\n //convert int data to floats\r\n if ((window.Uint8ClampedArray && data instanceof window.Uint8ClampedArray) || (window.Uint8Array && data instanceof window.Uint8Array)) {\r\n intData = data\r\n data = Array(w * h)\r\n\r\n for (i = 0, l = intData.length; i < l; i++) {\r\n data[i] = intData[i * stride + channel] / 255\r\n }\r\n }\r\n else {\r\n if (stride !== 1) throw Error('Raw data can have only 1 value per pixel')\r\n }\r\n\r\n // temporary arrays for the distance transform\r\n var gridOuter = Array(w * h)\r\n var gridInner = Array(w * h)\r\n var f = Array(size)\r\n var d = Array(size)\r\n var z = Array(size + 1)\r\n var v = Array(size)\r\n\r\n for (i = 0, l = w * h; i < l; i++) {\r\n var a = data[i]\r\n gridOuter[i] = a === 1 ? 0 : a === 0 ? INF : Math.pow(Math.max(0, 0.5 - a), 2)\r\n gridInner[i] = a === 1 ? INF : a === 0 ? 0 : Math.pow(Math.max(0, a - 0.5), 2)\r\n }\r\n\r\n edt(gridOuter, w, h, f, d, v, z)\r\n edt(gridInner, w, h, f, d, v, z)\r\n\r\n var dist = window.Float32Array ? new Float32Array(w * h) : new Array(w * h)\r\n\r\n for (i = 0, l = w * h; i < l; i++) {\r\n dist[i] = clamp(1 - ((gridOuter[i] - gridInner[i]) / radius + cutoff), 0, 1)\r\n }\r\n\r\n return dist\r\n }\r\n\r\n // 2D Euclidean distance transform by Felzenszwalb & Huttenlocher https://cs.brown.edu/~pff/dt/\r\n function edt(data, width, height, f, d, v, z) {\r\n for (var x = 0; x < width; x++) {\r\n for (var y = 0; y < height; y++) {\r\n f[y] = data[y * width + x]\r\n }\r\n edt1d(f, d, v, z, height)\r\n for (y = 0; y < height; y++) {\r\n data[y * width + x] = d[y]\r\n }\r\n }\r\n for (y = 0; y < height; y++) {\r\n for (x = 0; x < width; x++) {\r\n f[x] = data[y * width + x]\r\n }\r\n edt1d(f, d, v, z, width)\r\n for (x = 0; x < width; x++) {\r\n data[y * width + x] = Math.sqrt(d[x])\r\n }\r\n }\r\n }\r\n\r\n // 1D squared distance transform\r\n function edt1d(f, d, v, z, n) {\r\n v[0] = 0;\r\n z[0] = -INF\r\n z[1] = +INF\r\n\r\n for (var q = 1, k = 0; q < n; q++) {\r\n var s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k])\r\n while (s <= z[k]) {\r\n k--\r\n s = ((f[q] + q * q) - (f[v[k]] + v[k] * v[k])) / (2 * q - 2 * v[k])\r\n }\r\n k++\r\n v[k] = q\r\n z[k] = s\r\n z[k + 1] = +INF\r\n }\r\n\r\n for (q = 0, k = 0; q < n; q++) {\r\n while (z[k + 1] < q) k++\r\n d[q] = (q - v[k]) * (q - v[k]) + f[v[k]]\r\n }\r\n }\r\n\r\n export default calcSDF;\r\n","/**\r\n * Describes how to draw a label.\r\n *\r\n * @enum {Number}\r\n *\r\n * @see Label#style\r\n */\r\nvar LabelStyle = {\r\n /**\r\n * Fill the text of the label, but do not outline.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n FILL: 0,\r\n\r\n /**\r\n * Outline the text of the label, but do not fill.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n OUTLINE: 1,\r\n\r\n /**\r\n * Fill and outline the text of the label.\r\n *\r\n * @type {Number}\r\n * @constant\r\n */\r\n FILL_AND_OUTLINE: 2,\r\n};\r\nexport default Object.freeze(LabelStyle);\r\n","import BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport NearFarScalar from \"../Core/NearFarScalar.js\";\r\nimport Billboard from \"./Billboard.js\";\r\nimport HeightReference from \"./HeightReference.js\";\r\nimport HorizontalOrigin from \"./HorizontalOrigin.js\";\r\nimport LabelStyle from \"./LabelStyle.js\";\r\nimport SDFSettings from \"./SDFSettings.js\";\r\nimport VerticalOrigin from \"./VerticalOrigin.js\";\r\n\r\nvar fontInfoCache = {};\r\nvar fontInfoCacheLength = 0;\r\nvar fontInfoCacheMaxSize = 256;\r\nvar defaultBackgroundColor = new Color(0.165, 0.165, 0.165, 0.8);\r\nvar defaultBackgroundPadding = new Cartesian2(7, 5);\r\n\r\nvar textTypes = Object.freeze({\r\n LTR: 0,\r\n RTL: 1,\r\n WEAK: 2,\r\n BRACKETS: 3,\r\n});\r\n\r\nfunction rebindAllGlyphs(label) {\r\n if (!label._rebindAllGlyphs && !label._repositionAllGlyphs) {\r\n // only push label if it's not already been marked dirty\r\n label._labelCollection._labelsToUpdate.push(label);\r\n }\r\n label._rebindAllGlyphs = true;\r\n}\r\n\r\nfunction repositionAllGlyphs(label) {\r\n if (!label._rebindAllGlyphs && !label._repositionAllGlyphs) {\r\n // only push label if it's not already been marked dirty\r\n label._labelCollection._labelsToUpdate.push(label);\r\n }\r\n label._repositionAllGlyphs = true;\r\n}\r\n\r\nfunction getCSSValue(element, property) {\r\n return document.defaultView\r\n .getComputedStyle(element, null)\r\n .getPropertyValue(property);\r\n}\r\n\r\nfunction parseFont(label) {\r\n var fontInfo = fontInfoCache[label._font];\r\n if (!defined(fontInfo)) {\r\n var div = document.createElement(\"div\");\r\n div.style.position = \"absolute\";\r\n div.style.opacity = 0;\r\n div.style.font = label._font;\r\n document.body.appendChild(div);\r\n\r\n var lineHeight = parseFloat(getCSSValue(div, \"line-height\"));\r\n if (isNaN(lineHeight)) {\r\n // line-height isn't a number, i.e. 'normal'; apply default line-spacing\r\n lineHeight = undefined;\r\n }\r\n\r\n fontInfo = {\r\n family: getCSSValue(div, \"font-family\"),\r\n size: getCSSValue(div, \"font-size\").replace(\"px\", \"\"),\r\n style: getCSSValue(div, \"font-style\"),\r\n weight: getCSSValue(div, \"font-weight\"),\r\n lineHeight: lineHeight,\r\n };\r\n\r\n document.body.removeChild(div);\r\n if (fontInfoCacheLength < fontInfoCacheMaxSize) {\r\n fontInfoCache[label._font] = fontInfo;\r\n fontInfoCacheLength++;\r\n }\r\n }\r\n label._fontFamily = fontInfo.family;\r\n label._fontSize = fontInfo.size;\r\n label._fontStyle = fontInfo.style;\r\n label._fontWeight = fontInfo.weight;\r\n label._lineHeight = fontInfo.lineHeight;\r\n}\r\n\r\n/**\r\n * A Label draws viewport-aligned text positioned in the 3D scene. This constructor\r\n * should not be used directly, instead create labels by calling {@link LabelCollection#add}.\r\n *\r\n * @alias Label\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near\r\n * @exception {DeveloperError} pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near\r\n * @exception {DeveloperError} distanceDisplayCondition.far must be greater than distanceDisplayCondition.near\r\n *\r\n * @see LabelCollection\r\n * @see LabelCollection#add\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Labels.html|Cesium Sandcastle Labels Demo}\r\n */\r\nfunction Label(options, labelCollection) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n defined(options.disableDepthTestDistance) &&\r\n options.disableDepthTestDistance < 0.0\r\n ) {\r\n throw new DeveloperError(\r\n \"disableDepthTestDistance must be greater than 0.0.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var translucencyByDistance = options.translucencyByDistance;\r\n var pixelOffsetScaleByDistance = options.pixelOffsetScaleByDistance;\r\n var scaleByDistance = options.scaleByDistance;\r\n var distanceDisplayCondition = options.distanceDisplayCondition;\r\n if (defined(translucencyByDistance)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (translucencyByDistance.far <= translucencyByDistance.near) {\r\n throw new DeveloperError(\r\n \"translucencyByDistance.far must be greater than translucencyByDistance.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n translucencyByDistance = NearFarScalar.clone(translucencyByDistance);\r\n }\r\n if (defined(pixelOffsetScaleByDistance)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (pixelOffsetScaleByDistance.far <= pixelOffsetScaleByDistance.near) {\r\n throw new DeveloperError(\r\n \"pixelOffsetScaleByDistance.far must be greater than pixelOffsetScaleByDistance.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n pixelOffsetScaleByDistance = NearFarScalar.clone(\r\n pixelOffsetScaleByDistance\r\n );\r\n }\r\n if (defined(scaleByDistance)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (scaleByDistance.far <= scaleByDistance.near) {\r\n throw new DeveloperError(\r\n \"scaleByDistance.far must be greater than scaleByDistance.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n scaleByDistance = NearFarScalar.clone(scaleByDistance);\r\n }\r\n if (defined(distanceDisplayCondition)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (distanceDisplayCondition.far <= distanceDisplayCondition.near) {\r\n throw new DeveloperError(\r\n \"distanceDisplayCondition.far must be greater than distanceDisplayCondition.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n distanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition\r\n );\r\n }\r\n\r\n this._renderedText = undefined;\r\n this._text = undefined;\r\n this._show = defaultValue(options.show, true);\r\n this._font = defaultValue(options.font, \"30px sans-serif\");\r\n this._fillColor = Color.clone(defaultValue(options.fillColor, Color.WHITE));\r\n this._outlineColor = Color.clone(\r\n defaultValue(options.outlineColor, Color.BLACK)\r\n );\r\n this._outlineWidth = defaultValue(options.outlineWidth, 1.0);\r\n this._showBackground = defaultValue(options.showBackground, false);\r\n this._backgroundColor = Color.clone(\r\n defaultValue(options.backgroundColor, defaultBackgroundColor)\r\n );\r\n this._backgroundPadding = Cartesian2.clone(\r\n defaultValue(options.backgroundPadding, defaultBackgroundPadding)\r\n );\r\n this._style = defaultValue(options.style, LabelStyle.FILL);\r\n this._verticalOrigin = defaultValue(\r\n options.verticalOrigin,\r\n VerticalOrigin.BASELINE\r\n );\r\n this._horizontalOrigin = defaultValue(\r\n options.horizontalOrigin,\r\n HorizontalOrigin.LEFT\r\n );\r\n this._pixelOffset = Cartesian2.clone(\r\n defaultValue(options.pixelOffset, Cartesian2.ZERO)\r\n );\r\n this._eyeOffset = Cartesian3.clone(\r\n defaultValue(options.eyeOffset, Cartesian3.ZERO)\r\n );\r\n this._position = Cartesian3.clone(\r\n defaultValue(options.position, Cartesian3.ZERO)\r\n );\r\n this._scale = defaultValue(options.scale, 1.0);\r\n this._id = options.id;\r\n this._translucencyByDistance = translucencyByDistance;\r\n this._pixelOffsetScaleByDistance = pixelOffsetScaleByDistance;\r\n this._scaleByDistance = scaleByDistance;\r\n this._heightReference = defaultValue(\r\n options.heightReference,\r\n HeightReference.NONE\r\n );\r\n this._distanceDisplayCondition = distanceDisplayCondition;\r\n this._disableDepthTestDistance = options.disableDepthTestDistance;\r\n\r\n this._labelCollection = labelCollection;\r\n this._glyphs = [];\r\n this._backgroundBillboard = undefined;\r\n this._batchIndex = undefined; // Used only by Vector3DTilePoints and BillboardCollection\r\n\r\n this._rebindAllGlyphs = true;\r\n this._repositionAllGlyphs = true;\r\n\r\n this._actualClampedPosition = undefined;\r\n this._removeCallbackFunc = undefined;\r\n this._mode = undefined;\r\n\r\n this._clusterShow = true;\r\n\r\n this.text = defaultValue(options.text, \"\");\r\n\r\n this._relativeSize = 1.0;\r\n\r\n parseFont(this);\r\n\r\n this._updateClamping();\r\n}\r\n\r\nObject.defineProperties(Label.prototype, {\r\n /**\r\n * Determines if this label will be shown. Use this to hide or show a label, instead\r\n * of removing it and re-adding it to the collection.\r\n * @memberof Label.prototype\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n show: {\r\n get: function () {\r\n return this._show;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._show !== value) {\r\n this._show = value;\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var billboard = glyphs[i].billboard;\r\n if (defined(billboard)) {\r\n billboard.show = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.show = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the Cartesian position of this label.\r\n * @memberof Label.prototype\r\n * @type {Cartesian3}\r\n */\r\n position: {\r\n get: function () {\r\n return this._position;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var position = this._position;\r\n if (!Cartesian3.equals(position, value)) {\r\n Cartesian3.clone(value, position);\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var billboard = glyphs[i].billboard;\r\n if (defined(billboard)) {\r\n billboard.position = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.position = value;\r\n }\r\n\r\n this._updateClamping();\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the height reference of this billboard.\r\n * @memberof Label.prototype\r\n * @type {HeightReference}\r\n * @default HeightReference.NONE\r\n */\r\n heightReference: {\r\n get: function () {\r\n return this._heightReference;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (value !== this._heightReference) {\r\n this._heightReference = value;\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var billboard = glyphs[i].billboard;\r\n if (defined(billboard)) {\r\n billboard.heightReference = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.heightReference = value;\r\n }\r\n\r\n repositionAllGlyphs(this);\r\n\r\n this._updateClamping();\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the text of this label.\r\n * @memberof Label.prototype\r\n * @type {String}\r\n */\r\n text: {\r\n get: function () {\r\n return this._text;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._text !== value) {\r\n this._text = value;\r\n this._renderedText = Label.enableRightToLeftDetection\r\n ? reverseRtl(value)\r\n : value;\r\n rebindAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the font used to draw this label. Fonts are specified using the same syntax as the CSS 'font' property.\r\n * @memberof Label.prototype\r\n * @type {String}\r\n * @default '30px sans-serif'\r\n * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#text-styles|HTML canvas 2D context text styles}\r\n */\r\n font: {\r\n get: function () {\r\n return this._font;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._font !== value) {\r\n this._font = value;\r\n rebindAllGlyphs(this);\r\n parseFont(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the fill color of this label.\r\n * @memberof Label.prototype\r\n * @type {Color}\r\n * @default Color.WHITE\r\n * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}\r\n */\r\n fillColor: {\r\n get: function () {\r\n return this._fillColor;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var fillColor = this._fillColor;\r\n if (!Color.equals(fillColor, value)) {\r\n Color.clone(value, fillColor);\r\n rebindAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the outline color of this label.\r\n * @memberof Label.prototype\r\n * @type {Color}\r\n * @default Color.BLACK\r\n * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}\r\n */\r\n outlineColor: {\r\n get: function () {\r\n return this._outlineColor;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var outlineColor = this._outlineColor;\r\n if (!Color.equals(outlineColor, value)) {\r\n Color.clone(value, outlineColor);\r\n rebindAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the outline width of this label.\r\n * @memberof Label.prototype\r\n * @type {Number}\r\n * @default 1.0\r\n * @see {@link http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html#fill-and-stroke-styles|HTML canvas 2D context fill and stroke styles}\r\n */\r\n outlineWidth: {\r\n get: function () {\r\n return this._outlineWidth;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._outlineWidth !== value) {\r\n this._outlineWidth = value;\r\n rebindAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Determines if a background behind this label will be shown.\r\n * @memberof Label.prototype\r\n * @default false\r\n * @type {Boolean}\r\n */\r\n showBackground: {\r\n get: function () {\r\n return this._showBackground;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._showBackground !== value) {\r\n this._showBackground = value;\r\n rebindAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the background color of this label.\r\n * @memberof Label.prototype\r\n * @type {Color}\r\n * @default new Color(0.165, 0.165, 0.165, 0.8)\r\n */\r\n backgroundColor: {\r\n get: function () {\r\n return this._backgroundColor;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var backgroundColor = this._backgroundColor;\r\n if (!Color.equals(backgroundColor, value)) {\r\n Color.clone(value, backgroundColor);\r\n\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.color = backgroundColor;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the background padding, in pixels, of this label. The x value\r\n * controls horizontal padding, and the y value controls vertical padding.\r\n * @memberof Label.prototype\r\n * @type {Cartesian2}\r\n * @default new Cartesian2(7, 5)\r\n */\r\n backgroundPadding: {\r\n get: function () {\r\n return this._backgroundPadding;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var backgroundPadding = this._backgroundPadding;\r\n if (!Cartesian2.equals(backgroundPadding, value)) {\r\n Cartesian2.clone(value, backgroundPadding);\r\n repositionAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the style of this label.\r\n * @memberof Label.prototype\r\n * @type {LabelStyle}\r\n * @default LabelStyle.FILL\r\n */\r\n style: {\r\n get: function () {\r\n return this._style;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._style !== value) {\r\n this._style = value;\r\n rebindAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the pixel offset in screen space from the origin of this label. This is commonly used\r\n * to align multiple labels and billboards at the same position, e.g., an image and text. The\r\n * screen space origin is the top, left corner of the canvas; x increases from\r\n * left to right, and y increases from top to bottom.\r\n *

\r\n *
\r\n * \r\n * \r\n * \r\n *
default
l.pixeloffset = new Cartesian2(25, 75);
\r\n * The label's origin is indicated by the yellow point.\r\n *
\r\n * @memberof Label.prototype\r\n * @type {Cartesian2}\r\n * @default Cartesian2.ZERO\r\n */\r\n pixelOffset: {\r\n get: function () {\r\n return this._pixelOffset;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var pixelOffset = this._pixelOffset;\r\n if (!Cartesian2.equals(pixelOffset, value)) {\r\n Cartesian2.clone(value, pixelOffset);\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.pixelOffset = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.pixelOffset = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets near and far translucency properties of a Label based on the Label's distance from the camera.\r\n * A label's translucency will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the label's translucency remains clamped to the nearest bound. If undefined,\r\n * translucencyByDistance will be disabled.\r\n * @memberof Label.prototype\r\n * @type {NearFarScalar}\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a label's translucencyByDistance to 1.0 when the\r\n * // camera is 1500 meters from the label and disappear as\r\n * // the camera distance approaches 8.0e6 meters.\r\n * text.translucencyByDistance = new Cesium.NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0);\r\n *\r\n * @example\r\n * // Example 2.\r\n * // disable translucency by distance\r\n * text.translucencyByDistance = undefined;\r\n */\r\n translucencyByDistance: {\r\n get: function () {\r\n return this._translucencyByDistance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var translucencyByDistance = this._translucencyByDistance;\r\n if (!NearFarScalar.equals(translucencyByDistance, value)) {\r\n this._translucencyByDistance = NearFarScalar.clone(\r\n value,\r\n translucencyByDistance\r\n );\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.translucencyByDistance = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.translucencyByDistance = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets near and far pixel offset scaling properties of a Label based on the Label's distance from the camera.\r\n * A label's pixel offset will be scaled between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the label's pixel offset scaling remains clamped to the nearest bound. If undefined,\r\n * pixelOffsetScaleByDistance will be disabled.\r\n * @memberof Label.prototype\r\n * @type {NearFarScalar}\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a label's pixel offset scale to 0.0 when the\r\n * // camera is 1500 meters from the label and scale pixel offset to 10.0 pixels\r\n * // in the y direction the camera distance approaches 8.0e6 meters.\r\n * text.pixelOffset = new Cesium.Cartesian2(0.0, 1.0);\r\n * text.pixelOffsetScaleByDistance = new Cesium.NearFarScalar(1.5e2, 0.0, 8.0e6, 10.0);\r\n *\r\n * @example\r\n * // Example 2.\r\n * // disable pixel offset by distance\r\n * text.pixelOffsetScaleByDistance = undefined;\r\n */\r\n pixelOffsetScaleByDistance: {\r\n get: function () {\r\n return this._pixelOffsetScaleByDistance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var pixelOffsetScaleByDistance = this._pixelOffsetScaleByDistance;\r\n if (!NearFarScalar.equals(pixelOffsetScaleByDistance, value)) {\r\n this._pixelOffsetScaleByDistance = NearFarScalar.clone(\r\n value,\r\n pixelOffsetScaleByDistance\r\n );\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.pixelOffsetScaleByDistance = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.pixelOffsetScaleByDistance = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets near and far scaling properties of a Label based on the label's distance from the camera.\r\n * A label's scale will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the label's scale remains clamped to the nearest bound. If undefined,\r\n * scaleByDistance will be disabled.\r\n * @memberof Label.prototype\r\n * @type {NearFarScalar}\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a label's scaleByDistance to scale by 1.5 when the\r\n * // camera is 1500 meters from the label and disappear as\r\n * // the camera distance approaches 8.0e6 meters.\r\n * label.scaleByDistance = new Cesium.NearFarScalar(1.5e2, 1.5, 8.0e6, 0.0);\r\n *\r\n * @example\r\n * // Example 2.\r\n * // disable scaling by distance\r\n * label.scaleByDistance = undefined;\r\n */\r\n scaleByDistance: {\r\n get: function () {\r\n return this._scaleByDistance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var scaleByDistance = this._scaleByDistance;\r\n if (!NearFarScalar.equals(scaleByDistance, value)) {\r\n this._scaleByDistance = NearFarScalar.clone(value, scaleByDistance);\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.scaleByDistance = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.scaleByDistance = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets and sets the 3D Cartesian offset applied to this label in eye coordinates. Eye coordinates is a left-handed\r\n * coordinate system, where x points towards the viewer's right, y points up, and\r\n * z points into the screen. Eye coordinates use the same scale as world and model coordinates,\r\n * which is typically meters.\r\n *

\r\n * An eye offset is commonly used to arrange multiple label or objects at the same position, e.g., to\r\n * arrange a label above its corresponding 3D model.\r\n *

\r\n * Below, the label is positioned at the center of the Earth but an eye offset makes it always\r\n * appear on top of the Earth regardless of the viewer's or Earth's orientation.\r\n *

\r\n *
\r\n * \r\n * \r\n * \r\n *
\r\n * l.eyeOffset = new Cartesian3(0.0, 8000000.0, 0.0);

\r\n *
\r\n * @memberof Label.prototype\r\n * @type {Cartesian3}\r\n * @default Cartesian3.ZERO\r\n */\r\n eyeOffset: {\r\n get: function () {\r\n return this._eyeOffset;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var eyeOffset = this._eyeOffset;\r\n if (!Cartesian3.equals(eyeOffset, value)) {\r\n Cartesian3.clone(value, eyeOffset);\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.eyeOffset = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.eyeOffset = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the horizontal origin of this label, which determines if the label is drawn\r\n * to the left, center, or right of its anchor position.\r\n *

\r\n *
\r\n *
\r\n *
\r\n * @memberof Label.prototype\r\n * @type {HorizontalOrigin}\r\n * @default HorizontalOrigin.LEFT\r\n * @example\r\n * // Use a top, right origin\r\n * l.horizontalOrigin = Cesium.HorizontalOrigin.RIGHT;\r\n * l.verticalOrigin = Cesium.VerticalOrigin.TOP;\r\n */\r\n horizontalOrigin: {\r\n get: function () {\r\n return this._horizontalOrigin;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._horizontalOrigin !== value) {\r\n this._horizontalOrigin = value;\r\n repositionAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the vertical origin of this label, which determines if the label is\r\n * to the above, below, or at the center of its anchor position.\r\n *

\r\n *
\r\n *
\r\n *
\r\n * @memberof Label.prototype\r\n * @type {VerticalOrigin}\r\n * @default VerticalOrigin.BASELINE\r\n * @example\r\n * // Use a top, right origin\r\n * l.horizontalOrigin = Cesium.HorizontalOrigin.RIGHT;\r\n * l.verticalOrigin = Cesium.VerticalOrigin.TOP;\r\n */\r\n verticalOrigin: {\r\n get: function () {\r\n return this._verticalOrigin;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._verticalOrigin !== value) {\r\n this._verticalOrigin = value;\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.verticalOrigin = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.verticalOrigin = value;\r\n }\r\n\r\n repositionAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the uniform scale that is multiplied with the label's size in pixels.\r\n * A scale of 1.0 does not change the size of the label; a scale greater than\r\n * 1.0 enlarges the label; a positive scale less than 1.0 shrinks\r\n * the label.\r\n *

\r\n * Applying a large scale value may pixelate the label. To make text larger without pixelation,\r\n * use a larger font size when calling {@link Label#font} instead.\r\n *

\r\n *
\r\n *
\r\n * From left to right in the above image, the scales are 0.5, 1.0,\r\n * and 2.0.\r\n *
\r\n * @memberof Label.prototype\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n scale: {\r\n get: function () {\r\n return this._scale;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._scale !== value) {\r\n this._scale = value;\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.scale = value * this._relativeSize;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.scale = value * this._relativeSize;\r\n }\r\n\r\n repositionAllGlyphs(this);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets the total scale of the label, which is the label's scale multiplied by the computed relative size\r\n * of the desired font compared to the generated glyph size.\r\n * @memberof Label.prototype\r\n * @type {Number}\r\n * @default 1.0\r\n */\r\n totalScale: {\r\n get: function () {\r\n return this._scale * this._relativeSize;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the condition specifying at what distance from the camera that this label will be displayed.\r\n * @memberof Label.prototype\r\n * @type {DistanceDisplayCondition}\r\n * @default undefined\r\n */\r\n distanceDisplayCondition: {\r\n get: function () {\r\n return this._distanceDisplayCondition;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\"far must be greater than near\");\r\n }\r\n //>>includeEnd('debug');\r\n if (\r\n !DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)\r\n ) {\r\n this._distanceDisplayCondition = DistanceDisplayCondition.clone(\r\n value,\r\n this._distanceDisplayCondition\r\n );\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.distanceDisplayCondition = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.distanceDisplayCondition = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.\r\n * When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.\r\n * @memberof Label.prototype\r\n * @type {Number}\r\n */\r\n disableDepthTestDistance: {\r\n get: function () {\r\n return this._disableDepthTestDistance;\r\n },\r\n set: function (value) {\r\n if (this._disableDepthTestDistance !== value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value < 0.0) {\r\n throw new DeveloperError(\r\n \"disableDepthTestDistance must be greater than 0.0.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n this._disableDepthTestDistance = value;\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.disableDepthTestDistance = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.disableDepthTestDistance = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the user-defined value returned when the label is picked.\r\n * @memberof Label.prototype\r\n * @type {*}\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n set: function (value) {\r\n if (this._id !== value) {\r\n this._id = value;\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.id = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.id = value;\r\n }\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n pickId: {\r\n get: function () {\r\n if (this._glyphs.length === 0 || !defined(this._glyphs[0].billboard)) {\r\n return undefined;\r\n }\r\n return this._glyphs[0].billboard.pickId;\r\n },\r\n },\r\n\r\n /**\r\n * Keeps track of the position of the label based on the height reference.\r\n * @memberof Label.prototype\r\n * @type {Cartesian3}\r\n * @private\r\n */\r\n _clampedPosition: {\r\n get: function () {\r\n return this._actualClampedPosition;\r\n },\r\n set: function (value) {\r\n this._actualClampedPosition = Cartesian3.clone(\r\n value,\r\n this._actualClampedPosition\r\n );\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n // Set all the private values here, because we already clamped to ground\r\n // so we don't want to do it again for every glyph\r\n glyph.billboard._clampedPosition = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard._clampedPosition = value;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Determines whether or not this label will be shown or hidden because it was clustered.\r\n * @memberof Label.prototype\r\n * @type {Boolean}\r\n * @default true\r\n * @private\r\n */\r\n clusterShow: {\r\n get: function () {\r\n return this._clusterShow;\r\n },\r\n set: function (value) {\r\n if (this._clusterShow !== value) {\r\n this._clusterShow = value;\r\n\r\n var glyphs = this._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; i++) {\r\n var glyph = glyphs[i];\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard.clusterShow = value;\r\n }\r\n }\r\n var backgroundBillboard = this._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboard.clusterShow = value;\r\n }\r\n }\r\n },\r\n },\r\n});\r\n\r\nLabel.prototype._updateClamping = function () {\r\n Billboard._updateClamping(this._labelCollection, this);\r\n};\r\n\r\n/**\r\n * Computes the screen-space position of the label's origin, taking into account eye and pixel offsets.\r\n * The screen space origin is the top, left corner of the canvas; x increases from\r\n * left to right, and y increases from top to bottom.\r\n *\r\n * @param {Scene} scene The scene the label is in.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The screen-space position of the label.\r\n *\r\n *\r\n * @example\r\n * console.log(l.computeScreenSpacePosition(scene).toString());\r\n *\r\n * @see Label#eyeOffset\r\n * @see Label#pixelOffset\r\n */\r\nLabel.prototype.computeScreenSpacePosition = function (scene, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(scene)) {\r\n throw new DeveloperError(\"scene is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = new Cartesian2();\r\n }\r\n\r\n var labelCollection = this._labelCollection;\r\n var modelMatrix = labelCollection.modelMatrix;\r\n var actualPosition = defined(this._actualClampedPosition)\r\n ? this._actualClampedPosition\r\n : this._position;\r\n\r\n var windowCoordinates = Billboard._computeScreenSpacePosition(\r\n modelMatrix,\r\n actualPosition,\r\n this._eyeOffset,\r\n this._pixelOffset,\r\n scene,\r\n result\r\n );\r\n return windowCoordinates;\r\n};\r\n\r\n/**\r\n * Gets a label's screen space bounding box centered around screenSpacePosition.\r\n * @param {Label} label The label to get the screen space bounding box for.\r\n * @param {Cartesian2} screenSpacePosition The screen space center of the label.\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The screen space bounding box.\r\n *\r\n * @private\r\n */\r\nLabel.getScreenSpaceBoundingBox = function (\r\n label,\r\n screenSpacePosition,\r\n result\r\n) {\r\n var x = 0;\r\n var y = 0;\r\n var width = 0;\r\n var height = 0;\r\n var scale = label.totalScale;\r\n\r\n var backgroundBillboard = label._backgroundBillboard;\r\n if (defined(backgroundBillboard)) {\r\n x = screenSpacePosition.x + backgroundBillboard._translate.x;\r\n y = screenSpacePosition.y - backgroundBillboard._translate.y;\r\n width = backgroundBillboard.width * scale;\r\n height = backgroundBillboard.height * scale;\r\n\r\n if (\r\n label.verticalOrigin === VerticalOrigin.BOTTOM ||\r\n label.verticalOrigin === VerticalOrigin.BASELINE\r\n ) {\r\n y -= height;\r\n } else if (label.verticalOrigin === VerticalOrigin.CENTER) {\r\n y -= height * 0.5;\r\n }\r\n } else {\r\n x = Number.POSITIVE_INFINITY;\r\n y = Number.POSITIVE_INFINITY;\r\n var maxX = 0;\r\n var maxY = 0;\r\n var glyphs = label._glyphs;\r\n var length = glyphs.length;\r\n for (var i = 0; i < length; ++i) {\r\n var glyph = glyphs[i];\r\n var billboard = glyph.billboard;\r\n if (!defined(billboard)) {\r\n continue;\r\n }\r\n\r\n var glyphX = screenSpacePosition.x + billboard._translate.x;\r\n var glyphY = screenSpacePosition.y - billboard._translate.y;\r\n var glyphWidth = glyph.dimensions.width * scale;\r\n var glyphHeight = glyph.dimensions.height * scale;\r\n\r\n if (\r\n label.verticalOrigin === VerticalOrigin.BOTTOM ||\r\n label.verticalOrigin === VerticalOrigin.BASELINE\r\n ) {\r\n glyphY -= glyphHeight;\r\n } else if (label.verticalOrigin === VerticalOrigin.CENTER) {\r\n glyphY -= glyphHeight * 0.5;\r\n }\r\n\r\n if (label._verticalOrigin === VerticalOrigin.TOP) {\r\n glyphY += SDFSettings.PADDING * scale;\r\n } else if (\r\n label._verticalOrigin === VerticalOrigin.BOTTOM ||\r\n label._verticalOrigin === VerticalOrigin.BASELINE\r\n ) {\r\n glyphY -= SDFSettings.PADDING * scale;\r\n }\r\n\r\n x = Math.min(x, glyphX);\r\n y = Math.min(y, glyphY);\r\n maxX = Math.max(maxX, glyphX + glyphWidth);\r\n maxY = Math.max(maxY, glyphY + glyphHeight);\r\n }\r\n\r\n width = maxX - x;\r\n height = maxY - y;\r\n }\r\n\r\n if (!defined(result)) {\r\n result = new BoundingRectangle();\r\n }\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.width = width;\r\n result.height = height;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines if this label equals another label. Labels are equal if all their properties\r\n * are equal. Labels in different collections can be equal.\r\n *\r\n * @param {Label} other The label to compare for equality.\r\n * @returns {Boolean} true if the labels are equal; otherwise, false.\r\n */\r\nLabel.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (defined(other) &&\r\n this._show === other._show &&\r\n this._scale === other._scale &&\r\n this._outlineWidth === other._outlineWidth &&\r\n this._showBackground === other._showBackground &&\r\n this._style === other._style &&\r\n this._verticalOrigin === other._verticalOrigin &&\r\n this._horizontalOrigin === other._horizontalOrigin &&\r\n this._heightReference === other._heightReference &&\r\n this._renderedText === other._renderedText &&\r\n this._font === other._font &&\r\n Cartesian3.equals(this._position, other._position) &&\r\n Color.equals(this._fillColor, other._fillColor) &&\r\n Color.equals(this._outlineColor, other._outlineColor) &&\r\n Color.equals(this._backgroundColor, other._backgroundColor) &&\r\n Cartesian2.equals(this._backgroundPadding, other._backgroundPadding) &&\r\n Cartesian2.equals(this._pixelOffset, other._pixelOffset) &&\r\n Cartesian3.equals(this._eyeOffset, other._eyeOffset) &&\r\n NearFarScalar.equals(\r\n this._translucencyByDistance,\r\n other._translucencyByDistance\r\n ) &&\r\n NearFarScalar.equals(\r\n this._pixelOffsetScaleByDistance,\r\n other._pixelOffsetScaleByDistance\r\n ) &&\r\n NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance) &&\r\n DistanceDisplayCondition.equals(\r\n this._distanceDisplayCondition,\r\n other._distanceDisplayCondition\r\n ) &&\r\n this._disableDepthTestDistance === other._disableDepthTestDistance &&\r\n this._id === other._id)\r\n );\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nLabel.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Determines whether or not run the algorithm, that match the text of the label to right-to-left languages\r\n * @memberof Label\r\n * @type {Boolean}\r\n * @default false\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a label's rightToLeft before init\r\n * Cesium.Label.enableRightToLeftDetection = true;\r\n * var myLabelEntity = viewer.entities.add({\r\n * label: {\r\n * id: 'my label',\r\n * text: 'זה טקסט בעברית \\n ועכשיו יורדים שורה',\r\n * }\r\n * });\r\n *\r\n * @example\r\n * // Example 2.\r\n * var myLabelEntity = viewer.entities.add({\r\n * label: {\r\n * id: 'my label',\r\n * text: 'English text'\r\n * }\r\n * });\r\n * // Set a label's rightToLeft after init\r\n * Cesium.Label.enableRightToLeftDetection = true;\r\n * myLabelEntity.text = 'טקסט חדש';\r\n */\r\nLabel.enableRightToLeftDetection = false;\r\n\r\nfunction convertTextToTypes(text, rtlChars) {\r\n var ltrChars = /[a-zA-Z0-9]/;\r\n var bracketsChars = /[()[\\]{}<>]/;\r\n var parsedText = [];\r\n var word = \"\";\r\n var lastType = textTypes.LTR;\r\n var currentType = \"\";\r\n var textLength = text.length;\r\n for (var textIndex = 0; textIndex < textLength; ++textIndex) {\r\n var character = text.charAt(textIndex);\r\n if (rtlChars.test(character)) {\r\n currentType = textTypes.RTL;\r\n } else if (ltrChars.test(character)) {\r\n currentType = textTypes.LTR;\r\n } else if (bracketsChars.test(character)) {\r\n currentType = textTypes.BRACKETS;\r\n } else {\r\n currentType = textTypes.WEAK;\r\n }\r\n\r\n if (textIndex === 0) {\r\n lastType = currentType;\r\n }\r\n\r\n if (lastType === currentType && currentType !== textTypes.BRACKETS) {\r\n word += character;\r\n } else {\r\n if (word !== \"\") {\r\n parsedText.push({ Type: lastType, Word: word });\r\n }\r\n lastType = currentType;\r\n word = character;\r\n }\r\n }\r\n parsedText.push({ Type: currentType, Word: word });\r\n return parsedText;\r\n}\r\n\r\nfunction reverseWord(word) {\r\n return word.split(\"\").reverse().join(\"\");\r\n}\r\n\r\nfunction spliceWord(result, pointer, word) {\r\n return result.slice(0, pointer) + word + result.slice(pointer);\r\n}\r\n\r\nfunction reverseBrackets(bracket) {\r\n switch (bracket) {\r\n case \"(\":\r\n return \")\";\r\n case \")\":\r\n return \"(\";\r\n case \"[\":\r\n return \"]\";\r\n case \"]\":\r\n return \"[\";\r\n case \"{\":\r\n return \"}\";\r\n case \"}\":\r\n return \"{\";\r\n case \"<\":\r\n return \">\";\r\n case \">\":\r\n return \"<\";\r\n }\r\n}\r\n\r\n//To add another language, simply add its Unicode block range(s) to the below regex.\r\nvar hebrew = \"\\u05D0-\\u05EA\";\r\nvar arabic = \"\\u0600-\\u06FF\\u0750-\\u077F\\u08A0-\\u08FF\";\r\nvar rtlChars = new RegExp(\"[\" + hebrew + arabic + \"]\");\r\n\r\n/**\r\n *\r\n * @param {String} value the text to parse and reorder\r\n * @returns {String} the text as rightToLeft direction\r\n * @private\r\n */\r\nfunction reverseRtl(value) {\r\n var texts = value.split(\"\\n\");\r\n var result = \"\";\r\n for (var i = 0; i < texts.length; i++) {\r\n var text = texts[i];\r\n // first character of the line is a RTL character, so need to manage different cases\r\n var rtlDir = rtlChars.test(text.charAt(0));\r\n var parsedText = convertTextToTypes(text, rtlChars);\r\n\r\n var splicePointer = 0;\r\n var line = \"\";\r\n for (var wordIndex = 0; wordIndex < parsedText.length; ++wordIndex) {\r\n var subText = parsedText[wordIndex];\r\n var reverse =\r\n subText.Type === textTypes.BRACKETS\r\n ? reverseBrackets(subText.Word)\r\n : reverseWord(subText.Word);\r\n if (rtlDir) {\r\n if (subText.Type === textTypes.RTL) {\r\n line = reverse + line;\r\n splicePointer = 0;\r\n } else if (subText.Type === textTypes.LTR) {\r\n line = spliceWord(line, splicePointer, subText.Word);\r\n splicePointer += subText.Word.length;\r\n } else if (\r\n subText.Type === textTypes.WEAK ||\r\n subText.Type === textTypes.BRACKETS\r\n ) {\r\n // current word is weak, last one was bracket\r\n if (\r\n subText.Type === textTypes.WEAK &&\r\n parsedText[wordIndex - 1].Type === textTypes.BRACKETS\r\n ) {\r\n line = reverse + line;\r\n }\r\n // current word is weak or bracket, last one was rtl\r\n else if (parsedText[wordIndex - 1].Type === textTypes.RTL) {\r\n line = reverse + line;\r\n splicePointer = 0;\r\n }\r\n // current word is weak or bracket, there is at least one more word\r\n else if (parsedText.length > wordIndex + 1) {\r\n // next word is rtl\r\n if (parsedText[wordIndex + 1].Type === textTypes.RTL) {\r\n line = reverse + line;\r\n splicePointer = 0;\r\n } else {\r\n line = spliceWord(line, splicePointer, subText.Word);\r\n splicePointer += subText.Word.length;\r\n }\r\n }\r\n // current word is weak or bracket, and it the last in this line\r\n else {\r\n line = spliceWord(line, 0, reverse);\r\n }\r\n }\r\n }\r\n // ltr line, rtl word\r\n else if (subText.Type === textTypes.RTL) {\r\n line = spliceWord(line, splicePointer, reverse);\r\n }\r\n // ltr line, ltr word\r\n else if (subText.Type === textTypes.LTR) {\r\n line += subText.Word;\r\n splicePointer = line.length;\r\n }\r\n // ltr line, weak or bracket word\r\n else if (\r\n subText.Type === textTypes.WEAK ||\r\n subText.Type === textTypes.BRACKETS\r\n ) {\r\n // not first word in line\r\n if (wordIndex > 0) {\r\n // last word was rtl\r\n if (parsedText[wordIndex - 1].Type === textTypes.RTL) {\r\n // there is at least one more word\r\n if (parsedText.length > wordIndex + 1) {\r\n // next word is rtl\r\n if (parsedText[wordIndex + 1].Type === textTypes.RTL) {\r\n line = spliceWord(line, splicePointer, reverse);\r\n } else {\r\n line += subText.Word;\r\n splicePointer = line.length;\r\n }\r\n } else {\r\n line += subText.Word;\r\n }\r\n } else {\r\n line += subText.Word;\r\n splicePointer = line.length;\r\n }\r\n } else {\r\n line += subText.Word;\r\n splicePointer = line.length;\r\n }\r\n }\r\n }\r\n\r\n result += line;\r\n if (i < texts.length - 1) {\r\n result += \"\\n\";\r\n }\r\n }\r\n return result;\r\n}\r\nexport default Label;\r\n","/*\r\nBreaks a Javascript string into individual user-perceived \"characters\"\r\ncalled extended grapheme clusters by implementing the Unicode UAX-29 standard, version 10.0.0\r\nUsage:\r\nvar splitter = new GraphemeSplitter();\r\n//returns an array of strings, one string for each grapheme cluster\r\nvar graphemes = splitter.splitGraphemes(string);\r\n*/\r\nfunction GraphemeSplitter(){\r\n\tvar CR = 0,\r\n\t\tLF = 1,\r\n\t\tControl = 2,\r\n\t\tExtend = 3,\r\n\t\tRegional_Indicator = 4,\r\n\t\tSpacingMark = 5,\r\n\t\tL = 6,\r\n\t\tV = 7,\r\n\t\tT = 8,\r\n\t\tLV = 9,\r\n\t\tLVT = 10,\r\n\t\tOther = 11,\r\n\t\tPrepend = 12,\r\n\t\tE_Base = 13,\r\n\t\tE_Modifier = 14,\r\n\t\tZWJ = 15,\r\n\t\tGlue_After_Zwj = 16,\r\n\t\tE_Base_GAZ = 17;\r\n\r\n\t// BreakTypes\r\n\tvar NotBreak = 0,\r\n\t\tBreakStart = 1,\r\n\t\tBreak = 2,\r\n\t\tBreakLastRegional = 3,\r\n\t\tBreakPenultimateRegional = 4;\r\n\r\n\tfunction isSurrogate(str, pos) {\r\n\t\treturn 0xd800 <= str.charCodeAt(pos) && str.charCodeAt(pos) <= 0xdbff &&\r\n\t\t\t\t0xdc00 <= str.charCodeAt(pos + 1) && str.charCodeAt(pos + 1) <= 0xdfff;\r\n\t}\r\n\r\n\t// Private function, gets a Unicode code point from a JavaScript UTF-16 string\r\n\t// handling surrogate pairs appropriately\r\n\tfunction codePointAt(str, idx){\r\n\t\tif(idx === undefined){\r\n\t\t\tidx = 0;\r\n\t\t}\r\n\t\tvar code = str.charCodeAt(idx);\r\n\r\n\t\t// if a high surrogate\r\n\t\tif (0xD800 <= code && code <= 0xDBFF &&\r\n\t\t\tidx < str.length - 1){\r\n\t\t\tvar hi = code;\r\n\t\t\tvar low = str.charCodeAt(idx + 1);\r\n\t\t\tif (0xDC00 <= low && low <= 0xDFFF){\r\n\t\t\t\treturn ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;\r\n\t\t\t}\r\n\t\t\treturn hi;\r\n\t\t}\r\n\r\n\t\t// if a low surrogate\r\n\t\tif (0xDC00 <= code && code <= 0xDFFF &&\r\n\t\t\tidx >= 1){\r\n\t\t\tvar hi = str.charCodeAt(idx - 1);\r\n\t\t\tvar low = code;\r\n\t\t\tif (0xD800 <= hi && hi <= 0xDBFF){\r\n\t\t\t\treturn ((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000;\r\n\t\t\t}\r\n\t\t\treturn low;\r\n\t\t}\r\n\r\n\t\t//just return the char if an unmatched surrogate half or a\r\n\t\t//single-char codepoint\r\n\t\treturn code;\r\n\t}\r\n\r\n\t// Private function, returns whether a break is allowed between the\r\n\t// two given grapheme breaking classes\r\n\tfunction shouldBreak(start, mid, end){\r\n\t\tvar all = [start].concat(mid).concat([end]);\r\n\t\tvar previous = all[all.length - 2]\r\n\t\tvar next = end\r\n\r\n\t\t// Lookahead termintor for:\r\n\t\t// GB10. (E_Base | EBG) Extend* ?\tE_Modifier\r\n\t\tvar eModifierIndex = all.lastIndexOf(E_Modifier)\r\n\t\tif(eModifierIndex > 1 &&\r\n\t\t\tall.slice(1, eModifierIndex).every(function(c){return c == Extend}) &&\r\n\t\t\t[Extend, E_Base, E_Base_GAZ].indexOf(start) == -1){\r\n\t\t\treturn Break\r\n\t\t}\r\n\r\n\t\t// Lookahead termintor for:\r\n\t\t// GB12. ^ (RI RI)* RI\t?\tRI\r\n\t\t// GB13. [^RI] (RI RI)* RI\t?\tRI\r\n\t\tvar rIIndex = all.lastIndexOf(Regional_Indicator)\r\n\t\tif(rIIndex > 0 &&\r\n\t\t\tall.slice(1, rIIndex).every(function(c){return c == Regional_Indicator}) &&\r\n\t\t\t[Prepend, Regional_Indicator].indexOf(previous) == -1) {\r\n\t\t\tif(all.filter(function(c){return c == Regional_Indicator}).length % 2 == 1) {\r\n\t\t\t\treturn BreakLastRegional\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\treturn BreakPenultimateRegional\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// GB3. CR X LF\r\n\t\tif(previous == CR && next == LF){\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\t\t// GB4. (Control|CR|LF) ÷\r\n\t\telse if(previous == Control || previous == CR || previous == LF){\r\n\t\t\tif(next == E_Modifier && mid.every(function(c){return c == Extend})){\r\n\t\t\t\treturn Break\r\n\t\t\t}\r\n\t\t\telse {\r\n\t\t\t\treturn BreakStart\r\n\t\t\t}\r\n\t\t}\r\n\t\t// GB5. ÷ (Control|CR|LF)\r\n\t\telse if(next == Control || next == CR || next == LF){\r\n\t\t\treturn BreakStart;\r\n\t\t}\r\n\t\t// GB6. L X (L|V|LV|LVT)\r\n\t\telse if(previous == L &&\r\n\t\t\t(next == L || next == V || next == LV || next == LVT)){\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\t\t// GB7. (LV|V) X (V|T)\r\n\t\telse if((previous == LV || previous == V) &&\r\n\t\t\t(next == V || next == T)){\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\t\t// GB8. (LVT|T) X (T)\r\n\t\telse if((previous == LVT || previous == T) &&\r\n\t\t\tnext == T){\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\t\t// GB9. X (Extend|ZWJ)\r\n\t\telse if (next == Extend || next == ZWJ){\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\t\t// GB9a. X SpacingMark\r\n\t\telse if(next == SpacingMark){\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\t\t// GB9b. Prepend X\r\n\t\telse if (previous == Prepend){\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\r\n\t\t// GB10. (E_Base | EBG) Extend* ?\tE_Modifier\r\n\t\tvar previousNonExtendIndex = all.indexOf(Extend) != -1 ? all.lastIndexOf(Extend) - 1 : all.length - 2;\r\n\t\tif([E_Base, E_Base_GAZ].indexOf(all[previousNonExtendIndex]) != -1 &&\r\n\t\t\tall.slice(previousNonExtendIndex + 1, -1).every(function(c){return c == Extend}) &&\r\n\t\t\tnext == E_Modifier){\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\r\n\t\t// GB11. ZWJ ? (Glue_After_Zwj | EBG)\r\n\t\tif(previous == ZWJ && [Glue_After_Zwj, E_Base_GAZ].indexOf(next) != -1) {\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\r\n\t\t// GB12. ^ (RI RI)* RI ? RI\r\n\t\t// GB13. [^RI] (RI RI)* RI ? RI\r\n\t\tif(mid.indexOf(Regional_Indicator) != -1) {\r\n\t\t\treturn Break;\r\n\t\t}\r\n\t\tif(previous == Regional_Indicator && next == Regional_Indicator) {\r\n\t\t\treturn NotBreak;\r\n\t\t}\r\n\r\n\t\t// GB999. Any ? Any\r\n\t\treturn BreakStart;\r\n\t}\r\n\r\n\t// Returns the next grapheme break in the string after the given index\r\n\tthis.nextBreak = function(string, index){\r\n\t\tif(index === undefined){\r\n\t\t\tindex = 0;\r\n\t\t}\r\n\t\tif(index < 0){\r\n\t\t\treturn 0;\r\n\t\t}\r\n\t\tif(index >= string.length - 1){\r\n\t\t\treturn string.length;\r\n\t\t}\r\n\t\tvar prev = getGraphemeBreakProperty(codePointAt(string, index));\r\n\t\tvar mid = []\r\n\t\tfor (var i = index + 1; i < string.length; i++) {\r\n\t\t\t// check for already processed low surrogates\r\n\t\t\tif(isSurrogate(string, i - 1)){\r\n\t\t\t\tcontinue;\r\n\t\t\t}\r\n\r\n\t\t\tvar next = getGraphemeBreakProperty(codePointAt(string, i));\r\n\t\t\tif(shouldBreak(prev, mid, next)){\r\n\t\t\t\treturn i;\r\n\t\t\t}\r\n\r\n\t\t\tmid.push(next);\r\n\t\t}\r\n\t\treturn string.length;\r\n\t};\r\n\r\n\t// Breaks the given string into an array of grapheme cluster strings\r\n\tthis.splitGraphemes = function(str){\r\n\t\tvar res = [];\r\n\t\tvar index = 0;\r\n\t\tvar brk;\r\n\t\twhile((brk = this.nextBreak(str, index)) < str.length){\r\n\t\t\tres.push(str.slice(index, brk));\r\n\t\t\tindex = brk;\r\n\t\t}\r\n\t\tif(index < str.length){\r\n\t\t\tres.push(str.slice(index));\r\n\t\t}\r\n\t\treturn res;\r\n\t};\r\n\r\n\t// Returns the iterator of grapheme clusters there are in the given string\r\n\tthis.iterateGraphemes = function(str) {\r\n\t\tvar index = 0;\r\n\t\tvar res = {\r\n\t\t\tnext: (function() {\r\n\t\t\t\tvar value;\r\n\t\t\t\tvar brk;\r\n\t\t\t\tif ((brk = this.nextBreak(str, index)) < str.length) {\r\n\t\t\t\t\tvalue = str.slice(index, brk);\r\n\t\t\t\t\tindex = brk;\r\n\t\t\t\t\treturn { value: value, done: false };\r\n\t\t\t\t}\r\n\t\t\t\tif (index < str.length) {\r\n\t\t\t\t\tvalue = str.slice(index);\r\n\t\t\t\t\tindex = str.length;\r\n\t\t\t\t\treturn { value: value, done: false };\r\n\t\t\t\t}\r\n\t\t\t\treturn { value: undefined, done: true };\r\n\t\t\t}).bind(this)\r\n\t\t};\r\n\t\t// ES2015 @@iterator method (iterable) for spread syntax and for...of statement\r\n\t\tif (typeof Symbol !== 'undefined' && Symbol.iterator) {\r\n\t\t\tres[Symbol.iterator] = function() {return res};\r\n\t\t}\r\n\t\treturn res;\r\n\t};\r\n\r\n\t// Returns the number of grapheme clusters there are in the given string\r\n\tthis.countGraphemes = function(str){\r\n\t\tvar count = 0;\r\n\t\tvar index = 0;\r\n\t\tvar brk;\r\n\t\twhile((brk = this.nextBreak(str, index)) < str.length){\r\n\t\t\tindex = brk;\r\n\t\t\tcount++;\r\n\t\t}\r\n\t\tif(index < str.length){\r\n\t\t\tcount++;\r\n\t\t}\r\n\t\treturn count;\r\n\t};\r\n\r\n\t//given a Unicode code point, determines this symbol's grapheme break property\r\n\tfunction getGraphemeBreakProperty(code){\r\n\r\n\t\t//grapheme break property for Unicode 10.0.0,\r\n\t\t//taken from http://www.unicode.org/Public/10.0.0/ucd/auxiliary/GraphemeBreakProperty.txt\r\n\t\t//and adapted to JavaScript rules\r\n\r\n\t\tif(\r\n\t\t(0x0600 <= code && code <= 0x0605) || // Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE\r\n\t\t0x06DD == code || // Cf ARABIC END OF AYAH\r\n\t\t0x070F == code || // Cf SYRIAC ABBREVIATION MARK\r\n\t\t0x08E2 == code || // Cf ARABIC DISPUTED END OF AYAH\r\n\t\t0x0D4E == code || // Lo MALAYALAM LETTER DOT REPH\r\n\t\t0x110BD == code || // Cf KAITHI NUMBER SIGN\r\n\t\t(0x111C2 <= code && code <= 0x111C3) || // Lo [2] SHARADA SIGN JIHVAMULIYA..SHARADA SIGN UPADHMANIYA\r\n\t\t0x11A3A == code || // Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA\r\n\t\t(0x11A86 <= code && code <= 0x11A89) || // Lo [4] SOYOMBO CLUSTER-INITIAL LETTER RA..SOYOMBO CLUSTER-INITIAL LETTER SA\r\n\t\t0x11D46 == code // Lo MASARAM GONDI REPHA\r\n\t\t){\r\n\t\t\treturn Prepend;\r\n\t\t}\r\n\t\tif(\r\n\t\t0x000D == code // Cc \r\n\t\t){\r\n\t\t\treturn CR;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t0x000A == code // Cc \r\n\t\t){\r\n\t\t\treturn LF;\r\n\t\t}\r\n\r\n\r\n\t\tif(\r\n\t\t(0x0000 <= code && code <= 0x0009) || // Cc [10] ..\r\n\t\t(0x000B <= code && code <= 0x000C) || // Cc [2] ..\r\n\t\t(0x000E <= code && code <= 0x001F) || // Cc [18] ..\r\n\t\t(0x007F <= code && code <= 0x009F) || // Cc [33] ..\r\n\t\t0x00AD == code || // Cf SOFT HYPHEN\r\n\t\t0x061C == code || // Cf ARABIC LETTER MARK\r\n\r\n\t\t0x180E == code || // Cf MONGOLIAN VOWEL SEPARATOR\r\n\t\t0x200B == code || // Cf ZERO WIDTH SPACE\r\n\t\t(0x200E <= code && code <= 0x200F) || // Cf [2] LEFT-TO-RIGHT MARK..RIGHT-TO-LEFT MARK\r\n\t\t0x2028 == code || // Zl LINE SEPARATOR\r\n\t\t0x2029 == code || // Zp PARAGRAPH SEPARATOR\r\n\t\t(0x202A <= code && code <= 0x202E) || // Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE\r\n\t\t(0x2060 <= code && code <= 0x2064) || // Cf [5] WORD JOINER..INVISIBLE PLUS\r\n\t\t0x2065 == code || // Cn \r\n\t\t(0x2066 <= code && code <= 0x206F) || // Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES\r\n\t\t(0xD800 <= code && code <= 0xDFFF) || // Cs [2048] ..\r\n\t\t0xFEFF == code || // Cf ZERO WIDTH NO-BREAK SPACE\r\n\t\t(0xFFF0 <= code && code <= 0xFFF8) || // Cn [9] ..\r\n\t\t(0xFFF9 <= code && code <= 0xFFFB) || // Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR\r\n\t\t(0x1BCA0 <= code && code <= 0x1BCA3) || // Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP\r\n\t\t(0x1D173 <= code && code <= 0x1D17A) || // Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE\r\n\t\t0xE0000 == code || // Cn \r\n\t\t0xE0001 == code || // Cf LANGUAGE TAG\r\n\t\t(0xE0002 <= code && code <= 0xE001F) || // Cn [30] ..\r\n\t\t(0xE0080 <= code && code <= 0xE00FF) || // Cn [128] ..\r\n\t\t(0xE01F0 <= code && code <= 0xE0FFF) // Cn [3600] ..\r\n\t\t){\r\n\t\t\treturn Control;\r\n\t\t}\r\n\r\n\r\n\t\tif(\r\n\t\t(0x0300 <= code && code <= 0x036F) || // Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X\r\n\t\t(0x0483 <= code && code <= 0x0487) || // Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE\r\n\t\t(0x0488 <= code && code <= 0x0489) || // Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN\r\n\t\t(0x0591 <= code && code <= 0x05BD) || // Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG\r\n\t\t0x05BF == code || // Mn HEBREW POINT RAFE\r\n\t\t(0x05C1 <= code && code <= 0x05C2) || // Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT\r\n\t\t(0x05C4 <= code && code <= 0x05C5) || // Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT\r\n\t\t0x05C7 == code || // Mn HEBREW POINT QAMATS QATAN\r\n\t\t(0x0610 <= code && code <= 0x061A) || // Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA\r\n\t\t(0x064B <= code && code <= 0x065F) || // Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW\r\n\t\t0x0670 == code || // Mn ARABIC LETTER SUPERSCRIPT ALEF\r\n\t\t(0x06D6 <= code && code <= 0x06DC) || // Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN\r\n\t\t(0x06DF <= code && code <= 0x06E4) || // Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA\r\n\t\t(0x06E7 <= code && code <= 0x06E8) || // Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON\r\n\t\t(0x06EA <= code && code <= 0x06ED) || // Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM\r\n\t\t0x0711 == code || // Mn SYRIAC LETTER SUPERSCRIPT ALAPH\r\n\t\t(0x0730 <= code && code <= 0x074A) || // Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH\r\n\t\t(0x07A6 <= code && code <= 0x07B0) || // Mn [11] THAANA ABAFILI..THAANA SUKUN\r\n\t\t(0x07EB <= code && code <= 0x07F3) || // Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE\r\n\t\t(0x0816 <= code && code <= 0x0819) || // Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH\r\n\t\t(0x081B <= code && code <= 0x0823) || // Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A\r\n\t\t(0x0825 <= code && code <= 0x0827) || // Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U\r\n\t\t(0x0829 <= code && code <= 0x082D) || // Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA\r\n\t\t(0x0859 <= code && code <= 0x085B) || // Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK\r\n\t\t(0x08D4 <= code && code <= 0x08E1) || // Mn [14] ARABIC SMALL HIGH WORD AR-RUB..ARABIC SMALL HIGH SIGN SAFHA\r\n\t\t(0x08E3 <= code && code <= 0x0902) || // Mn [32] ARABIC TURNED DAMMA BELOW..DEVANAGARI SIGN ANUSVARA\r\n\t\t0x093A == code || // Mn DEVANAGARI VOWEL SIGN OE\r\n\t\t0x093C == code || // Mn DEVANAGARI SIGN NUKTA\r\n\t\t(0x0941 <= code && code <= 0x0948) || // Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI\r\n\t\t0x094D == code || // Mn DEVANAGARI SIGN VIRAMA\r\n\t\t(0x0951 <= code && code <= 0x0957) || // Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE\r\n\t\t(0x0962 <= code && code <= 0x0963) || // Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL\r\n\t\t0x0981 == code || // Mn BENGALI SIGN CANDRABINDU\r\n\t\t0x09BC == code || // Mn BENGALI SIGN NUKTA\r\n\t\t0x09BE == code || // Mc BENGALI VOWEL SIGN AA\r\n\t\t(0x09C1 <= code && code <= 0x09C4) || // Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR\r\n\t\t0x09CD == code || // Mn BENGALI SIGN VIRAMA\r\n\t\t0x09D7 == code || // Mc BENGALI AU LENGTH MARK\r\n\t\t(0x09E2 <= code && code <= 0x09E3) || // Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL\r\n\t\t(0x0A01 <= code && code <= 0x0A02) || // Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI\r\n\t\t0x0A3C == code || // Mn GURMUKHI SIGN NUKTA\r\n\t\t(0x0A41 <= code && code <= 0x0A42) || // Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU\r\n\t\t(0x0A47 <= code && code <= 0x0A48) || // Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI\r\n\t\t(0x0A4B <= code && code <= 0x0A4D) || // Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA\r\n\t\t0x0A51 == code || // Mn GURMUKHI SIGN UDAAT\r\n\t\t(0x0A70 <= code && code <= 0x0A71) || // Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK\r\n\t\t0x0A75 == code || // Mn GURMUKHI SIGN YAKASH\r\n\t\t(0x0A81 <= code && code <= 0x0A82) || // Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA\r\n\t\t0x0ABC == code || // Mn GUJARATI SIGN NUKTA\r\n\t\t(0x0AC1 <= code && code <= 0x0AC5) || // Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E\r\n\t\t(0x0AC7 <= code && code <= 0x0AC8) || // Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI\r\n\t\t0x0ACD == code || // Mn GUJARATI SIGN VIRAMA\r\n\t\t(0x0AE2 <= code && code <= 0x0AE3) || // Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL\r\n\t\t(0x0AFA <= code && code <= 0x0AFF) || // Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE\r\n\t\t0x0B01 == code || // Mn ORIYA SIGN CANDRABINDU\r\n\t\t0x0B3C == code || // Mn ORIYA SIGN NUKTA\r\n\t\t0x0B3E == code || // Mc ORIYA VOWEL SIGN AA\r\n\t\t0x0B3F == code || // Mn ORIYA VOWEL SIGN I\r\n\t\t(0x0B41 <= code && code <= 0x0B44) || // Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR\r\n\t\t0x0B4D == code || // Mn ORIYA SIGN VIRAMA\r\n\t\t0x0B56 == code || // Mn ORIYA AI LENGTH MARK\r\n\t\t0x0B57 == code || // Mc ORIYA AU LENGTH MARK\r\n\t\t(0x0B62 <= code && code <= 0x0B63) || // Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL\r\n\t\t0x0B82 == code || // Mn TAMIL SIGN ANUSVARA\r\n\t\t0x0BBE == code || // Mc TAMIL VOWEL SIGN AA\r\n\t\t0x0BC0 == code || // Mn TAMIL VOWEL SIGN II\r\n\t\t0x0BCD == code || // Mn TAMIL SIGN VIRAMA\r\n\t\t0x0BD7 == code || // Mc TAMIL AU LENGTH MARK\r\n\t\t0x0C00 == code || // Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE\r\n\t\t(0x0C3E <= code && code <= 0x0C40) || // Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II\r\n\t\t(0x0C46 <= code && code <= 0x0C48) || // Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI\r\n\t\t(0x0C4A <= code && code <= 0x0C4D) || // Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA\r\n\t\t(0x0C55 <= code && code <= 0x0C56) || // Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK\r\n\t\t(0x0C62 <= code && code <= 0x0C63) || // Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL\r\n\t\t0x0C81 == code || // Mn KANNADA SIGN CANDRABINDU\r\n\t\t0x0CBC == code || // Mn KANNADA SIGN NUKTA\r\n\t\t0x0CBF == code || // Mn KANNADA VOWEL SIGN I\r\n\t\t0x0CC2 == code || // Mc KANNADA VOWEL SIGN UU\r\n\t\t0x0CC6 == code || // Mn KANNADA VOWEL SIGN E\r\n\t\t(0x0CCC <= code && code <= 0x0CCD) || // Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA\r\n\t\t(0x0CD5 <= code && code <= 0x0CD6) || // Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK\r\n\t\t(0x0CE2 <= code && code <= 0x0CE3) || // Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL\r\n\t\t(0x0D00 <= code && code <= 0x0D01) || // Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU\r\n\t\t(0x0D3B <= code && code <= 0x0D3C) || // Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA\r\n\t\t0x0D3E == code || // Mc MALAYALAM VOWEL SIGN AA\r\n\t\t(0x0D41 <= code && code <= 0x0D44) || // Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR\r\n\t\t0x0D4D == code || // Mn MALAYALAM SIGN VIRAMA\r\n\t\t0x0D57 == code || // Mc MALAYALAM AU LENGTH MARK\r\n\t\t(0x0D62 <= code && code <= 0x0D63) || // Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL\r\n\t\t0x0DCA == code || // Mn SINHALA SIGN AL-LAKUNA\r\n\t\t0x0DCF == code || // Mc SINHALA VOWEL SIGN AELA-PILLA\r\n\t\t(0x0DD2 <= code && code <= 0x0DD4) || // Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA\r\n\t\t0x0DD6 == code || // Mn SINHALA VOWEL SIGN DIGA PAA-PILLA\r\n\t\t0x0DDF == code || // Mc SINHALA VOWEL SIGN GAYANUKITTA\r\n\t\t0x0E31 == code || // Mn THAI CHARACTER MAI HAN-AKAT\r\n\t\t(0x0E34 <= code && code <= 0x0E3A) || // Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU\r\n\t\t(0x0E47 <= code && code <= 0x0E4E) || // Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN\r\n\t\t0x0EB1 == code || // Mn LAO VOWEL SIGN MAI KAN\r\n\t\t(0x0EB4 <= code && code <= 0x0EB9) || // Mn [6] LAO VOWEL SIGN I..LAO VOWEL SIGN UU\r\n\t\t(0x0EBB <= code && code <= 0x0EBC) || // Mn [2] LAO VOWEL SIGN MAI KON..LAO SEMIVOWEL SIGN LO\r\n\t\t(0x0EC8 <= code && code <= 0x0ECD) || // Mn [6] LAO TONE MAI EK..LAO NIGGAHITA\r\n\t\t(0x0F18 <= code && code <= 0x0F19) || // Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS\r\n\t\t0x0F35 == code || // Mn TIBETAN MARK NGAS BZUNG NYI ZLA\r\n\t\t0x0F37 == code || // Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS\r\n\t\t0x0F39 == code || // Mn TIBETAN MARK TSA -PHRU\r\n\t\t(0x0F71 <= code && code <= 0x0F7E) || // Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO\r\n\t\t(0x0F80 <= code && code <= 0x0F84) || // Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA\r\n\t\t(0x0F86 <= code && code <= 0x0F87) || // Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS\r\n\t\t(0x0F8D <= code && code <= 0x0F97) || // Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA\r\n\t\t(0x0F99 <= code && code <= 0x0FBC) || // Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA\r\n\t\t0x0FC6 == code || // Mn TIBETAN SYMBOL PADMA GDAN\r\n\t\t(0x102D <= code && code <= 0x1030) || // Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU\r\n\t\t(0x1032 <= code && code <= 0x1037) || // Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW\r\n\t\t(0x1039 <= code && code <= 0x103A) || // Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT\r\n\t\t(0x103D <= code && code <= 0x103E) || // Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA\r\n\t\t(0x1058 <= code && code <= 0x1059) || // Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL\r\n\t\t(0x105E <= code && code <= 0x1060) || // Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA\r\n\t\t(0x1071 <= code && code <= 0x1074) || // Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE\r\n\t\t0x1082 == code || // Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA\r\n\t\t(0x1085 <= code && code <= 0x1086) || // Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y\r\n\t\t0x108D == code || // Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE\r\n\t\t0x109D == code || // Mn MYANMAR VOWEL SIGN AITON AI\r\n\t\t(0x135D <= code && code <= 0x135F) || // Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK\r\n\t\t(0x1712 <= code && code <= 0x1714) || // Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA\r\n\t\t(0x1732 <= code && code <= 0x1734) || // Mn [3] HANUNOO VOWEL SIGN I..HANUNOO SIGN PAMUDPOD\r\n\t\t(0x1752 <= code && code <= 0x1753) || // Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U\r\n\t\t(0x1772 <= code && code <= 0x1773) || // Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U\r\n\t\t(0x17B4 <= code && code <= 0x17B5) || // Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA\r\n\t\t(0x17B7 <= code && code <= 0x17BD) || // Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA\r\n\t\t0x17C6 == code || // Mn KHMER SIGN NIKAHIT\r\n\t\t(0x17C9 <= code && code <= 0x17D3) || // Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT\r\n\t\t0x17DD == code || // Mn KHMER SIGN ATTHACAN\r\n\t\t(0x180B <= code && code <= 0x180D) || // Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE\r\n\t\t(0x1885 <= code && code <= 0x1886) || // Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA\r\n\t\t0x18A9 == code || // Mn MONGOLIAN LETTER ALI GALI DAGALGA\r\n\t\t(0x1920 <= code && code <= 0x1922) || // Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U\r\n\t\t(0x1927 <= code && code <= 0x1928) || // Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O\r\n\t\t0x1932 == code || // Mn LIMBU SMALL LETTER ANUSVARA\r\n\t\t(0x1939 <= code && code <= 0x193B) || // Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I\r\n\t\t(0x1A17 <= code && code <= 0x1A18) || // Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U\r\n\t\t0x1A1B == code || // Mn BUGINESE VOWEL SIGN AE\r\n\t\t0x1A56 == code || // Mn TAI THAM CONSONANT SIGN MEDIAL LA\r\n\t\t(0x1A58 <= code && code <= 0x1A5E) || // Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA\r\n\t\t0x1A60 == code || // Mn TAI THAM SIGN SAKOT\r\n\t\t0x1A62 == code || // Mn TAI THAM VOWEL SIGN MAI SAT\r\n\t\t(0x1A65 <= code && code <= 0x1A6C) || // Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW\r\n\t\t(0x1A73 <= code && code <= 0x1A7C) || // Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN\r\n\t\t0x1A7F == code || // Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT\r\n\t\t(0x1AB0 <= code && code <= 0x1ABD) || // Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW\r\n\t\t0x1ABE == code || // Me COMBINING PARENTHESES OVERLAY\r\n\t\t(0x1B00 <= code && code <= 0x1B03) || // Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG\r\n\t\t0x1B34 == code || // Mn BALINESE SIGN REREKAN\r\n\t\t(0x1B36 <= code && code <= 0x1B3A) || // Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA\r\n\t\t0x1B3C == code || // Mn BALINESE VOWEL SIGN LA LENGA\r\n\t\t0x1B42 == code || // Mn BALINESE VOWEL SIGN PEPET\r\n\t\t(0x1B6B <= code && code <= 0x1B73) || // Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG\r\n\t\t(0x1B80 <= code && code <= 0x1B81) || // Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR\r\n\t\t(0x1BA2 <= code && code <= 0x1BA5) || // Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU\r\n\t\t(0x1BA8 <= code && code <= 0x1BA9) || // Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG\r\n\t\t(0x1BAB <= code && code <= 0x1BAD) || // Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA\r\n\t\t0x1BE6 == code || // Mn BATAK SIGN TOMPI\r\n\t\t(0x1BE8 <= code && code <= 0x1BE9) || // Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE\r\n\t\t0x1BED == code || // Mn BATAK VOWEL SIGN KARO O\r\n\t\t(0x1BEF <= code && code <= 0x1BF1) || // Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H\r\n\t\t(0x1C2C <= code && code <= 0x1C33) || // Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T\r\n\t\t(0x1C36 <= code && code <= 0x1C37) || // Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA\r\n\t\t(0x1CD0 <= code && code <= 0x1CD2) || // Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA\r\n\t\t(0x1CD4 <= code && code <= 0x1CE0) || // Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA\r\n\t\t(0x1CE2 <= code && code <= 0x1CE8) || // Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL\r\n\t\t0x1CED == code || // Mn VEDIC SIGN TIRYAK\r\n\t\t0x1CF4 == code || // Mn VEDIC TONE CANDRA ABOVE\r\n\t\t(0x1CF8 <= code && code <= 0x1CF9) || // Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE\r\n\t\t(0x1DC0 <= code && code <= 0x1DF9) || // Mn [58] COMBINING DOTTED GRAVE ACCENT..COMBINING WIDE INVERTED BRIDGE BELOW\r\n\t\t(0x1DFB <= code && code <= 0x1DFF) || // Mn [5] COMBINING DELETION MARK..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW\r\n\t\t0x200C == code || // Cf ZERO WIDTH NON-JOINER\r\n\t\t(0x20D0 <= code && code <= 0x20DC) || // Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE\r\n\t\t(0x20DD <= code && code <= 0x20E0) || // Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH\r\n\t\t0x20E1 == code || // Mn COMBINING LEFT RIGHT ARROW ABOVE\r\n\t\t(0x20E2 <= code && code <= 0x20E4) || // Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE\r\n\t\t(0x20E5 <= code && code <= 0x20F0) || // Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE\r\n\t\t(0x2CEF <= code && code <= 0x2CF1) || // Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS\r\n\t\t0x2D7F == code || // Mn TIFINAGH CONSONANT JOINER\r\n\t\t(0x2DE0 <= code && code <= 0x2DFF) || // Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS\r\n\t\t(0x302A <= code && code <= 0x302D) || // Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK\r\n\t\t(0x302E <= code && code <= 0x302F) || // Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK\r\n\t\t(0x3099 <= code && code <= 0x309A) || // Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK\r\n\t\t0xA66F == code || // Mn COMBINING CYRILLIC VZMET\r\n\t\t(0xA670 <= code && code <= 0xA672) || // Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN\r\n\t\t(0xA674 <= code && code <= 0xA67D) || // Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK\r\n\t\t(0xA69E <= code && code <= 0xA69F) || // Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E\r\n\t\t(0xA6F0 <= code && code <= 0xA6F1) || // Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS\r\n\t\t0xA802 == code || // Mn SYLOTI NAGRI SIGN DVISVARA\r\n\t\t0xA806 == code || // Mn SYLOTI NAGRI SIGN HASANTA\r\n\t\t0xA80B == code || // Mn SYLOTI NAGRI SIGN ANUSVARA\r\n\t\t(0xA825 <= code && code <= 0xA826) || // Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E\r\n\t\t(0xA8C4 <= code && code <= 0xA8C5) || // Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU\r\n\t\t(0xA8E0 <= code && code <= 0xA8F1) || // Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA\r\n\t\t(0xA926 <= code && code <= 0xA92D) || // Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU\r\n\t\t(0xA947 <= code && code <= 0xA951) || // Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R\r\n\t\t(0xA980 <= code && code <= 0xA982) || // Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR\r\n\t\t0xA9B3 == code || // Mn JAVANESE SIGN CECAK TELU\r\n\t\t(0xA9B6 <= code && code <= 0xA9B9) || // Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT\r\n\t\t0xA9BC == code || // Mn JAVANESE VOWEL SIGN PEPET\r\n\t\t0xA9E5 == code || // Mn MYANMAR SIGN SHAN SAW\r\n\t\t(0xAA29 <= code && code <= 0xAA2E) || // Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE\r\n\t\t(0xAA31 <= code && code <= 0xAA32) || // Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE\r\n\t\t(0xAA35 <= code && code <= 0xAA36) || // Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA\r\n\t\t0xAA43 == code || // Mn CHAM CONSONANT SIGN FINAL NG\r\n\t\t0xAA4C == code || // Mn CHAM CONSONANT SIGN FINAL M\r\n\t\t0xAA7C == code || // Mn MYANMAR SIGN TAI LAING TONE-2\r\n\t\t0xAAB0 == code || // Mn TAI VIET MAI KANG\r\n\t\t(0xAAB2 <= code && code <= 0xAAB4) || // Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U\r\n\t\t(0xAAB7 <= code && code <= 0xAAB8) || // Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA\r\n\t\t(0xAABE <= code && code <= 0xAABF) || // Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK\r\n\t\t0xAAC1 == code || // Mn TAI VIET TONE MAI THO\r\n\t\t(0xAAEC <= code && code <= 0xAAED) || // Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI\r\n\t\t0xAAF6 == code || // Mn MEETEI MAYEK VIRAMA\r\n\t\t0xABE5 == code || // Mn MEETEI MAYEK VOWEL SIGN ANAP\r\n\t\t0xABE8 == code || // Mn MEETEI MAYEK VOWEL SIGN UNAP\r\n\t\t0xABED == code || // Mn MEETEI MAYEK APUN IYEK\r\n\t\t0xFB1E == code || // Mn HEBREW POINT JUDEO-SPANISH VARIKA\r\n\t\t(0xFE00 <= code && code <= 0xFE0F) || // Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16\r\n\t\t(0xFE20 <= code && code <= 0xFE2F) || // Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF\r\n\t\t(0xFF9E <= code && code <= 0xFF9F) || // Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK\r\n\t\t0x101FD == code || // Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE\r\n\t\t0x102E0 == code || // Mn COPTIC EPACT THOUSANDS MARK\r\n\t\t(0x10376 <= code && code <= 0x1037A) || // Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII\r\n\t\t(0x10A01 <= code && code <= 0x10A03) || // Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R\r\n\t\t(0x10A05 <= code && code <= 0x10A06) || // Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O\r\n\t\t(0x10A0C <= code && code <= 0x10A0F) || // Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA\r\n\t\t(0x10A38 <= code && code <= 0x10A3A) || // Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW\r\n\t\t0x10A3F == code || // Mn KHAROSHTHI VIRAMA\r\n\t\t(0x10AE5 <= code && code <= 0x10AE6) || // Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW\r\n\t\t0x11001 == code || // Mn BRAHMI SIGN ANUSVARA\r\n\t\t(0x11038 <= code && code <= 0x11046) || // Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA\r\n\t\t(0x1107F <= code && code <= 0x11081) || // Mn [3] BRAHMI NUMBER JOINER..KAITHI SIGN ANUSVARA\r\n\t\t(0x110B3 <= code && code <= 0x110B6) || // Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI\r\n\t\t(0x110B9 <= code && code <= 0x110BA) || // Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA\r\n\t\t(0x11100 <= code && code <= 0x11102) || // Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA\r\n\t\t(0x11127 <= code && code <= 0x1112B) || // Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU\r\n\t\t(0x1112D <= code && code <= 0x11134) || // Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA\r\n\t\t0x11173 == code || // Mn MAHAJANI SIGN NUKTA\r\n\t\t(0x11180 <= code && code <= 0x11181) || // Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA\r\n\t\t(0x111B6 <= code && code <= 0x111BE) || // Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O\r\n\t\t(0x111CA <= code && code <= 0x111CC) || // Mn [3] SHARADA SIGN NUKTA..SHARADA EXTRA SHORT VOWEL MARK\r\n\t\t(0x1122F <= code && code <= 0x11231) || // Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI\r\n\t\t0x11234 == code || // Mn KHOJKI SIGN ANUSVARA\r\n\t\t(0x11236 <= code && code <= 0x11237) || // Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA\r\n\t\t0x1123E == code || // Mn KHOJKI SIGN SUKUN\r\n\t\t0x112DF == code || // Mn KHUDAWADI SIGN ANUSVARA\r\n\t\t(0x112E3 <= code && code <= 0x112EA) || // Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA\r\n\t\t(0x11300 <= code && code <= 0x11301) || // Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU\r\n\t\t0x1133C == code || // Mn GRANTHA SIGN NUKTA\r\n\t\t0x1133E == code || // Mc GRANTHA VOWEL SIGN AA\r\n\t\t0x11340 == code || // Mn GRANTHA VOWEL SIGN II\r\n\t\t0x11357 == code || // Mc GRANTHA AU LENGTH MARK\r\n\t\t(0x11366 <= code && code <= 0x1136C) || // Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX\r\n\t\t(0x11370 <= code && code <= 0x11374) || // Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA\r\n\t\t(0x11438 <= code && code <= 0x1143F) || // Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI\r\n\t\t(0x11442 <= code && code <= 0x11444) || // Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA\r\n\t\t0x11446 == code || // Mn NEWA SIGN NUKTA\r\n\t\t0x114B0 == code || // Mc TIRHUTA VOWEL SIGN AA\r\n\t\t(0x114B3 <= code && code <= 0x114B8) || // Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL\r\n\t\t0x114BA == code || // Mn TIRHUTA VOWEL SIGN SHORT E\r\n\t\t0x114BD == code || // Mc TIRHUTA VOWEL SIGN SHORT O\r\n\t\t(0x114BF <= code && code <= 0x114C0) || // Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA\r\n\t\t(0x114C2 <= code && code <= 0x114C3) || // Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA\r\n\t\t0x115AF == code || // Mc SIDDHAM VOWEL SIGN AA\r\n\t\t(0x115B2 <= code && code <= 0x115B5) || // Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR\r\n\t\t(0x115BC <= code && code <= 0x115BD) || // Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA\r\n\t\t(0x115BF <= code && code <= 0x115C0) || // Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA\r\n\t\t(0x115DC <= code && code <= 0x115DD) || // Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU\r\n\t\t(0x11633 <= code && code <= 0x1163A) || // Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI\r\n\t\t0x1163D == code || // Mn MODI SIGN ANUSVARA\r\n\t\t(0x1163F <= code && code <= 0x11640) || // Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA\r\n\t\t0x116AB == code || // Mn TAKRI SIGN ANUSVARA\r\n\t\t0x116AD == code || // Mn TAKRI VOWEL SIGN AA\r\n\t\t(0x116B0 <= code && code <= 0x116B5) || // Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU\r\n\t\t0x116B7 == code || // Mn TAKRI SIGN NUKTA\r\n\t\t(0x1171D <= code && code <= 0x1171F) || // Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA\r\n\t\t(0x11722 <= code && code <= 0x11725) || // Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU\r\n\t\t(0x11727 <= code && code <= 0x1172B) || // Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER\r\n\t\t(0x11A01 <= code && code <= 0x11A06) || // Mn [6] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL SIGN O\r\n\t\t(0x11A09 <= code && code <= 0x11A0A) || // Mn [2] ZANABAZAR SQUARE VOWEL SIGN REVERSED I..ZANABAZAR SQUARE VOWEL LENGTH MARK\r\n\t\t(0x11A33 <= code && code <= 0x11A38) || // Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA\r\n\t\t(0x11A3B <= code && code <= 0x11A3E) || // Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA\r\n\t\t0x11A47 == code || // Mn ZANABAZAR SQUARE SUBJOINER\r\n\t\t(0x11A51 <= code && code <= 0x11A56) || // Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE\r\n\t\t(0x11A59 <= code && code <= 0x11A5B) || // Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK\r\n\t\t(0x11A8A <= code && code <= 0x11A96) || // Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA\r\n\t\t(0x11A98 <= code && code <= 0x11A99) || // Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER\r\n\t\t(0x11C30 <= code && code <= 0x11C36) || // Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L\r\n\t\t(0x11C38 <= code && code <= 0x11C3D) || // Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA\r\n\t\t0x11C3F == code || // Mn BHAIKSUKI SIGN VIRAMA\r\n\t\t(0x11C92 <= code && code <= 0x11CA7) || // Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA\r\n\t\t(0x11CAA <= code && code <= 0x11CB0) || // Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA\r\n\t\t(0x11CB2 <= code && code <= 0x11CB3) || // Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E\r\n\t\t(0x11CB5 <= code && code <= 0x11CB6) || // Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU\r\n\t\t(0x11D31 <= code && code <= 0x11D36) || // Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R\r\n\t\t0x11D3A == code || // Mn MASARAM GONDI VOWEL SIGN E\r\n\t\t(0x11D3C <= code && code <= 0x11D3D) || // Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O\r\n\t\t(0x11D3F <= code && code <= 0x11D45) || // Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA\r\n\t\t0x11D47 == code || // Mn MASARAM GONDI RA-KARA\r\n\t\t(0x16AF0 <= code && code <= 0x16AF4) || // Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE\r\n\t\t(0x16B30 <= code && code <= 0x16B36) || // Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM\r\n\t\t(0x16F8F <= code && code <= 0x16F92) || // Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW\r\n\t\t(0x1BC9D <= code && code <= 0x1BC9E) || // Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK\r\n\t\t0x1D165 == code || // Mc MUSICAL SYMBOL COMBINING STEM\r\n\t\t(0x1D167 <= code && code <= 0x1D169) || // Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3\r\n\t\t(0x1D16E <= code && code <= 0x1D172) || // Mc [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5\r\n\t\t(0x1D17B <= code && code <= 0x1D182) || // Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE\r\n\t\t(0x1D185 <= code && code <= 0x1D18B) || // Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE\r\n\t\t(0x1D1AA <= code && code <= 0x1D1AD) || // Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO\r\n\t\t(0x1D242 <= code && code <= 0x1D244) || // Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME\r\n\t\t(0x1DA00 <= code && code <= 0x1DA36) || // Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN\r\n\t\t(0x1DA3B <= code && code <= 0x1DA6C) || // Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT\r\n\t\t0x1DA75 == code || // Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS\r\n\t\t0x1DA84 == code || // Mn SIGNWRITING LOCATION HEAD NECK\r\n\t\t(0x1DA9B <= code && code <= 0x1DA9F) || // Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6\r\n\t\t(0x1DAA1 <= code && code <= 0x1DAAF) || // Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16\r\n\t\t(0x1E000 <= code && code <= 0x1E006) || // Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE\r\n\t\t(0x1E008 <= code && code <= 0x1E018) || // Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU\r\n\t\t(0x1E01B <= code && code <= 0x1E021) || // Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI\r\n\t\t(0x1E023 <= code && code <= 0x1E024) || // Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS\r\n\t\t(0x1E026 <= code && code <= 0x1E02A) || // Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA\r\n\t\t(0x1E8D0 <= code && code <= 0x1E8D6) || // Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS\r\n\t\t(0x1E944 <= code && code <= 0x1E94A) || // Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA\r\n\t\t(0xE0020 <= code && code <= 0xE007F) || // Cf [96] TAG SPACE..CANCEL TAG\r\n\t\t(0xE0100 <= code && code <= 0xE01EF) // Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256\r\n\t\t){\r\n\t\t\treturn Extend;\r\n\t\t}\r\n\r\n\r\n\t\tif(\r\n\t\t(0x1F1E6 <= code && code <= 0x1F1FF) // So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z\r\n\t\t){\r\n\t\t\treturn Regional_Indicator;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t0x0903 == code || // Mc DEVANAGARI SIGN VISARGA\r\n\t\t0x093B == code || // Mc DEVANAGARI VOWEL SIGN OOE\r\n\t\t(0x093E <= code && code <= 0x0940) || // Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II\r\n\t\t(0x0949 <= code && code <= 0x094C) || // Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU\r\n\t\t(0x094E <= code && code <= 0x094F) || // Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW\r\n\t\t(0x0982 <= code && code <= 0x0983) || // Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA\r\n\t\t(0x09BF <= code && code <= 0x09C0) || // Mc [2] BENGALI VOWEL SIGN I..BENGALI VOWEL SIGN II\r\n\t\t(0x09C7 <= code && code <= 0x09C8) || // Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI\r\n\t\t(0x09CB <= code && code <= 0x09CC) || // Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU\r\n\t\t0x0A03 == code || // Mc GURMUKHI SIGN VISARGA\r\n\t\t(0x0A3E <= code && code <= 0x0A40) || // Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II\r\n\t\t0x0A83 == code || // Mc GUJARATI SIGN VISARGA\r\n\t\t(0x0ABE <= code && code <= 0x0AC0) || // Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II\r\n\t\t0x0AC9 == code || // Mc GUJARATI VOWEL SIGN CANDRA O\r\n\t\t(0x0ACB <= code && code <= 0x0ACC) || // Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU\r\n\t\t(0x0B02 <= code && code <= 0x0B03) || // Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA\r\n\t\t0x0B40 == code || // Mc ORIYA VOWEL SIGN II\r\n\t\t(0x0B47 <= code && code <= 0x0B48) || // Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI\r\n\t\t(0x0B4B <= code && code <= 0x0B4C) || // Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU\r\n\t\t0x0BBF == code || // Mc TAMIL VOWEL SIGN I\r\n\t\t(0x0BC1 <= code && code <= 0x0BC2) || // Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU\r\n\t\t(0x0BC6 <= code && code <= 0x0BC8) || // Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI\r\n\t\t(0x0BCA <= code && code <= 0x0BCC) || // Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU\r\n\t\t(0x0C01 <= code && code <= 0x0C03) || // Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA\r\n\t\t(0x0C41 <= code && code <= 0x0C44) || // Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR\r\n\t\t(0x0C82 <= code && code <= 0x0C83) || // Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA\r\n\t\t0x0CBE == code || // Mc KANNADA VOWEL SIGN AA\r\n\t\t(0x0CC0 <= code && code <= 0x0CC1) || // Mc [2] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN U\r\n\t\t(0x0CC3 <= code && code <= 0x0CC4) || // Mc [2] KANNADA VOWEL SIGN VOCALIC R..KANNADA VOWEL SIGN VOCALIC RR\r\n\t\t(0x0CC7 <= code && code <= 0x0CC8) || // Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI\r\n\t\t(0x0CCA <= code && code <= 0x0CCB) || // Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO\r\n\t\t(0x0D02 <= code && code <= 0x0D03) || // Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA\r\n\t\t(0x0D3F <= code && code <= 0x0D40) || // Mc [2] MALAYALAM VOWEL SIGN I..MALAYALAM VOWEL SIGN II\r\n\t\t(0x0D46 <= code && code <= 0x0D48) || // Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI\r\n\t\t(0x0D4A <= code && code <= 0x0D4C) || // Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU\r\n\t\t(0x0D82 <= code && code <= 0x0D83) || // Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA\r\n\t\t(0x0DD0 <= code && code <= 0x0DD1) || // Mc [2] SINHALA VOWEL SIGN KETTI AEDA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA\r\n\t\t(0x0DD8 <= code && code <= 0x0DDE) || // Mc [7] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN KOMBUVA HAA GAYANUKITTA\r\n\t\t(0x0DF2 <= code && code <= 0x0DF3) || // Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA\r\n\t\t0x0E33 == code || // Lo THAI CHARACTER SARA AM\r\n\t\t0x0EB3 == code || // Lo LAO VOWEL SIGN AM\r\n\t\t(0x0F3E <= code && code <= 0x0F3F) || // Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES\r\n\t\t0x0F7F == code || // Mc TIBETAN SIGN RNAM BCAD\r\n\t\t0x1031 == code || // Mc MYANMAR VOWEL SIGN E\r\n\t\t(0x103B <= code && code <= 0x103C) || // Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA\r\n\t\t(0x1056 <= code && code <= 0x1057) || // Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR\r\n\t\t0x1084 == code || // Mc MYANMAR VOWEL SIGN SHAN E\r\n\t\t0x17B6 == code || // Mc KHMER VOWEL SIGN AA\r\n\t\t(0x17BE <= code && code <= 0x17C5) || // Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU\r\n\t\t(0x17C7 <= code && code <= 0x17C8) || // Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU\r\n\t\t(0x1923 <= code && code <= 0x1926) || // Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU\r\n\t\t(0x1929 <= code && code <= 0x192B) || // Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA\r\n\t\t(0x1930 <= code && code <= 0x1931) || // Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA\r\n\t\t(0x1933 <= code && code <= 0x1938) || // Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA\r\n\t\t(0x1A19 <= code && code <= 0x1A1A) || // Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O\r\n\t\t0x1A55 == code || // Mc TAI THAM CONSONANT SIGN MEDIAL RA\r\n\t\t0x1A57 == code || // Mc TAI THAM CONSONANT SIGN LA TANG LAI\r\n\t\t(0x1A6D <= code && code <= 0x1A72) || // Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI\r\n\t\t0x1B04 == code || // Mc BALINESE SIGN BISAH\r\n\t\t0x1B35 == code || // Mc BALINESE VOWEL SIGN TEDUNG\r\n\t\t0x1B3B == code || // Mc BALINESE VOWEL SIGN RA REPA TEDUNG\r\n\t\t(0x1B3D <= code && code <= 0x1B41) || // Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG\r\n\t\t(0x1B43 <= code && code <= 0x1B44) || // Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG\r\n\t\t0x1B82 == code || // Mc SUNDANESE SIGN PANGWISAD\r\n\t\t0x1BA1 == code || // Mc SUNDANESE CONSONANT SIGN PAMINGKAL\r\n\t\t(0x1BA6 <= code && code <= 0x1BA7) || // Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG\r\n\t\t0x1BAA == code || // Mc SUNDANESE SIGN PAMAAEH\r\n\t\t0x1BE7 == code || // Mc BATAK VOWEL SIGN E\r\n\t\t(0x1BEA <= code && code <= 0x1BEC) || // Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O\r\n\t\t0x1BEE == code || // Mc BATAK VOWEL SIGN U\r\n\t\t(0x1BF2 <= code && code <= 0x1BF3) || // Mc [2] BATAK PANGOLAT..BATAK PANONGONAN\r\n\t\t(0x1C24 <= code && code <= 0x1C2B) || // Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU\r\n\t\t(0x1C34 <= code && code <= 0x1C35) || // Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG\r\n\t\t0x1CE1 == code || // Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA\r\n\t\t(0x1CF2 <= code && code <= 0x1CF3) || // Mc [2] VEDIC SIGN ARDHAVISARGA..VEDIC SIGN ROTATED ARDHAVISARGA\r\n\t\t0x1CF7 == code || // Mc VEDIC SIGN ATIKRAMA\r\n\t\t(0xA823 <= code && code <= 0xA824) || // Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I\r\n\t\t0xA827 == code || // Mc SYLOTI NAGRI VOWEL SIGN OO\r\n\t\t(0xA880 <= code && code <= 0xA881) || // Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA\r\n\t\t(0xA8B4 <= code && code <= 0xA8C3) || // Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU\r\n\t\t(0xA952 <= code && code <= 0xA953) || // Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA\r\n\t\t0xA983 == code || // Mc JAVANESE SIGN WIGNYAN\r\n\t\t(0xA9B4 <= code && code <= 0xA9B5) || // Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG\r\n\t\t(0xA9BA <= code && code <= 0xA9BB) || // Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE\r\n\t\t(0xA9BD <= code && code <= 0xA9C0) || // Mc [4] JAVANESE CONSONANT SIGN KERET..JAVANESE PANGKON\r\n\t\t(0xAA2F <= code && code <= 0xAA30) || // Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI\r\n\t\t(0xAA33 <= code && code <= 0xAA34) || // Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA\r\n\t\t0xAA4D == code || // Mc CHAM CONSONANT SIGN FINAL H\r\n\t\t0xAAEB == code || // Mc MEETEI MAYEK VOWEL SIGN II\r\n\t\t(0xAAEE <= code && code <= 0xAAEF) || // Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU\r\n\t\t0xAAF5 == code || // Mc MEETEI MAYEK VOWEL SIGN VISARGA\r\n\t\t(0xABE3 <= code && code <= 0xABE4) || // Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP\r\n\t\t(0xABE6 <= code && code <= 0xABE7) || // Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP\r\n\t\t(0xABE9 <= code && code <= 0xABEA) || // Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG\r\n\t\t0xABEC == code || // Mc MEETEI MAYEK LUM IYEK\r\n\t\t0x11000 == code || // Mc BRAHMI SIGN CANDRABINDU\r\n\t\t0x11002 == code || // Mc BRAHMI SIGN VISARGA\r\n\t\t0x11082 == code || // Mc KAITHI SIGN VISARGA\r\n\t\t(0x110B0 <= code && code <= 0x110B2) || // Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II\r\n\t\t(0x110B7 <= code && code <= 0x110B8) || // Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU\r\n\t\t0x1112C == code || // Mc CHAKMA VOWEL SIGN E\r\n\t\t0x11182 == code || // Mc SHARADA SIGN VISARGA\r\n\t\t(0x111B3 <= code && code <= 0x111B5) || // Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II\r\n\t\t(0x111BF <= code && code <= 0x111C0) || // Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA\r\n\t\t(0x1122C <= code && code <= 0x1122E) || // Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II\r\n\t\t(0x11232 <= code && code <= 0x11233) || // Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU\r\n\t\t0x11235 == code || // Mc KHOJKI SIGN VIRAMA\r\n\t\t(0x112E0 <= code && code <= 0x112E2) || // Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II\r\n\t\t(0x11302 <= code && code <= 0x11303) || // Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA\r\n\t\t0x1133F == code || // Mc GRANTHA VOWEL SIGN I\r\n\t\t(0x11341 <= code && code <= 0x11344) || // Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR\r\n\t\t(0x11347 <= code && code <= 0x11348) || // Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI\r\n\t\t(0x1134B <= code && code <= 0x1134D) || // Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA\r\n\t\t(0x11362 <= code && code <= 0x11363) || // Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL\r\n\t\t(0x11435 <= code && code <= 0x11437) || // Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II\r\n\t\t(0x11440 <= code && code <= 0x11441) || // Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU\r\n\t\t0x11445 == code || // Mc NEWA SIGN VISARGA\r\n\t\t(0x114B1 <= code && code <= 0x114B2) || // Mc [2] TIRHUTA VOWEL SIGN I..TIRHUTA VOWEL SIGN II\r\n\t\t0x114B9 == code || // Mc TIRHUTA VOWEL SIGN E\r\n\t\t(0x114BB <= code && code <= 0x114BC) || // Mc [2] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN O\r\n\t\t0x114BE == code || // Mc TIRHUTA VOWEL SIGN AU\r\n\t\t0x114C1 == code || // Mc TIRHUTA SIGN VISARGA\r\n\t\t(0x115B0 <= code && code <= 0x115B1) || // Mc [2] SIDDHAM VOWEL SIGN I..SIDDHAM VOWEL SIGN II\r\n\t\t(0x115B8 <= code && code <= 0x115BB) || // Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU\r\n\t\t0x115BE == code || // Mc SIDDHAM SIGN VISARGA\r\n\t\t(0x11630 <= code && code <= 0x11632) || // Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II\r\n\t\t(0x1163B <= code && code <= 0x1163C) || // Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU\r\n\t\t0x1163E == code || // Mc MODI SIGN VISARGA\r\n\t\t0x116AC == code || // Mc TAKRI SIGN VISARGA\r\n\t\t(0x116AE <= code && code <= 0x116AF) || // Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II\r\n\t\t0x116B6 == code || // Mc TAKRI SIGN VIRAMA\r\n\t\t(0x11720 <= code && code <= 0x11721) || // Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA\r\n\t\t0x11726 == code || // Mc AHOM VOWEL SIGN E\r\n\t\t(0x11A07 <= code && code <= 0x11A08) || // Mc [2] ZANABAZAR SQUARE VOWEL SIGN AI..ZANABAZAR SQUARE VOWEL SIGN AU\r\n\t\t0x11A39 == code || // Mc ZANABAZAR SQUARE SIGN VISARGA\r\n\t\t(0x11A57 <= code && code <= 0x11A58) || // Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU\r\n\t\t0x11A97 == code || // Mc SOYOMBO SIGN VISARGA\r\n\t\t0x11C2F == code || // Mc BHAIKSUKI VOWEL SIGN AA\r\n\t\t0x11C3E == code || // Mc BHAIKSUKI SIGN VISARGA\r\n\t\t0x11CA9 == code || // Mc MARCHEN SUBJOINED LETTER YA\r\n\t\t0x11CB1 == code || // Mc MARCHEN VOWEL SIGN I\r\n\t\t0x11CB4 == code || // Mc MARCHEN VOWEL SIGN O\r\n\t\t(0x16F51 <= code && code <= 0x16F7E) || // Mc [46] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN NG\r\n\t\t0x1D166 == code || // Mc MUSICAL SYMBOL COMBINING SPRECHGESANG STEM\r\n\t\t0x1D16D == code // Mc MUSICAL SYMBOL COMBINING AUGMENTATION DOT\r\n\t\t){\r\n\t\t\treturn SpacingMark;\r\n\t\t}\r\n\r\n\r\n\t\tif(\r\n\t\t(0x1100 <= code && code <= 0x115F) || // Lo [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER\r\n\t\t(0xA960 <= code && code <= 0xA97C) // Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH\r\n\t\t){\r\n\t\t\treturn L;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t(0x1160 <= code && code <= 0x11A7) || // Lo [72] HANGUL JUNGSEONG FILLER..HANGUL JUNGSEONG O-YAE\r\n\t\t(0xD7B0 <= code && code <= 0xD7C6) // Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E\r\n\t\t){\r\n\t\t\treturn V;\r\n\t\t}\r\n\r\n\r\n\t\tif(\r\n\t\t(0x11A8 <= code && code <= 0x11FF) || // Lo [88] HANGUL JONGSEONG KIYEOK..HANGUL JONGSEONG SSANGNIEUN\r\n\t\t(0xD7CB <= code && code <= 0xD7FB) // Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH\r\n\t\t){\r\n\t\t\treturn T;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t0xAC00 == code || // Lo HANGUL SYLLABLE GA\r\n\t\t0xAC1C == code || // Lo HANGUL SYLLABLE GAE\r\n\t\t0xAC38 == code || // Lo HANGUL SYLLABLE GYA\r\n\t\t0xAC54 == code || // Lo HANGUL SYLLABLE GYAE\r\n\t\t0xAC70 == code || // Lo HANGUL SYLLABLE GEO\r\n\t\t0xAC8C == code || // Lo HANGUL SYLLABLE GE\r\n\t\t0xACA8 == code || // Lo HANGUL SYLLABLE GYEO\r\n\t\t0xACC4 == code || // Lo HANGUL SYLLABLE GYE\r\n\t\t0xACE0 == code || // Lo HANGUL SYLLABLE GO\r\n\t\t0xACFC == code || // Lo HANGUL SYLLABLE GWA\r\n\t\t0xAD18 == code || // Lo HANGUL SYLLABLE GWAE\r\n\t\t0xAD34 == code || // Lo HANGUL SYLLABLE GOE\r\n\t\t0xAD50 == code || // Lo HANGUL SYLLABLE GYO\r\n\t\t0xAD6C == code || // Lo HANGUL SYLLABLE GU\r\n\t\t0xAD88 == code || // Lo HANGUL SYLLABLE GWEO\r\n\t\t0xADA4 == code || // Lo HANGUL SYLLABLE GWE\r\n\t\t0xADC0 == code || // Lo HANGUL SYLLABLE GWI\r\n\t\t0xADDC == code || // Lo HANGUL SYLLABLE GYU\r\n\t\t0xADF8 == code || // Lo HANGUL SYLLABLE GEU\r\n\t\t0xAE14 == code || // Lo HANGUL SYLLABLE GYI\r\n\t\t0xAE30 == code || // Lo HANGUL SYLLABLE GI\r\n\t\t0xAE4C == code || // Lo HANGUL SYLLABLE GGA\r\n\t\t0xAE68 == code || // Lo HANGUL SYLLABLE GGAE\r\n\t\t0xAE84 == code || // Lo HANGUL SYLLABLE GGYA\r\n\t\t0xAEA0 == code || // Lo HANGUL SYLLABLE GGYAE\r\n\t\t0xAEBC == code || // Lo HANGUL SYLLABLE GGEO\r\n\t\t0xAED8 == code || // Lo HANGUL SYLLABLE GGE\r\n\t\t0xAEF4 == code || // Lo HANGUL SYLLABLE GGYEO\r\n\t\t0xAF10 == code || // Lo HANGUL SYLLABLE GGYE\r\n\t\t0xAF2C == code || // Lo HANGUL SYLLABLE GGO\r\n\t\t0xAF48 == code || // Lo HANGUL SYLLABLE GGWA\r\n\t\t0xAF64 == code || // Lo HANGUL SYLLABLE GGWAE\r\n\t\t0xAF80 == code || // Lo HANGUL SYLLABLE GGOE\r\n\t\t0xAF9C == code || // Lo HANGUL SYLLABLE GGYO\r\n\t\t0xAFB8 == code || // Lo HANGUL SYLLABLE GGU\r\n\t\t0xAFD4 == code || // Lo HANGUL SYLLABLE GGWEO\r\n\t\t0xAFF0 == code || // Lo HANGUL SYLLABLE GGWE\r\n\t\t0xB00C == code || // Lo HANGUL SYLLABLE GGWI\r\n\t\t0xB028 == code || // Lo HANGUL SYLLABLE GGYU\r\n\t\t0xB044 == code || // Lo HANGUL SYLLABLE GGEU\r\n\t\t0xB060 == code || // Lo HANGUL SYLLABLE GGYI\r\n\t\t0xB07C == code || // Lo HANGUL SYLLABLE GGI\r\n\t\t0xB098 == code || // Lo HANGUL SYLLABLE NA\r\n\t\t0xB0B4 == code || // Lo HANGUL SYLLABLE NAE\r\n\t\t0xB0D0 == code || // Lo HANGUL SYLLABLE NYA\r\n\t\t0xB0EC == code || // Lo HANGUL SYLLABLE NYAE\r\n\t\t0xB108 == code || // Lo HANGUL SYLLABLE NEO\r\n\t\t0xB124 == code || // Lo HANGUL SYLLABLE NE\r\n\t\t0xB140 == code || // Lo HANGUL SYLLABLE NYEO\r\n\t\t0xB15C == code || // Lo HANGUL SYLLABLE NYE\r\n\t\t0xB178 == code || // Lo HANGUL SYLLABLE NO\r\n\t\t0xB194 == code || // Lo HANGUL SYLLABLE NWA\r\n\t\t0xB1B0 == code || // Lo HANGUL SYLLABLE NWAE\r\n\t\t0xB1CC == code || // Lo HANGUL SYLLABLE NOE\r\n\t\t0xB1E8 == code || // Lo HANGUL SYLLABLE NYO\r\n\t\t0xB204 == code || // Lo HANGUL SYLLABLE NU\r\n\t\t0xB220 == code || // Lo HANGUL SYLLABLE NWEO\r\n\t\t0xB23C == code || // Lo HANGUL SYLLABLE NWE\r\n\t\t0xB258 == code || // Lo HANGUL SYLLABLE NWI\r\n\t\t0xB274 == code || // Lo HANGUL SYLLABLE NYU\r\n\t\t0xB290 == code || // Lo HANGUL SYLLABLE NEU\r\n\t\t0xB2AC == code || // Lo HANGUL SYLLABLE NYI\r\n\t\t0xB2C8 == code || // Lo HANGUL SYLLABLE NI\r\n\t\t0xB2E4 == code || // Lo HANGUL SYLLABLE DA\r\n\t\t0xB300 == code || // Lo HANGUL SYLLABLE DAE\r\n\t\t0xB31C == code || // Lo HANGUL SYLLABLE DYA\r\n\t\t0xB338 == code || // Lo HANGUL SYLLABLE DYAE\r\n\t\t0xB354 == code || // Lo HANGUL SYLLABLE DEO\r\n\t\t0xB370 == code || // Lo HANGUL SYLLABLE DE\r\n\t\t0xB38C == code || // Lo HANGUL SYLLABLE DYEO\r\n\t\t0xB3A8 == code || // Lo HANGUL SYLLABLE DYE\r\n\t\t0xB3C4 == code || // Lo HANGUL SYLLABLE DO\r\n\t\t0xB3E0 == code || // Lo HANGUL SYLLABLE DWA\r\n\t\t0xB3FC == code || // Lo HANGUL SYLLABLE DWAE\r\n\t\t0xB418 == code || // Lo HANGUL SYLLABLE DOE\r\n\t\t0xB434 == code || // Lo HANGUL SYLLABLE DYO\r\n\t\t0xB450 == code || // Lo HANGUL SYLLABLE DU\r\n\t\t0xB46C == code || // Lo HANGUL SYLLABLE DWEO\r\n\t\t0xB488 == code || // Lo HANGUL SYLLABLE DWE\r\n\t\t0xB4A4 == code || // Lo HANGUL SYLLABLE DWI\r\n\t\t0xB4C0 == code || // Lo HANGUL SYLLABLE DYU\r\n\t\t0xB4DC == code || // Lo HANGUL SYLLABLE DEU\r\n\t\t0xB4F8 == code || // Lo HANGUL SYLLABLE DYI\r\n\t\t0xB514 == code || // Lo HANGUL SYLLABLE DI\r\n\t\t0xB530 == code || // Lo HANGUL SYLLABLE DDA\r\n\t\t0xB54C == code || // Lo HANGUL SYLLABLE DDAE\r\n\t\t0xB568 == code || // Lo HANGUL SYLLABLE DDYA\r\n\t\t0xB584 == code || // Lo HANGUL SYLLABLE DDYAE\r\n\t\t0xB5A0 == code || // Lo HANGUL SYLLABLE DDEO\r\n\t\t0xB5BC == code || // Lo HANGUL SYLLABLE DDE\r\n\t\t0xB5D8 == code || // Lo HANGUL SYLLABLE DDYEO\r\n\t\t0xB5F4 == code || // Lo HANGUL SYLLABLE DDYE\r\n\t\t0xB610 == code || // Lo HANGUL SYLLABLE DDO\r\n\t\t0xB62C == code || // Lo HANGUL SYLLABLE DDWA\r\n\t\t0xB648 == code || // Lo HANGUL SYLLABLE DDWAE\r\n\t\t0xB664 == code || // Lo HANGUL SYLLABLE DDOE\r\n\t\t0xB680 == code || // Lo HANGUL SYLLABLE DDYO\r\n\t\t0xB69C == code || // Lo HANGUL SYLLABLE DDU\r\n\t\t0xB6B8 == code || // Lo HANGUL SYLLABLE DDWEO\r\n\t\t0xB6D4 == code || // Lo HANGUL SYLLABLE DDWE\r\n\t\t0xB6F0 == code || // Lo HANGUL SYLLABLE DDWI\r\n\t\t0xB70C == code || // Lo HANGUL SYLLABLE DDYU\r\n\t\t0xB728 == code || // Lo HANGUL SYLLABLE DDEU\r\n\t\t0xB744 == code || // Lo HANGUL SYLLABLE DDYI\r\n\t\t0xB760 == code || // Lo HANGUL SYLLABLE DDI\r\n\t\t0xB77C == code || // Lo HANGUL SYLLABLE RA\r\n\t\t0xB798 == code || // Lo HANGUL SYLLABLE RAE\r\n\t\t0xB7B4 == code || // Lo HANGUL SYLLABLE RYA\r\n\t\t0xB7D0 == code || // Lo HANGUL SYLLABLE RYAE\r\n\t\t0xB7EC == code || // Lo HANGUL SYLLABLE REO\r\n\t\t0xB808 == code || // Lo HANGUL SYLLABLE RE\r\n\t\t0xB824 == code || // Lo HANGUL SYLLABLE RYEO\r\n\t\t0xB840 == code || // Lo HANGUL SYLLABLE RYE\r\n\t\t0xB85C == code || // Lo HANGUL SYLLABLE RO\r\n\t\t0xB878 == code || // Lo HANGUL SYLLABLE RWA\r\n\t\t0xB894 == code || // Lo HANGUL SYLLABLE RWAE\r\n\t\t0xB8B0 == code || // Lo HANGUL SYLLABLE ROE\r\n\t\t0xB8CC == code || // Lo HANGUL SYLLABLE RYO\r\n\t\t0xB8E8 == code || // Lo HANGUL SYLLABLE RU\r\n\t\t0xB904 == code || // Lo HANGUL SYLLABLE RWEO\r\n\t\t0xB920 == code || // Lo HANGUL SYLLABLE RWE\r\n\t\t0xB93C == code || // Lo HANGUL SYLLABLE RWI\r\n\t\t0xB958 == code || // Lo HANGUL SYLLABLE RYU\r\n\t\t0xB974 == code || // Lo HANGUL SYLLABLE REU\r\n\t\t0xB990 == code || // Lo HANGUL SYLLABLE RYI\r\n\t\t0xB9AC == code || // Lo HANGUL SYLLABLE RI\r\n\t\t0xB9C8 == code || // Lo HANGUL SYLLABLE MA\r\n\t\t0xB9E4 == code || // Lo HANGUL SYLLABLE MAE\r\n\t\t0xBA00 == code || // Lo HANGUL SYLLABLE MYA\r\n\t\t0xBA1C == code || // Lo HANGUL SYLLABLE MYAE\r\n\t\t0xBA38 == code || // Lo HANGUL SYLLABLE MEO\r\n\t\t0xBA54 == code || // Lo HANGUL SYLLABLE ME\r\n\t\t0xBA70 == code || // Lo HANGUL SYLLABLE MYEO\r\n\t\t0xBA8C == code || // Lo HANGUL SYLLABLE MYE\r\n\t\t0xBAA8 == code || // Lo HANGUL SYLLABLE MO\r\n\t\t0xBAC4 == code || // Lo HANGUL SYLLABLE MWA\r\n\t\t0xBAE0 == code || // Lo HANGUL SYLLABLE MWAE\r\n\t\t0xBAFC == code || // Lo HANGUL SYLLABLE MOE\r\n\t\t0xBB18 == code || // Lo HANGUL SYLLABLE MYO\r\n\t\t0xBB34 == code || // Lo HANGUL SYLLABLE MU\r\n\t\t0xBB50 == code || // Lo HANGUL SYLLABLE MWEO\r\n\t\t0xBB6C == code || // Lo HANGUL SYLLABLE MWE\r\n\t\t0xBB88 == code || // Lo HANGUL SYLLABLE MWI\r\n\t\t0xBBA4 == code || // Lo HANGUL SYLLABLE MYU\r\n\t\t0xBBC0 == code || // Lo HANGUL SYLLABLE MEU\r\n\t\t0xBBDC == code || // Lo HANGUL SYLLABLE MYI\r\n\t\t0xBBF8 == code || // Lo HANGUL SYLLABLE MI\r\n\t\t0xBC14 == code || // Lo HANGUL SYLLABLE BA\r\n\t\t0xBC30 == code || // Lo HANGUL SYLLABLE BAE\r\n\t\t0xBC4C == code || // Lo HANGUL SYLLABLE BYA\r\n\t\t0xBC68 == code || // Lo HANGUL SYLLABLE BYAE\r\n\t\t0xBC84 == code || // Lo HANGUL SYLLABLE BEO\r\n\t\t0xBCA0 == code || // Lo HANGUL SYLLABLE BE\r\n\t\t0xBCBC == code || // Lo HANGUL SYLLABLE BYEO\r\n\t\t0xBCD8 == code || // Lo HANGUL SYLLABLE BYE\r\n\t\t0xBCF4 == code || // Lo HANGUL SYLLABLE BO\r\n\t\t0xBD10 == code || // Lo HANGUL SYLLABLE BWA\r\n\t\t0xBD2C == code || // Lo HANGUL SYLLABLE BWAE\r\n\t\t0xBD48 == code || // Lo HANGUL SYLLABLE BOE\r\n\t\t0xBD64 == code || // Lo HANGUL SYLLABLE BYO\r\n\t\t0xBD80 == code || // Lo HANGUL SYLLABLE BU\r\n\t\t0xBD9C == code || // Lo HANGUL SYLLABLE BWEO\r\n\t\t0xBDB8 == code || // Lo HANGUL SYLLABLE BWE\r\n\t\t0xBDD4 == code || // Lo HANGUL SYLLABLE BWI\r\n\t\t0xBDF0 == code || // Lo HANGUL SYLLABLE BYU\r\n\t\t0xBE0C == code || // Lo HANGUL SYLLABLE BEU\r\n\t\t0xBE28 == code || // Lo HANGUL SYLLABLE BYI\r\n\t\t0xBE44 == code || // Lo HANGUL SYLLABLE BI\r\n\t\t0xBE60 == code || // Lo HANGUL SYLLABLE BBA\r\n\t\t0xBE7C == code || // Lo HANGUL SYLLABLE BBAE\r\n\t\t0xBE98 == code || // Lo HANGUL SYLLABLE BBYA\r\n\t\t0xBEB4 == code || // Lo HANGUL SYLLABLE BBYAE\r\n\t\t0xBED0 == code || // Lo HANGUL SYLLABLE BBEO\r\n\t\t0xBEEC == code || // Lo HANGUL SYLLABLE BBE\r\n\t\t0xBF08 == code || // Lo HANGUL SYLLABLE BBYEO\r\n\t\t0xBF24 == code || // Lo HANGUL SYLLABLE BBYE\r\n\t\t0xBF40 == code || // Lo HANGUL SYLLABLE BBO\r\n\t\t0xBF5C == code || // Lo HANGUL SYLLABLE BBWA\r\n\t\t0xBF78 == code || // Lo HANGUL SYLLABLE BBWAE\r\n\t\t0xBF94 == code || // Lo HANGUL SYLLABLE BBOE\r\n\t\t0xBFB0 == code || // Lo HANGUL SYLLABLE BBYO\r\n\t\t0xBFCC == code || // Lo HANGUL SYLLABLE BBU\r\n\t\t0xBFE8 == code || // Lo HANGUL SYLLABLE BBWEO\r\n\t\t0xC004 == code || // Lo HANGUL SYLLABLE BBWE\r\n\t\t0xC020 == code || // Lo HANGUL SYLLABLE BBWI\r\n\t\t0xC03C == code || // Lo HANGUL SYLLABLE BBYU\r\n\t\t0xC058 == code || // Lo HANGUL SYLLABLE BBEU\r\n\t\t0xC074 == code || // Lo HANGUL SYLLABLE BBYI\r\n\t\t0xC090 == code || // Lo HANGUL SYLLABLE BBI\r\n\t\t0xC0AC == code || // Lo HANGUL SYLLABLE SA\r\n\t\t0xC0C8 == code || // Lo HANGUL SYLLABLE SAE\r\n\t\t0xC0E4 == code || // Lo HANGUL SYLLABLE SYA\r\n\t\t0xC100 == code || // Lo HANGUL SYLLABLE SYAE\r\n\t\t0xC11C == code || // Lo HANGUL SYLLABLE SEO\r\n\t\t0xC138 == code || // Lo HANGUL SYLLABLE SE\r\n\t\t0xC154 == code || // Lo HANGUL SYLLABLE SYEO\r\n\t\t0xC170 == code || // Lo HANGUL SYLLABLE SYE\r\n\t\t0xC18C == code || // Lo HANGUL SYLLABLE SO\r\n\t\t0xC1A8 == code || // Lo HANGUL SYLLABLE SWA\r\n\t\t0xC1C4 == code || // Lo HANGUL SYLLABLE SWAE\r\n\t\t0xC1E0 == code || // Lo HANGUL SYLLABLE SOE\r\n\t\t0xC1FC == code || // Lo HANGUL SYLLABLE SYO\r\n\t\t0xC218 == code || // Lo HANGUL SYLLABLE SU\r\n\t\t0xC234 == code || // Lo HANGUL SYLLABLE SWEO\r\n\t\t0xC250 == code || // Lo HANGUL SYLLABLE SWE\r\n\t\t0xC26C == code || // Lo HANGUL SYLLABLE SWI\r\n\t\t0xC288 == code || // Lo HANGUL SYLLABLE SYU\r\n\t\t0xC2A4 == code || // Lo HANGUL SYLLABLE SEU\r\n\t\t0xC2C0 == code || // Lo HANGUL SYLLABLE SYI\r\n\t\t0xC2DC == code || // Lo HANGUL SYLLABLE SI\r\n\t\t0xC2F8 == code || // Lo HANGUL SYLLABLE SSA\r\n\t\t0xC314 == code || // Lo HANGUL SYLLABLE SSAE\r\n\t\t0xC330 == code || // Lo HANGUL SYLLABLE SSYA\r\n\t\t0xC34C == code || // Lo HANGUL SYLLABLE SSYAE\r\n\t\t0xC368 == code || // Lo HANGUL SYLLABLE SSEO\r\n\t\t0xC384 == code || // Lo HANGUL SYLLABLE SSE\r\n\t\t0xC3A0 == code || // Lo HANGUL SYLLABLE SSYEO\r\n\t\t0xC3BC == code || // Lo HANGUL SYLLABLE SSYE\r\n\t\t0xC3D8 == code || // Lo HANGUL SYLLABLE SSO\r\n\t\t0xC3F4 == code || // Lo HANGUL SYLLABLE SSWA\r\n\t\t0xC410 == code || // Lo HANGUL SYLLABLE SSWAE\r\n\t\t0xC42C == code || // Lo HANGUL SYLLABLE SSOE\r\n\t\t0xC448 == code || // Lo HANGUL SYLLABLE SSYO\r\n\t\t0xC464 == code || // Lo HANGUL SYLLABLE SSU\r\n\t\t0xC480 == code || // Lo HANGUL SYLLABLE SSWEO\r\n\t\t0xC49C == code || // Lo HANGUL SYLLABLE SSWE\r\n\t\t0xC4B8 == code || // Lo HANGUL SYLLABLE SSWI\r\n\t\t0xC4D4 == code || // Lo HANGUL SYLLABLE SSYU\r\n\t\t0xC4F0 == code || // Lo HANGUL SYLLABLE SSEU\r\n\t\t0xC50C == code || // Lo HANGUL SYLLABLE SSYI\r\n\t\t0xC528 == code || // Lo HANGUL SYLLABLE SSI\r\n\t\t0xC544 == code || // Lo HANGUL SYLLABLE A\r\n\t\t0xC560 == code || // Lo HANGUL SYLLABLE AE\r\n\t\t0xC57C == code || // Lo HANGUL SYLLABLE YA\r\n\t\t0xC598 == code || // Lo HANGUL SYLLABLE YAE\r\n\t\t0xC5B4 == code || // Lo HANGUL SYLLABLE EO\r\n\t\t0xC5D0 == code || // Lo HANGUL SYLLABLE E\r\n\t\t0xC5EC == code || // Lo HANGUL SYLLABLE YEO\r\n\t\t0xC608 == code || // Lo HANGUL SYLLABLE YE\r\n\t\t0xC624 == code || // Lo HANGUL SYLLABLE O\r\n\t\t0xC640 == code || // Lo HANGUL SYLLABLE WA\r\n\t\t0xC65C == code || // Lo HANGUL SYLLABLE WAE\r\n\t\t0xC678 == code || // Lo HANGUL SYLLABLE OE\r\n\t\t0xC694 == code || // Lo HANGUL SYLLABLE YO\r\n\t\t0xC6B0 == code || // Lo HANGUL SYLLABLE U\r\n\t\t0xC6CC == code || // Lo HANGUL SYLLABLE WEO\r\n\t\t0xC6E8 == code || // Lo HANGUL SYLLABLE WE\r\n\t\t0xC704 == code || // Lo HANGUL SYLLABLE WI\r\n\t\t0xC720 == code || // Lo HANGUL SYLLABLE YU\r\n\t\t0xC73C == code || // Lo HANGUL SYLLABLE EU\r\n\t\t0xC758 == code || // Lo HANGUL SYLLABLE YI\r\n\t\t0xC774 == code || // Lo HANGUL SYLLABLE I\r\n\t\t0xC790 == code || // Lo HANGUL SYLLABLE JA\r\n\t\t0xC7AC == code || // Lo HANGUL SYLLABLE JAE\r\n\t\t0xC7C8 == code || // Lo HANGUL SYLLABLE JYA\r\n\t\t0xC7E4 == code || // Lo HANGUL SYLLABLE JYAE\r\n\t\t0xC800 == code || // Lo HANGUL SYLLABLE JEO\r\n\t\t0xC81C == code || // Lo HANGUL SYLLABLE JE\r\n\t\t0xC838 == code || // Lo HANGUL SYLLABLE JYEO\r\n\t\t0xC854 == code || // Lo HANGUL SYLLABLE JYE\r\n\t\t0xC870 == code || // Lo HANGUL SYLLABLE JO\r\n\t\t0xC88C == code || // Lo HANGUL SYLLABLE JWA\r\n\t\t0xC8A8 == code || // Lo HANGUL SYLLABLE JWAE\r\n\t\t0xC8C4 == code || // Lo HANGUL SYLLABLE JOE\r\n\t\t0xC8E0 == code || // Lo HANGUL SYLLABLE JYO\r\n\t\t0xC8FC == code || // Lo HANGUL SYLLABLE JU\r\n\t\t0xC918 == code || // Lo HANGUL SYLLABLE JWEO\r\n\t\t0xC934 == code || // Lo HANGUL SYLLABLE JWE\r\n\t\t0xC950 == code || // Lo HANGUL SYLLABLE JWI\r\n\t\t0xC96C == code || // Lo HANGUL SYLLABLE JYU\r\n\t\t0xC988 == code || // Lo HANGUL SYLLABLE JEU\r\n\t\t0xC9A4 == code || // Lo HANGUL SYLLABLE JYI\r\n\t\t0xC9C0 == code || // Lo HANGUL SYLLABLE JI\r\n\t\t0xC9DC == code || // Lo HANGUL SYLLABLE JJA\r\n\t\t0xC9F8 == code || // Lo HANGUL SYLLABLE JJAE\r\n\t\t0xCA14 == code || // Lo HANGUL SYLLABLE JJYA\r\n\t\t0xCA30 == code || // Lo HANGUL SYLLABLE JJYAE\r\n\t\t0xCA4C == code || // Lo HANGUL SYLLABLE JJEO\r\n\t\t0xCA68 == code || // Lo HANGUL SYLLABLE JJE\r\n\t\t0xCA84 == code || // Lo HANGUL SYLLABLE JJYEO\r\n\t\t0xCAA0 == code || // Lo HANGUL SYLLABLE JJYE\r\n\t\t0xCABC == code || // Lo HANGUL SYLLABLE JJO\r\n\t\t0xCAD8 == code || // Lo HANGUL SYLLABLE JJWA\r\n\t\t0xCAF4 == code || // Lo HANGUL SYLLABLE JJWAE\r\n\t\t0xCB10 == code || // Lo HANGUL SYLLABLE JJOE\r\n\t\t0xCB2C == code || // Lo HANGUL SYLLABLE JJYO\r\n\t\t0xCB48 == code || // Lo HANGUL SYLLABLE JJU\r\n\t\t0xCB64 == code || // Lo HANGUL SYLLABLE JJWEO\r\n\t\t0xCB80 == code || // Lo HANGUL SYLLABLE JJWE\r\n\t\t0xCB9C == code || // Lo HANGUL SYLLABLE JJWI\r\n\t\t0xCBB8 == code || // Lo HANGUL SYLLABLE JJYU\r\n\t\t0xCBD4 == code || // Lo HANGUL SYLLABLE JJEU\r\n\t\t0xCBF0 == code || // Lo HANGUL SYLLABLE JJYI\r\n\t\t0xCC0C == code || // Lo HANGUL SYLLABLE JJI\r\n\t\t0xCC28 == code || // Lo HANGUL SYLLABLE CA\r\n\t\t0xCC44 == code || // Lo HANGUL SYLLABLE CAE\r\n\t\t0xCC60 == code || // Lo HANGUL SYLLABLE CYA\r\n\t\t0xCC7C == code || // Lo HANGUL SYLLABLE CYAE\r\n\t\t0xCC98 == code || // Lo HANGUL SYLLABLE CEO\r\n\t\t0xCCB4 == code || // Lo HANGUL SYLLABLE CE\r\n\t\t0xCCD0 == code || // Lo HANGUL SYLLABLE CYEO\r\n\t\t0xCCEC == code || // Lo HANGUL SYLLABLE CYE\r\n\t\t0xCD08 == code || // Lo HANGUL SYLLABLE CO\r\n\t\t0xCD24 == code || // Lo HANGUL SYLLABLE CWA\r\n\t\t0xCD40 == code || // Lo HANGUL SYLLABLE CWAE\r\n\t\t0xCD5C == code || // Lo HANGUL SYLLABLE COE\r\n\t\t0xCD78 == code || // Lo HANGUL SYLLABLE CYO\r\n\t\t0xCD94 == code || // Lo HANGUL SYLLABLE CU\r\n\t\t0xCDB0 == code || // Lo HANGUL SYLLABLE CWEO\r\n\t\t0xCDCC == code || // Lo HANGUL SYLLABLE CWE\r\n\t\t0xCDE8 == code || // Lo HANGUL SYLLABLE CWI\r\n\t\t0xCE04 == code || // Lo HANGUL SYLLABLE CYU\r\n\t\t0xCE20 == code || // Lo HANGUL SYLLABLE CEU\r\n\t\t0xCE3C == code || // Lo HANGUL SYLLABLE CYI\r\n\t\t0xCE58 == code || // Lo HANGUL SYLLABLE CI\r\n\t\t0xCE74 == code || // Lo HANGUL SYLLABLE KA\r\n\t\t0xCE90 == code || // Lo HANGUL SYLLABLE KAE\r\n\t\t0xCEAC == code || // Lo HANGUL SYLLABLE KYA\r\n\t\t0xCEC8 == code || // Lo HANGUL SYLLABLE KYAE\r\n\t\t0xCEE4 == code || // Lo HANGUL SYLLABLE KEO\r\n\t\t0xCF00 == code || // Lo HANGUL SYLLABLE KE\r\n\t\t0xCF1C == code || // Lo HANGUL SYLLABLE KYEO\r\n\t\t0xCF38 == code || // Lo HANGUL SYLLABLE KYE\r\n\t\t0xCF54 == code || // Lo HANGUL SYLLABLE KO\r\n\t\t0xCF70 == code || // Lo HANGUL SYLLABLE KWA\r\n\t\t0xCF8C == code || // Lo HANGUL SYLLABLE KWAE\r\n\t\t0xCFA8 == code || // Lo HANGUL SYLLABLE KOE\r\n\t\t0xCFC4 == code || // Lo HANGUL SYLLABLE KYO\r\n\t\t0xCFE0 == code || // Lo HANGUL SYLLABLE KU\r\n\t\t0xCFFC == code || // Lo HANGUL SYLLABLE KWEO\r\n\t\t0xD018 == code || // Lo HANGUL SYLLABLE KWE\r\n\t\t0xD034 == code || // Lo HANGUL SYLLABLE KWI\r\n\t\t0xD050 == code || // Lo HANGUL SYLLABLE KYU\r\n\t\t0xD06C == code || // Lo HANGUL SYLLABLE KEU\r\n\t\t0xD088 == code || // Lo HANGUL SYLLABLE KYI\r\n\t\t0xD0A4 == code || // Lo HANGUL SYLLABLE KI\r\n\t\t0xD0C0 == code || // Lo HANGUL SYLLABLE TA\r\n\t\t0xD0DC == code || // Lo HANGUL SYLLABLE TAE\r\n\t\t0xD0F8 == code || // Lo HANGUL SYLLABLE TYA\r\n\t\t0xD114 == code || // Lo HANGUL SYLLABLE TYAE\r\n\t\t0xD130 == code || // Lo HANGUL SYLLABLE TEO\r\n\t\t0xD14C == code || // Lo HANGUL SYLLABLE TE\r\n\t\t0xD168 == code || // Lo HANGUL SYLLABLE TYEO\r\n\t\t0xD184 == code || // Lo HANGUL SYLLABLE TYE\r\n\t\t0xD1A0 == code || // Lo HANGUL SYLLABLE TO\r\n\t\t0xD1BC == code || // Lo HANGUL SYLLABLE TWA\r\n\t\t0xD1D8 == code || // Lo HANGUL SYLLABLE TWAE\r\n\t\t0xD1F4 == code || // Lo HANGUL SYLLABLE TOE\r\n\t\t0xD210 == code || // Lo HANGUL SYLLABLE TYO\r\n\t\t0xD22C == code || // Lo HANGUL SYLLABLE TU\r\n\t\t0xD248 == code || // Lo HANGUL SYLLABLE TWEO\r\n\t\t0xD264 == code || // Lo HANGUL SYLLABLE TWE\r\n\t\t0xD280 == code || // Lo HANGUL SYLLABLE TWI\r\n\t\t0xD29C == code || // Lo HANGUL SYLLABLE TYU\r\n\t\t0xD2B8 == code || // Lo HANGUL SYLLABLE TEU\r\n\t\t0xD2D4 == code || // Lo HANGUL SYLLABLE TYI\r\n\t\t0xD2F0 == code || // Lo HANGUL SYLLABLE TI\r\n\t\t0xD30C == code || // Lo HANGUL SYLLABLE PA\r\n\t\t0xD328 == code || // Lo HANGUL SYLLABLE PAE\r\n\t\t0xD344 == code || // Lo HANGUL SYLLABLE PYA\r\n\t\t0xD360 == code || // Lo HANGUL SYLLABLE PYAE\r\n\t\t0xD37C == code || // Lo HANGUL SYLLABLE PEO\r\n\t\t0xD398 == code || // Lo HANGUL SYLLABLE PE\r\n\t\t0xD3B4 == code || // Lo HANGUL SYLLABLE PYEO\r\n\t\t0xD3D0 == code || // Lo HANGUL SYLLABLE PYE\r\n\t\t0xD3EC == code || // Lo HANGUL SYLLABLE PO\r\n\t\t0xD408 == code || // Lo HANGUL SYLLABLE PWA\r\n\t\t0xD424 == code || // Lo HANGUL SYLLABLE PWAE\r\n\t\t0xD440 == code || // Lo HANGUL SYLLABLE POE\r\n\t\t0xD45C == code || // Lo HANGUL SYLLABLE PYO\r\n\t\t0xD478 == code || // Lo HANGUL SYLLABLE PU\r\n\t\t0xD494 == code || // Lo HANGUL SYLLABLE PWEO\r\n\t\t0xD4B0 == code || // Lo HANGUL SYLLABLE PWE\r\n\t\t0xD4CC == code || // Lo HANGUL SYLLABLE PWI\r\n\t\t0xD4E8 == code || // Lo HANGUL SYLLABLE PYU\r\n\t\t0xD504 == code || // Lo HANGUL SYLLABLE PEU\r\n\t\t0xD520 == code || // Lo HANGUL SYLLABLE PYI\r\n\t\t0xD53C == code || // Lo HANGUL SYLLABLE PI\r\n\t\t0xD558 == code || // Lo HANGUL SYLLABLE HA\r\n\t\t0xD574 == code || // Lo HANGUL SYLLABLE HAE\r\n\t\t0xD590 == code || // Lo HANGUL SYLLABLE HYA\r\n\t\t0xD5AC == code || // Lo HANGUL SYLLABLE HYAE\r\n\t\t0xD5C8 == code || // Lo HANGUL SYLLABLE HEO\r\n\t\t0xD5E4 == code || // Lo HANGUL SYLLABLE HE\r\n\t\t0xD600 == code || // Lo HANGUL SYLLABLE HYEO\r\n\t\t0xD61C == code || // Lo HANGUL SYLLABLE HYE\r\n\t\t0xD638 == code || // Lo HANGUL SYLLABLE HO\r\n\t\t0xD654 == code || // Lo HANGUL SYLLABLE HWA\r\n\t\t0xD670 == code || // Lo HANGUL SYLLABLE HWAE\r\n\t\t0xD68C == code || // Lo HANGUL SYLLABLE HOE\r\n\t\t0xD6A8 == code || // Lo HANGUL SYLLABLE HYO\r\n\t\t0xD6C4 == code || // Lo HANGUL SYLLABLE HU\r\n\t\t0xD6E0 == code || // Lo HANGUL SYLLABLE HWEO\r\n\t\t0xD6FC == code || // Lo HANGUL SYLLABLE HWE\r\n\t\t0xD718 == code || // Lo HANGUL SYLLABLE HWI\r\n\t\t0xD734 == code || // Lo HANGUL SYLLABLE HYU\r\n\t\t0xD750 == code || // Lo HANGUL SYLLABLE HEU\r\n\t\t0xD76C == code || // Lo HANGUL SYLLABLE HYI\r\n\t\t0xD788 == code // Lo HANGUL SYLLABLE HI\r\n\t\t){\r\n\t\t\treturn LV;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t(0xAC01 <= code && code <= 0xAC1B) || // Lo [27] HANGUL SYLLABLE GAG..HANGUL SYLLABLE GAH\r\n\t\t(0xAC1D <= code && code <= 0xAC37) || // Lo [27] HANGUL SYLLABLE GAEG..HANGUL SYLLABLE GAEH\r\n\t\t(0xAC39 <= code && code <= 0xAC53) || // Lo [27] HANGUL SYLLABLE GYAG..HANGUL SYLLABLE GYAH\r\n\t\t(0xAC55 <= code && code <= 0xAC6F) || // Lo [27] HANGUL SYLLABLE GYAEG..HANGUL SYLLABLE GYAEH\r\n\t\t(0xAC71 <= code && code <= 0xAC8B) || // Lo [27] HANGUL SYLLABLE GEOG..HANGUL SYLLABLE GEOH\r\n\t\t(0xAC8D <= code && code <= 0xACA7) || // Lo [27] HANGUL SYLLABLE GEG..HANGUL SYLLABLE GEH\r\n\t\t(0xACA9 <= code && code <= 0xACC3) || // Lo [27] HANGUL SYLLABLE GYEOG..HANGUL SYLLABLE GYEOH\r\n\t\t(0xACC5 <= code && code <= 0xACDF) || // Lo [27] HANGUL SYLLABLE GYEG..HANGUL SYLLABLE GYEH\r\n\t\t(0xACE1 <= code && code <= 0xACFB) || // Lo [27] HANGUL SYLLABLE GOG..HANGUL SYLLABLE GOH\r\n\t\t(0xACFD <= code && code <= 0xAD17) || // Lo [27] HANGUL SYLLABLE GWAG..HANGUL SYLLABLE GWAH\r\n\t\t(0xAD19 <= code && code <= 0xAD33) || // Lo [27] HANGUL SYLLABLE GWAEG..HANGUL SYLLABLE GWAEH\r\n\t\t(0xAD35 <= code && code <= 0xAD4F) || // Lo [27] HANGUL SYLLABLE GOEG..HANGUL SYLLABLE GOEH\r\n\t\t(0xAD51 <= code && code <= 0xAD6B) || // Lo [27] HANGUL SYLLABLE GYOG..HANGUL SYLLABLE GYOH\r\n\t\t(0xAD6D <= code && code <= 0xAD87) || // Lo [27] HANGUL SYLLABLE GUG..HANGUL SYLLABLE GUH\r\n\t\t(0xAD89 <= code && code <= 0xADA3) || // Lo [27] HANGUL SYLLABLE GWEOG..HANGUL SYLLABLE GWEOH\r\n\t\t(0xADA5 <= code && code <= 0xADBF) || // Lo [27] HANGUL SYLLABLE GWEG..HANGUL SYLLABLE GWEH\r\n\t\t(0xADC1 <= code && code <= 0xADDB) || // Lo [27] HANGUL SYLLABLE GWIG..HANGUL SYLLABLE GWIH\r\n\t\t(0xADDD <= code && code <= 0xADF7) || // Lo [27] HANGUL SYLLABLE GYUG..HANGUL SYLLABLE GYUH\r\n\t\t(0xADF9 <= code && code <= 0xAE13) || // Lo [27] HANGUL SYLLABLE GEUG..HANGUL SYLLABLE GEUH\r\n\t\t(0xAE15 <= code && code <= 0xAE2F) || // Lo [27] HANGUL SYLLABLE GYIG..HANGUL SYLLABLE GYIH\r\n\t\t(0xAE31 <= code && code <= 0xAE4B) || // Lo [27] HANGUL SYLLABLE GIG..HANGUL SYLLABLE GIH\r\n\t\t(0xAE4D <= code && code <= 0xAE67) || // Lo [27] HANGUL SYLLABLE GGAG..HANGUL SYLLABLE GGAH\r\n\t\t(0xAE69 <= code && code <= 0xAE83) || // Lo [27] HANGUL SYLLABLE GGAEG..HANGUL SYLLABLE GGAEH\r\n\t\t(0xAE85 <= code && code <= 0xAE9F) || // Lo [27] HANGUL SYLLABLE GGYAG..HANGUL SYLLABLE GGYAH\r\n\t\t(0xAEA1 <= code && code <= 0xAEBB) || // Lo [27] HANGUL SYLLABLE GGYAEG..HANGUL SYLLABLE GGYAEH\r\n\t\t(0xAEBD <= code && code <= 0xAED7) || // Lo [27] HANGUL SYLLABLE GGEOG..HANGUL SYLLABLE GGEOH\r\n\t\t(0xAED9 <= code && code <= 0xAEF3) || // Lo [27] HANGUL SYLLABLE GGEG..HANGUL SYLLABLE GGEH\r\n\t\t(0xAEF5 <= code && code <= 0xAF0F) || // Lo [27] HANGUL SYLLABLE GGYEOG..HANGUL SYLLABLE GGYEOH\r\n\t\t(0xAF11 <= code && code <= 0xAF2B) || // Lo [27] HANGUL SYLLABLE GGYEG..HANGUL SYLLABLE GGYEH\r\n\t\t(0xAF2D <= code && code <= 0xAF47) || // Lo [27] HANGUL SYLLABLE GGOG..HANGUL SYLLABLE GGOH\r\n\t\t(0xAF49 <= code && code <= 0xAF63) || // Lo [27] HANGUL SYLLABLE GGWAG..HANGUL SYLLABLE GGWAH\r\n\t\t(0xAF65 <= code && code <= 0xAF7F) || // Lo [27] HANGUL SYLLABLE GGWAEG..HANGUL SYLLABLE GGWAEH\r\n\t\t(0xAF81 <= code && code <= 0xAF9B) || // Lo [27] HANGUL SYLLABLE GGOEG..HANGUL SYLLABLE GGOEH\r\n\t\t(0xAF9D <= code && code <= 0xAFB7) || // Lo [27] HANGUL SYLLABLE GGYOG..HANGUL SYLLABLE GGYOH\r\n\t\t(0xAFB9 <= code && code <= 0xAFD3) || // Lo [27] HANGUL SYLLABLE GGUG..HANGUL SYLLABLE GGUH\r\n\t\t(0xAFD5 <= code && code <= 0xAFEF) || // Lo [27] HANGUL SYLLABLE GGWEOG..HANGUL SYLLABLE GGWEOH\r\n\t\t(0xAFF1 <= code && code <= 0xB00B) || // Lo [27] HANGUL SYLLABLE GGWEG..HANGUL SYLLABLE GGWEH\r\n\t\t(0xB00D <= code && code <= 0xB027) || // Lo [27] HANGUL SYLLABLE GGWIG..HANGUL SYLLABLE GGWIH\r\n\t\t(0xB029 <= code && code <= 0xB043) || // Lo [27] HANGUL SYLLABLE GGYUG..HANGUL SYLLABLE GGYUH\r\n\t\t(0xB045 <= code && code <= 0xB05F) || // Lo [27] HANGUL SYLLABLE GGEUG..HANGUL SYLLABLE GGEUH\r\n\t\t(0xB061 <= code && code <= 0xB07B) || // Lo [27] HANGUL SYLLABLE GGYIG..HANGUL SYLLABLE GGYIH\r\n\t\t(0xB07D <= code && code <= 0xB097) || // Lo [27] HANGUL SYLLABLE GGIG..HANGUL SYLLABLE GGIH\r\n\t\t(0xB099 <= code && code <= 0xB0B3) || // Lo [27] HANGUL SYLLABLE NAG..HANGUL SYLLABLE NAH\r\n\t\t(0xB0B5 <= code && code <= 0xB0CF) || // Lo [27] HANGUL SYLLABLE NAEG..HANGUL SYLLABLE NAEH\r\n\t\t(0xB0D1 <= code && code <= 0xB0EB) || // Lo [27] HANGUL SYLLABLE NYAG..HANGUL SYLLABLE NYAH\r\n\t\t(0xB0ED <= code && code <= 0xB107) || // Lo [27] HANGUL SYLLABLE NYAEG..HANGUL SYLLABLE NYAEH\r\n\t\t(0xB109 <= code && code <= 0xB123) || // Lo [27] HANGUL SYLLABLE NEOG..HANGUL SYLLABLE NEOH\r\n\t\t(0xB125 <= code && code <= 0xB13F) || // Lo [27] HANGUL SYLLABLE NEG..HANGUL SYLLABLE NEH\r\n\t\t(0xB141 <= code && code <= 0xB15B) || // Lo [27] HANGUL SYLLABLE NYEOG..HANGUL SYLLABLE NYEOH\r\n\t\t(0xB15D <= code && code <= 0xB177) || // Lo [27] HANGUL SYLLABLE NYEG..HANGUL SYLLABLE NYEH\r\n\t\t(0xB179 <= code && code <= 0xB193) || // Lo [27] HANGUL SYLLABLE NOG..HANGUL SYLLABLE NOH\r\n\t\t(0xB195 <= code && code <= 0xB1AF) || // Lo [27] HANGUL SYLLABLE NWAG..HANGUL SYLLABLE NWAH\r\n\t\t(0xB1B1 <= code && code <= 0xB1CB) || // Lo [27] HANGUL SYLLABLE NWAEG..HANGUL SYLLABLE NWAEH\r\n\t\t(0xB1CD <= code && code <= 0xB1E7) || // Lo [27] HANGUL SYLLABLE NOEG..HANGUL SYLLABLE NOEH\r\n\t\t(0xB1E9 <= code && code <= 0xB203) || // Lo [27] HANGUL SYLLABLE NYOG..HANGUL SYLLABLE NYOH\r\n\t\t(0xB205 <= code && code <= 0xB21F) || // Lo [27] HANGUL SYLLABLE NUG..HANGUL SYLLABLE NUH\r\n\t\t(0xB221 <= code && code <= 0xB23B) || // Lo [27] HANGUL SYLLABLE NWEOG..HANGUL SYLLABLE NWEOH\r\n\t\t(0xB23D <= code && code <= 0xB257) || // Lo [27] HANGUL SYLLABLE NWEG..HANGUL SYLLABLE NWEH\r\n\t\t(0xB259 <= code && code <= 0xB273) || // Lo [27] HANGUL SYLLABLE NWIG..HANGUL SYLLABLE NWIH\r\n\t\t(0xB275 <= code && code <= 0xB28F) || // Lo [27] HANGUL SYLLABLE NYUG..HANGUL SYLLABLE NYUH\r\n\t\t(0xB291 <= code && code <= 0xB2AB) || // Lo [27] HANGUL SYLLABLE NEUG..HANGUL SYLLABLE NEUH\r\n\t\t(0xB2AD <= code && code <= 0xB2C7) || // Lo [27] HANGUL SYLLABLE NYIG..HANGUL SYLLABLE NYIH\r\n\t\t(0xB2C9 <= code && code <= 0xB2E3) || // Lo [27] HANGUL SYLLABLE NIG..HANGUL SYLLABLE NIH\r\n\t\t(0xB2E5 <= code && code <= 0xB2FF) || // Lo [27] HANGUL SYLLABLE DAG..HANGUL SYLLABLE DAH\r\n\t\t(0xB301 <= code && code <= 0xB31B) || // Lo [27] HANGUL SYLLABLE DAEG..HANGUL SYLLABLE DAEH\r\n\t\t(0xB31D <= code && code <= 0xB337) || // Lo [27] HANGUL SYLLABLE DYAG..HANGUL SYLLABLE DYAH\r\n\t\t(0xB339 <= code && code <= 0xB353) || // Lo [27] HANGUL SYLLABLE DYAEG..HANGUL SYLLABLE DYAEH\r\n\t\t(0xB355 <= code && code <= 0xB36F) || // Lo [27] HANGUL SYLLABLE DEOG..HANGUL SYLLABLE DEOH\r\n\t\t(0xB371 <= code && code <= 0xB38B) || // Lo [27] HANGUL SYLLABLE DEG..HANGUL SYLLABLE DEH\r\n\t\t(0xB38D <= code && code <= 0xB3A7) || // Lo [27] HANGUL SYLLABLE DYEOG..HANGUL SYLLABLE DYEOH\r\n\t\t(0xB3A9 <= code && code <= 0xB3C3) || // Lo [27] HANGUL SYLLABLE DYEG..HANGUL SYLLABLE DYEH\r\n\t\t(0xB3C5 <= code && code <= 0xB3DF) || // Lo [27] HANGUL SYLLABLE DOG..HANGUL SYLLABLE DOH\r\n\t\t(0xB3E1 <= code && code <= 0xB3FB) || // Lo [27] HANGUL SYLLABLE DWAG..HANGUL SYLLABLE DWAH\r\n\t\t(0xB3FD <= code && code <= 0xB417) || // Lo [27] HANGUL SYLLABLE DWAEG..HANGUL SYLLABLE DWAEH\r\n\t\t(0xB419 <= code && code <= 0xB433) || // Lo [27] HANGUL SYLLABLE DOEG..HANGUL SYLLABLE DOEH\r\n\t\t(0xB435 <= code && code <= 0xB44F) || // Lo [27] HANGUL SYLLABLE DYOG..HANGUL SYLLABLE DYOH\r\n\t\t(0xB451 <= code && code <= 0xB46B) || // Lo [27] HANGUL SYLLABLE DUG..HANGUL SYLLABLE DUH\r\n\t\t(0xB46D <= code && code <= 0xB487) || // Lo [27] HANGUL SYLLABLE DWEOG..HANGUL SYLLABLE DWEOH\r\n\t\t(0xB489 <= code && code <= 0xB4A3) || // Lo [27] HANGUL SYLLABLE DWEG..HANGUL SYLLABLE DWEH\r\n\t\t(0xB4A5 <= code && code <= 0xB4BF) || // Lo [27] HANGUL SYLLABLE DWIG..HANGUL SYLLABLE DWIH\r\n\t\t(0xB4C1 <= code && code <= 0xB4DB) || // Lo [27] HANGUL SYLLABLE DYUG..HANGUL SYLLABLE DYUH\r\n\t\t(0xB4DD <= code && code <= 0xB4F7) || // Lo [27] HANGUL SYLLABLE DEUG..HANGUL SYLLABLE DEUH\r\n\t\t(0xB4F9 <= code && code <= 0xB513) || // Lo [27] HANGUL SYLLABLE DYIG..HANGUL SYLLABLE DYIH\r\n\t\t(0xB515 <= code && code <= 0xB52F) || // Lo [27] HANGUL SYLLABLE DIG..HANGUL SYLLABLE DIH\r\n\t\t(0xB531 <= code && code <= 0xB54B) || // Lo [27] HANGUL SYLLABLE DDAG..HANGUL SYLLABLE DDAH\r\n\t\t(0xB54D <= code && code <= 0xB567) || // Lo [27] HANGUL SYLLABLE DDAEG..HANGUL SYLLABLE DDAEH\r\n\t\t(0xB569 <= code && code <= 0xB583) || // Lo [27] HANGUL SYLLABLE DDYAG..HANGUL SYLLABLE DDYAH\r\n\t\t(0xB585 <= code && code <= 0xB59F) || // Lo [27] HANGUL SYLLABLE DDYAEG..HANGUL SYLLABLE DDYAEH\r\n\t\t(0xB5A1 <= code && code <= 0xB5BB) || // Lo [27] HANGUL SYLLABLE DDEOG..HANGUL SYLLABLE DDEOH\r\n\t\t(0xB5BD <= code && code <= 0xB5D7) || // Lo [27] HANGUL SYLLABLE DDEG..HANGUL SYLLABLE DDEH\r\n\t\t(0xB5D9 <= code && code <= 0xB5F3) || // Lo [27] HANGUL SYLLABLE DDYEOG..HANGUL SYLLABLE DDYEOH\r\n\t\t(0xB5F5 <= code && code <= 0xB60F) || // Lo [27] HANGUL SYLLABLE DDYEG..HANGUL SYLLABLE DDYEH\r\n\t\t(0xB611 <= code && code <= 0xB62B) || // Lo [27] HANGUL SYLLABLE DDOG..HANGUL SYLLABLE DDOH\r\n\t\t(0xB62D <= code && code <= 0xB647) || // Lo [27] HANGUL SYLLABLE DDWAG..HANGUL SYLLABLE DDWAH\r\n\t\t(0xB649 <= code && code <= 0xB663) || // Lo [27] HANGUL SYLLABLE DDWAEG..HANGUL SYLLABLE DDWAEH\r\n\t\t(0xB665 <= code && code <= 0xB67F) || // Lo [27] HANGUL SYLLABLE DDOEG..HANGUL SYLLABLE DDOEH\r\n\t\t(0xB681 <= code && code <= 0xB69B) || // Lo [27] HANGUL SYLLABLE DDYOG..HANGUL SYLLABLE DDYOH\r\n\t\t(0xB69D <= code && code <= 0xB6B7) || // Lo [27] HANGUL SYLLABLE DDUG..HANGUL SYLLABLE DDUH\r\n\t\t(0xB6B9 <= code && code <= 0xB6D3) || // Lo [27] HANGUL SYLLABLE DDWEOG..HANGUL SYLLABLE DDWEOH\r\n\t\t(0xB6D5 <= code && code <= 0xB6EF) || // Lo [27] HANGUL SYLLABLE DDWEG..HANGUL SYLLABLE DDWEH\r\n\t\t(0xB6F1 <= code && code <= 0xB70B) || // Lo [27] HANGUL SYLLABLE DDWIG..HANGUL SYLLABLE DDWIH\r\n\t\t(0xB70D <= code && code <= 0xB727) || // Lo [27] HANGUL SYLLABLE DDYUG..HANGUL SYLLABLE DDYUH\r\n\t\t(0xB729 <= code && code <= 0xB743) || // Lo [27] HANGUL SYLLABLE DDEUG..HANGUL SYLLABLE DDEUH\r\n\t\t(0xB745 <= code && code <= 0xB75F) || // Lo [27] HANGUL SYLLABLE DDYIG..HANGUL SYLLABLE DDYIH\r\n\t\t(0xB761 <= code && code <= 0xB77B) || // Lo [27] HANGUL SYLLABLE DDIG..HANGUL SYLLABLE DDIH\r\n\t\t(0xB77D <= code && code <= 0xB797) || // Lo [27] HANGUL SYLLABLE RAG..HANGUL SYLLABLE RAH\r\n\t\t(0xB799 <= code && code <= 0xB7B3) || // Lo [27] HANGUL SYLLABLE RAEG..HANGUL SYLLABLE RAEH\r\n\t\t(0xB7B5 <= code && code <= 0xB7CF) || // Lo [27] HANGUL SYLLABLE RYAG..HANGUL SYLLABLE RYAH\r\n\t\t(0xB7D1 <= code && code <= 0xB7EB) || // Lo [27] HANGUL SYLLABLE RYAEG..HANGUL SYLLABLE RYAEH\r\n\t\t(0xB7ED <= code && code <= 0xB807) || // Lo [27] HANGUL SYLLABLE REOG..HANGUL SYLLABLE REOH\r\n\t\t(0xB809 <= code && code <= 0xB823) || // Lo [27] HANGUL SYLLABLE REG..HANGUL SYLLABLE REH\r\n\t\t(0xB825 <= code && code <= 0xB83F) || // Lo [27] HANGUL SYLLABLE RYEOG..HANGUL SYLLABLE RYEOH\r\n\t\t(0xB841 <= code && code <= 0xB85B) || // Lo [27] HANGUL SYLLABLE RYEG..HANGUL SYLLABLE RYEH\r\n\t\t(0xB85D <= code && code <= 0xB877) || // Lo [27] HANGUL SYLLABLE ROG..HANGUL SYLLABLE ROH\r\n\t\t(0xB879 <= code && code <= 0xB893) || // Lo [27] HANGUL SYLLABLE RWAG..HANGUL SYLLABLE RWAH\r\n\t\t(0xB895 <= code && code <= 0xB8AF) || // Lo [27] HANGUL SYLLABLE RWAEG..HANGUL SYLLABLE RWAEH\r\n\t\t(0xB8B1 <= code && code <= 0xB8CB) || // Lo [27] HANGUL SYLLABLE ROEG..HANGUL SYLLABLE ROEH\r\n\t\t(0xB8CD <= code && code <= 0xB8E7) || // Lo [27] HANGUL SYLLABLE RYOG..HANGUL SYLLABLE RYOH\r\n\t\t(0xB8E9 <= code && code <= 0xB903) || // Lo [27] HANGUL SYLLABLE RUG..HANGUL SYLLABLE RUH\r\n\t\t(0xB905 <= code && code <= 0xB91F) || // Lo [27] HANGUL SYLLABLE RWEOG..HANGUL SYLLABLE RWEOH\r\n\t\t(0xB921 <= code && code <= 0xB93B) || // Lo [27] HANGUL SYLLABLE RWEG..HANGUL SYLLABLE RWEH\r\n\t\t(0xB93D <= code && code <= 0xB957) || // Lo [27] HANGUL SYLLABLE RWIG..HANGUL SYLLABLE RWIH\r\n\t\t(0xB959 <= code && code <= 0xB973) || // Lo [27] HANGUL SYLLABLE RYUG..HANGUL SYLLABLE RYUH\r\n\t\t(0xB975 <= code && code <= 0xB98F) || // Lo [27] HANGUL SYLLABLE REUG..HANGUL SYLLABLE REUH\r\n\t\t(0xB991 <= code && code <= 0xB9AB) || // Lo [27] HANGUL SYLLABLE RYIG..HANGUL SYLLABLE RYIH\r\n\t\t(0xB9AD <= code && code <= 0xB9C7) || // Lo [27] HANGUL SYLLABLE RIG..HANGUL SYLLABLE RIH\r\n\t\t(0xB9C9 <= code && code <= 0xB9E3) || // Lo [27] HANGUL SYLLABLE MAG..HANGUL SYLLABLE MAH\r\n\t\t(0xB9E5 <= code && code <= 0xB9FF) || // Lo [27] HANGUL SYLLABLE MAEG..HANGUL SYLLABLE MAEH\r\n\t\t(0xBA01 <= code && code <= 0xBA1B) || // Lo [27] HANGUL SYLLABLE MYAG..HANGUL SYLLABLE MYAH\r\n\t\t(0xBA1D <= code && code <= 0xBA37) || // Lo [27] HANGUL SYLLABLE MYAEG..HANGUL SYLLABLE MYAEH\r\n\t\t(0xBA39 <= code && code <= 0xBA53) || // Lo [27] HANGUL SYLLABLE MEOG..HANGUL SYLLABLE MEOH\r\n\t\t(0xBA55 <= code && code <= 0xBA6F) || // Lo [27] HANGUL SYLLABLE MEG..HANGUL SYLLABLE MEH\r\n\t\t(0xBA71 <= code && code <= 0xBA8B) || // Lo [27] HANGUL SYLLABLE MYEOG..HANGUL SYLLABLE MYEOH\r\n\t\t(0xBA8D <= code && code <= 0xBAA7) || // Lo [27] HANGUL SYLLABLE MYEG..HANGUL SYLLABLE MYEH\r\n\t\t(0xBAA9 <= code && code <= 0xBAC3) || // Lo [27] HANGUL SYLLABLE MOG..HANGUL SYLLABLE MOH\r\n\t\t(0xBAC5 <= code && code <= 0xBADF) || // Lo [27] HANGUL SYLLABLE MWAG..HANGUL SYLLABLE MWAH\r\n\t\t(0xBAE1 <= code && code <= 0xBAFB) || // Lo [27] HANGUL SYLLABLE MWAEG..HANGUL SYLLABLE MWAEH\r\n\t\t(0xBAFD <= code && code <= 0xBB17) || // Lo [27] HANGUL SYLLABLE MOEG..HANGUL SYLLABLE MOEH\r\n\t\t(0xBB19 <= code && code <= 0xBB33) || // Lo [27] HANGUL SYLLABLE MYOG..HANGUL SYLLABLE MYOH\r\n\t\t(0xBB35 <= code && code <= 0xBB4F) || // Lo [27] HANGUL SYLLABLE MUG..HANGUL SYLLABLE MUH\r\n\t\t(0xBB51 <= code && code <= 0xBB6B) || // Lo [27] HANGUL SYLLABLE MWEOG..HANGUL SYLLABLE MWEOH\r\n\t\t(0xBB6D <= code && code <= 0xBB87) || // Lo [27] HANGUL SYLLABLE MWEG..HANGUL SYLLABLE MWEH\r\n\t\t(0xBB89 <= code && code <= 0xBBA3) || // Lo [27] HANGUL SYLLABLE MWIG..HANGUL SYLLABLE MWIH\r\n\t\t(0xBBA5 <= code && code <= 0xBBBF) || // Lo [27] HANGUL SYLLABLE MYUG..HANGUL SYLLABLE MYUH\r\n\t\t(0xBBC1 <= code && code <= 0xBBDB) || // Lo [27] HANGUL SYLLABLE MEUG..HANGUL SYLLABLE MEUH\r\n\t\t(0xBBDD <= code && code <= 0xBBF7) || // Lo [27] HANGUL SYLLABLE MYIG..HANGUL SYLLABLE MYIH\r\n\t\t(0xBBF9 <= code && code <= 0xBC13) || // Lo [27] HANGUL SYLLABLE MIG..HANGUL SYLLABLE MIH\r\n\t\t(0xBC15 <= code && code <= 0xBC2F) || // Lo [27] HANGUL SYLLABLE BAG..HANGUL SYLLABLE BAH\r\n\t\t(0xBC31 <= code && code <= 0xBC4B) || // Lo [27] HANGUL SYLLABLE BAEG..HANGUL SYLLABLE BAEH\r\n\t\t(0xBC4D <= code && code <= 0xBC67) || // Lo [27] HANGUL SYLLABLE BYAG..HANGUL SYLLABLE BYAH\r\n\t\t(0xBC69 <= code && code <= 0xBC83) || // Lo [27] HANGUL SYLLABLE BYAEG..HANGUL SYLLABLE BYAEH\r\n\t\t(0xBC85 <= code && code <= 0xBC9F) || // Lo [27] HANGUL SYLLABLE BEOG..HANGUL SYLLABLE BEOH\r\n\t\t(0xBCA1 <= code && code <= 0xBCBB) || // Lo [27] HANGUL SYLLABLE BEG..HANGUL SYLLABLE BEH\r\n\t\t(0xBCBD <= code && code <= 0xBCD7) || // Lo [27] HANGUL SYLLABLE BYEOG..HANGUL SYLLABLE BYEOH\r\n\t\t(0xBCD9 <= code && code <= 0xBCF3) || // Lo [27] HANGUL SYLLABLE BYEG..HANGUL SYLLABLE BYEH\r\n\t\t(0xBCF5 <= code && code <= 0xBD0F) || // Lo [27] HANGUL SYLLABLE BOG..HANGUL SYLLABLE BOH\r\n\t\t(0xBD11 <= code && code <= 0xBD2B) || // Lo [27] HANGUL SYLLABLE BWAG..HANGUL SYLLABLE BWAH\r\n\t\t(0xBD2D <= code && code <= 0xBD47) || // Lo [27] HANGUL SYLLABLE BWAEG..HANGUL SYLLABLE BWAEH\r\n\t\t(0xBD49 <= code && code <= 0xBD63) || // Lo [27] HANGUL SYLLABLE BOEG..HANGUL SYLLABLE BOEH\r\n\t\t(0xBD65 <= code && code <= 0xBD7F) || // Lo [27] HANGUL SYLLABLE BYOG..HANGUL SYLLABLE BYOH\r\n\t\t(0xBD81 <= code && code <= 0xBD9B) || // Lo [27] HANGUL SYLLABLE BUG..HANGUL SYLLABLE BUH\r\n\t\t(0xBD9D <= code && code <= 0xBDB7) || // Lo [27] HANGUL SYLLABLE BWEOG..HANGUL SYLLABLE BWEOH\r\n\t\t(0xBDB9 <= code && code <= 0xBDD3) || // Lo [27] HANGUL SYLLABLE BWEG..HANGUL SYLLABLE BWEH\r\n\t\t(0xBDD5 <= code && code <= 0xBDEF) || // Lo [27] HANGUL SYLLABLE BWIG..HANGUL SYLLABLE BWIH\r\n\t\t(0xBDF1 <= code && code <= 0xBE0B) || // Lo [27] HANGUL SYLLABLE BYUG..HANGUL SYLLABLE BYUH\r\n\t\t(0xBE0D <= code && code <= 0xBE27) || // Lo [27] HANGUL SYLLABLE BEUG..HANGUL SYLLABLE BEUH\r\n\t\t(0xBE29 <= code && code <= 0xBE43) || // Lo [27] HANGUL SYLLABLE BYIG..HANGUL SYLLABLE BYIH\r\n\t\t(0xBE45 <= code && code <= 0xBE5F) || // Lo [27] HANGUL SYLLABLE BIG..HANGUL SYLLABLE BIH\r\n\t\t(0xBE61 <= code && code <= 0xBE7B) || // Lo [27] HANGUL SYLLABLE BBAG..HANGUL SYLLABLE BBAH\r\n\t\t(0xBE7D <= code && code <= 0xBE97) || // Lo [27] HANGUL SYLLABLE BBAEG..HANGUL SYLLABLE BBAEH\r\n\t\t(0xBE99 <= code && code <= 0xBEB3) || // Lo [27] HANGUL SYLLABLE BBYAG..HANGUL SYLLABLE BBYAH\r\n\t\t(0xBEB5 <= code && code <= 0xBECF) || // Lo [27] HANGUL SYLLABLE BBYAEG..HANGUL SYLLABLE BBYAEH\r\n\t\t(0xBED1 <= code && code <= 0xBEEB) || // Lo [27] HANGUL SYLLABLE BBEOG..HANGUL SYLLABLE BBEOH\r\n\t\t(0xBEED <= code && code <= 0xBF07) || // Lo [27] HANGUL SYLLABLE BBEG..HANGUL SYLLABLE BBEH\r\n\t\t(0xBF09 <= code && code <= 0xBF23) || // Lo [27] HANGUL SYLLABLE BBYEOG..HANGUL SYLLABLE BBYEOH\r\n\t\t(0xBF25 <= code && code <= 0xBF3F) || // Lo [27] HANGUL SYLLABLE BBYEG..HANGUL SYLLABLE BBYEH\r\n\t\t(0xBF41 <= code && code <= 0xBF5B) || // Lo [27] HANGUL SYLLABLE BBOG..HANGUL SYLLABLE BBOH\r\n\t\t(0xBF5D <= code && code <= 0xBF77) || // Lo [27] HANGUL SYLLABLE BBWAG..HANGUL SYLLABLE BBWAH\r\n\t\t(0xBF79 <= code && code <= 0xBF93) || // Lo [27] HANGUL SYLLABLE BBWAEG..HANGUL SYLLABLE BBWAEH\r\n\t\t(0xBF95 <= code && code <= 0xBFAF) || // Lo [27] HANGUL SYLLABLE BBOEG..HANGUL SYLLABLE BBOEH\r\n\t\t(0xBFB1 <= code && code <= 0xBFCB) || // Lo [27] HANGUL SYLLABLE BBYOG..HANGUL SYLLABLE BBYOH\r\n\t\t(0xBFCD <= code && code <= 0xBFE7) || // Lo [27] HANGUL SYLLABLE BBUG..HANGUL SYLLABLE BBUH\r\n\t\t(0xBFE9 <= code && code <= 0xC003) || // Lo [27] HANGUL SYLLABLE BBWEOG..HANGUL SYLLABLE BBWEOH\r\n\t\t(0xC005 <= code && code <= 0xC01F) || // Lo [27] HANGUL SYLLABLE BBWEG..HANGUL SYLLABLE BBWEH\r\n\t\t(0xC021 <= code && code <= 0xC03B) || // Lo [27] HANGUL SYLLABLE BBWIG..HANGUL SYLLABLE BBWIH\r\n\t\t(0xC03D <= code && code <= 0xC057) || // Lo [27] HANGUL SYLLABLE BBYUG..HANGUL SYLLABLE BBYUH\r\n\t\t(0xC059 <= code && code <= 0xC073) || // Lo [27] HANGUL SYLLABLE BBEUG..HANGUL SYLLABLE BBEUH\r\n\t\t(0xC075 <= code && code <= 0xC08F) || // Lo [27] HANGUL SYLLABLE BBYIG..HANGUL SYLLABLE BBYIH\r\n\t\t(0xC091 <= code && code <= 0xC0AB) || // Lo [27] HANGUL SYLLABLE BBIG..HANGUL SYLLABLE BBIH\r\n\t\t(0xC0AD <= code && code <= 0xC0C7) || // Lo [27] HANGUL SYLLABLE SAG..HANGUL SYLLABLE SAH\r\n\t\t(0xC0C9 <= code && code <= 0xC0E3) || // Lo [27] HANGUL SYLLABLE SAEG..HANGUL SYLLABLE SAEH\r\n\t\t(0xC0E5 <= code && code <= 0xC0FF) || // Lo [27] HANGUL SYLLABLE SYAG..HANGUL SYLLABLE SYAH\r\n\t\t(0xC101 <= code && code <= 0xC11B) || // Lo [27] HANGUL SYLLABLE SYAEG..HANGUL SYLLABLE SYAEH\r\n\t\t(0xC11D <= code && code <= 0xC137) || // Lo [27] HANGUL SYLLABLE SEOG..HANGUL SYLLABLE SEOH\r\n\t\t(0xC139 <= code && code <= 0xC153) || // Lo [27] HANGUL SYLLABLE SEG..HANGUL SYLLABLE SEH\r\n\t\t(0xC155 <= code && code <= 0xC16F) || // Lo [27] HANGUL SYLLABLE SYEOG..HANGUL SYLLABLE SYEOH\r\n\t\t(0xC171 <= code && code <= 0xC18B) || // Lo [27] HANGUL SYLLABLE SYEG..HANGUL SYLLABLE SYEH\r\n\t\t(0xC18D <= code && code <= 0xC1A7) || // Lo [27] HANGUL SYLLABLE SOG..HANGUL SYLLABLE SOH\r\n\t\t(0xC1A9 <= code && code <= 0xC1C3) || // Lo [27] HANGUL SYLLABLE SWAG..HANGUL SYLLABLE SWAH\r\n\t\t(0xC1C5 <= code && code <= 0xC1DF) || // Lo [27] HANGUL SYLLABLE SWAEG..HANGUL SYLLABLE SWAEH\r\n\t\t(0xC1E1 <= code && code <= 0xC1FB) || // Lo [27] HANGUL SYLLABLE SOEG..HANGUL SYLLABLE SOEH\r\n\t\t(0xC1FD <= code && code <= 0xC217) || // Lo [27] HANGUL SYLLABLE SYOG..HANGUL SYLLABLE SYOH\r\n\t\t(0xC219 <= code && code <= 0xC233) || // Lo [27] HANGUL SYLLABLE SUG..HANGUL SYLLABLE SUH\r\n\t\t(0xC235 <= code && code <= 0xC24F) || // Lo [27] HANGUL SYLLABLE SWEOG..HANGUL SYLLABLE SWEOH\r\n\t\t(0xC251 <= code && code <= 0xC26B) || // Lo [27] HANGUL SYLLABLE SWEG..HANGUL SYLLABLE SWEH\r\n\t\t(0xC26D <= code && code <= 0xC287) || // Lo [27] HANGUL SYLLABLE SWIG..HANGUL SYLLABLE SWIH\r\n\t\t(0xC289 <= code && code <= 0xC2A3) || // Lo [27] HANGUL SYLLABLE SYUG..HANGUL SYLLABLE SYUH\r\n\t\t(0xC2A5 <= code && code <= 0xC2BF) || // Lo [27] HANGUL SYLLABLE SEUG..HANGUL SYLLABLE SEUH\r\n\t\t(0xC2C1 <= code && code <= 0xC2DB) || // Lo [27] HANGUL SYLLABLE SYIG..HANGUL SYLLABLE SYIH\r\n\t\t(0xC2DD <= code && code <= 0xC2F7) || // Lo [27] HANGUL SYLLABLE SIG..HANGUL SYLLABLE SIH\r\n\t\t(0xC2F9 <= code && code <= 0xC313) || // Lo [27] HANGUL SYLLABLE SSAG..HANGUL SYLLABLE SSAH\r\n\t\t(0xC315 <= code && code <= 0xC32F) || // Lo [27] HANGUL SYLLABLE SSAEG..HANGUL SYLLABLE SSAEH\r\n\t\t(0xC331 <= code && code <= 0xC34B) || // Lo [27] HANGUL SYLLABLE SSYAG..HANGUL SYLLABLE SSYAH\r\n\t\t(0xC34D <= code && code <= 0xC367) || // Lo [27] HANGUL SYLLABLE SSYAEG..HANGUL SYLLABLE SSYAEH\r\n\t\t(0xC369 <= code && code <= 0xC383) || // Lo [27] HANGUL SYLLABLE SSEOG..HANGUL SYLLABLE SSEOH\r\n\t\t(0xC385 <= code && code <= 0xC39F) || // Lo [27] HANGUL SYLLABLE SSEG..HANGUL SYLLABLE SSEH\r\n\t\t(0xC3A1 <= code && code <= 0xC3BB) || // Lo [27] HANGUL SYLLABLE SSYEOG..HANGUL SYLLABLE SSYEOH\r\n\t\t(0xC3BD <= code && code <= 0xC3D7) || // Lo [27] HANGUL SYLLABLE SSYEG..HANGUL SYLLABLE SSYEH\r\n\t\t(0xC3D9 <= code && code <= 0xC3F3) || // Lo [27] HANGUL SYLLABLE SSOG..HANGUL SYLLABLE SSOH\r\n\t\t(0xC3F5 <= code && code <= 0xC40F) || // Lo [27] HANGUL SYLLABLE SSWAG..HANGUL SYLLABLE SSWAH\r\n\t\t(0xC411 <= code && code <= 0xC42B) || // Lo [27] HANGUL SYLLABLE SSWAEG..HANGUL SYLLABLE SSWAEH\r\n\t\t(0xC42D <= code && code <= 0xC447) || // Lo [27] HANGUL SYLLABLE SSOEG..HANGUL SYLLABLE SSOEH\r\n\t\t(0xC449 <= code && code <= 0xC463) || // Lo [27] HANGUL SYLLABLE SSYOG..HANGUL SYLLABLE SSYOH\r\n\t\t(0xC465 <= code && code <= 0xC47F) || // Lo [27] HANGUL SYLLABLE SSUG..HANGUL SYLLABLE SSUH\r\n\t\t(0xC481 <= code && code <= 0xC49B) || // Lo [27] HANGUL SYLLABLE SSWEOG..HANGUL SYLLABLE SSWEOH\r\n\t\t(0xC49D <= code && code <= 0xC4B7) || // Lo [27] HANGUL SYLLABLE SSWEG..HANGUL SYLLABLE SSWEH\r\n\t\t(0xC4B9 <= code && code <= 0xC4D3) || // Lo [27] HANGUL SYLLABLE SSWIG..HANGUL SYLLABLE SSWIH\r\n\t\t(0xC4D5 <= code && code <= 0xC4EF) || // Lo [27] HANGUL SYLLABLE SSYUG..HANGUL SYLLABLE SSYUH\r\n\t\t(0xC4F1 <= code && code <= 0xC50B) || // Lo [27] HANGUL SYLLABLE SSEUG..HANGUL SYLLABLE SSEUH\r\n\t\t(0xC50D <= code && code <= 0xC527) || // Lo [27] HANGUL SYLLABLE SSYIG..HANGUL SYLLABLE SSYIH\r\n\t\t(0xC529 <= code && code <= 0xC543) || // Lo [27] HANGUL SYLLABLE SSIG..HANGUL SYLLABLE SSIH\r\n\t\t(0xC545 <= code && code <= 0xC55F) || // Lo [27] HANGUL SYLLABLE AG..HANGUL SYLLABLE AH\r\n\t\t(0xC561 <= code && code <= 0xC57B) || // Lo [27] HANGUL SYLLABLE AEG..HANGUL SYLLABLE AEH\r\n\t\t(0xC57D <= code && code <= 0xC597) || // Lo [27] HANGUL SYLLABLE YAG..HANGUL SYLLABLE YAH\r\n\t\t(0xC599 <= code && code <= 0xC5B3) || // Lo [27] HANGUL SYLLABLE YAEG..HANGUL SYLLABLE YAEH\r\n\t\t(0xC5B5 <= code && code <= 0xC5CF) || // Lo [27] HANGUL SYLLABLE EOG..HANGUL SYLLABLE EOH\r\n\t\t(0xC5D1 <= code && code <= 0xC5EB) || // Lo [27] HANGUL SYLLABLE EG..HANGUL SYLLABLE EH\r\n\t\t(0xC5ED <= code && code <= 0xC607) || // Lo [27] HANGUL SYLLABLE YEOG..HANGUL SYLLABLE YEOH\r\n\t\t(0xC609 <= code && code <= 0xC623) || // Lo [27] HANGUL SYLLABLE YEG..HANGUL SYLLABLE YEH\r\n\t\t(0xC625 <= code && code <= 0xC63F) || // Lo [27] HANGUL SYLLABLE OG..HANGUL SYLLABLE OH\r\n\t\t(0xC641 <= code && code <= 0xC65B) || // Lo [27] HANGUL SYLLABLE WAG..HANGUL SYLLABLE WAH\r\n\t\t(0xC65D <= code && code <= 0xC677) || // Lo [27] HANGUL SYLLABLE WAEG..HANGUL SYLLABLE WAEH\r\n\t\t(0xC679 <= code && code <= 0xC693) || // Lo [27] HANGUL SYLLABLE OEG..HANGUL SYLLABLE OEH\r\n\t\t(0xC695 <= code && code <= 0xC6AF) || // Lo [27] HANGUL SYLLABLE YOG..HANGUL SYLLABLE YOH\r\n\t\t(0xC6B1 <= code && code <= 0xC6CB) || // Lo [27] HANGUL SYLLABLE UG..HANGUL SYLLABLE UH\r\n\t\t(0xC6CD <= code && code <= 0xC6E7) || // Lo [27] HANGUL SYLLABLE WEOG..HANGUL SYLLABLE WEOH\r\n\t\t(0xC6E9 <= code && code <= 0xC703) || // Lo [27] HANGUL SYLLABLE WEG..HANGUL SYLLABLE WEH\r\n\t\t(0xC705 <= code && code <= 0xC71F) || // Lo [27] HANGUL SYLLABLE WIG..HANGUL SYLLABLE WIH\r\n\t\t(0xC721 <= code && code <= 0xC73B) || // Lo [27] HANGUL SYLLABLE YUG..HANGUL SYLLABLE YUH\r\n\t\t(0xC73D <= code && code <= 0xC757) || // Lo [27] HANGUL SYLLABLE EUG..HANGUL SYLLABLE EUH\r\n\t\t(0xC759 <= code && code <= 0xC773) || // Lo [27] HANGUL SYLLABLE YIG..HANGUL SYLLABLE YIH\r\n\t\t(0xC775 <= code && code <= 0xC78F) || // Lo [27] HANGUL SYLLABLE IG..HANGUL SYLLABLE IH\r\n\t\t(0xC791 <= code && code <= 0xC7AB) || // Lo [27] HANGUL SYLLABLE JAG..HANGUL SYLLABLE JAH\r\n\t\t(0xC7AD <= code && code <= 0xC7C7) || // Lo [27] HANGUL SYLLABLE JAEG..HANGUL SYLLABLE JAEH\r\n\t\t(0xC7C9 <= code && code <= 0xC7E3) || // Lo [27] HANGUL SYLLABLE JYAG..HANGUL SYLLABLE JYAH\r\n\t\t(0xC7E5 <= code && code <= 0xC7FF) || // Lo [27] HANGUL SYLLABLE JYAEG..HANGUL SYLLABLE JYAEH\r\n\t\t(0xC801 <= code && code <= 0xC81B) || // Lo [27] HANGUL SYLLABLE JEOG..HANGUL SYLLABLE JEOH\r\n\t\t(0xC81D <= code && code <= 0xC837) || // Lo [27] HANGUL SYLLABLE JEG..HANGUL SYLLABLE JEH\r\n\t\t(0xC839 <= code && code <= 0xC853) || // Lo [27] HANGUL SYLLABLE JYEOG..HANGUL SYLLABLE JYEOH\r\n\t\t(0xC855 <= code && code <= 0xC86F) || // Lo [27] HANGUL SYLLABLE JYEG..HANGUL SYLLABLE JYEH\r\n\t\t(0xC871 <= code && code <= 0xC88B) || // Lo [27] HANGUL SYLLABLE JOG..HANGUL SYLLABLE JOH\r\n\t\t(0xC88D <= code && code <= 0xC8A7) || // Lo [27] HANGUL SYLLABLE JWAG..HANGUL SYLLABLE JWAH\r\n\t\t(0xC8A9 <= code && code <= 0xC8C3) || // Lo [27] HANGUL SYLLABLE JWAEG..HANGUL SYLLABLE JWAEH\r\n\t\t(0xC8C5 <= code && code <= 0xC8DF) || // Lo [27] HANGUL SYLLABLE JOEG..HANGUL SYLLABLE JOEH\r\n\t\t(0xC8E1 <= code && code <= 0xC8FB) || // Lo [27] HANGUL SYLLABLE JYOG..HANGUL SYLLABLE JYOH\r\n\t\t(0xC8FD <= code && code <= 0xC917) || // Lo [27] HANGUL SYLLABLE JUG..HANGUL SYLLABLE JUH\r\n\t\t(0xC919 <= code && code <= 0xC933) || // Lo [27] HANGUL SYLLABLE JWEOG..HANGUL SYLLABLE JWEOH\r\n\t\t(0xC935 <= code && code <= 0xC94F) || // Lo [27] HANGUL SYLLABLE JWEG..HANGUL SYLLABLE JWEH\r\n\t\t(0xC951 <= code && code <= 0xC96B) || // Lo [27] HANGUL SYLLABLE JWIG..HANGUL SYLLABLE JWIH\r\n\t\t(0xC96D <= code && code <= 0xC987) || // Lo [27] HANGUL SYLLABLE JYUG..HANGUL SYLLABLE JYUH\r\n\t\t(0xC989 <= code && code <= 0xC9A3) || // Lo [27] HANGUL SYLLABLE JEUG..HANGUL SYLLABLE JEUH\r\n\t\t(0xC9A5 <= code && code <= 0xC9BF) || // Lo [27] HANGUL SYLLABLE JYIG..HANGUL SYLLABLE JYIH\r\n\t\t(0xC9C1 <= code && code <= 0xC9DB) || // Lo [27] HANGUL SYLLABLE JIG..HANGUL SYLLABLE JIH\r\n\t\t(0xC9DD <= code && code <= 0xC9F7) || // Lo [27] HANGUL SYLLABLE JJAG..HANGUL SYLLABLE JJAH\r\n\t\t(0xC9F9 <= code && code <= 0xCA13) || // Lo [27] HANGUL SYLLABLE JJAEG..HANGUL SYLLABLE JJAEH\r\n\t\t(0xCA15 <= code && code <= 0xCA2F) || // Lo [27] HANGUL SYLLABLE JJYAG..HANGUL SYLLABLE JJYAH\r\n\t\t(0xCA31 <= code && code <= 0xCA4B) || // Lo [27] HANGUL SYLLABLE JJYAEG..HANGUL SYLLABLE JJYAEH\r\n\t\t(0xCA4D <= code && code <= 0xCA67) || // Lo [27] HANGUL SYLLABLE JJEOG..HANGUL SYLLABLE JJEOH\r\n\t\t(0xCA69 <= code && code <= 0xCA83) || // Lo [27] HANGUL SYLLABLE JJEG..HANGUL SYLLABLE JJEH\r\n\t\t(0xCA85 <= code && code <= 0xCA9F) || // Lo [27] HANGUL SYLLABLE JJYEOG..HANGUL SYLLABLE JJYEOH\r\n\t\t(0xCAA1 <= code && code <= 0xCABB) || // Lo [27] HANGUL SYLLABLE JJYEG..HANGUL SYLLABLE JJYEH\r\n\t\t(0xCABD <= code && code <= 0xCAD7) || // Lo [27] HANGUL SYLLABLE JJOG..HANGUL SYLLABLE JJOH\r\n\t\t(0xCAD9 <= code && code <= 0xCAF3) || // Lo [27] HANGUL SYLLABLE JJWAG..HANGUL SYLLABLE JJWAH\r\n\t\t(0xCAF5 <= code && code <= 0xCB0F) || // Lo [27] HANGUL SYLLABLE JJWAEG..HANGUL SYLLABLE JJWAEH\r\n\t\t(0xCB11 <= code && code <= 0xCB2B) || // Lo [27] HANGUL SYLLABLE JJOEG..HANGUL SYLLABLE JJOEH\r\n\t\t(0xCB2D <= code && code <= 0xCB47) || // Lo [27] HANGUL SYLLABLE JJYOG..HANGUL SYLLABLE JJYOH\r\n\t\t(0xCB49 <= code && code <= 0xCB63) || // Lo [27] HANGUL SYLLABLE JJUG..HANGUL SYLLABLE JJUH\r\n\t\t(0xCB65 <= code && code <= 0xCB7F) || // Lo [27] HANGUL SYLLABLE JJWEOG..HANGUL SYLLABLE JJWEOH\r\n\t\t(0xCB81 <= code && code <= 0xCB9B) || // Lo [27] HANGUL SYLLABLE JJWEG..HANGUL SYLLABLE JJWEH\r\n\t\t(0xCB9D <= code && code <= 0xCBB7) || // Lo [27] HANGUL SYLLABLE JJWIG..HANGUL SYLLABLE JJWIH\r\n\t\t(0xCBB9 <= code && code <= 0xCBD3) || // Lo [27] HANGUL SYLLABLE JJYUG..HANGUL SYLLABLE JJYUH\r\n\t\t(0xCBD5 <= code && code <= 0xCBEF) || // Lo [27] HANGUL SYLLABLE JJEUG..HANGUL SYLLABLE JJEUH\r\n\t\t(0xCBF1 <= code && code <= 0xCC0B) || // Lo [27] HANGUL SYLLABLE JJYIG..HANGUL SYLLABLE JJYIH\r\n\t\t(0xCC0D <= code && code <= 0xCC27) || // Lo [27] HANGUL SYLLABLE JJIG..HANGUL SYLLABLE JJIH\r\n\t\t(0xCC29 <= code && code <= 0xCC43) || // Lo [27] HANGUL SYLLABLE CAG..HANGUL SYLLABLE CAH\r\n\t\t(0xCC45 <= code && code <= 0xCC5F) || // Lo [27] HANGUL SYLLABLE CAEG..HANGUL SYLLABLE CAEH\r\n\t\t(0xCC61 <= code && code <= 0xCC7B) || // Lo [27] HANGUL SYLLABLE CYAG..HANGUL SYLLABLE CYAH\r\n\t\t(0xCC7D <= code && code <= 0xCC97) || // Lo [27] HANGUL SYLLABLE CYAEG..HANGUL SYLLABLE CYAEH\r\n\t\t(0xCC99 <= code && code <= 0xCCB3) || // Lo [27] HANGUL SYLLABLE CEOG..HANGUL SYLLABLE CEOH\r\n\t\t(0xCCB5 <= code && code <= 0xCCCF) || // Lo [27] HANGUL SYLLABLE CEG..HANGUL SYLLABLE CEH\r\n\t\t(0xCCD1 <= code && code <= 0xCCEB) || // Lo [27] HANGUL SYLLABLE CYEOG..HANGUL SYLLABLE CYEOH\r\n\t\t(0xCCED <= code && code <= 0xCD07) || // Lo [27] HANGUL SYLLABLE CYEG..HANGUL SYLLABLE CYEH\r\n\t\t(0xCD09 <= code && code <= 0xCD23) || // Lo [27] HANGUL SYLLABLE COG..HANGUL SYLLABLE COH\r\n\t\t(0xCD25 <= code && code <= 0xCD3F) || // Lo [27] HANGUL SYLLABLE CWAG..HANGUL SYLLABLE CWAH\r\n\t\t(0xCD41 <= code && code <= 0xCD5B) || // Lo [27] HANGUL SYLLABLE CWAEG..HANGUL SYLLABLE CWAEH\r\n\t\t(0xCD5D <= code && code <= 0xCD77) || // Lo [27] HANGUL SYLLABLE COEG..HANGUL SYLLABLE COEH\r\n\t\t(0xCD79 <= code && code <= 0xCD93) || // Lo [27] HANGUL SYLLABLE CYOG..HANGUL SYLLABLE CYOH\r\n\t\t(0xCD95 <= code && code <= 0xCDAF) || // Lo [27] HANGUL SYLLABLE CUG..HANGUL SYLLABLE CUH\r\n\t\t(0xCDB1 <= code && code <= 0xCDCB) || // Lo [27] HANGUL SYLLABLE CWEOG..HANGUL SYLLABLE CWEOH\r\n\t\t(0xCDCD <= code && code <= 0xCDE7) || // Lo [27] HANGUL SYLLABLE CWEG..HANGUL SYLLABLE CWEH\r\n\t\t(0xCDE9 <= code && code <= 0xCE03) || // Lo [27] HANGUL SYLLABLE CWIG..HANGUL SYLLABLE CWIH\r\n\t\t(0xCE05 <= code && code <= 0xCE1F) || // Lo [27] HANGUL SYLLABLE CYUG..HANGUL SYLLABLE CYUH\r\n\t\t(0xCE21 <= code && code <= 0xCE3B) || // Lo [27] HANGUL SYLLABLE CEUG..HANGUL SYLLABLE CEUH\r\n\t\t(0xCE3D <= code && code <= 0xCE57) || // Lo [27] HANGUL SYLLABLE CYIG..HANGUL SYLLABLE CYIH\r\n\t\t(0xCE59 <= code && code <= 0xCE73) || // Lo [27] HANGUL SYLLABLE CIG..HANGUL SYLLABLE CIH\r\n\t\t(0xCE75 <= code && code <= 0xCE8F) || // Lo [27] HANGUL SYLLABLE KAG..HANGUL SYLLABLE KAH\r\n\t\t(0xCE91 <= code && code <= 0xCEAB) || // Lo [27] HANGUL SYLLABLE KAEG..HANGUL SYLLABLE KAEH\r\n\t\t(0xCEAD <= code && code <= 0xCEC7) || // Lo [27] HANGUL SYLLABLE KYAG..HANGUL SYLLABLE KYAH\r\n\t\t(0xCEC9 <= code && code <= 0xCEE3) || // Lo [27] HANGUL SYLLABLE KYAEG..HANGUL SYLLABLE KYAEH\r\n\t\t(0xCEE5 <= code && code <= 0xCEFF) || // Lo [27] HANGUL SYLLABLE KEOG..HANGUL SYLLABLE KEOH\r\n\t\t(0xCF01 <= code && code <= 0xCF1B) || // Lo [27] HANGUL SYLLABLE KEG..HANGUL SYLLABLE KEH\r\n\t\t(0xCF1D <= code && code <= 0xCF37) || // Lo [27] HANGUL SYLLABLE KYEOG..HANGUL SYLLABLE KYEOH\r\n\t\t(0xCF39 <= code && code <= 0xCF53) || // Lo [27] HANGUL SYLLABLE KYEG..HANGUL SYLLABLE KYEH\r\n\t\t(0xCF55 <= code && code <= 0xCF6F) || // Lo [27] HANGUL SYLLABLE KOG..HANGUL SYLLABLE KOH\r\n\t\t(0xCF71 <= code && code <= 0xCF8B) || // Lo [27] HANGUL SYLLABLE KWAG..HANGUL SYLLABLE KWAH\r\n\t\t(0xCF8D <= code && code <= 0xCFA7) || // Lo [27] HANGUL SYLLABLE KWAEG..HANGUL SYLLABLE KWAEH\r\n\t\t(0xCFA9 <= code && code <= 0xCFC3) || // Lo [27] HANGUL SYLLABLE KOEG..HANGUL SYLLABLE KOEH\r\n\t\t(0xCFC5 <= code && code <= 0xCFDF) || // Lo [27] HANGUL SYLLABLE KYOG..HANGUL SYLLABLE KYOH\r\n\t\t(0xCFE1 <= code && code <= 0xCFFB) || // Lo [27] HANGUL SYLLABLE KUG..HANGUL SYLLABLE KUH\r\n\t\t(0xCFFD <= code && code <= 0xD017) || // Lo [27] HANGUL SYLLABLE KWEOG..HANGUL SYLLABLE KWEOH\r\n\t\t(0xD019 <= code && code <= 0xD033) || // Lo [27] HANGUL SYLLABLE KWEG..HANGUL SYLLABLE KWEH\r\n\t\t(0xD035 <= code && code <= 0xD04F) || // Lo [27] HANGUL SYLLABLE KWIG..HANGUL SYLLABLE KWIH\r\n\t\t(0xD051 <= code && code <= 0xD06B) || // Lo [27] HANGUL SYLLABLE KYUG..HANGUL SYLLABLE KYUH\r\n\t\t(0xD06D <= code && code <= 0xD087) || // Lo [27] HANGUL SYLLABLE KEUG..HANGUL SYLLABLE KEUH\r\n\t\t(0xD089 <= code && code <= 0xD0A3) || // Lo [27] HANGUL SYLLABLE KYIG..HANGUL SYLLABLE KYIH\r\n\t\t(0xD0A5 <= code && code <= 0xD0BF) || // Lo [27] HANGUL SYLLABLE KIG..HANGUL SYLLABLE KIH\r\n\t\t(0xD0C1 <= code && code <= 0xD0DB) || // Lo [27] HANGUL SYLLABLE TAG..HANGUL SYLLABLE TAH\r\n\t\t(0xD0DD <= code && code <= 0xD0F7) || // Lo [27] HANGUL SYLLABLE TAEG..HANGUL SYLLABLE TAEH\r\n\t\t(0xD0F9 <= code && code <= 0xD113) || // Lo [27] HANGUL SYLLABLE TYAG..HANGUL SYLLABLE TYAH\r\n\t\t(0xD115 <= code && code <= 0xD12F) || // Lo [27] HANGUL SYLLABLE TYAEG..HANGUL SYLLABLE TYAEH\r\n\t\t(0xD131 <= code && code <= 0xD14B) || // Lo [27] HANGUL SYLLABLE TEOG..HANGUL SYLLABLE TEOH\r\n\t\t(0xD14D <= code && code <= 0xD167) || // Lo [27] HANGUL SYLLABLE TEG..HANGUL SYLLABLE TEH\r\n\t\t(0xD169 <= code && code <= 0xD183) || // Lo [27] HANGUL SYLLABLE TYEOG..HANGUL SYLLABLE TYEOH\r\n\t\t(0xD185 <= code && code <= 0xD19F) || // Lo [27] HANGUL SYLLABLE TYEG..HANGUL SYLLABLE TYEH\r\n\t\t(0xD1A1 <= code && code <= 0xD1BB) || // Lo [27] HANGUL SYLLABLE TOG..HANGUL SYLLABLE TOH\r\n\t\t(0xD1BD <= code && code <= 0xD1D7) || // Lo [27] HANGUL SYLLABLE TWAG..HANGUL SYLLABLE TWAH\r\n\t\t(0xD1D9 <= code && code <= 0xD1F3) || // Lo [27] HANGUL SYLLABLE TWAEG..HANGUL SYLLABLE TWAEH\r\n\t\t(0xD1F5 <= code && code <= 0xD20F) || // Lo [27] HANGUL SYLLABLE TOEG..HANGUL SYLLABLE TOEH\r\n\t\t(0xD211 <= code && code <= 0xD22B) || // Lo [27] HANGUL SYLLABLE TYOG..HANGUL SYLLABLE TYOH\r\n\t\t(0xD22D <= code && code <= 0xD247) || // Lo [27] HANGUL SYLLABLE TUG..HANGUL SYLLABLE TUH\r\n\t\t(0xD249 <= code && code <= 0xD263) || // Lo [27] HANGUL SYLLABLE TWEOG..HANGUL SYLLABLE TWEOH\r\n\t\t(0xD265 <= code && code <= 0xD27F) || // Lo [27] HANGUL SYLLABLE TWEG..HANGUL SYLLABLE TWEH\r\n\t\t(0xD281 <= code && code <= 0xD29B) || // Lo [27] HANGUL SYLLABLE TWIG..HANGUL SYLLABLE TWIH\r\n\t\t(0xD29D <= code && code <= 0xD2B7) || // Lo [27] HANGUL SYLLABLE TYUG..HANGUL SYLLABLE TYUH\r\n\t\t(0xD2B9 <= code && code <= 0xD2D3) || // Lo [27] HANGUL SYLLABLE TEUG..HANGUL SYLLABLE TEUH\r\n\t\t(0xD2D5 <= code && code <= 0xD2EF) || // Lo [27] HANGUL SYLLABLE TYIG..HANGUL SYLLABLE TYIH\r\n\t\t(0xD2F1 <= code && code <= 0xD30B) || // Lo [27] HANGUL SYLLABLE TIG..HANGUL SYLLABLE TIH\r\n\t\t(0xD30D <= code && code <= 0xD327) || // Lo [27] HANGUL SYLLABLE PAG..HANGUL SYLLABLE PAH\r\n\t\t(0xD329 <= code && code <= 0xD343) || // Lo [27] HANGUL SYLLABLE PAEG..HANGUL SYLLABLE PAEH\r\n\t\t(0xD345 <= code && code <= 0xD35F) || // Lo [27] HANGUL SYLLABLE PYAG..HANGUL SYLLABLE PYAH\r\n\t\t(0xD361 <= code && code <= 0xD37B) || // Lo [27] HANGUL SYLLABLE PYAEG..HANGUL SYLLABLE PYAEH\r\n\t\t(0xD37D <= code && code <= 0xD397) || // Lo [27] HANGUL SYLLABLE PEOG..HANGUL SYLLABLE PEOH\r\n\t\t(0xD399 <= code && code <= 0xD3B3) || // Lo [27] HANGUL SYLLABLE PEG..HANGUL SYLLABLE PEH\r\n\t\t(0xD3B5 <= code && code <= 0xD3CF) || // Lo [27] HANGUL SYLLABLE PYEOG..HANGUL SYLLABLE PYEOH\r\n\t\t(0xD3D1 <= code && code <= 0xD3EB) || // Lo [27] HANGUL SYLLABLE PYEG..HANGUL SYLLABLE PYEH\r\n\t\t(0xD3ED <= code && code <= 0xD407) || // Lo [27] HANGUL SYLLABLE POG..HANGUL SYLLABLE POH\r\n\t\t(0xD409 <= code && code <= 0xD423) || // Lo [27] HANGUL SYLLABLE PWAG..HANGUL SYLLABLE PWAH\r\n\t\t(0xD425 <= code && code <= 0xD43F) || // Lo [27] HANGUL SYLLABLE PWAEG..HANGUL SYLLABLE PWAEH\r\n\t\t(0xD441 <= code && code <= 0xD45B) || // Lo [27] HANGUL SYLLABLE POEG..HANGUL SYLLABLE POEH\r\n\t\t(0xD45D <= code && code <= 0xD477) || // Lo [27] HANGUL SYLLABLE PYOG..HANGUL SYLLABLE PYOH\r\n\t\t(0xD479 <= code && code <= 0xD493) || // Lo [27] HANGUL SYLLABLE PUG..HANGUL SYLLABLE PUH\r\n\t\t(0xD495 <= code && code <= 0xD4AF) || // Lo [27] HANGUL SYLLABLE PWEOG..HANGUL SYLLABLE PWEOH\r\n\t\t(0xD4B1 <= code && code <= 0xD4CB) || // Lo [27] HANGUL SYLLABLE PWEG..HANGUL SYLLABLE PWEH\r\n\t\t(0xD4CD <= code && code <= 0xD4E7) || // Lo [27] HANGUL SYLLABLE PWIG..HANGUL SYLLABLE PWIH\r\n\t\t(0xD4E9 <= code && code <= 0xD503) || // Lo [27] HANGUL SYLLABLE PYUG..HANGUL SYLLABLE PYUH\r\n\t\t(0xD505 <= code && code <= 0xD51F) || // Lo [27] HANGUL SYLLABLE PEUG..HANGUL SYLLABLE PEUH\r\n\t\t(0xD521 <= code && code <= 0xD53B) || // Lo [27] HANGUL SYLLABLE PYIG..HANGUL SYLLABLE PYIH\r\n\t\t(0xD53D <= code && code <= 0xD557) || // Lo [27] HANGUL SYLLABLE PIG..HANGUL SYLLABLE PIH\r\n\t\t(0xD559 <= code && code <= 0xD573) || // Lo [27] HANGUL SYLLABLE HAG..HANGUL SYLLABLE HAH\r\n\t\t(0xD575 <= code && code <= 0xD58F) || // Lo [27] HANGUL SYLLABLE HAEG..HANGUL SYLLABLE HAEH\r\n\t\t(0xD591 <= code && code <= 0xD5AB) || // Lo [27] HANGUL SYLLABLE HYAG..HANGUL SYLLABLE HYAH\r\n\t\t(0xD5AD <= code && code <= 0xD5C7) || // Lo [27] HANGUL SYLLABLE HYAEG..HANGUL SYLLABLE HYAEH\r\n\t\t(0xD5C9 <= code && code <= 0xD5E3) || // Lo [27] HANGUL SYLLABLE HEOG..HANGUL SYLLABLE HEOH\r\n\t\t(0xD5E5 <= code && code <= 0xD5FF) || // Lo [27] HANGUL SYLLABLE HEG..HANGUL SYLLABLE HEH\r\n\t\t(0xD601 <= code && code <= 0xD61B) || // Lo [27] HANGUL SYLLABLE HYEOG..HANGUL SYLLABLE HYEOH\r\n\t\t(0xD61D <= code && code <= 0xD637) || // Lo [27] HANGUL SYLLABLE HYEG..HANGUL SYLLABLE HYEH\r\n\t\t(0xD639 <= code && code <= 0xD653) || // Lo [27] HANGUL SYLLABLE HOG..HANGUL SYLLABLE HOH\r\n\t\t(0xD655 <= code && code <= 0xD66F) || // Lo [27] HANGUL SYLLABLE HWAG..HANGUL SYLLABLE HWAH\r\n\t\t(0xD671 <= code && code <= 0xD68B) || // Lo [27] HANGUL SYLLABLE HWAEG..HANGUL SYLLABLE HWAEH\r\n\t\t(0xD68D <= code && code <= 0xD6A7) || // Lo [27] HANGUL SYLLABLE HOEG..HANGUL SYLLABLE HOEH\r\n\t\t(0xD6A9 <= code && code <= 0xD6C3) || // Lo [27] HANGUL SYLLABLE HYOG..HANGUL SYLLABLE HYOH\r\n\t\t(0xD6C5 <= code && code <= 0xD6DF) || // Lo [27] HANGUL SYLLABLE HUG..HANGUL SYLLABLE HUH\r\n\t\t(0xD6E1 <= code && code <= 0xD6FB) || // Lo [27] HANGUL SYLLABLE HWEOG..HANGUL SYLLABLE HWEOH\r\n\t\t(0xD6FD <= code && code <= 0xD717) || // Lo [27] HANGUL SYLLABLE HWEG..HANGUL SYLLABLE HWEH\r\n\t\t(0xD719 <= code && code <= 0xD733) || // Lo [27] HANGUL SYLLABLE HWIG..HANGUL SYLLABLE HWIH\r\n\t\t(0xD735 <= code && code <= 0xD74F) || // Lo [27] HANGUL SYLLABLE HYUG..HANGUL SYLLABLE HYUH\r\n\t\t(0xD751 <= code && code <= 0xD76B) || // Lo [27] HANGUL SYLLABLE HEUG..HANGUL SYLLABLE HEUH\r\n\t\t(0xD76D <= code && code <= 0xD787) || // Lo [27] HANGUL SYLLABLE HYIG..HANGUL SYLLABLE HYIH\r\n\t\t(0xD789 <= code && code <= 0xD7A3) // Lo [27] HANGUL SYLLABLE HIG..HANGUL SYLLABLE HIH\r\n\t\t){\r\n\t\t\treturn LVT;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t0x261D == code || // So WHITE UP POINTING INDEX\r\n\t\t0x26F9 == code || // So PERSON WITH BALL\r\n\t\t(0x270A <= code && code <= 0x270D) || // So [4] RAISED FIST..WRITING HAND\r\n\t\t0x1F385 == code || // So FATHER CHRISTMAS\r\n\t\t(0x1F3C2 <= code && code <= 0x1F3C4) || // So [3] SNOWBOARDER..SURFER\r\n\t\t0x1F3C7 == code || // So HORSE RACING\r\n\t\t(0x1F3CA <= code && code <= 0x1F3CC) || // So [3] SWIMMER..GOLFER\r\n\t\t(0x1F442 <= code && code <= 0x1F443) || // So [2] EAR..NOSE\r\n\t\t(0x1F446 <= code && code <= 0x1F450) || // So [11] WHITE UP POINTING BACKHAND INDEX..OPEN HANDS SIGN\r\n\t\t0x1F46E == code || // So POLICE OFFICER\r\n\t\t(0x1F470 <= code && code <= 0x1F478) || // So [9] BRIDE WITH VEIL..PRINCESS\r\n\t\t0x1F47C == code || // So BABY ANGEL\r\n\t\t(0x1F481 <= code && code <= 0x1F483) || // So [3] INFORMATION DESK PERSON..DANCER\r\n\t\t(0x1F485 <= code && code <= 0x1F487) || // So [3] NAIL POLISH..HAIRCUT\r\n\t\t0x1F4AA == code || // So FLEXED BICEPS\r\n\t\t(0x1F574 <= code && code <= 0x1F575) || // So [2] MAN IN BUSINESS SUIT LEVITATING..SLEUTH OR SPY\r\n\t\t0x1F57A == code || // So MAN DANCING\r\n\t\t0x1F590 == code || // So RAISED HAND WITH FINGERS SPLAYED\r\n\t\t(0x1F595 <= code && code <= 0x1F596) || // So [2] REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS\r\n\t\t(0x1F645 <= code && code <= 0x1F647) || // So [3] FACE WITH NO GOOD GESTURE..PERSON BOWING DEEPLY\r\n\t\t(0x1F64B <= code && code <= 0x1F64F) || // So [5] HAPPY PERSON RAISING ONE HAND..PERSON WITH FOLDED HANDS\r\n\t\t0x1F6A3 == code || // So ROWBOAT\r\n\t\t(0x1F6B4 <= code && code <= 0x1F6B6) || // So [3] BICYCLIST..PEDESTRIAN\r\n\t\t0x1F6C0 == code || // So BATH\r\n\t\t0x1F6CC == code || // So SLEEPING ACCOMMODATION\r\n\t\t(0x1F918 <= code && code <= 0x1F91C) || // So [5] SIGN OF THE HORNS..RIGHT-FACING FIST\r\n\t\t(0x1F91E <= code && code <= 0x1F91F) || // So [2] HAND WITH INDEX AND MIDDLE FINGERS CROSSED..I LOVE YOU HAND SIGN\r\n\t\t0x1F926 == code || // So FACE PALM\r\n\t\t(0x1F930 <= code && code <= 0x1F939) || // So [10] PREGNANT WOMAN..JUGGLING\r\n\t\t(0x1F93D <= code && code <= 0x1F93E) || // So [2] WATER POLO..HANDBALL\r\n\t\t(0x1F9D1 <= code && code <= 0x1F9DD) // So [13] ADULT..ELF\r\n\t\t){\r\n\t\t\treturn E_Base;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t(0x1F3FB <= code && code <= 0x1F3FF) // Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6\r\n\t\t){\r\n\t\t\treturn E_Modifier;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t0x200D == code // Cf ZERO WIDTH JOINER\r\n\t\t){\r\n\t\t\treturn ZWJ;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t0x2640 == code || // So FEMALE SIGN\r\n\t\t0x2642 == code || // So MALE SIGN\r\n\t\t(0x2695 <= code && code <= 0x2696) || // So [2] STAFF OF AESCULAPIUS..SCALES\r\n\t\t0x2708 == code || // So AIRPLANE\r\n\t\t0x2764 == code || // So HEAVY BLACK HEART\r\n\t\t0x1F308 == code || // So RAINBOW\r\n\t\t0x1F33E == code || // So EAR OF RICE\r\n\t\t0x1F373 == code || // So COOKING\r\n\t\t0x1F393 == code || // So GRADUATION CAP\r\n\t\t0x1F3A4 == code || // So MICROPHONE\r\n\t\t0x1F3A8 == code || // So ARTIST PALETTE\r\n\t\t0x1F3EB == code || // So SCHOOL\r\n\t\t0x1F3ED == code || // So FACTORY\r\n\t\t0x1F48B == code || // So KISS MARK\r\n\t\t(0x1F4BB <= code && code <= 0x1F4BC) || // So [2] PERSONAL COMPUTER..BRIEFCASE\r\n\t\t0x1F527 == code || // So WRENCH\r\n\t\t0x1F52C == code || // So MICROSCOPE\r\n\t\t0x1F5E8 == code || // So LEFT SPEECH BUBBLE\r\n\t\t0x1F680 == code || // So ROCKET\r\n\t\t0x1F692 == code // So FIRE ENGINE\r\n\t\t){\r\n\t\t\treturn Glue_After_Zwj;\r\n\t\t}\r\n\r\n\t\tif(\r\n\t\t(0x1F466 <= code && code <= 0x1F469) // So [4] BOY..WOMAN\r\n\t\t){\r\n\t\t\treturn E_Base_GAZ;\r\n\t\t}\r\n\r\n\r\n\t\t//all unlisted characters have a grapheme break property of \"Other\"\r\n\t\treturn Other;\r\n\t}\r\n\treturn this;\r\n}\r\n\r\nexport default GraphemeSplitter;\r\n","import BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport writeTextToCanvas from \"../Core/writeTextToCanvas.js\";\r\nimport bitmapSDF from \"../ThirdParty/bitmap-sdf.js\";\r\nimport BillboardCollection from \"./BillboardCollection.js\";\r\nimport BlendOption from \"./BlendOption.js\";\r\nimport HeightReference from \"./HeightReference.js\";\r\nimport HorizontalOrigin from \"./HorizontalOrigin.js\";\r\nimport Label from \"./Label.js\";\r\nimport LabelStyle from \"./LabelStyle.js\";\r\nimport SDFSettings from \"./SDFSettings.js\";\r\nimport TextureAtlas from \"./TextureAtlas.js\";\r\nimport VerticalOrigin from \"./VerticalOrigin.js\";\r\nimport GraphemeSplitter from \"../ThirdParty/graphemesplitter.js\";\r\n\r\n// A glyph represents a single character in a particular label. It may or may\r\n// not have a billboard, depending on whether the texture info has an index into\r\n// the the label collection's texture atlas. Invisible characters have no texture, and\r\n// no billboard. However, it always has a valid dimensions object.\r\nfunction Glyph() {\r\n this.textureInfo = undefined;\r\n this.dimensions = undefined;\r\n this.billboard = undefined;\r\n}\r\n\r\n// GlyphTextureInfo represents a single character, drawn in a particular style,\r\n// shared and reference counted across all labels. It may or may not have an\r\n// index into the label collection's texture atlas, depending on whether the character\r\n// has both width and height, but it always has a valid dimensions object.\r\nfunction GlyphTextureInfo(labelCollection, index, dimensions) {\r\n this.labelCollection = labelCollection;\r\n this.index = index;\r\n this.dimensions = dimensions;\r\n}\r\n\r\n// Traditionally, leading is %20 of the font size.\r\nvar defaultLineSpacingPercent = 1.2;\r\n\r\nvar whitePixelCanvasId = \"ID_WHITE_PIXEL\";\r\nvar whitePixelSize = new Cartesian2(4, 4);\r\nvar whitePixelBoundingRegion = new BoundingRectangle(1, 1, 1, 1);\r\n\r\nfunction addWhitePixelCanvas(textureAtlas, labelCollection) {\r\n var canvas = document.createElement(\"canvas\");\r\n canvas.width = whitePixelSize.x;\r\n canvas.height = whitePixelSize.y;\r\n\r\n var context2D = canvas.getContext(\"2d\");\r\n context2D.fillStyle = \"#fff\";\r\n context2D.fillRect(0, 0, canvas.width, canvas.height);\r\n\r\n textureAtlas.addImage(whitePixelCanvasId, canvas).then(function (index) {\r\n labelCollection._whitePixelIndex = index;\r\n });\r\n}\r\n\r\n// reusable object for calling writeTextToCanvas\r\nvar writeTextToCanvasParameters = {};\r\nfunction createGlyphCanvas(\r\n character,\r\n font,\r\n fillColor,\r\n outlineColor,\r\n outlineWidth,\r\n style,\r\n verticalOrigin\r\n) {\r\n writeTextToCanvasParameters.font = font;\r\n writeTextToCanvasParameters.fillColor = fillColor;\r\n writeTextToCanvasParameters.strokeColor = outlineColor;\r\n writeTextToCanvasParameters.strokeWidth = outlineWidth;\r\n // Setting the padding to something bigger is necessary to get enough space for the outlining.\r\n writeTextToCanvasParameters.padding = SDFSettings.PADDING;\r\n\r\n if (verticalOrigin === VerticalOrigin.CENTER) {\r\n writeTextToCanvasParameters.textBaseline = \"middle\";\r\n } else if (verticalOrigin === VerticalOrigin.TOP) {\r\n writeTextToCanvasParameters.textBaseline = \"top\";\r\n } else {\r\n // VerticalOrigin.BOTTOM and VerticalOrigin.BASELINE\r\n writeTextToCanvasParameters.textBaseline = \"bottom\";\r\n }\r\n\r\n writeTextToCanvasParameters.fill =\r\n style === LabelStyle.FILL || style === LabelStyle.FILL_AND_OUTLINE;\r\n writeTextToCanvasParameters.stroke =\r\n style === LabelStyle.OUTLINE || style === LabelStyle.FILL_AND_OUTLINE;\r\n writeTextToCanvasParameters.backgroundColor = Color.BLACK;\r\n\r\n return writeTextToCanvas(character, writeTextToCanvasParameters);\r\n}\r\n\r\nfunction unbindGlyph(labelCollection, glyph) {\r\n glyph.textureInfo = undefined;\r\n glyph.dimensions = undefined;\r\n\r\n var billboard = glyph.billboard;\r\n if (defined(billboard)) {\r\n billboard.show = false;\r\n billboard.image = undefined;\r\n if (defined(billboard._removeCallbackFunc)) {\r\n billboard._removeCallbackFunc();\r\n billboard._removeCallbackFunc = undefined;\r\n }\r\n labelCollection._spareBillboards.push(billboard);\r\n glyph.billboard = undefined;\r\n }\r\n}\r\n\r\nfunction addGlyphToTextureAtlas(textureAtlas, id, canvas, glyphTextureInfo) {\r\n textureAtlas.addImage(id, canvas).then(function (index) {\r\n glyphTextureInfo.index = index;\r\n });\r\n}\r\n\r\nvar splitter = new GraphemeSplitter();\r\n\r\nfunction rebindAllGlyphs(labelCollection, label) {\r\n var text = label._renderedText;\r\n var graphemes = splitter.splitGraphemes(text);\r\n var textLength = graphemes.length;\r\n var glyphs = label._glyphs;\r\n var glyphsLength = glyphs.length;\r\n\r\n var glyph;\r\n var glyphIndex;\r\n var textIndex;\r\n\r\n // Compute a font size scale relative to the sdf font generated size.\r\n label._relativeSize = label._fontSize / SDFSettings.FONT_SIZE;\r\n\r\n // if we have more glyphs than needed, unbind the extras.\r\n if (textLength < glyphsLength) {\r\n for (glyphIndex = textLength; glyphIndex < glyphsLength; ++glyphIndex) {\r\n unbindGlyph(labelCollection, glyphs[glyphIndex]);\r\n }\r\n }\r\n\r\n // presize glyphs to match the new text length\r\n glyphs.length = textLength;\r\n\r\n var showBackground =\r\n label._showBackground && text.split(\"\\n\").join(\"\").length > 0;\r\n var backgroundBillboard = label._backgroundBillboard;\r\n var backgroundBillboardCollection =\r\n labelCollection._backgroundBillboardCollection;\r\n if (!showBackground) {\r\n if (defined(backgroundBillboard)) {\r\n backgroundBillboardCollection.remove(backgroundBillboard);\r\n label._backgroundBillboard = backgroundBillboard = undefined;\r\n }\r\n } else {\r\n if (!defined(backgroundBillboard)) {\r\n backgroundBillboard = backgroundBillboardCollection.add({\r\n collection: labelCollection,\r\n image: whitePixelCanvasId,\r\n imageSubRegion: whitePixelBoundingRegion,\r\n });\r\n label._backgroundBillboard = backgroundBillboard;\r\n }\r\n\r\n backgroundBillboard.color = label._backgroundColor;\r\n backgroundBillboard.show = label._show;\r\n backgroundBillboard.position = label._position;\r\n backgroundBillboard.eyeOffset = label._eyeOffset;\r\n backgroundBillboard.pixelOffset = label._pixelOffset;\r\n backgroundBillboard.horizontalOrigin = HorizontalOrigin.LEFT;\r\n backgroundBillboard.verticalOrigin = label._verticalOrigin;\r\n backgroundBillboard.heightReference = label._heightReference;\r\n backgroundBillboard.scale = label.totalScale;\r\n backgroundBillboard.pickPrimitive = label;\r\n backgroundBillboard.id = label._id;\r\n backgroundBillboard.translucencyByDistance = label._translucencyByDistance;\r\n backgroundBillboard.pixelOffsetScaleByDistance =\r\n label._pixelOffsetScaleByDistance;\r\n backgroundBillboard.scaleByDistance = label._scaleByDistance;\r\n backgroundBillboard.distanceDisplayCondition =\r\n label._distanceDisplayCondition;\r\n backgroundBillboard.disableDepthTestDistance =\r\n label._disableDepthTestDistance;\r\n }\r\n\r\n var glyphTextureCache = labelCollection._glyphTextureCache;\r\n\r\n // walk the text looking for new characters (creating new glyphs for each)\r\n // or changed characters (rebinding existing glyphs)\r\n for (textIndex = 0; textIndex < textLength; ++textIndex) {\r\n var character = graphemes[textIndex];\r\n var verticalOrigin = label._verticalOrigin;\r\n\r\n var id = JSON.stringify([\r\n character,\r\n label._fontFamily,\r\n label._fontStyle,\r\n label._fontWeight,\r\n +verticalOrigin,\r\n ]);\r\n\r\n var glyphTextureInfo = glyphTextureCache[id];\r\n if (!defined(glyphTextureInfo)) {\r\n var glyphFont =\r\n label._fontStyle +\r\n \" \" +\r\n label._fontWeight +\r\n \" \" +\r\n SDFSettings.FONT_SIZE +\r\n \"px \" +\r\n label._fontFamily;\r\n\r\n var canvas = createGlyphCanvas(\r\n character,\r\n glyphFont,\r\n Color.WHITE,\r\n Color.WHITE,\r\n 0.0,\r\n LabelStyle.FILL,\r\n verticalOrigin\r\n );\r\n\r\n glyphTextureInfo = new GlyphTextureInfo(\r\n labelCollection,\r\n -1,\r\n canvas.dimensions\r\n );\r\n glyphTextureCache[id] = glyphTextureInfo;\r\n\r\n if (canvas.width > 0 && canvas.height > 0) {\r\n var sdfValues = bitmapSDF(canvas, {\r\n cutoff: SDFSettings.CUTOFF,\r\n radius: SDFSettings.RADIUS,\r\n });\r\n\r\n var ctx = canvas.getContext(\"2d\");\r\n var canvasWidth = canvas.width;\r\n var canvasHeight = canvas.height;\r\n var imgData = ctx.getImageData(0, 0, canvasWidth, canvasHeight);\r\n for (var i = 0; i < canvasWidth; i++) {\r\n for (var j = 0; j < canvasHeight; j++) {\r\n var baseIndex = j * canvasWidth + i;\r\n var alpha = sdfValues[baseIndex] * 255;\r\n var imageIndex = baseIndex * 4;\r\n imgData.data[imageIndex + 0] = alpha;\r\n imgData.data[imageIndex + 1] = alpha;\r\n imgData.data[imageIndex + 2] = alpha;\r\n imgData.data[imageIndex + 3] = alpha;\r\n }\r\n }\r\n ctx.putImageData(imgData, 0, 0);\r\n if (character !== \" \") {\r\n addGlyphToTextureAtlas(\r\n labelCollection._textureAtlas,\r\n id,\r\n canvas,\r\n glyphTextureInfo\r\n );\r\n }\r\n }\r\n }\r\n\r\n glyph = glyphs[textIndex];\r\n\r\n if (defined(glyph)) {\r\n // clean up leftover information from the previous glyph\r\n if (glyphTextureInfo.index === -1) {\r\n // no texture, and therefore no billboard, for this glyph.\r\n // so, completely unbind glyph.\r\n unbindGlyph(labelCollection, glyph);\r\n } else if (defined(glyph.textureInfo)) {\r\n // we have a texture and billboard. If we had one before, release\r\n // our reference to that texture info, but reuse the billboard.\r\n glyph.textureInfo = undefined;\r\n }\r\n } else {\r\n // create a glyph object\r\n glyph = new Glyph();\r\n glyphs[textIndex] = glyph;\r\n }\r\n\r\n glyph.textureInfo = glyphTextureInfo;\r\n glyph.dimensions = glyphTextureInfo.dimensions;\r\n\r\n // if we have a texture, configure the existing billboard, or obtain one\r\n if (glyphTextureInfo.index !== -1) {\r\n var billboard = glyph.billboard;\r\n var spareBillboards = labelCollection._spareBillboards;\r\n if (!defined(billboard)) {\r\n if (spareBillboards.length > 0) {\r\n billboard = spareBillboards.pop();\r\n } else {\r\n billboard = labelCollection._billboardCollection.add({\r\n collection: labelCollection,\r\n });\r\n billboard._labelDimensions = new Cartesian2();\r\n billboard._labelTranslate = new Cartesian2();\r\n }\r\n glyph.billboard = billboard;\r\n }\r\n\r\n billboard.show = label._show;\r\n billboard.position = label._position;\r\n billboard.eyeOffset = label._eyeOffset;\r\n billboard.pixelOffset = label._pixelOffset;\r\n billboard.horizontalOrigin = HorizontalOrigin.LEFT;\r\n billboard.verticalOrigin = label._verticalOrigin;\r\n billboard.heightReference = label._heightReference;\r\n billboard.scale = label.totalScale;\r\n billboard.pickPrimitive = label;\r\n billboard.id = label._id;\r\n billboard.image = id;\r\n billboard.translucencyByDistance = label._translucencyByDistance;\r\n billboard.pixelOffsetScaleByDistance = label._pixelOffsetScaleByDistance;\r\n billboard.scaleByDistance = label._scaleByDistance;\r\n billboard.distanceDisplayCondition = label._distanceDisplayCondition;\r\n billboard.disableDepthTestDistance = label._disableDepthTestDistance;\r\n billboard._batchIndex = label._batchIndex;\r\n billboard.outlineColor = label.outlineColor;\r\n if (label.style === LabelStyle.FILL_AND_OUTLINE) {\r\n billboard.color = label._fillColor;\r\n billboard.outlineWidth = label.outlineWidth;\r\n } else if (label.style === LabelStyle.FILL) {\r\n billboard.color = label._fillColor;\r\n billboard.outlineWidth = 0.0;\r\n } else if (label.style === LabelStyle.OUTLINE) {\r\n billboard.color = Color.TRANSPARENT;\r\n billboard.outlineWidth = label.outlineWidth;\r\n }\r\n }\r\n }\r\n\r\n // changing glyphs will cause the position of the\r\n // glyphs to change, since different characters have different widths\r\n label._repositionAllGlyphs = true;\r\n}\r\n\r\nfunction calculateWidthOffset(lineWidth, horizontalOrigin, backgroundPadding) {\r\n if (horizontalOrigin === HorizontalOrigin.CENTER) {\r\n return -lineWidth / 2;\r\n } else if (horizontalOrigin === HorizontalOrigin.RIGHT) {\r\n return -(lineWidth + backgroundPadding.x);\r\n }\r\n return backgroundPadding.x;\r\n}\r\n\r\n// reusable Cartesian2 instances\r\nvar glyphPixelOffset = new Cartesian2();\r\nvar scratchBackgroundPadding = new Cartesian2();\r\n\r\nfunction repositionAllGlyphs(label) {\r\n var glyphs = label._glyphs;\r\n var text = label._renderedText;\r\n var glyph;\r\n var dimensions;\r\n var lastLineWidth = 0;\r\n var maxLineWidth = 0;\r\n var lineWidths = [];\r\n var maxGlyphDescent = Number.NEGATIVE_INFINITY;\r\n var maxGlyphY = 0;\r\n var numberOfLines = 1;\r\n var glyphIndex;\r\n var glyphLength = glyphs.length;\r\n\r\n var backgroundBillboard = label._backgroundBillboard;\r\n var backgroundPadding = Cartesian2.clone(\r\n defined(backgroundBillboard) ? label._backgroundPadding : Cartesian2.ZERO,\r\n scratchBackgroundPadding\r\n );\r\n\r\n // We need to scale the background padding, which is specified in pixels by the inverse of the relative size so it is scaled properly.\r\n backgroundPadding.x /= label._relativeSize;\r\n backgroundPadding.y /= label._relativeSize;\r\n\r\n for (glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) {\r\n if (text.charAt(glyphIndex) === \"\\n\") {\r\n lineWidths.push(lastLineWidth);\r\n ++numberOfLines;\r\n lastLineWidth = 0;\r\n } else {\r\n glyph = glyphs[glyphIndex];\r\n dimensions = glyph.dimensions;\r\n maxGlyphY = Math.max(maxGlyphY, dimensions.height - dimensions.descent);\r\n maxGlyphDescent = Math.max(maxGlyphDescent, dimensions.descent);\r\n\r\n //Computing the line width must also account for the kerning that occurs between letters.\r\n lastLineWidth += dimensions.width - dimensions.bounds.minx;\r\n if (glyphIndex < glyphLength - 1) {\r\n lastLineWidth += glyphs[glyphIndex + 1].dimensions.bounds.minx;\r\n }\r\n maxLineWidth = Math.max(maxLineWidth, lastLineWidth);\r\n }\r\n }\r\n lineWidths.push(lastLineWidth);\r\n var maxLineHeight = maxGlyphY + maxGlyphDescent;\r\n\r\n var scale = label.totalScale;\r\n var horizontalOrigin = label._horizontalOrigin;\r\n var verticalOrigin = label._verticalOrigin;\r\n var lineIndex = 0;\r\n var lineWidth = lineWidths[lineIndex];\r\n var widthOffset = calculateWidthOffset(\r\n lineWidth,\r\n horizontalOrigin,\r\n backgroundPadding\r\n );\r\n var lineSpacing =\r\n (defined(label._lineHeight)\r\n ? label._lineHeight\r\n : defaultLineSpacingPercent * label._fontSize) / label._relativeSize;\r\n var otherLinesHeight = lineSpacing * (numberOfLines - 1);\r\n var totalLineWidth = maxLineWidth;\r\n var totalLineHeight = maxLineHeight + otherLinesHeight;\r\n\r\n if (defined(backgroundBillboard)) {\r\n totalLineWidth += backgroundPadding.x * 2;\r\n totalLineHeight += backgroundPadding.y * 2;\r\n backgroundBillboard._labelHorizontalOrigin = horizontalOrigin;\r\n }\r\n\r\n glyphPixelOffset.x = widthOffset * scale;\r\n glyphPixelOffset.y = 0;\r\n\r\n var firstCharOfLine = true;\r\n\r\n var lineOffsetY = 0;\r\n for (glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) {\r\n if (text.charAt(glyphIndex) === \"\\n\") {\r\n ++lineIndex;\r\n lineOffsetY += lineSpacing;\r\n lineWidth = lineWidths[lineIndex];\r\n widthOffset = calculateWidthOffset(\r\n lineWidth,\r\n horizontalOrigin,\r\n backgroundPadding\r\n );\r\n glyphPixelOffset.x = widthOffset * scale;\r\n firstCharOfLine = true;\r\n } else {\r\n glyph = glyphs[glyphIndex];\r\n dimensions = glyph.dimensions;\r\n\r\n if (verticalOrigin === VerticalOrigin.TOP) {\r\n glyphPixelOffset.y =\r\n dimensions.height - maxGlyphY - backgroundPadding.y;\r\n glyphPixelOffset.y += SDFSettings.PADDING;\r\n } else if (verticalOrigin === VerticalOrigin.CENTER) {\r\n glyphPixelOffset.y =\r\n (otherLinesHeight + dimensions.height - maxGlyphY) / 2;\r\n } else if (verticalOrigin === VerticalOrigin.BASELINE) {\r\n glyphPixelOffset.y = otherLinesHeight;\r\n glyphPixelOffset.y -= SDFSettings.PADDING;\r\n } else {\r\n // VerticalOrigin.BOTTOM\r\n glyphPixelOffset.y =\r\n otherLinesHeight + maxGlyphDescent + backgroundPadding.y;\r\n glyphPixelOffset.y -= SDFSettings.PADDING;\r\n }\r\n glyphPixelOffset.y =\r\n (glyphPixelOffset.y - dimensions.descent - lineOffsetY) * scale;\r\n\r\n // Handle any offsets for the first character of the line since the bounds might not be right on the bottom left pixel.\r\n if (firstCharOfLine) {\r\n glyphPixelOffset.x -= SDFSettings.PADDING * scale;\r\n firstCharOfLine = false;\r\n }\r\n\r\n if (defined(glyph.billboard)) {\r\n glyph.billboard._setTranslate(glyphPixelOffset);\r\n glyph.billboard._labelDimensions.x = totalLineWidth;\r\n glyph.billboard._labelDimensions.y = totalLineHeight;\r\n glyph.billboard._labelHorizontalOrigin = horizontalOrigin;\r\n }\r\n\r\n //Compute the next x offset taking into account the kerning performed\r\n //on both the current letter as well as the next letter to be drawn\r\n //as well as any applied scale.\r\n if (glyphIndex < glyphLength - 1) {\r\n var nextGlyph = glyphs[glyphIndex + 1];\r\n glyphPixelOffset.x +=\r\n (dimensions.width -\r\n dimensions.bounds.minx +\r\n nextGlyph.dimensions.bounds.minx) *\r\n scale;\r\n }\r\n }\r\n }\r\n\r\n if (defined(backgroundBillboard) && text.split(\"\\n\").join(\"\").length > 0) {\r\n if (horizontalOrigin === HorizontalOrigin.CENTER) {\r\n widthOffset = -maxLineWidth / 2 - backgroundPadding.x;\r\n } else if (horizontalOrigin === HorizontalOrigin.RIGHT) {\r\n widthOffset = -(maxLineWidth + backgroundPadding.x * 2);\r\n } else {\r\n widthOffset = 0;\r\n }\r\n glyphPixelOffset.x = widthOffset * scale;\r\n\r\n if (verticalOrigin === VerticalOrigin.TOP) {\r\n glyphPixelOffset.y = maxLineHeight - maxGlyphY - maxGlyphDescent;\r\n } else if (verticalOrigin === VerticalOrigin.CENTER) {\r\n glyphPixelOffset.y = (maxLineHeight - maxGlyphY) / 2 - maxGlyphDescent;\r\n } else if (verticalOrigin === VerticalOrigin.BASELINE) {\r\n glyphPixelOffset.y = -backgroundPadding.y - maxGlyphDescent;\r\n } else {\r\n // VerticalOrigin.BOTTOM\r\n glyphPixelOffset.y = 0;\r\n }\r\n glyphPixelOffset.y = glyphPixelOffset.y * scale;\r\n\r\n backgroundBillboard.width = totalLineWidth;\r\n backgroundBillboard.height = totalLineHeight;\r\n backgroundBillboard._setTranslate(glyphPixelOffset);\r\n backgroundBillboard._labelTranslate = Cartesian2.clone(\r\n glyphPixelOffset,\r\n backgroundBillboard._labelTranslate\r\n );\r\n }\r\n\r\n if (label.heightReference === HeightReference.CLAMP_TO_GROUND) {\r\n for (glyphIndex = 0; glyphIndex < glyphLength; ++glyphIndex) {\r\n glyph = glyphs[glyphIndex];\r\n var billboard = glyph.billboard;\r\n if (defined(billboard)) {\r\n billboard._labelTranslate = Cartesian2.clone(\r\n glyphPixelOffset,\r\n billboard._labelTranslate\r\n );\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction destroyLabel(labelCollection, label) {\r\n var glyphs = label._glyphs;\r\n for (var i = 0, len = glyphs.length; i < len; ++i) {\r\n unbindGlyph(labelCollection, glyphs[i]);\r\n }\r\n if (defined(label._backgroundBillboard)) {\r\n labelCollection._backgroundBillboardCollection.remove(\r\n label._backgroundBillboard\r\n );\r\n label._backgroundBillboard = undefined;\r\n }\r\n label._labelCollection = undefined;\r\n\r\n if (defined(label._removeCallbackFunc)) {\r\n label._removeCallbackFunc();\r\n }\r\n\r\n destroyObject(label);\r\n}\r\n\r\n/**\r\n * A renderable collection of labels. Labels are viewport-aligned text positioned in the 3D scene.\r\n * Each label can have a different font, color, scale, etc.\r\n *

\r\n *
\r\n *
\r\n * Example labels\r\n *
\r\n *

\r\n * Labels are added and removed from the collection using {@link LabelCollection#add}\r\n * and {@link LabelCollection#remove}.\r\n *\r\n * @alias LabelCollection\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms each label from model to world coordinates.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.\r\n * @param {Scene} [options.scene] Must be passed in for labels that use the height reference property or will be depth tested against the globe.\r\n * @param {BlendOption} [options.blendOption=BlendOption.OPAQUE_AND_TRANSLUCENT] The label blending option. The default\r\n * is used for rendering both opaque and translucent labels. However, if either all of the labels are completely opaque or all are completely translucent,\r\n * setting the technique to BlendOption.OPAQUE or BlendOption.TRANSLUCENT can improve performance by up to 2x.\r\n * @param {Boolean} [options.show=true] Determines if the labels in the collection will be shown.\r\n *\r\n * @performance For best performance, prefer a few collections, each with many labels, to\r\n * many collections with only a few labels each. Avoid having collections where some\r\n * labels change every frame and others do not; instead, create one or more collections\r\n * for static labels, and one or more collections for dynamic labels.\r\n *\r\n * @see LabelCollection#add\r\n * @see LabelCollection#remove\r\n * @see Label\r\n * @see BillboardCollection\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Labels.html|Cesium Sandcastle Labels Demo}\r\n *\r\n * @example\r\n * // Create a label collection with two labels\r\n * var labels = scene.primitives.add(new Cesium.LabelCollection());\r\n * labels.add({\r\n * position : new Cesium.Cartesian3(1.0, 2.0, 3.0),\r\n * text : 'A label'\r\n * });\r\n * labels.add({\r\n * position : new Cesium.Cartesian3(4.0, 5.0, 6.0),\r\n * text : 'Another label'\r\n * });\r\n */\r\nfunction LabelCollection(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._scene = options.scene;\r\n this._batchTable = options.batchTable;\r\n\r\n this._textureAtlas = undefined;\r\n this._backgroundTextureAtlas = undefined;\r\n this._whitePixelIndex = undefined;\r\n\r\n this._backgroundBillboardCollection = new BillboardCollection({\r\n scene: this._scene,\r\n });\r\n this._backgroundBillboardCollection.destroyTextureAtlas = false;\r\n\r\n this._billboardCollection = new BillboardCollection({\r\n scene: this._scene,\r\n batchTable: this._batchTable,\r\n });\r\n this._billboardCollection.destroyTextureAtlas = false;\r\n this._billboardCollection._sdf = true;\r\n\r\n this._spareBillboards = [];\r\n this._glyphTextureCache = {};\r\n this._labels = [];\r\n this._labelsToUpdate = [];\r\n this._totalGlyphCount = 0;\r\n\r\n this._highlightColor = Color.clone(Color.WHITE); // Only used by Vector3DTilePoints\r\n\r\n /**\r\n * Determines if labels in this collection will be shown.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * The 4x4 transformation matrix that transforms each label in this collection from model to world coordinates.\r\n * When this is the identity matrix, the labels are drawn in world coordinates, i.e., Earth's WGS84 coordinates.\r\n * Local reference frames can be used by providing a different transformation matrix, like that returned\r\n * by {@link Transforms.eastNorthUpToFixedFrame}.\r\n *\r\n * @type Matrix4\r\n * @default {@link Matrix4.IDENTITY}\r\n *\r\n * @example\r\n * var center = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);\r\n * labels.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);\r\n * labels.add({\r\n * position : new Cesium.Cartesian3(0.0, 0.0, 0.0),\r\n * text : 'Center'\r\n * });\r\n * labels.add({\r\n * position : new Cesium.Cartesian3(1000000.0, 0.0, 0.0),\r\n * text : 'East'\r\n * });\r\n * labels.add({\r\n * position : new Cesium.Cartesian3(0.0, 1000000.0, 0.0),\r\n * text : 'North'\r\n * });\r\n * labels.add({\r\n * position : new Cesium.Cartesian3(0.0, 0.0, 1000000.0),\r\n * text : 'Up'\r\n * });\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n\r\n /**\r\n * The label blending option. The default is used for rendering both opaque and translucent labels.\r\n * However, if either all of the labels are completely opaque or all are completely translucent,\r\n * setting the technique to BlendOption.OPAQUE or BlendOption.TRANSLUCENT can improve\r\n * performance by up to 2x.\r\n * @type {BlendOption}\r\n * @default BlendOption.OPAQUE_AND_TRANSLUCENT\r\n */\r\n this.blendOption = defaultValue(\r\n options.blendOption,\r\n BlendOption.OPAQUE_AND_TRANSLUCENT\r\n );\r\n}\r\n\r\nObject.defineProperties(LabelCollection.prototype, {\r\n /**\r\n * Returns the number of labels in this collection. This is commonly used with\r\n * {@link LabelCollection#get} to iterate over all the labels\r\n * in the collection.\r\n * @memberof LabelCollection.prototype\r\n * @type {Number}\r\n */\r\n length: {\r\n get: function () {\r\n return this._labels.length;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates and adds a label with the specified initial properties to the collection.\r\n * The added label is returned so it can be modified or removed from the collection later.\r\n *\r\n * @param {Object} [options] A template describing the label's properties as shown in Example 1.\r\n * @returns {Label} The label that was added to the collection.\r\n *\r\n * @performance Calling add is expected constant time. However, the collection's vertex buffer\r\n * is rewritten; this operations is O(n) and also incurs\r\n * CPU to GPU overhead. For best performance, add as many billboards as possible before\r\n * calling update.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * // Example 1: Add a label, specifying all the default values.\r\n * var l = labels.add({\r\n * show : true,\r\n * position : Cesium.Cartesian3.ZERO,\r\n * text : '',\r\n * font : '30px sans-serif',\r\n * fillColor : Cesium.Color.WHITE,\r\n * outlineColor : Cesium.Color.BLACK,\r\n * outlineWidth : 1.0,\r\n * showBackground : false,\r\n * backgroundColor : new Cesium.Color(0.165, 0.165, 0.165, 0.8),\r\n * backgroundPadding : new Cesium.Cartesian2(7, 5),\r\n * style : Cesium.LabelStyle.FILL,\r\n * pixelOffset : Cesium.Cartesian2.ZERO,\r\n * eyeOffset : Cesium.Cartesian3.ZERO,\r\n * horizontalOrigin : Cesium.HorizontalOrigin.LEFT,\r\n * verticalOrigin : Cesium.VerticalOrigin.BASELINE,\r\n * scale : 1.0,\r\n * translucencyByDistance : undefined,\r\n * pixelOffsetScaleByDistance : undefined,\r\n * heightReference : HeightReference.NONE,\r\n * distanceDisplayCondition : undefined\r\n * });\r\n *\r\n * @example\r\n * // Example 2: Specify only the label's cartographic position,\r\n * // text, and font.\r\n * var l = labels.add({\r\n * position : Cesium.Cartesian3.fromRadians(longitude, latitude, height),\r\n * text : 'Hello World',\r\n * font : '24px Helvetica',\r\n * });\r\n *\r\n * @see LabelCollection#remove\r\n * @see LabelCollection#removeAll\r\n */\r\nLabelCollection.prototype.add = function (options) {\r\n var label = new Label(options, this);\r\n\r\n this._labels.push(label);\r\n this._labelsToUpdate.push(label);\r\n\r\n return label;\r\n};\r\n\r\n/**\r\n * Removes a label from the collection. Once removed, a label is no longer usable.\r\n *\r\n * @param {Label} label The label to remove.\r\n * @returns {Boolean} true if the label was removed; false if the label was not found in the collection.\r\n *\r\n * @performance Calling remove is expected constant time. However, the collection's vertex buffer\r\n * is rewritten - an O(n) operation that also incurs CPU to GPU overhead. For\r\n * best performance, remove as many labels as possible before calling update.\r\n * If you intend to temporarily hide a label, it is usually more efficient to call\r\n * {@link Label#show} instead of removing and re-adding the label.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * var l = labels.add(...);\r\n * labels.remove(l); // Returns true\r\n *\r\n * @see LabelCollection#add\r\n * @see LabelCollection#removeAll\r\n * @see Label#show\r\n */\r\nLabelCollection.prototype.remove = function (label) {\r\n if (defined(label) && label._labelCollection === this) {\r\n var index = this._labels.indexOf(label);\r\n if (index !== -1) {\r\n this._labels.splice(index, 1);\r\n destroyLabel(this, label);\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes all labels from the collection.\r\n *\r\n * @performance O(n). It is more efficient to remove all the labels\r\n * from a collection and then add new ones than to create a new collection entirely.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * labels.add(...);\r\n * labels.add(...);\r\n * labels.removeAll();\r\n *\r\n * @see LabelCollection#add\r\n * @see LabelCollection#remove\r\n */\r\nLabelCollection.prototype.removeAll = function () {\r\n var labels = this._labels;\r\n\r\n for (var i = 0, len = labels.length; i < len; ++i) {\r\n destroyLabel(this, labels[i]);\r\n }\r\n\r\n labels.length = 0;\r\n};\r\n\r\n/**\r\n * Check whether this collection contains a given label.\r\n *\r\n * @param {Label} label The label to check for.\r\n * @returns {Boolean} true if this collection contains the label, false otherwise.\r\n *\r\n * @see LabelCollection#get\r\n *\r\n */\r\nLabelCollection.prototype.contains = function (label) {\r\n return defined(label) && label._labelCollection === this;\r\n};\r\n\r\n/**\r\n * Returns the label in the collection at the specified index. Indices are zero-based\r\n * and increase as labels are added. Removing a label shifts all labels after\r\n * it to the left, changing their indices. This function is commonly used with\r\n * {@link LabelCollection#length} to iterate over all the labels\r\n * in the collection.\r\n *\r\n * @param {Number} index The zero-based index of the billboard.\r\n *\r\n * @returns {Label} The label at the specified index.\r\n *\r\n * @performance Expected constant time. If labels were removed from the collection and\r\n * {@link Scene#render} was not called, an implicit O(n)\r\n * operation is performed.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * // Toggle the show property of every label in the collection\r\n * var len = labels.length;\r\n * for (var i = 0; i < len; ++i) {\r\n * var l = billboards.get(i);\r\n * l.show = !l.show;\r\n * }\r\n *\r\n * @see LabelCollection#length\r\n */\r\nLabelCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._labels[index];\r\n};\r\n\r\n/**\r\n * @private\r\n *\r\n */\r\nLabelCollection.prototype.update = function (frameState) {\r\n if (!this.show) {\r\n return;\r\n }\r\n\r\n var billboardCollection = this._billboardCollection;\r\n var backgroundBillboardCollection = this._backgroundBillboardCollection;\r\n\r\n billboardCollection.modelMatrix = this.modelMatrix;\r\n billboardCollection.debugShowBoundingVolume = this.debugShowBoundingVolume;\r\n backgroundBillboardCollection.modelMatrix = this.modelMatrix;\r\n backgroundBillboardCollection.debugShowBoundingVolume = this.debugShowBoundingVolume;\r\n\r\n var context = frameState.context;\r\n\r\n if (!defined(this._textureAtlas)) {\r\n this._textureAtlas = new TextureAtlas({\r\n context: context,\r\n });\r\n billboardCollection.textureAtlas = this._textureAtlas;\r\n }\r\n\r\n if (!defined(this._backgroundTextureAtlas)) {\r\n this._backgroundTextureAtlas = new TextureAtlas({\r\n context: context,\r\n initialSize: whitePixelSize,\r\n });\r\n backgroundBillboardCollection.textureAtlas = this._backgroundTextureAtlas;\r\n addWhitePixelCanvas(this._backgroundTextureAtlas, this);\r\n }\r\n\r\n var len = this._labelsToUpdate.length;\r\n for (var i = 0; i < len; ++i) {\r\n var label = this._labelsToUpdate[i];\r\n if (label.isDestroyed()) {\r\n continue;\r\n }\r\n\r\n var preUpdateGlyphCount = label._glyphs.length;\r\n\r\n if (label._rebindAllGlyphs) {\r\n rebindAllGlyphs(this, label);\r\n label._rebindAllGlyphs = false;\r\n }\r\n\r\n if (label._repositionAllGlyphs) {\r\n repositionAllGlyphs(label);\r\n label._repositionAllGlyphs = false;\r\n }\r\n\r\n var glyphCountDifference = label._glyphs.length - preUpdateGlyphCount;\r\n this._totalGlyphCount += glyphCountDifference;\r\n }\r\n\r\n var blendOption =\r\n backgroundBillboardCollection.length > 0\r\n ? BlendOption.TRANSLUCENT\r\n : this.blendOption;\r\n billboardCollection.blendOption = blendOption;\r\n backgroundBillboardCollection.blendOption = blendOption;\r\n\r\n billboardCollection._highlightColor = this._highlightColor;\r\n backgroundBillboardCollection._highlightColor = this._highlightColor;\r\n\r\n this._labelsToUpdate.length = 0;\r\n backgroundBillboardCollection.update(frameState);\r\n billboardCollection.update(frameState);\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n *\r\n * @see LabelCollection#destroy\r\n */\r\nLabelCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * labels = labels && labels.destroy();\r\n *\r\n * @see LabelCollection#isDestroyed\r\n */\r\nLabelCollection.prototype.destroy = function () {\r\n this.removeAll();\r\n this._billboardCollection = this._billboardCollection.destroy();\r\n this._textureAtlas = this._textureAtlas && this._textureAtlas.destroy();\r\n this._backgroundBillboardCollection = this._backgroundBillboardCollection.destroy();\r\n this._backgroundTextureAtlas =\r\n this._backgroundTextureAtlas && this._backgroundTextureAtlas.destroy();\r\n\r\n return destroyObject(this);\r\n};\r\nexport default LabelCollection;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 position3DHigh;\\n\\\nattribute vec3 position3DLow;\\n\\\nattribute vec3 position2DHigh;\\n\\\nattribute vec3 position2DLow;\\n\\\nattribute vec3 prevPosition3DHigh;\\n\\\nattribute vec3 prevPosition3DLow;\\n\\\nattribute vec3 prevPosition2DHigh;\\n\\\nattribute vec3 prevPosition2DLow;\\n\\\nattribute vec3 nextPosition3DHigh;\\n\\\nattribute vec3 nextPosition3DLow;\\n\\\nattribute vec3 nextPosition2DHigh;\\n\\\nattribute vec3 nextPosition2DLow;\\n\\\nattribute vec4 texCoordExpandAndBatchIndex;\\n\\\nvarying vec2 v_st;\\n\\\nvarying float v_width;\\n\\\nvarying vec4 v_pickColor;\\n\\\nvarying float v_polylineAngle;\\n\\\nvoid main()\\n\\\n{\\n\\\nfloat texCoord = texCoordExpandAndBatchIndex.x;\\n\\\nfloat expandDir = texCoordExpandAndBatchIndex.y;\\n\\\nbool usePrev = texCoordExpandAndBatchIndex.z < 0.0;\\n\\\nfloat batchTableIndex = texCoordExpandAndBatchIndex.w;\\n\\\nvec2 widthAndShow = batchTable_getWidthAndShow(batchTableIndex);\\n\\\nfloat width = widthAndShow.x + 0.5;\\n\\\nfloat show = widthAndShow.y;\\n\\\nif (width < 1.0)\\n\\\n{\\n\\\nshow = 0.0;\\n\\\n}\\n\\\nvec4 pickColor = batchTable_getPickColor(batchTableIndex);\\n\\\nvec4 p, prev, next;\\n\\\nif (czm_morphTime == 1.0)\\n\\\n{\\n\\\np = czm_translateRelativeToEye(position3DHigh.xyz, position3DLow.xyz);\\n\\\nprev = czm_translateRelativeToEye(prevPosition3DHigh.xyz, prevPosition3DLow.xyz);\\n\\\nnext = czm_translateRelativeToEye(nextPosition3DHigh.xyz, nextPosition3DLow.xyz);\\n\\\n}\\n\\\nelse if (czm_morphTime == 0.0)\\n\\\n{\\n\\\np = czm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy);\\n\\\nprev = czm_translateRelativeToEye(prevPosition2DHigh.zxy, prevPosition2DLow.zxy);\\n\\\nnext = czm_translateRelativeToEye(nextPosition2DHigh.zxy, nextPosition2DLow.zxy);\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\np = czm_columbusViewMorph(\\n\\\nczm_translateRelativeToEye(position2DHigh.zxy, position2DLow.zxy),\\n\\\nczm_translateRelativeToEye(position3DHigh.xyz, position3DLow.xyz),\\n\\\nczm_morphTime);\\n\\\nprev = czm_columbusViewMorph(\\n\\\nczm_translateRelativeToEye(prevPosition2DHigh.zxy, prevPosition2DLow.zxy),\\n\\\nczm_translateRelativeToEye(prevPosition3DHigh.xyz, prevPosition3DLow.xyz),\\n\\\nczm_morphTime);\\n\\\nnext = czm_columbusViewMorph(\\n\\\nczm_translateRelativeToEye(nextPosition2DHigh.zxy, nextPosition2DLow.zxy),\\n\\\nczm_translateRelativeToEye(nextPosition3DHigh.xyz, nextPosition3DLow.xyz),\\n\\\nczm_morphTime);\\n\\\n}\\n\\\n#ifdef DISTANCE_DISPLAY_CONDITION\\n\\\nvec3 centerHigh = batchTable_getCenterHigh(batchTableIndex);\\n\\\nvec4 centerLowAndRadius = batchTable_getCenterLowAndRadius(batchTableIndex);\\n\\\nvec3 centerLow = centerLowAndRadius.xyz;\\n\\\nfloat radius = centerLowAndRadius.w;\\n\\\nvec2 distanceDisplayCondition = batchTable_getDistanceDisplayCondition(batchTableIndex);\\n\\\nfloat lengthSq;\\n\\\nif (czm_sceneMode == czm_sceneMode2D)\\n\\\n{\\n\\\nlengthSq = czm_eyeHeight2D.y;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nvec4 center = czm_translateRelativeToEye(centerHigh.xyz, centerLow.xyz);\\n\\\nlengthSq = max(0.0, dot(center.xyz, center.xyz) - radius * radius);\\n\\\n}\\n\\\nfloat nearSq = distanceDisplayCondition.x * distanceDisplayCondition.x;\\n\\\nfloat farSq = distanceDisplayCondition.y * distanceDisplayCondition.y;\\n\\\nif (lengthSq < nearSq || lengthSq > farSq)\\n\\\n{\\n\\\nshow = 0.0;\\n\\\n}\\n\\\n#endif\\n\\\nfloat polylineAngle;\\n\\\nvec4 positionWC = getPolylineWindowCoordinates(p, prev, next, expandDir, width, usePrev, polylineAngle);\\n\\\ngl_Position = czm_viewportOrthographic * positionWC * show;\\n\\\nv_st.s = texCoord;\\n\\\nv_st.t = czm_writeNonPerspective(clamp(expandDir, 0.0, 1.0), gl_Position.w);\\n\\\nv_width = width;\\n\\\nv_pickColor = pickColor;\\n\\\nv_polylineAngle = polylineAngle;\\n\\\n}\\n\\\n\";\n","import arrayRemoveDuplicates from \"../Core/arrayRemoveDuplicates.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport PolylinePipeline from \"../Core/PolylinePipeline.js\";\r\nimport Material from \"./Material.js\";\r\n\r\n/**\r\n * A renderable polyline. Create this by calling {@link PolylineCollection#add}\r\n *\r\n * @alias Polyline\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Boolean} [options.show=true] true if this polyline will be shown; otherwise, false.\r\n * @param {Number} [options.width=1.0] The width of the polyline in pixels.\r\n * @param {Boolean} [options.loop=false] Whether a line segment will be added between the last and first line positions to make this line a loop.\r\n * @param {Material} [options.material=Material.ColorType] The material.\r\n * @param {Cartesian3[]} [options.positions] The positions.\r\n * @param {Object} [options.id] The user-defined object to be returned when this polyline is picked.\r\n * @param {DistanceDisplayCondition} [options.distanceDisplayCondition] The condition specifying at what distance from the camera that this polyline will be displayed.\r\n * @param {PolylineCollection} polylineCollection The renderable polyline collection.\r\n *\r\n * @see PolylineCollection\r\n *\r\n */\r\nfunction Polyline(options, polylineCollection) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._show = defaultValue(options.show, true);\r\n this._width = defaultValue(options.width, 1.0);\r\n this._loop = defaultValue(options.loop, false);\r\n this._distanceDisplayCondition = options.distanceDisplayCondition;\r\n\r\n this._material = options.material;\r\n if (!defined(this._material)) {\r\n this._material = Material.fromType(Material.ColorType, {\r\n color: new Color(1.0, 1.0, 1.0, 1.0),\r\n });\r\n }\r\n\r\n var positions = options.positions;\r\n if (!defined(positions)) {\r\n positions = [];\r\n }\r\n\r\n this._positions = positions;\r\n this._actualPositions = arrayRemoveDuplicates(\r\n positions,\r\n Cartesian3.equalsEpsilon\r\n );\r\n\r\n if (this._loop && this._actualPositions.length > 2) {\r\n if (this._actualPositions === this._positions) {\r\n this._actualPositions = positions.slice();\r\n }\r\n this._actualPositions.push(Cartesian3.clone(this._actualPositions[0]));\r\n }\r\n\r\n this._length = this._actualPositions.length;\r\n this._id = options.id;\r\n\r\n var modelMatrix;\r\n if (defined(polylineCollection)) {\r\n modelMatrix = Matrix4.clone(polylineCollection.modelMatrix);\r\n }\r\n\r\n this._modelMatrix = modelMatrix;\r\n this._segments = PolylinePipeline.wrapLongitude(\r\n this._actualPositions,\r\n modelMatrix\r\n );\r\n\r\n this._actualLength = undefined;\r\n\r\n // eslint-disable-next-line no-use-before-define\r\n this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES);\r\n this._polylineCollection = polylineCollection;\r\n this._dirty = false;\r\n this._pickId = undefined;\r\n this._boundingVolume = BoundingSphere.fromPoints(this._actualPositions);\r\n this._boundingVolumeWC = BoundingSphere.transform(\r\n this._boundingVolume,\r\n this._modelMatrix\r\n );\r\n this._boundingVolume2D = new BoundingSphere(); // modified in PolylineCollection\r\n}\r\n\r\nvar POSITION_INDEX = (Polyline.POSITION_INDEX = 0);\r\nvar SHOW_INDEX = (Polyline.SHOW_INDEX = 1);\r\nvar WIDTH_INDEX = (Polyline.WIDTH_INDEX = 2);\r\nvar MATERIAL_INDEX = (Polyline.MATERIAL_INDEX = 3);\r\nvar POSITION_SIZE_INDEX = (Polyline.POSITION_SIZE_INDEX = 4);\r\nvar DISTANCE_DISPLAY_CONDITION = (Polyline.DISTANCE_DISPLAY_CONDITION = 5);\r\nvar NUMBER_OF_PROPERTIES = (Polyline.NUMBER_OF_PROPERTIES = 6);\r\n\r\nfunction makeDirty(polyline, propertyChanged) {\r\n ++polyline._propertiesChanged[propertyChanged];\r\n var polylineCollection = polyline._polylineCollection;\r\n if (defined(polylineCollection)) {\r\n polylineCollection._updatePolyline(polyline, propertyChanged);\r\n polyline._dirty = true;\r\n }\r\n}\r\n\r\nObject.defineProperties(Polyline.prototype, {\r\n /**\r\n * Determines if this polyline will be shown. Use this to hide or show a polyline, instead\r\n * of removing it and re-adding it to the collection.\r\n * @memberof Polyline.prototype\r\n * @type {Boolean}\r\n */\r\n show: {\r\n get: function () {\r\n return this._show;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (value !== this._show) {\r\n this._show = value;\r\n makeDirty(this, SHOW_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the positions of the polyline.\r\n * @memberof Polyline.prototype\r\n * @type {Cartesian3[]}\r\n * @example\r\n * polyline.positions = Cesium.Cartesian3.fromDegreesArray([\r\n * 0.0, 0.0,\r\n * 10.0, 0.0,\r\n * 0.0, 20.0\r\n * ]);\r\n */\r\n positions: {\r\n get: function () {\r\n return this._positions;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var positions = arrayRemoveDuplicates(value, Cartesian3.equalsEpsilon);\r\n\r\n if (this._loop && positions.length > 2) {\r\n if (positions === value) {\r\n positions = value.slice();\r\n }\r\n positions.push(Cartesian3.clone(positions[0]));\r\n }\r\n\r\n if (\r\n this._actualPositions.length !== positions.length ||\r\n this._actualPositions.length !== this._length\r\n ) {\r\n makeDirty(this, POSITION_SIZE_INDEX);\r\n }\r\n\r\n this._positions = value;\r\n this._actualPositions = positions;\r\n this._length = positions.length;\r\n this._boundingVolume = BoundingSphere.fromPoints(\r\n this._actualPositions,\r\n this._boundingVolume\r\n );\r\n this._boundingVolumeWC = BoundingSphere.transform(\r\n this._boundingVolume,\r\n this._modelMatrix,\r\n this._boundingVolumeWC\r\n );\r\n makeDirty(this, POSITION_INDEX);\r\n\r\n this.update();\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the surface appearance of the polyline. This can be one of several built-in {@link Material} objects or a custom material, scripted with\r\n * {@link https://github.com/CesiumGS/cesium/wiki/Fabric|Fabric}.\r\n * @memberof Polyline.prototype\r\n * @type {Material}\r\n */\r\n material: {\r\n get: function () {\r\n return this._material;\r\n },\r\n set: function (material) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(material)) {\r\n throw new DeveloperError(\"material is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._material !== material) {\r\n this._material = material;\r\n makeDirty(this, MATERIAL_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the width of the polyline.\r\n * @memberof Polyline.prototype\r\n * @type {Number}\r\n */\r\n width: {\r\n get: function () {\r\n return this._width;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var width = this._width;\r\n if (value !== width) {\r\n this._width = value;\r\n makeDirty(this, WIDTH_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets whether a line segment will be added between the first and last polyline positions.\r\n * @memberof Polyline.prototype\r\n * @type {Boolean}\r\n */\r\n loop: {\r\n get: function () {\r\n return this._loop;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (value !== this._loop) {\r\n var positions = this._actualPositions;\r\n if (value) {\r\n if (\r\n positions.length > 2 &&\r\n !Cartesian3.equals(positions[0], positions[positions.length - 1])\r\n ) {\r\n if (positions.length === this._positions.length) {\r\n this._actualPositions = positions = this._positions.slice();\r\n }\r\n positions.push(Cartesian3.clone(positions[0]));\r\n }\r\n } else if (\r\n positions.length > 2 &&\r\n Cartesian3.equals(positions[0], positions[positions.length - 1])\r\n ) {\r\n if (positions.length - 1 === this._positions.length) {\r\n this._actualPositions = this._positions;\r\n } else {\r\n positions.pop();\r\n }\r\n }\r\n\r\n this._loop = value;\r\n makeDirty(this, POSITION_SIZE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the user-defined value returned when the polyline is picked.\r\n * @memberof Polyline.prototype\r\n * @type {*}\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n set: function (value) {\r\n this._id = value;\r\n if (defined(this._pickId)) {\r\n this._pickId.object.id = value;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n pickId: {\r\n get: function () {\r\n return this._pickId;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the destruction status of this polyline\r\n * @memberof Polyline.prototype\r\n * @type {Boolean}\r\n * @default false\r\n * @private\r\n */\r\n isDestroyed: {\r\n get: function () {\r\n return !defined(this._polylineCollection);\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the condition specifying at what distance from the camera that this polyline will be displayed.\r\n * @memberof Polyline.prototype\r\n * @type {DistanceDisplayCondition}\r\n * @default undefined\r\n */\r\n distanceDisplayCondition: {\r\n get: function () {\r\n return this._distanceDisplayCondition;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n if (\r\n !DistanceDisplayCondition.equals(value, this._distanceDisplayCondition)\r\n ) {\r\n this._distanceDisplayCondition = DistanceDisplayCondition.clone(\r\n value,\r\n this._distanceDisplayCondition\r\n );\r\n makeDirty(this, DISTANCE_DISPLAY_CONDITION);\r\n }\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * @private\r\n */\r\nPolyline.prototype.update = function () {\r\n var modelMatrix = Matrix4.IDENTITY;\r\n if (defined(this._polylineCollection)) {\r\n modelMatrix = this._polylineCollection.modelMatrix;\r\n }\r\n\r\n var segmentPositionsLength = this._segments.positions.length;\r\n var segmentLengths = this._segments.lengths;\r\n\r\n var positionsChanged =\r\n this._propertiesChanged[POSITION_INDEX] > 0 ||\r\n this._propertiesChanged[POSITION_SIZE_INDEX] > 0;\r\n if (!Matrix4.equals(modelMatrix, this._modelMatrix) || positionsChanged) {\r\n this._segments = PolylinePipeline.wrapLongitude(\r\n this._actualPositions,\r\n modelMatrix\r\n );\r\n this._boundingVolumeWC = BoundingSphere.transform(\r\n this._boundingVolume,\r\n modelMatrix,\r\n this._boundingVolumeWC\r\n );\r\n }\r\n\r\n this._modelMatrix = Matrix4.clone(modelMatrix, this._modelMatrix);\r\n\r\n if (this._segments.positions.length !== segmentPositionsLength) {\r\n // number of positions changed\r\n makeDirty(this, POSITION_SIZE_INDEX);\r\n } else {\r\n var length = segmentLengths.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (segmentLengths[i] !== this._segments.lengths[i]) {\r\n // indices changed\r\n makeDirty(this, POSITION_SIZE_INDEX);\r\n break;\r\n }\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPolyline.prototype.getPickId = function (context) {\r\n if (!defined(this._pickId)) {\r\n this._pickId = context.createPickId({\r\n primitive: this,\r\n collection: this._polylineCollection,\r\n id: this._id,\r\n });\r\n }\r\n return this._pickId;\r\n};\r\n\r\nPolyline.prototype._clean = function () {\r\n this._dirty = false;\r\n var properties = this._propertiesChanged;\r\n for (var k = 0; k < NUMBER_OF_PROPERTIES - 1; ++k) {\r\n properties[k] = 0;\r\n }\r\n};\r\n\r\nPolyline.prototype._destroy = function () {\r\n this._pickId = this._pickId && this._pickId.destroy();\r\n this._material = this._material && this._material.destroy();\r\n this._polylineCollection = undefined;\r\n};\r\nexport default Polyline;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport combine from \"../Core/combine.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport EncodedCartesian3 from \"../Core/EncodedCartesian3.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport Intersect from \"../Core/Intersect.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Plane from \"../Core/Plane.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport ContextLimits from \"../Renderer/ContextLimits.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport Texture from \"../Renderer/Texture.js\";\r\nimport VertexArray from \"../Renderer/VertexArray.js\";\r\nimport PolylineCommon from \"../Shaders/PolylineCommon.js\";\r\nimport PolylineFS from \"../Shaders/PolylineFS.js\";\r\nimport PolylineVS from \"../Shaders/PolylineVS.js\";\r\nimport BatchTable from \"./BatchTable.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport Material from \"./Material.js\";\r\nimport Polyline from \"./Polyline.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\n\r\nvar SHOW_INDEX = Polyline.SHOW_INDEX;\r\nvar WIDTH_INDEX = Polyline.WIDTH_INDEX;\r\nvar POSITION_INDEX = Polyline.POSITION_INDEX;\r\nvar MATERIAL_INDEX = Polyline.MATERIAL_INDEX;\r\n//POSITION_SIZE_INDEX is needed for when the polyline's position array changes size.\r\n//When it does, we need to recreate the indicesBuffer.\r\nvar POSITION_SIZE_INDEX = Polyline.POSITION_SIZE_INDEX;\r\nvar DISTANCE_DISPLAY_CONDITION = Polyline.DISTANCE_DISPLAY_CONDITION;\r\nvar NUMBER_OF_PROPERTIES = Polyline.NUMBER_OF_PROPERTIES;\r\n\r\nvar attributeLocations = {\r\n texCoordExpandAndBatchIndex: 0,\r\n position3DHigh: 1,\r\n position3DLow: 2,\r\n position2DHigh: 3,\r\n position2DLow: 4,\r\n prevPosition3DHigh: 5,\r\n prevPosition3DLow: 6,\r\n prevPosition2DHigh: 7,\r\n prevPosition2DLow: 8,\r\n nextPosition3DHigh: 9,\r\n nextPosition3DLow: 10,\r\n nextPosition2DHigh: 11,\r\n nextPosition2DLow: 12,\r\n};\r\n\r\n/**\r\n * A renderable collection of polylines.\r\n *

\r\n *
\r\n *
\r\n * Example polylines\r\n *
\r\n *

\r\n * Polylines are added and removed from the collection using {@link PolylineCollection#add}\r\n * and {@link PolylineCollection#remove}.\r\n *\r\n * @alias PolylineCollection\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms each polyline from model to world coordinates.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.\r\n * @param {Boolean} [options.show=true] Determines if the polylines in the collection will be shown.\r\n *\r\n * @performance For best performance, prefer a few collections, each with many polylines, to\r\n * many collections with only a few polylines each. Organize collections so that polylines\r\n * with the same update frequency are in the same collection, i.e., polylines that do not\r\n * change should be in one collection; polylines that change every frame should be in another\r\n * collection; and so on.\r\n *\r\n * @see PolylineCollection#add\r\n * @see PolylineCollection#remove\r\n * @see Polyline\r\n * @see LabelCollection\r\n *\r\n * @example\r\n * // Create a polyline collection with two polylines\r\n * var polylines = new Cesium.PolylineCollection();\r\n * polylines.add({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * -75.10, 39.57,\r\n * -77.02, 38.53,\r\n * -80.50, 35.14,\r\n * -80.12, 25.46]),\r\n * width : 2\r\n * });\r\n *\r\n * polylines.add({\r\n * positions : Cesium.Cartesian3.fromDegreesArray([\r\n * -73.10, 37.57,\r\n * -75.02, 36.53,\r\n * -78.50, 33.14,\r\n * -78.12, 23.46]),\r\n * width : 4\r\n * });\r\n */\r\nfunction PolylineCollection(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n /**\r\n * Determines if polylines in this collection will be shown.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * The 4x4 transformation matrix that transforms each polyline in this collection from model to world coordinates.\r\n * When this is the identity matrix, the polylines are drawn in world coordinates, i.e., Earth's WGS84 coordinates.\r\n * Local reference frames can be used by providing a different transformation matrix, like that returned\r\n * by {@link Transforms.eastNorthUpToFixedFrame}.\r\n *\r\n * @type {Matrix4}\r\n * @default {@link Matrix4.IDENTITY}\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n this._modelMatrix = Matrix4.clone(Matrix4.IDENTITY);\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n\r\n this._opaqueRS = undefined;\r\n this._translucentRS = undefined;\r\n\r\n this._colorCommands = [];\r\n\r\n this._polylinesUpdated = false;\r\n this._polylinesRemoved = false;\r\n this._createVertexArray = false;\r\n this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES);\r\n this._polylines = [];\r\n this._polylineBuckets = {};\r\n\r\n // The buffer usage is determined based on the usage of the attribute over time.\r\n this._positionBufferUsage = {\r\n bufferUsage: BufferUsage.STATIC_DRAW,\r\n frameCount: 0,\r\n };\r\n\r\n this._mode = undefined;\r\n\r\n this._polylinesToUpdate = [];\r\n this._vertexArrays = [];\r\n this._positionBuffer = undefined;\r\n this._texCoordExpandAndBatchIndexBuffer = undefined;\r\n\r\n this._batchTable = undefined;\r\n this._createBatchTable = false;\r\n\r\n // Only used by Vector3DTilePoints\r\n this._useHighlightColor = false;\r\n this._highlightColor = Color.clone(Color.WHITE);\r\n\r\n var that = this;\r\n this._uniformMap = {\r\n u_highlightColor: function () {\r\n return that._highlightColor;\r\n },\r\n };\r\n}\r\n\r\nObject.defineProperties(PolylineCollection.prototype, {\r\n /**\r\n * Returns the number of polylines in this collection. This is commonly used with\r\n * {@link PolylineCollection#get} to iterate over all the polylines\r\n * in the collection.\r\n * @memberof PolylineCollection.prototype\r\n * @type {Number}\r\n */\r\n length: {\r\n get: function () {\r\n removePolylines(this);\r\n return this._polylines.length;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates and adds a polyline with the specified initial properties to the collection.\r\n * The added polyline is returned so it can be modified or removed from the collection later.\r\n *\r\n * @param {Object}[options] A template describing the polyline's properties as shown in Example 1.\r\n * @returns {Polyline} The polyline that was added to the collection.\r\n *\r\n * @performance After calling add, {@link PolylineCollection#update} is called and\r\n * the collection's vertex buffer is rewritten - an O(n) operation that also incurs CPU to GPU overhead.\r\n * For best performance, add as many polylines as possible before calling update.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * // Example 1: Add a polyline, specifying all the default values.\r\n * var p = polylines.add({\r\n * show : true,\r\n * positions : ellipsoid.cartographicArrayToCartesianArray([\r\n Cesium.Cartographic.fromDegrees(-75.10, 39.57),\r\n Cesium.Cartographic.fromDegrees(-77.02, 38.53)]),\r\n * width : 1\r\n * });\r\n *\r\n * @see PolylineCollection#remove\r\n * @see PolylineCollection#removeAll\r\n * @see PolylineCollection#update\r\n */\r\nPolylineCollection.prototype.add = function (options) {\r\n var p = new Polyline(options, this);\r\n p._index = this._polylines.length;\r\n this._polylines.push(p);\r\n this._createVertexArray = true;\r\n this._createBatchTable = true;\r\n return p;\r\n};\r\n\r\n/**\r\n * Removes a polyline from the collection.\r\n *\r\n * @param {Polyline} polyline The polyline to remove.\r\n * @returns {Boolean} true if the polyline was removed; false if the polyline was not found in the collection.\r\n *\r\n * @performance After calling remove, {@link PolylineCollection#update} is called and\r\n * the collection's vertex buffer is rewritten - an O(n) operation that also incurs CPU to GPU overhead.\r\n * For best performance, remove as many polylines as possible before calling update.\r\n * If you intend to temporarily hide a polyline, it is usually more efficient to call\r\n * {@link Polyline#show} instead of removing and re-adding the polyline.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * var p = polylines.add(...);\r\n * polylines.remove(p); // Returns true\r\n *\r\n * @see PolylineCollection#add\r\n * @see PolylineCollection#removeAll\r\n * @see PolylineCollection#update\r\n * @see Polyline#show\r\n */\r\nPolylineCollection.prototype.remove = function (polyline) {\r\n if (this.contains(polyline)) {\r\n this._polylinesRemoved = true;\r\n this._createVertexArray = true;\r\n this._createBatchTable = true;\r\n if (defined(polyline._bucket)) {\r\n var bucket = polyline._bucket;\r\n bucket.shaderProgram =\r\n bucket.shaderProgram && bucket.shaderProgram.destroy();\r\n }\r\n polyline._destroy();\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes all polylines from the collection.\r\n *\r\n * @performance O(n). It is more efficient to remove all the polylines\r\n * from a collection and then add new ones than to create a new collection entirely.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * polylines.add(...);\r\n * polylines.add(...);\r\n * polylines.removeAll();\r\n *\r\n * @see PolylineCollection#add\r\n * @see PolylineCollection#remove\r\n * @see PolylineCollection#update\r\n */\r\nPolylineCollection.prototype.removeAll = function () {\r\n releaseShaders(this);\r\n destroyPolylines(this);\r\n this._polylineBuckets = {};\r\n this._polylinesRemoved = false;\r\n this._polylines.length = 0;\r\n this._polylinesToUpdate.length = 0;\r\n this._createVertexArray = true;\r\n};\r\n\r\n/**\r\n * Determines if this collection contains the specified polyline.\r\n *\r\n * @param {Polyline} polyline The polyline to check for.\r\n * @returns {Boolean} true if this collection contains the polyline, false otherwise.\r\n *\r\n * @see PolylineCollection#get\r\n */\r\nPolylineCollection.prototype.contains = function (polyline) {\r\n return defined(polyline) && polyline._polylineCollection === this;\r\n};\r\n\r\n/**\r\n * Returns the polyline in the collection at the specified index. Indices are zero-based\r\n * and increase as polylines are added. Removing a polyline shifts all polylines after\r\n * it to the left, changing their indices. This function is commonly used with\r\n * {@link PolylineCollection#length} to iterate over all the polylines\r\n * in the collection.\r\n *\r\n * @param {Number} index The zero-based index of the polyline.\r\n * @returns {Polyline} The polyline at the specified index.\r\n *\r\n * @performance If polylines were removed from the collection and\r\n * {@link PolylineCollection#update} was not called, an implicit O(n)\r\n * operation is performed.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * // Toggle the show property of every polyline in the collection\r\n * var len = polylines.length;\r\n * for (var i = 0; i < len; ++i) {\r\n * var p = polylines.get(i);\r\n * p.show = !p.show;\r\n * }\r\n *\r\n * @see PolylineCollection#length\r\n */\r\nPolylineCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n removePolylines(this);\r\n return this._polylines[index];\r\n};\r\n\r\nfunction createBatchTable(collection, context) {\r\n if (defined(collection._batchTable)) {\r\n collection._batchTable.destroy();\r\n }\r\n\r\n var attributes = [\r\n {\r\n functionName: \"batchTable_getWidthAndShow\",\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 2,\r\n },\r\n {\r\n functionName: \"batchTable_getPickColor\",\r\n componentDatatype: ComponentDatatype.UNSIGNED_BYTE,\r\n componentsPerAttribute: 4,\r\n normalize: true,\r\n },\r\n {\r\n functionName: \"batchTable_getCenterHigh\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n functionName: \"batchTable_getCenterLowAndRadius\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n },\r\n {\r\n functionName: \"batchTable_getDistanceDisplayCondition\",\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n },\r\n ];\r\n\r\n collection._batchTable = new BatchTable(\r\n context,\r\n attributes,\r\n collection._polylines.length\r\n );\r\n}\r\n\r\nvar scratchUpdatePolylineEncodedCartesian = new EncodedCartesian3();\r\nvar scratchUpdatePolylineCartesian4 = new Cartesian4();\r\nvar scratchNearFarCartesian2 = new Cartesian2();\r\n\r\n/**\r\n * Called when {@link Viewer} or {@link CesiumWidget} render the scene to\r\n * get the draw commands needed to render this primitive.\r\n *

\r\n * Do not call this function directly. This is documented just to\r\n * list the exceptions that may be propagated when the scene is rendered:\r\n *

\r\n *\r\n * @exception {RuntimeError} Vertex texture fetch support is required to render primitives with per-instance attributes. The maximum number of vertex texture image units must be greater than zero.\r\n */\r\nPolylineCollection.prototype.update = function (frameState) {\r\n removePolylines(this);\r\n\r\n if (this._polylines.length === 0 || !this.show) {\r\n return;\r\n }\r\n\r\n updateMode(this, frameState);\r\n\r\n var context = frameState.context;\r\n var projection = frameState.mapProjection;\r\n var polyline;\r\n var properties = this._propertiesChanged;\r\n\r\n if (this._createBatchTable) {\r\n if (ContextLimits.maximumVertexTextureImageUnits === 0) {\r\n throw new RuntimeError(\r\n \"Vertex texture fetch support is required to render polylines. The maximum number of vertex texture image units must be greater than zero.\"\r\n );\r\n }\r\n createBatchTable(this, context);\r\n this._createBatchTable = false;\r\n }\r\n\r\n if (this._createVertexArray || computeNewBuffersUsage(this)) {\r\n createVertexArrays(this, context, projection);\r\n } else if (this._polylinesUpdated) {\r\n // Polylines were modified, but no polylines were added or removed.\r\n var polylinesToUpdate = this._polylinesToUpdate;\r\n if (this._mode !== SceneMode.SCENE3D) {\r\n var updateLength = polylinesToUpdate.length;\r\n for (var i = 0; i < updateLength; ++i) {\r\n polyline = polylinesToUpdate[i];\r\n polyline.update();\r\n }\r\n }\r\n\r\n // if a polyline's positions size changes, we need to recreate the vertex arrays and vertex buffers because the indices will be different.\r\n // if a polyline's material changes, we need to recreate the VAOs and VBOs because they will be batched differently.\r\n if (properties[POSITION_SIZE_INDEX] || properties[MATERIAL_INDEX]) {\r\n createVertexArrays(this, context, projection);\r\n } else {\r\n var length = polylinesToUpdate.length;\r\n var polylineBuckets = this._polylineBuckets;\r\n for (var ii = 0; ii < length; ++ii) {\r\n polyline = polylinesToUpdate[ii];\r\n properties = polyline._propertiesChanged;\r\n var bucket = polyline._bucket;\r\n var index = 0;\r\n for (var x in polylineBuckets) {\r\n if (polylineBuckets.hasOwnProperty(x)) {\r\n if (polylineBuckets[x] === bucket) {\r\n if (properties[POSITION_INDEX]) {\r\n bucket.writeUpdate(\r\n index,\r\n polyline,\r\n this._positionBuffer,\r\n projection\r\n );\r\n }\r\n break;\r\n }\r\n index += polylineBuckets[x].lengthOfPositions;\r\n }\r\n }\r\n\r\n if (properties[SHOW_INDEX] || properties[WIDTH_INDEX]) {\r\n this._batchTable.setBatchedAttribute(\r\n polyline._index,\r\n 0,\r\n new Cartesian2(polyline._width, polyline._show)\r\n );\r\n }\r\n\r\n if (this._batchTable.attributes.length > 2) {\r\n if (properties[POSITION_INDEX] || properties[POSITION_SIZE_INDEX]) {\r\n var boundingSphere =\r\n frameState.mode === SceneMode.SCENE2D\r\n ? polyline._boundingVolume2D\r\n : polyline._boundingVolumeWC;\r\n var encodedCenter = EncodedCartesian3.fromCartesian(\r\n boundingSphere.center,\r\n scratchUpdatePolylineEncodedCartesian\r\n );\r\n var low = Cartesian4.fromElements(\r\n encodedCenter.low.x,\r\n encodedCenter.low.y,\r\n encodedCenter.low.z,\r\n boundingSphere.radius,\r\n scratchUpdatePolylineCartesian4\r\n );\r\n this._batchTable.setBatchedAttribute(\r\n polyline._index,\r\n 2,\r\n encodedCenter.high\r\n );\r\n this._batchTable.setBatchedAttribute(polyline._index, 3, low);\r\n }\r\n\r\n if (properties[DISTANCE_DISPLAY_CONDITION]) {\r\n var nearFarCartesian = scratchNearFarCartesian2;\r\n nearFarCartesian.x = 0.0;\r\n nearFarCartesian.y = Number.MAX_VALUE;\r\n\r\n var distanceDisplayCondition = polyline.distanceDisplayCondition;\r\n if (defined(distanceDisplayCondition)) {\r\n nearFarCartesian.x = distanceDisplayCondition.near;\r\n nearFarCartesian.y = distanceDisplayCondition.far;\r\n }\r\n\r\n this._batchTable.setBatchedAttribute(\r\n polyline._index,\r\n 4,\r\n nearFarCartesian\r\n );\r\n }\r\n }\r\n\r\n polyline._clean();\r\n }\r\n }\r\n polylinesToUpdate.length = 0;\r\n this._polylinesUpdated = false;\r\n }\r\n\r\n properties = this._propertiesChanged;\r\n for (var k = 0; k < NUMBER_OF_PROPERTIES; ++k) {\r\n properties[k] = 0;\r\n }\r\n\r\n var modelMatrix = Matrix4.IDENTITY;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n modelMatrix = this.modelMatrix;\r\n }\r\n\r\n var pass = frameState.passes;\r\n var useDepthTest = frameState.morphTime !== 0.0;\r\n\r\n if (\r\n !defined(this._opaqueRS) ||\r\n this._opaqueRS.depthTest.enabled !== useDepthTest\r\n ) {\r\n this._opaqueRS = RenderState.fromCache({\r\n depthMask: useDepthTest,\r\n depthTest: {\r\n enabled: useDepthTest,\r\n },\r\n });\r\n }\r\n\r\n if (\r\n !defined(this._translucentRS) ||\r\n this._translucentRS.depthTest.enabled !== useDepthTest\r\n ) {\r\n this._translucentRS = RenderState.fromCache({\r\n blending: BlendingState.ALPHA_BLEND,\r\n depthMask: !useDepthTest,\r\n depthTest: {\r\n enabled: useDepthTest,\r\n },\r\n });\r\n }\r\n\r\n this._batchTable.update(frameState);\r\n\r\n if (pass.render || pass.pick) {\r\n var colorList = this._colorCommands;\r\n createCommandLists(this, frameState, colorList, modelMatrix);\r\n }\r\n};\r\n\r\nvar boundingSphereScratch = new BoundingSphere();\r\nvar boundingSphereScratch2 = new BoundingSphere();\r\n\r\nfunction createCommandLists(\r\n polylineCollection,\r\n frameState,\r\n commands,\r\n modelMatrix\r\n) {\r\n var context = frameState.context;\r\n var commandList = frameState.commandList;\r\n\r\n var commandsLength = commands.length;\r\n var commandIndex = 0;\r\n var cloneBoundingSphere = true;\r\n\r\n var vertexArrays = polylineCollection._vertexArrays;\r\n var debugShowBoundingVolume = polylineCollection.debugShowBoundingVolume;\r\n\r\n var batchTable = polylineCollection._batchTable;\r\n var uniformCallback = batchTable.getUniformMapCallback();\r\n\r\n var length = vertexArrays.length;\r\n for (var m = 0; m < length; ++m) {\r\n var va = vertexArrays[m];\r\n var buckets = va.buckets;\r\n var bucketLength = buckets.length;\r\n\r\n for (var n = 0; n < bucketLength; ++n) {\r\n var bucketLocator = buckets[n];\r\n\r\n var offset = bucketLocator.offset;\r\n var sp = bucketLocator.bucket.shaderProgram;\r\n\r\n var polylines = bucketLocator.bucket.polylines;\r\n var polylineLength = polylines.length;\r\n var currentId;\r\n var currentMaterial;\r\n var count = 0;\r\n var command;\r\n var uniformMap;\r\n\r\n for (var s = 0; s < polylineLength; ++s) {\r\n var polyline = polylines[s];\r\n var mId = createMaterialId(polyline._material);\r\n if (mId !== currentId) {\r\n if (defined(currentId) && count > 0) {\r\n var translucent = currentMaterial.isTranslucent();\r\n\r\n if (commandIndex >= commandsLength) {\r\n command = new DrawCommand({\r\n owner: polylineCollection,\r\n });\r\n commands.push(command);\r\n } else {\r\n command = commands[commandIndex];\r\n }\r\n\r\n ++commandIndex;\r\n\r\n uniformMap = combine(\r\n uniformCallback(currentMaterial._uniforms),\r\n polylineCollection._uniformMap\r\n );\r\n\r\n command.boundingVolume = BoundingSphere.clone(\r\n boundingSphereScratch,\r\n command.boundingVolume\r\n );\r\n command.modelMatrix = modelMatrix;\r\n command.shaderProgram = sp;\r\n command.vertexArray = va.va;\r\n command.renderState = translucent\r\n ? polylineCollection._translucentRS\r\n : polylineCollection._opaqueRS;\r\n command.pass = translucent ? Pass.TRANSLUCENT : Pass.OPAQUE;\r\n command.debugShowBoundingVolume = debugShowBoundingVolume;\r\n command.pickId = \"v_pickColor\";\r\n\r\n command.uniformMap = uniformMap;\r\n command.count = count;\r\n command.offset = offset;\r\n\r\n offset += count;\r\n count = 0;\r\n cloneBoundingSphere = true;\r\n\r\n commandList.push(command);\r\n }\r\n\r\n currentMaterial = polyline._material;\r\n currentMaterial.update(context);\r\n currentId = mId;\r\n }\r\n\r\n var locators = polyline._locatorBuckets;\r\n var locatorLength = locators.length;\r\n for (var t = 0; t < locatorLength; ++t) {\r\n var locator = locators[t];\r\n if (locator.locator === bucketLocator) {\r\n count += locator.count;\r\n }\r\n }\r\n\r\n var boundingVolume;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n boundingVolume = polyline._boundingVolumeWC;\r\n } else if (frameState.mode === SceneMode.COLUMBUS_VIEW) {\r\n boundingVolume = polyline._boundingVolume2D;\r\n } else if (frameState.mode === SceneMode.SCENE2D) {\r\n if (defined(polyline._boundingVolume2D)) {\r\n boundingVolume = BoundingSphere.clone(\r\n polyline._boundingVolume2D,\r\n boundingSphereScratch2\r\n );\r\n boundingVolume.center.x = 0.0;\r\n }\r\n } else if (\r\n defined(polyline._boundingVolumeWC) &&\r\n defined(polyline._boundingVolume2D)\r\n ) {\r\n boundingVolume = BoundingSphere.union(\r\n polyline._boundingVolumeWC,\r\n polyline._boundingVolume2D,\r\n boundingSphereScratch2\r\n );\r\n }\r\n\r\n if (cloneBoundingSphere) {\r\n cloneBoundingSphere = false;\r\n BoundingSphere.clone(boundingVolume, boundingSphereScratch);\r\n } else {\r\n BoundingSphere.union(\r\n boundingVolume,\r\n boundingSphereScratch,\r\n boundingSphereScratch\r\n );\r\n }\r\n }\r\n\r\n if (defined(currentId) && count > 0) {\r\n if (commandIndex >= commandsLength) {\r\n command = new DrawCommand({\r\n owner: polylineCollection,\r\n });\r\n commands.push(command);\r\n } else {\r\n command = commands[commandIndex];\r\n }\r\n\r\n ++commandIndex;\r\n\r\n uniformMap = combine(\r\n uniformCallback(currentMaterial._uniforms),\r\n polylineCollection._uniformMap\r\n );\r\n\r\n command.boundingVolume = BoundingSphere.clone(\r\n boundingSphereScratch,\r\n command.boundingVolume\r\n );\r\n command.modelMatrix = modelMatrix;\r\n command.shaderProgram = sp;\r\n command.vertexArray = va.va;\r\n command.renderState = currentMaterial.isTranslucent()\r\n ? polylineCollection._translucentRS\r\n : polylineCollection._opaqueRS;\r\n command.pass = currentMaterial.isTranslucent()\r\n ? Pass.TRANSLUCENT\r\n : Pass.OPAQUE;\r\n command.debugShowBoundingVolume = debugShowBoundingVolume;\r\n command.pickId = \"v_pickColor\";\r\n\r\n command.uniformMap = uniformMap;\r\n command.count = count;\r\n command.offset = offset;\r\n\r\n cloneBoundingSphere = true;\r\n\r\n commandList.push(command);\r\n }\r\n\r\n currentId = undefined;\r\n }\r\n }\r\n\r\n commands.length = commandIndex;\r\n}\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see PolylineCollection#destroy\r\n */\r\nPolylineCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * polylines = polylines && polylines.destroy();\r\n *\r\n * @see PolylineCollection#isDestroyed\r\n */\r\nPolylineCollection.prototype.destroy = function () {\r\n destroyVertexArrays(this);\r\n releaseShaders(this);\r\n destroyPolylines(this);\r\n this._batchTable = this._batchTable && this._batchTable.destroy();\r\n return destroyObject(this);\r\n};\r\n\r\nfunction computeNewBuffersUsage(collection) {\r\n var usageChanged = false;\r\n var properties = collection._propertiesChanged;\r\n var bufferUsage = collection._positionBufferUsage;\r\n if (properties[POSITION_INDEX]) {\r\n if (bufferUsage.bufferUsage !== BufferUsage.STREAM_DRAW) {\r\n usageChanged = true;\r\n bufferUsage.bufferUsage = BufferUsage.STREAM_DRAW;\r\n bufferUsage.frameCount = 100;\r\n } else {\r\n bufferUsage.frameCount = 100;\r\n }\r\n } else if (bufferUsage.bufferUsage !== BufferUsage.STATIC_DRAW) {\r\n if (bufferUsage.frameCount === 0) {\r\n usageChanged = true;\r\n bufferUsage.bufferUsage = BufferUsage.STATIC_DRAW;\r\n } else {\r\n bufferUsage.frameCount--;\r\n }\r\n }\r\n\r\n return usageChanged;\r\n}\r\n\r\nvar emptyVertexBuffer = [0.0, 0.0, 0.0];\r\n\r\nfunction createVertexArrays(collection, context, projection) {\r\n collection._createVertexArray = false;\r\n releaseShaders(collection);\r\n destroyVertexArrays(collection);\r\n sortPolylinesIntoBuckets(collection);\r\n\r\n //stores all of the individual indices arrays.\r\n var totalIndices = [[]];\r\n var indices = totalIndices[0];\r\n\r\n var batchTable = collection._batchTable;\r\n var useHighlightColor = collection._useHighlightColor;\r\n\r\n //used to determine the vertexBuffer offset if the indicesArray goes over 64k.\r\n //if it's the same polyline while it goes over 64k, the offset needs to backtrack componentsPerAttribute * componentDatatype bytes\r\n //so that the polyline looks contiguous.\r\n //if the polyline ends at the 64k mark, then the offset is just 64k * componentsPerAttribute * componentDatatype\r\n var vertexBufferOffset = [0];\r\n var offset = 0;\r\n var vertexArrayBuckets = [[]];\r\n var totalLength = 0;\r\n var polylineBuckets = collection._polylineBuckets;\r\n var x;\r\n var bucket;\r\n for (x in polylineBuckets) {\r\n if (polylineBuckets.hasOwnProperty(x)) {\r\n bucket = polylineBuckets[x];\r\n bucket.updateShader(context, batchTable, useHighlightColor);\r\n totalLength += bucket.lengthOfPositions;\r\n }\r\n }\r\n\r\n if (totalLength > 0) {\r\n var mode = collection._mode;\r\n\r\n var positionArray = new Float32Array(6 * totalLength * 3);\r\n var texCoordExpandAndBatchIndexArray = new Float32Array(totalLength * 4);\r\n var position3DArray;\r\n\r\n var positionIndex = 0;\r\n var colorIndex = 0;\r\n var texCoordExpandAndBatchIndexIndex = 0;\r\n for (x in polylineBuckets) {\r\n if (polylineBuckets.hasOwnProperty(x)) {\r\n bucket = polylineBuckets[x];\r\n bucket.write(\r\n positionArray,\r\n texCoordExpandAndBatchIndexArray,\r\n positionIndex,\r\n colorIndex,\r\n texCoordExpandAndBatchIndexIndex,\r\n batchTable,\r\n context,\r\n projection\r\n );\r\n\r\n if (mode === SceneMode.MORPHING) {\r\n if (!defined(position3DArray)) {\r\n position3DArray = new Float32Array(6 * totalLength * 3);\r\n }\r\n bucket.writeForMorph(position3DArray, positionIndex);\r\n }\r\n\r\n var bucketLength = bucket.lengthOfPositions;\r\n positionIndex += 6 * bucketLength * 3;\r\n colorIndex += bucketLength * 4;\r\n texCoordExpandAndBatchIndexIndex += bucketLength * 4;\r\n offset = bucket.updateIndices(\r\n totalIndices,\r\n vertexBufferOffset,\r\n vertexArrayBuckets,\r\n offset\r\n );\r\n }\r\n }\r\n\r\n var positionBufferUsage = collection._positionBufferUsage.bufferUsage;\r\n var texCoordExpandAndBatchIndexBufferUsage = BufferUsage.STATIC_DRAW;\r\n\r\n collection._positionBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: positionArray,\r\n usage: positionBufferUsage,\r\n });\r\n var position3DBuffer;\r\n if (defined(position3DArray)) {\r\n position3DBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: position3DArray,\r\n usage: positionBufferUsage,\r\n });\r\n }\r\n collection._texCoordExpandAndBatchIndexBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: texCoordExpandAndBatchIndexArray,\r\n usage: texCoordExpandAndBatchIndexBufferUsage,\r\n });\r\n\r\n var positionSizeInBytes = 3 * Float32Array.BYTES_PER_ELEMENT;\r\n var texCoordExpandAndBatchIndexSizeInBytes =\r\n 4 * Float32Array.BYTES_PER_ELEMENT;\r\n\r\n var vbo = 0;\r\n var numberOfIndicesArrays = totalIndices.length;\r\n for (var k = 0; k < numberOfIndicesArrays; ++k) {\r\n indices = totalIndices[k];\r\n\r\n if (indices.length > 0) {\r\n var indicesArray = new Uint16Array(indices);\r\n var indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: indicesArray,\r\n usage: BufferUsage.STATIC_DRAW,\r\n indexDatatype: IndexDatatype.UNSIGNED_SHORT,\r\n });\r\n\r\n vbo += vertexBufferOffset[k];\r\n\r\n var positionHighOffset =\r\n 6 *\r\n (k * (positionSizeInBytes * CesiumMath.SIXTY_FOUR_KILOBYTES) -\r\n vbo * positionSizeInBytes); //componentsPerAttribute(3) * componentDatatype(4)\r\n var positionLowOffset = positionSizeInBytes + positionHighOffset;\r\n var prevPositionHighOffset = positionSizeInBytes + positionLowOffset;\r\n var prevPositionLowOffset =\r\n positionSizeInBytes + prevPositionHighOffset;\r\n var nextPositionHighOffset =\r\n positionSizeInBytes + prevPositionLowOffset;\r\n var nextPositionLowOffset =\r\n positionSizeInBytes + nextPositionHighOffset;\r\n var vertexTexCoordExpandAndBatchIndexBufferOffset =\r\n k *\r\n (texCoordExpandAndBatchIndexSizeInBytes *\r\n CesiumMath.SIXTY_FOUR_KILOBYTES) -\r\n vbo * texCoordExpandAndBatchIndexSizeInBytes;\r\n\r\n var attributes = [\r\n {\r\n index: attributeLocations.position3DHigh,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: positionHighOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.position3DLow,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: positionLowOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.position2DHigh,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: positionHighOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.position2DLow,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: positionLowOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.prevPosition3DHigh,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: prevPositionHighOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.prevPosition3DLow,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: prevPositionLowOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.prevPosition2DHigh,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: prevPositionHighOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.prevPosition2DLow,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: prevPositionLowOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.nextPosition3DHigh,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: nextPositionHighOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.nextPosition3DLow,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: nextPositionLowOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.nextPosition2DHigh,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: nextPositionHighOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.nextPosition2DLow,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n offsetInBytes: nextPositionLowOffset,\r\n strideInBytes: 6 * positionSizeInBytes,\r\n },\r\n {\r\n index: attributeLocations.texCoordExpandAndBatchIndex,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n vertexBuffer: collection._texCoordExpandAndBatchIndexBuffer,\r\n offsetInBytes: vertexTexCoordExpandAndBatchIndexBufferOffset,\r\n },\r\n ];\r\n\r\n var buffer3D;\r\n var bufferProperty3D;\r\n var buffer2D;\r\n var bufferProperty2D;\r\n\r\n if (mode === SceneMode.SCENE3D) {\r\n buffer3D = collection._positionBuffer;\r\n bufferProperty3D = \"vertexBuffer\";\r\n buffer2D = emptyVertexBuffer;\r\n bufferProperty2D = \"value\";\r\n } else if (\r\n mode === SceneMode.SCENE2D ||\r\n mode === SceneMode.COLUMBUS_VIEW\r\n ) {\r\n buffer3D = emptyVertexBuffer;\r\n bufferProperty3D = \"value\";\r\n buffer2D = collection._positionBuffer;\r\n bufferProperty2D = \"vertexBuffer\";\r\n } else {\r\n buffer3D = position3DBuffer;\r\n bufferProperty3D = \"vertexBuffer\";\r\n buffer2D = collection._positionBuffer;\r\n bufferProperty2D = \"vertexBuffer\";\r\n }\r\n\r\n attributes[0][bufferProperty3D] = buffer3D;\r\n attributes[1][bufferProperty3D] = buffer3D;\r\n attributes[2][bufferProperty2D] = buffer2D;\r\n attributes[3][bufferProperty2D] = buffer2D;\r\n attributes[4][bufferProperty3D] = buffer3D;\r\n attributes[5][bufferProperty3D] = buffer3D;\r\n attributes[6][bufferProperty2D] = buffer2D;\r\n attributes[7][bufferProperty2D] = buffer2D;\r\n attributes[8][bufferProperty3D] = buffer3D;\r\n attributes[9][bufferProperty3D] = buffer3D;\r\n attributes[10][bufferProperty2D] = buffer2D;\r\n attributes[11][bufferProperty2D] = buffer2D;\r\n\r\n var va = new VertexArray({\r\n context: context,\r\n attributes: attributes,\r\n indexBuffer: indexBuffer,\r\n });\r\n collection._vertexArrays.push({\r\n va: va,\r\n buckets: vertexArrayBuckets[k],\r\n });\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction replacer(key, value) {\r\n if (value instanceof Texture) {\r\n return value.id;\r\n }\r\n\r\n return value;\r\n}\r\n\r\nvar scratchUniformArray = [];\r\nfunction createMaterialId(material) {\r\n var uniforms = Material._uniformList[material.type];\r\n var length = uniforms.length;\r\n scratchUniformArray.length = 2.0 * length;\r\n\r\n var index = 0;\r\n for (var i = 0; i < length; ++i) {\r\n var uniform = uniforms[i];\r\n scratchUniformArray[index] = uniform;\r\n scratchUniformArray[index + 1] = material._uniforms[uniform]();\r\n index += 2;\r\n }\r\n\r\n return material.type + \":\" + JSON.stringify(scratchUniformArray, replacer);\r\n}\r\n\r\nfunction sortPolylinesIntoBuckets(collection) {\r\n var mode = collection._mode;\r\n var modelMatrix = collection._modelMatrix;\r\n\r\n var polylineBuckets = (collection._polylineBuckets = {});\r\n var polylines = collection._polylines;\r\n var length = polylines.length;\r\n for (var i = 0; i < length; ++i) {\r\n var p = polylines[i];\r\n if (p._actualPositions.length > 1) {\r\n p.update();\r\n var material = p.material;\r\n var value = polylineBuckets[material.type];\r\n if (!defined(value)) {\r\n value = polylineBuckets[material.type] = new PolylineBucket(\r\n material,\r\n mode,\r\n modelMatrix\r\n );\r\n }\r\n value.addPolyline(p);\r\n }\r\n }\r\n}\r\n\r\nfunction updateMode(collection, frameState) {\r\n var mode = frameState.mode;\r\n\r\n if (\r\n collection._mode !== mode ||\r\n !Matrix4.equals(collection._modelMatrix, collection.modelMatrix)\r\n ) {\r\n collection._mode = mode;\r\n collection._modelMatrix = Matrix4.clone(collection.modelMatrix);\r\n collection._createVertexArray = true;\r\n }\r\n}\r\n\r\nfunction removePolylines(collection) {\r\n if (collection._polylinesRemoved) {\r\n collection._polylinesRemoved = false;\r\n var definedPolylines = [];\r\n var definedPolylinesToUpdate = [];\r\n var polyIndex = 0;\r\n var polyline;\r\n\r\n var length = collection._polylines.length;\r\n for (var i = 0; i < length; ++i) {\r\n polyline = collection._polylines[i];\r\n if (!polyline.isDestroyed) {\r\n polyline._index = polyIndex++;\r\n definedPolylinesToUpdate.push(polyline);\r\n definedPolylines.push(polyline);\r\n }\r\n }\r\n\r\n collection._polylines = definedPolylines;\r\n collection._polylinesToUpdate = definedPolylinesToUpdate;\r\n }\r\n}\r\n\r\nfunction releaseShaders(collection) {\r\n var polylines = collection._polylines;\r\n var length = polylines.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (!polylines[i].isDestroyed) {\r\n var bucket = polylines[i]._bucket;\r\n if (defined(bucket)) {\r\n bucket.shaderProgram =\r\n bucket.shaderProgram && bucket.shaderProgram.destroy();\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction destroyVertexArrays(collection) {\r\n var length = collection._vertexArrays.length;\r\n for (var t = 0; t < length; ++t) {\r\n collection._vertexArrays[t].va.destroy();\r\n }\r\n collection._vertexArrays.length = 0;\r\n}\r\n\r\nPolylineCollection.prototype._updatePolyline = function (\r\n polyline,\r\n propertyChanged\r\n) {\r\n this._polylinesUpdated = true;\r\n if (!polyline._dirty) {\r\n this._polylinesToUpdate.push(polyline);\r\n }\r\n ++this._propertiesChanged[propertyChanged];\r\n};\r\n\r\nfunction destroyPolylines(collection) {\r\n var polylines = collection._polylines;\r\n var length = polylines.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (!polylines[i].isDestroyed) {\r\n polylines[i]._destroy();\r\n }\r\n }\r\n}\r\n\r\nfunction VertexArrayBucketLocator(count, offset, bucket) {\r\n this.count = count;\r\n this.offset = offset;\r\n this.bucket = bucket;\r\n}\r\n\r\nfunction PolylineBucket(material, mode, modelMatrix) {\r\n this.polylines = [];\r\n this.lengthOfPositions = 0;\r\n this.material = material;\r\n this.shaderProgram = undefined;\r\n this.mode = mode;\r\n this.modelMatrix = modelMatrix;\r\n}\r\n\r\nPolylineBucket.prototype.addPolyline = function (p) {\r\n var polylines = this.polylines;\r\n polylines.push(p);\r\n p._actualLength = this.getPolylinePositionsLength(p);\r\n this.lengthOfPositions += p._actualLength;\r\n p._bucket = this;\r\n};\r\n\r\nPolylineBucket.prototype.updateShader = function (\r\n context,\r\n batchTable,\r\n useHighlightColor\r\n) {\r\n if (defined(this.shaderProgram)) {\r\n return;\r\n }\r\n\r\n var defines = [\"DISTANCE_DISPLAY_CONDITION\"];\r\n if (useHighlightColor) {\r\n defines.push(\"VECTOR_TILE\");\r\n }\r\n\r\n // Check for use of v_polylineAngle in material shader\r\n if (\r\n this.material.shaderSource.search(/varying\\s+float\\s+v_polylineAngle;/g) !==\r\n -1\r\n ) {\r\n defines.push(\"POLYLINE_DASH\");\r\n }\r\n\r\n if (!FeatureDetection.isInternetExplorer()) {\r\n defines.push(\"CLIP_POLYLINE\");\r\n }\r\n\r\n var fs = new ShaderSource({\r\n defines: defines,\r\n sources: [\r\n \"varying vec4 v_pickColor;\\n\",\r\n this.material.shaderSource,\r\n PolylineFS,\r\n ],\r\n });\r\n\r\n var vsSource = batchTable.getVertexShaderCallback()(PolylineVS);\r\n var vs = new ShaderSource({\r\n defines: defines,\r\n sources: [PolylineCommon, vsSource],\r\n });\r\n\r\n this.shaderProgram = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n};\r\n\r\nfunction intersectsIDL(polyline) {\r\n return (\r\n Cartesian3.dot(Cartesian3.UNIT_X, polyline._boundingVolume.center) < 0 ||\r\n polyline._boundingVolume.intersectPlane(Plane.ORIGIN_ZX_PLANE) ===\r\n Intersect.INTERSECTING\r\n );\r\n}\r\n\r\nPolylineBucket.prototype.getPolylinePositionsLength = function (polyline) {\r\n var length;\r\n if (this.mode === SceneMode.SCENE3D || !intersectsIDL(polyline)) {\r\n length = polyline._actualPositions.length;\r\n return length * 4.0 - 4.0;\r\n }\r\n\r\n var count = 0;\r\n var segmentLengths = polyline._segments.lengths;\r\n length = segmentLengths.length;\r\n for (var i = 0; i < length; ++i) {\r\n count += segmentLengths[i] * 4.0 - 4.0;\r\n }\r\n\r\n return count;\r\n};\r\n\r\nvar scratchWritePosition = new Cartesian3();\r\nvar scratchWritePrevPosition = new Cartesian3();\r\nvar scratchWriteNextPosition = new Cartesian3();\r\nvar scratchWriteVector = new Cartesian3();\r\nvar scratchPickColorCartesian = new Cartesian4();\r\nvar scratchWidthShowCartesian = new Cartesian2();\r\n\r\nPolylineBucket.prototype.write = function (\r\n positionArray,\r\n texCoordExpandAndBatchIndexArray,\r\n positionIndex,\r\n colorIndex,\r\n texCoordExpandAndBatchIndexIndex,\r\n batchTable,\r\n context,\r\n projection\r\n) {\r\n var mode = this.mode;\r\n var maxLon = projection.ellipsoid.maximumRadius * CesiumMath.PI;\r\n\r\n var polylines = this.polylines;\r\n var length = polylines.length;\r\n for (var i = 0; i < length; ++i) {\r\n var polyline = polylines[i];\r\n var width = polyline.width;\r\n var show = polyline.show && width > 0.0;\r\n var polylineBatchIndex = polyline._index;\r\n var segments = this.getSegments(polyline, projection);\r\n var positions = segments.positions;\r\n var lengths = segments.lengths;\r\n var positionsLength = positions.length;\r\n\r\n var pickColor = polyline.getPickId(context).color;\r\n\r\n var segmentIndex = 0;\r\n var count = 0;\r\n var position;\r\n\r\n for (var j = 0; j < positionsLength; ++j) {\r\n if (j === 0) {\r\n if (polyline._loop) {\r\n position = positions[positionsLength - 2];\r\n } else {\r\n position = scratchWriteVector;\r\n Cartesian3.subtract(positions[0], positions[1], position);\r\n Cartesian3.add(positions[0], position, position);\r\n }\r\n } else {\r\n position = positions[j - 1];\r\n }\r\n\r\n Cartesian3.clone(position, scratchWritePrevPosition);\r\n Cartesian3.clone(positions[j], scratchWritePosition);\r\n\r\n if (j === positionsLength - 1) {\r\n if (polyline._loop) {\r\n position = positions[1];\r\n } else {\r\n position = scratchWriteVector;\r\n Cartesian3.subtract(\r\n positions[positionsLength - 1],\r\n positions[positionsLength - 2],\r\n position\r\n );\r\n Cartesian3.add(positions[positionsLength - 1], position, position);\r\n }\r\n } else {\r\n position = positions[j + 1];\r\n }\r\n\r\n Cartesian3.clone(position, scratchWriteNextPosition);\r\n\r\n var segmentLength = lengths[segmentIndex];\r\n if (j === count + segmentLength) {\r\n count += segmentLength;\r\n ++segmentIndex;\r\n }\r\n\r\n var segmentStart = j - count === 0;\r\n var segmentEnd = j === count + lengths[segmentIndex] - 1;\r\n\r\n if (mode === SceneMode.SCENE2D) {\r\n scratchWritePrevPosition.z = 0.0;\r\n scratchWritePosition.z = 0.0;\r\n scratchWriteNextPosition.z = 0.0;\r\n }\r\n\r\n if (mode === SceneMode.SCENE2D || mode === SceneMode.MORPHING) {\r\n if (\r\n (segmentStart || segmentEnd) &&\r\n maxLon - Math.abs(scratchWritePosition.x) < 1.0\r\n ) {\r\n if (\r\n (scratchWritePosition.x < 0.0 &&\r\n scratchWritePrevPosition.x > 0.0) ||\r\n (scratchWritePosition.x > 0.0 && scratchWritePrevPosition.x < 0.0)\r\n ) {\r\n Cartesian3.clone(scratchWritePosition, scratchWritePrevPosition);\r\n }\r\n\r\n if (\r\n (scratchWritePosition.x < 0.0 &&\r\n scratchWriteNextPosition.x > 0.0) ||\r\n (scratchWritePosition.x > 0.0 && scratchWriteNextPosition.x < 0.0)\r\n ) {\r\n Cartesian3.clone(scratchWritePosition, scratchWriteNextPosition);\r\n }\r\n }\r\n }\r\n\r\n var startK = segmentStart ? 2 : 0;\r\n var endK = segmentEnd ? 2 : 4;\r\n\r\n for (var k = startK; k < endK; ++k) {\r\n EncodedCartesian3.writeElements(\r\n scratchWritePosition,\r\n positionArray,\r\n positionIndex\r\n );\r\n EncodedCartesian3.writeElements(\r\n scratchWritePrevPosition,\r\n positionArray,\r\n positionIndex + 6\r\n );\r\n EncodedCartesian3.writeElements(\r\n scratchWriteNextPosition,\r\n positionArray,\r\n positionIndex + 12\r\n );\r\n\r\n var direction = k - 2 < 0 ? -1.0 : 1.0;\r\n texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex] =\r\n j / (positionsLength - 1); // s tex coord\r\n texCoordExpandAndBatchIndexArray[texCoordExpandAndBatchIndexIndex + 1] =\r\n 2 * (k % 2) - 1; // expand direction\r\n texCoordExpandAndBatchIndexArray[\r\n texCoordExpandAndBatchIndexIndex + 2\r\n ] = direction;\r\n texCoordExpandAndBatchIndexArray[\r\n texCoordExpandAndBatchIndexIndex + 3\r\n ] = polylineBatchIndex;\r\n\r\n positionIndex += 6 * 3;\r\n texCoordExpandAndBatchIndexIndex += 4;\r\n }\r\n }\r\n\r\n var colorCartesian = scratchPickColorCartesian;\r\n colorCartesian.x = Color.floatToByte(pickColor.red);\r\n colorCartesian.y = Color.floatToByte(pickColor.green);\r\n colorCartesian.z = Color.floatToByte(pickColor.blue);\r\n colorCartesian.w = Color.floatToByte(pickColor.alpha);\r\n\r\n var widthShowCartesian = scratchWidthShowCartesian;\r\n widthShowCartesian.x = width;\r\n widthShowCartesian.y = show ? 1.0 : 0.0;\r\n\r\n var boundingSphere =\r\n mode === SceneMode.SCENE2D\r\n ? polyline._boundingVolume2D\r\n : polyline._boundingVolumeWC;\r\n var encodedCenter = EncodedCartesian3.fromCartesian(\r\n boundingSphere.center,\r\n scratchUpdatePolylineEncodedCartesian\r\n );\r\n var high = encodedCenter.high;\r\n var low = Cartesian4.fromElements(\r\n encodedCenter.low.x,\r\n encodedCenter.low.y,\r\n encodedCenter.low.z,\r\n boundingSphere.radius,\r\n scratchUpdatePolylineCartesian4\r\n );\r\n\r\n var nearFarCartesian = scratchNearFarCartesian2;\r\n nearFarCartesian.x = 0.0;\r\n nearFarCartesian.y = Number.MAX_VALUE;\r\n\r\n var distanceDisplayCondition = polyline.distanceDisplayCondition;\r\n if (defined(distanceDisplayCondition)) {\r\n nearFarCartesian.x = distanceDisplayCondition.near;\r\n nearFarCartesian.y = distanceDisplayCondition.far;\r\n }\r\n\r\n batchTable.setBatchedAttribute(polylineBatchIndex, 0, widthShowCartesian);\r\n batchTable.setBatchedAttribute(polylineBatchIndex, 1, colorCartesian);\r\n\r\n if (batchTable.attributes.length > 2) {\r\n batchTable.setBatchedAttribute(polylineBatchIndex, 2, high);\r\n batchTable.setBatchedAttribute(polylineBatchIndex, 3, low);\r\n batchTable.setBatchedAttribute(polylineBatchIndex, 4, nearFarCartesian);\r\n }\r\n }\r\n};\r\n\r\nvar morphPositionScratch = new Cartesian3();\r\nvar morphPrevPositionScratch = new Cartesian3();\r\nvar morphNextPositionScratch = new Cartesian3();\r\nvar morphVectorScratch = new Cartesian3();\r\n\r\nPolylineBucket.prototype.writeForMorph = function (\r\n positionArray,\r\n positionIndex\r\n) {\r\n var modelMatrix = this.modelMatrix;\r\n var polylines = this.polylines;\r\n var length = polylines.length;\r\n for (var i = 0; i < length; ++i) {\r\n var polyline = polylines[i];\r\n var positions = polyline._segments.positions;\r\n var lengths = polyline._segments.lengths;\r\n var positionsLength = positions.length;\r\n\r\n var segmentIndex = 0;\r\n var count = 0;\r\n\r\n for (var j = 0; j < positionsLength; ++j) {\r\n var prevPosition;\r\n if (j === 0) {\r\n if (polyline._loop) {\r\n prevPosition = positions[positionsLength - 2];\r\n } else {\r\n prevPosition = morphVectorScratch;\r\n Cartesian3.subtract(positions[0], positions[1], prevPosition);\r\n Cartesian3.add(positions[0], prevPosition, prevPosition);\r\n }\r\n } else {\r\n prevPosition = positions[j - 1];\r\n }\r\n\r\n prevPosition = Matrix4.multiplyByPoint(\r\n modelMatrix,\r\n prevPosition,\r\n morphPrevPositionScratch\r\n );\r\n\r\n var position = Matrix4.multiplyByPoint(\r\n modelMatrix,\r\n positions[j],\r\n morphPositionScratch\r\n );\r\n\r\n var nextPosition;\r\n if (j === positionsLength - 1) {\r\n if (polyline._loop) {\r\n nextPosition = positions[1];\r\n } else {\r\n nextPosition = morphVectorScratch;\r\n Cartesian3.subtract(\r\n positions[positionsLength - 1],\r\n positions[positionsLength - 2],\r\n nextPosition\r\n );\r\n Cartesian3.add(\r\n positions[positionsLength - 1],\r\n nextPosition,\r\n nextPosition\r\n );\r\n }\r\n } else {\r\n nextPosition = positions[j + 1];\r\n }\r\n\r\n nextPosition = Matrix4.multiplyByPoint(\r\n modelMatrix,\r\n nextPosition,\r\n morphNextPositionScratch\r\n );\r\n\r\n var segmentLength = lengths[segmentIndex];\r\n if (j === count + segmentLength) {\r\n count += segmentLength;\r\n ++segmentIndex;\r\n }\r\n\r\n var segmentStart = j - count === 0;\r\n var segmentEnd = j === count + lengths[segmentIndex] - 1;\r\n\r\n var startK = segmentStart ? 2 : 0;\r\n var endK = segmentEnd ? 2 : 4;\r\n\r\n for (var k = startK; k < endK; ++k) {\r\n EncodedCartesian3.writeElements(position, positionArray, positionIndex);\r\n EncodedCartesian3.writeElements(\r\n prevPosition,\r\n positionArray,\r\n positionIndex + 6\r\n );\r\n EncodedCartesian3.writeElements(\r\n nextPosition,\r\n positionArray,\r\n positionIndex + 12\r\n );\r\n\r\n positionIndex += 6 * 3;\r\n }\r\n }\r\n }\r\n};\r\n\r\nvar scratchSegmentLengths = new Array(1);\r\n\r\nPolylineBucket.prototype.updateIndices = function (\r\n totalIndices,\r\n vertexBufferOffset,\r\n vertexArrayBuckets,\r\n offset\r\n) {\r\n var vaCount = vertexArrayBuckets.length - 1;\r\n var bucketLocator = new VertexArrayBucketLocator(0, offset, this);\r\n vertexArrayBuckets[vaCount].push(bucketLocator);\r\n var count = 0;\r\n var indices = totalIndices[totalIndices.length - 1];\r\n var indicesCount = 0;\r\n if (indices.length > 0) {\r\n indicesCount = indices[indices.length - 1] + 1;\r\n }\r\n var polylines = this.polylines;\r\n var length = polylines.length;\r\n for (var i = 0; i < length; ++i) {\r\n var polyline = polylines[i];\r\n polyline._locatorBuckets = [];\r\n\r\n var segments;\r\n if (this.mode === SceneMode.SCENE3D) {\r\n segments = scratchSegmentLengths;\r\n var positionsLength = polyline._actualPositions.length;\r\n if (positionsLength > 0) {\r\n segments[0] = positionsLength;\r\n } else {\r\n continue;\r\n }\r\n } else {\r\n segments = polyline._segments.lengths;\r\n }\r\n\r\n var numberOfSegments = segments.length;\r\n if (numberOfSegments > 0) {\r\n var segmentIndexCount = 0;\r\n for (var j = 0; j < numberOfSegments; ++j) {\r\n var segmentLength = segments[j] - 1.0;\r\n for (var k = 0; k < segmentLength; ++k) {\r\n if (indicesCount + 4 > CesiumMath.SIXTY_FOUR_KILOBYTES) {\r\n polyline._locatorBuckets.push({\r\n locator: bucketLocator,\r\n count: segmentIndexCount,\r\n });\r\n segmentIndexCount = 0;\r\n vertexBufferOffset.push(4);\r\n indices = [];\r\n totalIndices.push(indices);\r\n indicesCount = 0;\r\n bucketLocator.count = count;\r\n count = 0;\r\n offset = 0;\r\n bucketLocator = new VertexArrayBucketLocator(0, 0, this);\r\n vertexArrayBuckets[++vaCount] = [bucketLocator];\r\n }\r\n\r\n indices.push(indicesCount, indicesCount + 2, indicesCount + 1);\r\n indices.push(indicesCount + 1, indicesCount + 2, indicesCount + 3);\r\n\r\n segmentIndexCount += 6;\r\n count += 6;\r\n offset += 6;\r\n indicesCount += 4;\r\n }\r\n }\r\n\r\n polyline._locatorBuckets.push({\r\n locator: bucketLocator,\r\n count: segmentIndexCount,\r\n });\r\n\r\n if (indicesCount + 4 > CesiumMath.SIXTY_FOUR_KILOBYTES) {\r\n vertexBufferOffset.push(0);\r\n indices = [];\r\n totalIndices.push(indices);\r\n indicesCount = 0;\r\n bucketLocator.count = count;\r\n offset = 0;\r\n count = 0;\r\n bucketLocator = new VertexArrayBucketLocator(0, 0, this);\r\n vertexArrayBuckets[++vaCount] = [bucketLocator];\r\n }\r\n }\r\n polyline._clean();\r\n }\r\n bucketLocator.count = count;\r\n return offset;\r\n};\r\n\r\nPolylineBucket.prototype.getPolylineStartIndex = function (polyline) {\r\n var polylines = this.polylines;\r\n var positionIndex = 0;\r\n var length = polylines.length;\r\n for (var i = 0; i < length; ++i) {\r\n var p = polylines[i];\r\n if (p === polyline) {\r\n break;\r\n }\r\n positionIndex += p._actualLength;\r\n }\r\n return positionIndex;\r\n};\r\n\r\nvar scratchSegments = {\r\n positions: undefined,\r\n lengths: undefined,\r\n};\r\nvar scratchLengths = new Array(1);\r\nvar pscratch = new Cartesian3();\r\nvar scratchCartographic = new Cartographic();\r\n\r\nPolylineBucket.prototype.getSegments = function (polyline, projection) {\r\n var positions = polyline._actualPositions;\r\n\r\n if (this.mode === SceneMode.SCENE3D) {\r\n scratchLengths[0] = positions.length;\r\n scratchSegments.positions = positions;\r\n scratchSegments.lengths = scratchLengths;\r\n return scratchSegments;\r\n }\r\n\r\n if (intersectsIDL(polyline)) {\r\n positions = polyline._segments.positions;\r\n }\r\n\r\n var ellipsoid = projection.ellipsoid;\r\n var newPositions = [];\r\n var modelMatrix = this.modelMatrix;\r\n var length = positions.length;\r\n var position;\r\n var p = pscratch;\r\n\r\n for (var n = 0; n < length; ++n) {\r\n position = positions[n];\r\n p = Matrix4.multiplyByPoint(modelMatrix, position, p);\r\n newPositions.push(\r\n projection.project(\r\n ellipsoid.cartesianToCartographic(p, scratchCartographic)\r\n )\r\n );\r\n }\r\n\r\n if (newPositions.length > 0) {\r\n polyline._boundingVolume2D = BoundingSphere.fromPoints(\r\n newPositions,\r\n polyline._boundingVolume2D\r\n );\r\n var center2D = polyline._boundingVolume2D.center;\r\n polyline._boundingVolume2D.center = new Cartesian3(\r\n center2D.z,\r\n center2D.x,\r\n center2D.y\r\n );\r\n }\r\n\r\n scratchSegments.positions = newPositions;\r\n scratchSegments.lengths = polyline._segments.lengths;\r\n return scratchSegments;\r\n};\r\n\r\nvar scratchPositionsArray;\r\n\r\nPolylineBucket.prototype.writeUpdate = function (\r\n index,\r\n polyline,\r\n positionBuffer,\r\n projection\r\n) {\r\n var mode = this.mode;\r\n var maxLon = projection.ellipsoid.maximumRadius * CesiumMath.PI;\r\n\r\n var positionsLength = polyline._actualLength;\r\n if (positionsLength) {\r\n index += this.getPolylineStartIndex(polyline);\r\n\r\n var positionArray = scratchPositionsArray;\r\n var positionsArrayLength = 6 * positionsLength * 3;\r\n\r\n if (\r\n !defined(positionArray) ||\r\n positionArray.length < positionsArrayLength\r\n ) {\r\n positionArray = scratchPositionsArray = new Float32Array(\r\n positionsArrayLength\r\n );\r\n } else if (positionArray.length > positionsArrayLength) {\r\n positionArray = new Float32Array(\r\n positionArray.buffer,\r\n 0,\r\n positionsArrayLength\r\n );\r\n }\r\n\r\n var segments = this.getSegments(polyline, projection);\r\n var positions = segments.positions;\r\n var lengths = segments.lengths;\r\n\r\n var positionIndex = 0;\r\n var segmentIndex = 0;\r\n var count = 0;\r\n var position;\r\n\r\n positionsLength = positions.length;\r\n for (var i = 0; i < positionsLength; ++i) {\r\n if (i === 0) {\r\n if (polyline._loop) {\r\n position = positions[positionsLength - 2];\r\n } else {\r\n position = scratchWriteVector;\r\n Cartesian3.subtract(positions[0], positions[1], position);\r\n Cartesian3.add(positions[0], position, position);\r\n }\r\n } else {\r\n position = positions[i - 1];\r\n }\r\n\r\n Cartesian3.clone(position, scratchWritePrevPosition);\r\n Cartesian3.clone(positions[i], scratchWritePosition);\r\n\r\n if (i === positionsLength - 1) {\r\n if (polyline._loop) {\r\n position = positions[1];\r\n } else {\r\n position = scratchWriteVector;\r\n Cartesian3.subtract(\r\n positions[positionsLength - 1],\r\n positions[positionsLength - 2],\r\n position\r\n );\r\n Cartesian3.add(positions[positionsLength - 1], position, position);\r\n }\r\n } else {\r\n position = positions[i + 1];\r\n }\r\n\r\n Cartesian3.clone(position, scratchWriteNextPosition);\r\n\r\n var segmentLength = lengths[segmentIndex];\r\n if (i === count + segmentLength) {\r\n count += segmentLength;\r\n ++segmentIndex;\r\n }\r\n\r\n var segmentStart = i - count === 0;\r\n var segmentEnd = i === count + lengths[segmentIndex] - 1;\r\n\r\n if (mode === SceneMode.SCENE2D) {\r\n scratchWritePrevPosition.z = 0.0;\r\n scratchWritePosition.z = 0.0;\r\n scratchWriteNextPosition.z = 0.0;\r\n }\r\n\r\n if (mode === SceneMode.SCENE2D || mode === SceneMode.MORPHING) {\r\n if (\r\n (segmentStart || segmentEnd) &&\r\n maxLon - Math.abs(scratchWritePosition.x) < 1.0\r\n ) {\r\n if (\r\n (scratchWritePosition.x < 0.0 &&\r\n scratchWritePrevPosition.x > 0.0) ||\r\n (scratchWritePosition.x > 0.0 && scratchWritePrevPosition.x < 0.0)\r\n ) {\r\n Cartesian3.clone(scratchWritePosition, scratchWritePrevPosition);\r\n }\r\n\r\n if (\r\n (scratchWritePosition.x < 0.0 &&\r\n scratchWriteNextPosition.x > 0.0) ||\r\n (scratchWritePosition.x > 0.0 && scratchWriteNextPosition.x < 0.0)\r\n ) {\r\n Cartesian3.clone(scratchWritePosition, scratchWriteNextPosition);\r\n }\r\n }\r\n }\r\n\r\n var startJ = segmentStart ? 2 : 0;\r\n var endJ = segmentEnd ? 2 : 4;\r\n\r\n for (var j = startJ; j < endJ; ++j) {\r\n EncodedCartesian3.writeElements(\r\n scratchWritePosition,\r\n positionArray,\r\n positionIndex\r\n );\r\n EncodedCartesian3.writeElements(\r\n scratchWritePrevPosition,\r\n positionArray,\r\n positionIndex + 6\r\n );\r\n EncodedCartesian3.writeElements(\r\n scratchWriteNextPosition,\r\n positionArray,\r\n positionIndex + 12\r\n );\r\n positionIndex += 6 * 3;\r\n }\r\n }\r\n\r\n positionBuffer.copyFromArrayView(\r\n positionArray,\r\n 6 * 3 * Float32Array.BYTES_PER_ELEMENT * index\r\n );\r\n }\r\n};\r\nexport default PolylineCollection;\r\n","import arraySlice from \"../Core/arraySlice.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport NearFarScalar from \"../Core/NearFarScalar.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport TaskProcessor from \"../Core/TaskProcessor.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport BillboardCollection from \"./BillboardCollection.js\";\r\nimport Cesium3DTilePointFeature from \"./Cesium3DTilePointFeature.js\";\r\nimport HorizontalOrigin from \"./HorizontalOrigin.js\";\r\nimport LabelCollection from \"./LabelCollection.js\";\r\nimport LabelStyle from \"./LabelStyle.js\";\r\nimport PolylineCollection from \"./PolylineCollection.js\";\r\nimport VerticalOrigin from \"./VerticalOrigin.js\";\r\n\r\n/**\r\n * Creates a batch of points or billboards and labels.\r\n *\r\n * @alias Vector3DTilePoints\r\n * @constructor\r\n *\r\n * @param {Object} options An object with following properties:\r\n * @param {Uint16Array} options.positions The positions of the polygons.\r\n * @param {Number} options.minimumHeight The minimum height of the terrain covered by the tile.\r\n * @param {Number} options.maximumHeight The maximum height of the terrain covered by the tile.\r\n * @param {Rectangle} options.rectangle The rectangle containing the tile.\r\n * @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polygons.\r\n * @param {Uint16Array} options.batchIds The batch ids for each polygon.\r\n *\r\n * @private\r\n */\r\nfunction Vector3DTilePoints(options) {\r\n // released after the first update\r\n this._positions = options.positions;\r\n\r\n this._batchTable = options.batchTable;\r\n this._batchIds = options.batchIds;\r\n\r\n this._rectangle = options.rectangle;\r\n this._minHeight = options.minimumHeight;\r\n this._maxHeight = options.maximumHeight;\r\n\r\n this._billboardCollection = undefined;\r\n this._labelCollection = undefined;\r\n this._polylineCollection = undefined;\r\n\r\n this._verticesPromise = undefined;\r\n this._packedBuffer = undefined;\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n this._resolvedPromise = false;\r\n}\r\n\r\nObject.defineProperties(Vector3DTilePoints.prototype, {\r\n /**\r\n * Gets the number of points.\r\n *\r\n * @memberof Vector3DTilePoints.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n pointsLength: {\r\n get: function () {\r\n return this._billboardCollection.length;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the texture atlas memory in bytes.\r\n *\r\n * @memberof Vector3DTilePoints.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n texturesByteLength: {\r\n get: function () {\r\n var billboardSize = this._billboardCollection.textureAtlas.texture\r\n .sizeInBytes;\r\n var labelSize = this._labelCollection._textureAtlas.texture.sizeInBytes;\r\n return billboardSize + labelSize;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof Vector3DTilePoints.prototype\r\n * @type {Promise}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n});\r\n\r\nfunction packBuffer(points, ellipsoid) {\r\n var rectangle = points._rectangle;\r\n var minimumHeight = points._minHeight;\r\n var maximumHeight = points._maxHeight;\r\n\r\n var packedLength = 2 + Rectangle.packedLength + Ellipsoid.packedLength;\r\n var packedBuffer = new Float64Array(packedLength);\r\n\r\n var offset = 0;\r\n packedBuffer[offset++] = minimumHeight;\r\n packedBuffer[offset++] = maximumHeight;\r\n\r\n Rectangle.pack(rectangle, packedBuffer, offset);\r\n offset += Rectangle.packedLength;\r\n\r\n Ellipsoid.pack(ellipsoid, packedBuffer, offset);\r\n\r\n return packedBuffer;\r\n}\r\n\r\nvar createVerticesTaskProcessor = new TaskProcessor(\r\n \"createVectorTilePoints\",\r\n 5\r\n);\r\nvar scratchPosition = new Cartesian3();\r\n\r\nfunction createPoints(points, ellipsoid) {\r\n if (defined(points._billboardCollection)) {\r\n return;\r\n }\r\n\r\n var positions;\r\n if (!defined(points._verticesPromise)) {\r\n positions = points._positions;\r\n var packedBuffer = points._packedBuffer;\r\n\r\n if (!defined(packedBuffer)) {\r\n // Copy because they may be the views on the same buffer.\r\n positions = points._positions = arraySlice(positions);\r\n points._batchIds = arraySlice(points._batchIds);\r\n\r\n packedBuffer = points._packedBuffer = packBuffer(points, ellipsoid);\r\n }\r\n\r\n var transferrableObjects = [positions.buffer, packedBuffer.buffer];\r\n var parameters = {\r\n positions: positions.buffer,\r\n packedBuffer: packedBuffer.buffer,\r\n };\r\n\r\n var verticesPromise = (points._verticesPromise = createVerticesTaskProcessor.scheduleTask(\r\n parameters,\r\n transferrableObjects\r\n ));\r\n if (!defined(verticesPromise)) {\r\n // Postponed\r\n return;\r\n }\r\n\r\n verticesPromise.then(function (result) {\r\n points._positions = new Float64Array(result.positions);\r\n points._ready = true;\r\n });\r\n }\r\n\r\n if (points._ready && !defined(points._billboardCollection)) {\r\n positions = points._positions;\r\n var batchTable = points._batchTable;\r\n var batchIds = points._batchIds;\r\n\r\n var billboardCollection = (points._billboardCollection = new BillboardCollection(\r\n { batchTable: batchTable }\r\n ));\r\n var labelCollection = (points._labelCollection = new LabelCollection({\r\n batchTable: batchTable,\r\n }));\r\n var polylineCollection = (points._polylineCollection = new PolylineCollection());\r\n polylineCollection._useHighlightColor = true;\r\n\r\n var numberOfPoints = positions.length / 3;\r\n for (var i = 0; i < numberOfPoints; ++i) {\r\n var id = batchIds[i];\r\n\r\n var position = Cartesian3.unpack(positions, i * 3, scratchPosition);\r\n\r\n var b = billboardCollection.add();\r\n b.position = position;\r\n b._batchIndex = id;\r\n\r\n var l = labelCollection.add();\r\n l.text = \" \";\r\n l.position = position;\r\n l._batchIndex = id;\r\n\r\n var p = polylineCollection.add();\r\n p.positions = [Cartesian3.clone(position), Cartesian3.clone(position)];\r\n }\r\n\r\n points._positions = undefined;\r\n points._packedBuffer = undefined;\r\n }\r\n}\r\n\r\n/**\r\n * Creates features for each point and places it at the batch id index of features.\r\n *\r\n * @param {Vector3DTileContent} content The vector tile content.\r\n * @param {Cesium3DTileFeature[]} features An array of features where the point features will be placed.\r\n */\r\nVector3DTilePoints.prototype.createFeatures = function (content, features) {\r\n var billboardCollection = this._billboardCollection;\r\n var labelCollection = this._labelCollection;\r\n var polylineCollection = this._polylineCollection;\r\n\r\n var batchIds = this._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n\r\n var billboard = billboardCollection.get(i);\r\n var label = labelCollection.get(i);\r\n var polyline = polylineCollection.get(i);\r\n\r\n features[batchId] = new Cesium3DTilePointFeature(\r\n content,\r\n batchId,\r\n billboard,\r\n label,\r\n polyline\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Colors the entire tile when enabled is true. The resulting color will be (batch table color * color).\r\n *\r\n * @param {Boolean} enabled Whether to enable debug coloring.\r\n * @param {Color} color The debug color.\r\n */\r\nVector3DTilePoints.prototype.applyDebugSettings = function (enabled, color) {\r\n if (enabled) {\r\n Color.clone(color, this._billboardCollection._highlightColor);\r\n Color.clone(color, this._labelCollection._highlightColor);\r\n Color.clone(color, this._polylineCollection._highlightColor);\r\n } else {\r\n Color.clone(Color.WHITE, this._billboardCollection._highlightColor);\r\n Color.clone(Color.WHITE, this._labelCollection._highlightColor);\r\n Color.clone(Color.WHITE, this._polylineCollection._highlightColor);\r\n }\r\n};\r\n\r\nfunction clearStyle(polygons, features) {\r\n var batchIds = polygons._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n var feature = features[batchId];\r\n\r\n feature.show = true;\r\n feature.pointSize = Cesium3DTilePointFeature.defaultPointSize;\r\n feature.color = Cesium3DTilePointFeature.defaultColor;\r\n feature.pointOutlineColor =\r\n Cesium3DTilePointFeature.defaultPointOutlineColor;\r\n feature.pointOutlineWidth =\r\n Cesium3DTilePointFeature.defaultPointOutlineWidth;\r\n feature.labelColor = Color.WHITE;\r\n feature.labelOutlineColor = Color.WHITE;\r\n feature.labelOutlineWidth = 1.0;\r\n feature.font = \"30px sans-serif\";\r\n feature.labelStyle = LabelStyle.FILL;\r\n feature.labelText = undefined;\r\n feature.backgroundColor = new Color(0.165, 0.165, 0.165, 0.8);\r\n feature.backgroundPadding = new Cartesian2(7, 5);\r\n feature.backgroundEnabled = false;\r\n feature.scaleByDistance = undefined;\r\n feature.translucencyByDistance = undefined;\r\n feature.distanceDisplayCondition = undefined;\r\n feature.heightOffset = 0.0;\r\n feature.anchorLineEnabled = false;\r\n feature.anchorLineColor = Color.WHITE;\r\n feature.image = undefined;\r\n feature.disableDepthTestDistance = 0.0;\r\n feature.horizontalOrigin = HorizontalOrigin.CENTER;\r\n feature.verticalOrigin = VerticalOrigin.CENTER;\r\n feature.labelHorizontalOrigin = HorizontalOrigin.RIGHT;\r\n feature.labelVerticalOrigin = VerticalOrigin.BASELINE;\r\n }\r\n}\r\n\r\nvar scratchColor = new Color();\r\nvar scratchColor2 = new Color();\r\nvar scratchColor3 = new Color();\r\nvar scratchColor4 = new Color();\r\nvar scratchColor5 = new Color();\r\nvar scratchColor6 = new Color();\r\nvar scratchScaleByDistance = new NearFarScalar();\r\nvar scratchTranslucencyByDistance = new NearFarScalar();\r\nvar scratchDistanceDisplayCondition = new DistanceDisplayCondition();\r\n\r\n/**\r\n * Apply a style to the content.\r\n *\r\n * @param {Cesium3DTileStyle} style The style.\r\n * @param {Cesium3DTileFeature[]} features The array of features.\r\n */\r\nVector3DTilePoints.prototype.applyStyle = function (style, features) {\r\n if (!defined(style)) {\r\n clearStyle(this, features);\r\n return;\r\n }\r\n\r\n var batchIds = this._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n var feature = features[batchId];\r\n\r\n if (defined(style.show)) {\r\n feature.show = style.show.evaluate(feature);\r\n }\r\n\r\n if (defined(style.pointSize)) {\r\n feature.pointSize = style.pointSize.evaluate(feature);\r\n }\r\n\r\n if (defined(style.color)) {\r\n feature.color = style.color.evaluateColor(feature, scratchColor);\r\n }\r\n\r\n if (defined(style.pointOutlineColor)) {\r\n feature.pointOutlineColor = style.pointOutlineColor.evaluateColor(\r\n feature,\r\n scratchColor2\r\n );\r\n }\r\n\r\n if (defined(style.pointOutlineWidth)) {\r\n feature.pointOutlineWidth = style.pointOutlineWidth.evaluate(feature);\r\n }\r\n\r\n if (defined(style.labelColor)) {\r\n feature.labelColor = style.labelColor.evaluateColor(\r\n feature,\r\n scratchColor3\r\n );\r\n }\r\n\r\n if (defined(style.labelOutlineColor)) {\r\n feature.labelOutlineColor = style.labelOutlineColor.evaluateColor(\r\n feature,\r\n scratchColor4\r\n );\r\n }\r\n\r\n if (defined(style.labelOutlineWidth)) {\r\n feature.labelOutlineWidth = style.labelOutlineWidth.evaluate(feature);\r\n }\r\n\r\n if (defined(style.font)) {\r\n feature.font = style.font.evaluate(feature);\r\n }\r\n\r\n if (defined(style.labelStyle)) {\r\n feature.labelStyle = style.labelStyle.evaluate(feature);\r\n }\r\n\r\n if (defined(style.labelText)) {\r\n feature.labelText = style.labelText.evaluate(feature);\r\n } else {\r\n feature.labelText = undefined;\r\n }\r\n\r\n if (defined(style.backgroundColor)) {\r\n feature.backgroundColor = style.backgroundColor.evaluateColor(\r\n feature,\r\n scratchColor5\r\n );\r\n }\r\n\r\n if (defined(style.backgroundPadding)) {\r\n feature.backgroundPadding = style.backgroundPadding.evaluate(feature);\r\n }\r\n\r\n if (defined(style.backgroundEnabled)) {\r\n feature.backgroundEnabled = style.backgroundEnabled.evaluate(feature);\r\n }\r\n\r\n if (defined(style.scaleByDistance)) {\r\n var scaleByDistanceCart4 = style.scaleByDistance.evaluate(feature);\r\n scratchScaleByDistance.near = scaleByDistanceCart4.x;\r\n scratchScaleByDistance.nearValue = scaleByDistanceCart4.y;\r\n scratchScaleByDistance.far = scaleByDistanceCart4.z;\r\n scratchScaleByDistance.farValue = scaleByDistanceCart4.w;\r\n feature.scaleByDistance = scratchScaleByDistance;\r\n } else {\r\n feature.scaleByDistance = undefined;\r\n }\r\n\r\n if (defined(style.translucencyByDistance)) {\r\n var translucencyByDistanceCart4 = style.translucencyByDistance.evaluate(\r\n feature\r\n );\r\n scratchTranslucencyByDistance.near = translucencyByDistanceCart4.x;\r\n scratchTranslucencyByDistance.nearValue = translucencyByDistanceCart4.y;\r\n scratchTranslucencyByDistance.far = translucencyByDistanceCart4.z;\r\n scratchTranslucencyByDistance.farValue = translucencyByDistanceCart4.w;\r\n feature.translucencyByDistance = scratchTranslucencyByDistance;\r\n } else {\r\n feature.translucencyByDistance = undefined;\r\n }\r\n\r\n if (defined(style.distanceDisplayCondition)) {\r\n var distanceDisplayConditionCart2 = style.distanceDisplayCondition.evaluate(\r\n feature\r\n );\r\n scratchDistanceDisplayCondition.near = distanceDisplayConditionCart2.x;\r\n scratchDistanceDisplayCondition.far = distanceDisplayConditionCart2.y;\r\n feature.distanceDisplayCondition = scratchDistanceDisplayCondition;\r\n } else {\r\n feature.distanceDisplayCondition = undefined;\r\n }\r\n\r\n if (defined(style.heightOffset)) {\r\n feature.heightOffset = style.heightOffset.evaluate(feature);\r\n }\r\n\r\n if (defined(style.anchorLineEnabled)) {\r\n feature.anchorLineEnabled = style.anchorLineEnabled.evaluate(feature);\r\n }\r\n\r\n if (defined(style.anchorLineColor)) {\r\n feature.anchorLineColor = style.anchorLineColor.evaluateColor(\r\n feature,\r\n scratchColor6\r\n );\r\n }\r\n\r\n if (defined(style.image)) {\r\n feature.image = style.image.evaluate(feature);\r\n } else {\r\n feature.image = undefined;\r\n }\r\n\r\n if (defined(style.disableDepthTestDistance)) {\r\n feature.disableDepthTestDistance = style.disableDepthTestDistance.evaluate(\r\n feature\r\n );\r\n }\r\n\r\n if (defined(style.horizontalOrigin)) {\r\n feature.horizontalOrigin = style.horizontalOrigin.evaluate(feature);\r\n }\r\n\r\n if (defined(style.verticalOrigin)) {\r\n feature.verticalOrigin = style.verticalOrigin.evaluate(feature);\r\n }\r\n\r\n if (defined(style.labelHorizontalOrigin)) {\r\n feature.labelHorizontalOrigin = style.labelHorizontalOrigin.evaluate(\r\n feature\r\n );\r\n }\r\n\r\n if (defined(style.labelVerticalOrigin)) {\r\n feature.labelVerticalOrigin = style.labelVerticalOrigin.evaluate(feature);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nVector3DTilePoints.prototype.update = function (frameState) {\r\n createPoints(this, frameState.mapProjection.ellipsoid);\r\n\r\n if (!this._ready) {\r\n return;\r\n }\r\n\r\n this._polylineCollection.update(frameState);\r\n this._billboardCollection.update(frameState);\r\n this._labelCollection.update(frameState);\r\n\r\n if (!this._resolvedPromise) {\r\n this._readyPromise.resolve();\r\n this._resolvedPromise = true;\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n */\r\nVector3DTilePoints.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nVector3DTilePoints.prototype.destroy = function () {\r\n this._billboardCollection =\r\n this._billboardCollection && this._billboardCollection.destroy();\r\n this._labelCollection =\r\n this._labelCollection && this._labelCollection.destroy();\r\n this._polylineCollection =\r\n this._polylineCollection && this._polylineCollection.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Vector3DTilePoints;\r\n","import arraySlice from \"../Core/arraySlice.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport OrientedBoundingBox from \"../Core/OrientedBoundingBox.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport TaskProcessor from \"../Core/TaskProcessor.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport ClassificationType from \"./ClassificationType.js\";\r\nimport Vector3DTileBatch from \"./Vector3DTileBatch.js\";\r\nimport Vector3DTilePrimitive from \"./Vector3DTilePrimitive.js\";\r\n\r\n/**\r\n * Creates a batch of pre-triangulated polygons draped on terrain and/or 3D Tiles.\r\n *\r\n * @alias Vector3DTilePolygons\r\n * @constructor\r\n *\r\n * @param {Object} options An object with following properties:\r\n * @param {Float32Array|Uint16Array} options.positions The positions of the polygons. The positions must be contiguous\r\n * so that the positions for polygon n are in [c, c + counts[n]] where c = sum{counts[0], counts[n - 1]} and they are the outer ring of\r\n * the polygon in counter-clockwise order.\r\n * @param {Uint32Array} options.counts The number of positions in the each polygon.\r\n * @param {Uint32Array} options.indices The indices of the triangulated polygons. The indices must be contiguous so that\r\n * the indices for polygon n are in [i, i + indexCounts[n]] where i = sum{indexCounts[0], indexCounts[n - 1]}.\r\n * @param {Uint32Array} options.indexCounts The number of indices for each polygon.\r\n * @param {Number} options.minimumHeight The minimum height of the terrain covered by the tile.\r\n * @param {Number} options.maximumHeight The maximum height of the terrain covered by the tile.\r\n * @param {Float32Array} [options.polygonMinimumHeights] An array containing the minimum heights for each polygon.\r\n * @param {Float32Array} [options.polygonMaximumHeights] An array containing the maximum heights for each polygon.\r\n * @param {Rectangle} options.rectangle The rectangle containing the tile.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid.\r\n * @param {Cartesian3} [options.center=Cartesian3.ZERO] The RTC center.\r\n * @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polygons.\r\n * @param {Uint16Array} options.batchIds The batch ids for each polygon.\r\n * @param {BoundingSphere} options.boundingVolume The bounding volume for the entire batch of polygons.\r\n *\r\n * @private\r\n */\r\nfunction Vector3DTilePolygons(options) {\r\n // All of the private properties will be released except _readyPromise\r\n // and _primitive after the Vector3DTilePrimitive is created.\r\n this._batchTable = options.batchTable;\r\n\r\n this._batchIds = options.batchIds;\r\n this._positions = options.positions;\r\n this._counts = options.counts;\r\n\r\n this._indices = options.indices;\r\n this._indexCounts = options.indexCounts;\r\n this._indexOffsets = undefined;\r\n\r\n this._batchTableColors = undefined;\r\n this._packedBuffer = undefined;\r\n\r\n this._batchedPositions = undefined;\r\n this._transferrableBatchIds = undefined;\r\n this._vertexBatchIds = undefined;\r\n\r\n this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n this._minimumHeight = options.minimumHeight;\r\n this._maximumHeight = options.maximumHeight;\r\n this._polygonMinimumHeights = options.polygonMinimumHeights;\r\n this._polygonMaximumHeights = options.polygonMaximumHeights;\r\n this._center = defaultValue(options.center, Cartesian3.ZERO);\r\n this._rectangle = options.rectangle;\r\n\r\n this._center = undefined;\r\n\r\n this._boundingVolume = options.boundingVolume;\r\n this._boundingVolumes = undefined;\r\n\r\n this._batchedIndices = undefined;\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._verticesPromise = undefined;\r\n\r\n this._primitive = undefined;\r\n\r\n /**\r\n * Draws the wireframe of the classification meshes.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugWireframe = false;\r\n\r\n /**\r\n * Forces a re-batch instead of waiting after a number of frames have been rendered. For testing only.\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.forceRebatch = false;\r\n\r\n /**\r\n * What this tile will classify.\r\n * @type {ClassificationType}\r\n * @default ClassificationType.BOTH\r\n */\r\n this.classificationType = ClassificationType.BOTH;\r\n}\r\n\r\nObject.defineProperties(Vector3DTilePolygons.prototype, {\r\n /**\r\n * Gets the number of triangles.\r\n *\r\n * @memberof Vector3DTilePolygons.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n trianglesLength: {\r\n get: function () {\r\n if (defined(this._primitive)) {\r\n return this._primitive.trianglesLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the geometry memory in bytes.\r\n *\r\n * @memberof Vector3DTilePolygons.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n geometryByteLength: {\r\n get: function () {\r\n if (defined(this._primitive)) {\r\n return this._primitive.geometryByteLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof Vector3DTilePolygons.prototype\r\n * @type {Promise}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n});\r\n\r\nfunction packBuffer(polygons) {\r\n var packedBuffer = new Float64Array(\r\n 3 +\r\n Cartesian3.packedLength +\r\n Ellipsoid.packedLength +\r\n Rectangle.packedLength\r\n );\r\n\r\n var offset = 0;\r\n packedBuffer[offset++] = polygons._indices.BYTES_PER_ELEMENT;\r\n\r\n packedBuffer[offset++] = polygons._minimumHeight;\r\n packedBuffer[offset++] = polygons._maximumHeight;\r\n\r\n Cartesian3.pack(polygons._center, packedBuffer, offset);\r\n offset += Cartesian3.packedLength;\r\n\r\n Ellipsoid.pack(polygons._ellipsoid, packedBuffer, offset);\r\n offset += Ellipsoid.packedLength;\r\n\r\n Rectangle.pack(polygons._rectangle, packedBuffer, offset);\r\n\r\n return packedBuffer;\r\n}\r\n\r\nfunction unpackBuffer(polygons, packedBuffer) {\r\n var offset = 1;\r\n\r\n var numBVS = packedBuffer[offset++];\r\n var bvs = (polygons._boundingVolumes = new Array(numBVS));\r\n\r\n for (var i = 0; i < numBVS; ++i) {\r\n bvs[i] = OrientedBoundingBox.unpack(packedBuffer, offset);\r\n offset += OrientedBoundingBox.packedLength;\r\n }\r\n\r\n var numBatchedIndices = packedBuffer[offset++];\r\n var bis = (polygons._batchedIndices = new Array(numBatchedIndices));\r\n\r\n for (var j = 0; j < numBatchedIndices; ++j) {\r\n var color = Color.unpack(packedBuffer, offset);\r\n offset += Color.packedLength;\r\n\r\n var indexOffset = packedBuffer[offset++];\r\n var count = packedBuffer[offset++];\r\n\r\n var length = packedBuffer[offset++];\r\n var batchIds = new Array(length);\r\n\r\n for (var k = 0; k < length; ++k) {\r\n batchIds[k] = packedBuffer[offset++];\r\n }\r\n\r\n bis[j] = new Vector3DTileBatch({\r\n color: color,\r\n offset: indexOffset,\r\n count: count,\r\n batchIds: batchIds,\r\n });\r\n }\r\n}\r\n\r\nvar createVerticesTaskProcessor = new TaskProcessor(\r\n \"createVectorTilePolygons\",\r\n 5\r\n);\r\nvar scratchColor = new Color();\r\n\r\nfunction createPrimitive(polygons) {\r\n if (defined(polygons._primitive)) {\r\n return;\r\n }\r\n\r\n if (!defined(polygons._verticesPromise)) {\r\n var positions = polygons._positions;\r\n var counts = polygons._counts;\r\n var indexCounts = polygons._indexCounts;\r\n var indices = polygons._indices;\r\n\r\n var batchIds = polygons._transferrableBatchIds;\r\n var batchTableColors = polygons._batchTableColors;\r\n\r\n var packedBuffer = polygons._packedBuffer;\r\n\r\n if (!defined(batchTableColors)) {\r\n // Copy because they may be the views on the same buffer.\r\n positions = polygons._positions = arraySlice(polygons._positions);\r\n counts = polygons._counts = arraySlice(polygons._counts);\r\n indexCounts = polygons._indexCounts = arraySlice(polygons._indexCounts);\r\n indices = polygons._indices = arraySlice(polygons._indices);\r\n\r\n polygons._center = polygons._ellipsoid.cartographicToCartesian(\r\n Rectangle.center(polygons._rectangle)\r\n );\r\n\r\n batchIds = polygons._transferrableBatchIds = new Uint32Array(\r\n polygons._batchIds\r\n );\r\n batchTableColors = polygons._batchTableColors = new Uint32Array(\r\n batchIds.length\r\n );\r\n var batchTable = polygons._batchTable;\r\n\r\n var length = batchTableColors.length;\r\n for (var i = 0; i < length; ++i) {\r\n var color = batchTable.getColor(i, scratchColor);\r\n batchTableColors[i] = color.toRgba();\r\n }\r\n\r\n packedBuffer = polygons._packedBuffer = packBuffer(polygons);\r\n }\r\n\r\n var transferrableObjects = [\r\n positions.buffer,\r\n counts.buffer,\r\n indexCounts.buffer,\r\n indices.buffer,\r\n batchIds.buffer,\r\n batchTableColors.buffer,\r\n packedBuffer.buffer,\r\n ];\r\n var parameters = {\r\n packedBuffer: packedBuffer.buffer,\r\n positions: positions.buffer,\r\n counts: counts.buffer,\r\n indexCounts: indexCounts.buffer,\r\n indices: indices.buffer,\r\n batchIds: batchIds.buffer,\r\n batchTableColors: batchTableColors.buffer,\r\n };\r\n\r\n var minimumHeights = polygons._polygonMinimumHeights;\r\n var maximumHeights = polygons._polygonMaximumHeights;\r\n if (defined(minimumHeights) && defined(maximumHeights)) {\r\n minimumHeights = arraySlice(minimumHeights);\r\n maximumHeights = arraySlice(maximumHeights);\r\n\r\n transferrableObjects.push(minimumHeights.buffer, maximumHeights.buffer);\r\n parameters.minimumHeights = minimumHeights;\r\n parameters.maximumHeights = maximumHeights;\r\n }\r\n\r\n var verticesPromise = (polygons._verticesPromise = createVerticesTaskProcessor.scheduleTask(\r\n parameters,\r\n transferrableObjects\r\n ));\r\n if (!defined(verticesPromise)) {\r\n // Postponed\r\n return;\r\n }\r\n\r\n when(verticesPromise, function (result) {\r\n polygons._positions = undefined;\r\n polygons._counts = undefined;\r\n polygons._polygonMinimumHeights = undefined;\r\n polygons._polygonMaximumHeights = undefined;\r\n\r\n var packedBuffer = new Float64Array(result.packedBuffer);\r\n var indexDatatype = packedBuffer[0];\r\n unpackBuffer(polygons, packedBuffer);\r\n\r\n polygons._indices =\r\n IndexDatatype.getSizeInBytes(indexDatatype) === 2\r\n ? new Uint16Array(result.indices)\r\n : new Uint32Array(result.indices);\r\n polygons._indexOffsets = new Uint32Array(result.indexOffsets);\r\n polygons._indexCounts = new Uint32Array(result.indexCounts);\r\n\r\n // will be released\r\n polygons._batchedPositions = new Float32Array(result.positions);\r\n polygons._vertexBatchIds = new Uint16Array(result.batchIds);\r\n\r\n polygons._ready = true;\r\n });\r\n }\r\n\r\n if (polygons._ready && !defined(polygons._primitive)) {\r\n polygons._primitive = new Vector3DTilePrimitive({\r\n batchTable: polygons._batchTable,\r\n positions: polygons._batchedPositions,\r\n batchIds: polygons._batchIds,\r\n vertexBatchIds: polygons._vertexBatchIds,\r\n indices: polygons._indices,\r\n indexOffsets: polygons._indexOffsets,\r\n indexCounts: polygons._indexCounts,\r\n batchedIndices: polygons._batchedIndices,\r\n boundingVolume: polygons._boundingVolume,\r\n boundingVolumes: polygons._boundingVolumes,\r\n center: polygons._center,\r\n });\r\n\r\n polygons._batchTable = undefined;\r\n polygons._batchIds = undefined;\r\n polygons._positions = undefined;\r\n polygons._counts = undefined;\r\n polygons._indices = undefined;\r\n polygons._indexCounts = undefined;\r\n polygons._indexOffsets = undefined;\r\n polygons._batchTableColors = undefined;\r\n polygons._packedBuffer = undefined;\r\n polygons._batchedPositions = undefined;\r\n polygons._transferrableBatchIds = undefined;\r\n polygons._vertexBatchIds = undefined;\r\n polygons._ellipsoid = undefined;\r\n polygons._minimumHeight = undefined;\r\n polygons._maximumHeight = undefined;\r\n polygons._polygonMinimumHeights = undefined;\r\n polygons._polygonMaximumHeights = undefined;\r\n polygons._center = undefined;\r\n polygons._rectangle = undefined;\r\n polygons._boundingVolume = undefined;\r\n polygons._boundingVolumes = undefined;\r\n polygons._batchedIndices = undefined;\r\n polygons._verticesPromise = undefined;\r\n\r\n polygons._readyPromise.resolve();\r\n }\r\n}\r\n\r\n/**\r\n * Creates features for each polygon and places it at the batch id index of features.\r\n *\r\n * @param {Vector3DTileContent} content The vector tile content.\r\n * @param {Cesium3DTileFeature[]} features An array of features where the polygon features will be placed.\r\n */\r\nVector3DTilePolygons.prototype.createFeatures = function (content, features) {\r\n this._primitive.createFeatures(content, features);\r\n};\r\n\r\n/**\r\n * Colors the entire tile when enabled is true. The resulting color will be (polygon batch table color * color).\r\n *\r\n * @param {Boolean} enabled Whether to enable debug coloring.\r\n * @param {Color} color The debug color.\r\n */\r\nVector3DTilePolygons.prototype.applyDebugSettings = function (enabled, color) {\r\n this._primitive.applyDebugSettings(enabled, color);\r\n};\r\n\r\n/**\r\n * Apply a style to the content.\r\n *\r\n * @param {Cesium3DTileStyle} style The style.\r\n * @param {Cesium3DTileFeature[]} features The array of features.\r\n */\r\nVector3DTilePolygons.prototype.applyStyle = function (style, features) {\r\n this._primitive.applyStyle(style, features);\r\n};\r\n\r\n/**\r\n * Call when updating the color of a polygon with batchId changes color. The polygons will need to be re-batched\r\n * on the next update.\r\n *\r\n * @param {Number} batchId The batch id of the polygon whose color has changed.\r\n * @param {Color} color The new polygon color.\r\n */\r\nVector3DTilePolygons.prototype.updateCommands = function (batchId, color) {\r\n this._primitive.updateCommands(batchId, color);\r\n};\r\n\r\n/**\r\n * Updates the batches and queues the commands for rendering.\r\n *\r\n * @param {FrameState} frameState The current frame state.\r\n */\r\nVector3DTilePolygons.prototype.update = function (frameState) {\r\n createPrimitive(this);\r\n\r\n if (!this._ready) {\r\n return;\r\n }\r\n\r\n this._primitive.debugWireframe = this.debugWireframe;\r\n this._primitive.forceRebatch = this.forceRebatch;\r\n this._primitive.classificationType = this.classificationType;\r\n this._primitive.update(frameState);\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n */\r\nVector3DTilePolygons.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nVector3DTilePolygons.prototype.destroy = function () {\r\n this._primitive = this._primitive && this._primitive.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Vector3DTilePolygons;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec4 currentPosition;\\n\\\nattribute vec4 previousPosition;\\n\\\nattribute vec4 nextPosition;\\n\\\nattribute vec2 expandAndWidth;\\n\\\nattribute float a_batchId;\\n\\\nuniform mat4 u_modifiedModelView;\\n\\\nvoid main()\\n\\\n{\\n\\\nfloat expandDir = expandAndWidth.x;\\n\\\nfloat width = abs(expandAndWidth.y) + 0.5;\\n\\\nbool usePrev = expandAndWidth.y < 0.0;\\n\\\nvec4 p = u_modifiedModelView * currentPosition;\\n\\\nvec4 prev = u_modifiedModelView * previousPosition;\\n\\\nvec4 next = u_modifiedModelView * nextPosition;\\n\\\nfloat angle;\\n\\\nvec4 positionWC = getPolylineWindowCoordinatesEC(p, prev, next, expandDir, width, usePrev, angle);\\n\\\ngl_Position = czm_viewportOrthographic * positionWC;\\n\\\n}\\n\\\n\";\n","import arraySlice from \"../Core/arraySlice.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport TaskProcessor from \"../Core/TaskProcessor.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport VertexArray from \"../Renderer/VertexArray.js\";\r\nimport PolylineCommon from \"../Shaders/PolylineCommon.js\";\r\nimport Vector3DTilePolylinesVS from \"../Shaders/Vector3DTilePolylinesVS.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport Cesium3DTileFeature from \"./Cesium3DTileFeature.js\";\r\n\r\n/**\r\n * Creates a batch of polylines that have been subdivided to be draped on terrain.\r\n *\r\n * @alias Vector3DTilePolylines\r\n * @constructor\r\n *\r\n * @param {Object} options An object with following properties:\r\n * @param {Uint16Array} options.positions The positions of the polylines\r\n * @param {Uint32Array} options.counts The number or positions in the each polyline.\r\n * @param {Uint16Array} options.widths The width of each polyline.\r\n * @param {Number} options.minimumHeight The minimum height of the terrain covered by the tile.\r\n * @param {Number} options.maximumHeight The maximum height of the terrain covered by the tile.\r\n * @param {Rectangle} options.rectangle The rectangle containing the tile.\r\n * @param {Cartesian3} [options.center=Cartesian3.ZERO] The RTC center.\r\n * @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polylines.\r\n * @param {Uint16Array} options.batchIds The batch ids for each polyline.\r\n * @param {BoundingSphere} options.boundingVolume The bounding volume for the entire batch of polylines.\r\n *\r\n * @private\r\n */\r\nfunction Vector3DTilePolylines(options) {\r\n // these arrays are all released after the first update.\r\n this._positions = options.positions;\r\n this._widths = options.widths;\r\n this._counts = options.counts;\r\n this._batchIds = options.batchIds;\r\n\r\n this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n this._minimumHeight = options.minimumHeight;\r\n this._maximumHeight = options.maximumHeight;\r\n this._center = options.center;\r\n this._rectangle = options.rectangle;\r\n\r\n this._boundingVolume = options.boundingVolume;\r\n this._batchTable = options.batchTable;\r\n\r\n this._va = undefined;\r\n this._sp = undefined;\r\n this._rs = undefined;\r\n this._uniformMap = undefined;\r\n this._command = undefined;\r\n\r\n this._transferrableBatchIds = undefined;\r\n this._packedBuffer = undefined;\r\n\r\n this._currentPositions = undefined;\r\n this._previousPositions = undefined;\r\n this._nextPositions = undefined;\r\n this._expandAndWidth = undefined;\r\n this._vertexBatchIds = undefined;\r\n this._indices = undefined;\r\n\r\n this._constantColor = Color.clone(Color.WHITE);\r\n this._highlightColor = this._constantColor;\r\n\r\n this._trianglesLength = 0;\r\n this._geometryByteLength = 0;\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._verticesPromise = undefined;\r\n}\r\n\r\nObject.defineProperties(Vector3DTilePolylines.prototype, {\r\n /**\r\n * Gets the number of triangles.\r\n *\r\n * @memberof Vector3DTilePolylines.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n trianglesLength: {\r\n get: function () {\r\n return this._trianglesLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the geometry memory in bytes.\r\n *\r\n * @memberof Vector3DTilePolylines.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n geometryByteLength: {\r\n get: function () {\r\n return this._geometryByteLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof Vector3DTilePolylines.prototype\r\n * @type {Promise}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n});\r\n\r\nfunction packBuffer(polylines) {\r\n var rectangle = polylines._rectangle;\r\n var minimumHeight = polylines._minimumHeight;\r\n var maximumHeight = polylines._maximumHeight;\r\n var ellipsoid = polylines._ellipsoid;\r\n var center = polylines._center;\r\n\r\n var packedLength =\r\n 2 +\r\n Rectangle.packedLength +\r\n Ellipsoid.packedLength +\r\n Cartesian3.packedLength;\r\n var packedBuffer = new Float64Array(packedLength);\r\n\r\n var offset = 0;\r\n packedBuffer[offset++] = minimumHeight;\r\n packedBuffer[offset++] = maximumHeight;\r\n\r\n Rectangle.pack(rectangle, packedBuffer, offset);\r\n offset += Rectangle.packedLength;\r\n\r\n Ellipsoid.pack(ellipsoid, packedBuffer, offset);\r\n offset += Ellipsoid.packedLength;\r\n\r\n Cartesian3.pack(center, packedBuffer, offset);\r\n\r\n return packedBuffer;\r\n}\r\n\r\nvar createVerticesTaskProcessor = new TaskProcessor(\r\n \"createVectorTilePolylines\",\r\n 5\r\n);\r\nvar attributeLocations = {\r\n previousPosition: 0,\r\n currentPosition: 1,\r\n nextPosition: 2,\r\n expandAndWidth: 3,\r\n a_batchId: 4,\r\n};\r\n\r\nfunction createVertexArray(polylines, context) {\r\n if (defined(polylines._va)) {\r\n return;\r\n }\r\n\r\n if (!defined(polylines._verticesPromise)) {\r\n var positions = polylines._positions;\r\n var widths = polylines._widths;\r\n var counts = polylines._counts;\r\n var batchIds = polylines._transferrableBatchIds;\r\n\r\n var packedBuffer = polylines._packedBuffer;\r\n\r\n if (!defined(packedBuffer)) {\r\n // Copy because they may be the views on the same buffer.\r\n positions = polylines._positions = arraySlice(positions);\r\n widths = polylines._widths = arraySlice(widths);\r\n counts = polylines._counts = arraySlice(counts);\r\n\r\n batchIds = polylines._transferrableBatchIds = arraySlice(\r\n polylines._batchIds\r\n );\r\n\r\n packedBuffer = polylines._packedBuffer = packBuffer(polylines);\r\n }\r\n\r\n var transferrableObjects = [\r\n positions.buffer,\r\n widths.buffer,\r\n counts.buffer,\r\n batchIds.buffer,\r\n packedBuffer.buffer,\r\n ];\r\n var parameters = {\r\n positions: positions.buffer,\r\n widths: widths.buffer,\r\n counts: counts.buffer,\r\n batchIds: batchIds.buffer,\r\n packedBuffer: packedBuffer.buffer,\r\n };\r\n\r\n var verticesPromise = (polylines._verticesPromise = createVerticesTaskProcessor.scheduleTask(\r\n parameters,\r\n transferrableObjects\r\n ));\r\n if (!defined(verticesPromise)) {\r\n // Postponed\r\n return;\r\n }\r\n\r\n when(verticesPromise)\r\n .then(function (result) {\r\n polylines._currentPositions = new Float32Array(result.currentPositions);\r\n polylines._previousPositions = new Float32Array(\r\n result.previousPositions\r\n );\r\n polylines._nextPositions = new Float32Array(result.nextPositions);\r\n polylines._expandAndWidth = new Float32Array(result.expandAndWidth);\r\n polylines._vertexBatchIds = new Uint16Array(result.batchIds);\r\n\r\n var indexDatatype = result.indexDatatype;\r\n polylines._indices =\r\n indexDatatype === IndexDatatype.UNSIGNED_SHORT\r\n ? new Uint16Array(result.indices)\r\n : new Uint32Array(result.indices);\r\n\r\n polylines._ready = true;\r\n })\r\n .otherwise(function (error) {\r\n polylines._readyPromise.reject(error);\r\n });\r\n }\r\n\r\n if (polylines._ready && !defined(polylines._va)) {\r\n var curPositions = polylines._currentPositions;\r\n var prevPositions = polylines._previousPositions;\r\n var nextPositions = polylines._nextPositions;\r\n var expandAndWidth = polylines._expandAndWidth;\r\n var vertexBatchIds = polylines._vertexBatchIds;\r\n var indices = polylines._indices;\r\n\r\n var byteLength =\r\n prevPositions.byteLength +\r\n curPositions.byteLength +\r\n nextPositions.byteLength;\r\n byteLength +=\r\n expandAndWidth.byteLength +\r\n vertexBatchIds.byteLength +\r\n indices.byteLength;\r\n polylines._trianglesLength = indices.length / 3;\r\n polylines._geometryByteLength = byteLength;\r\n\r\n var prevPositionBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: prevPositions,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var curPositionBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: curPositions,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var nextPositionBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: nextPositions,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var expandAndWidthBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: expandAndWidth,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var idBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: vertexBatchIds,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n\r\n var indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: indices,\r\n usage: BufferUsage.STATIC_DRAW,\r\n indexDatatype:\r\n indices.BYTES_PER_ELEMENT === 2\r\n ? IndexDatatype.UNSIGNED_SHORT\r\n : IndexDatatype.UNSIGNED_INT,\r\n });\r\n\r\n var vertexAttributes = [\r\n {\r\n index: attributeLocations.previousPosition,\r\n vertexBuffer: prevPositionBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n index: attributeLocations.currentPosition,\r\n vertexBuffer: curPositionBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n index: attributeLocations.nextPosition,\r\n vertexBuffer: nextPositionBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n index: attributeLocations.expandAndWidth,\r\n vertexBuffer: expandAndWidthBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 2,\r\n },\r\n {\r\n index: attributeLocations.a_batchId,\r\n vertexBuffer: idBuffer,\r\n componentDatatype: ComponentDatatype.UNSIGNED_SHORT,\r\n componentsPerAttribute: 1,\r\n },\r\n ];\r\n\r\n polylines._va = new VertexArray({\r\n context: context,\r\n attributes: vertexAttributes,\r\n indexBuffer: indexBuffer,\r\n });\r\n\r\n polylines._positions = undefined;\r\n polylines._widths = undefined;\r\n polylines._counts = undefined;\r\n\r\n polylines._ellipsoid = undefined;\r\n polylines._minimumHeight = undefined;\r\n polylines._maximumHeight = undefined;\r\n polylines._rectangle = undefined;\r\n\r\n polylines._transferrableBatchIds = undefined;\r\n polylines._packedBuffer = undefined;\r\n\r\n polylines._currentPositions = undefined;\r\n polylines._previousPositions = undefined;\r\n polylines._nextPositions = undefined;\r\n polylines._expandAndWidth = undefined;\r\n polylines._vertexBatchIds = undefined;\r\n polylines._indices = undefined;\r\n\r\n polylines._readyPromise.resolve();\r\n }\r\n}\r\n\r\nvar modifiedModelViewScratch = new Matrix4();\r\nvar rtcScratch = new Cartesian3();\r\n\r\nfunction createUniformMap(primitive, context) {\r\n if (defined(primitive._uniformMap)) {\r\n return;\r\n }\r\n\r\n primitive._uniformMap = {\r\n u_modifiedModelView: function () {\r\n var viewMatrix = context.uniformState.view;\r\n Matrix4.clone(viewMatrix, modifiedModelViewScratch);\r\n Matrix4.multiplyByPoint(\r\n modifiedModelViewScratch,\r\n primitive._center,\r\n rtcScratch\r\n );\r\n Matrix4.setTranslation(\r\n modifiedModelViewScratch,\r\n rtcScratch,\r\n modifiedModelViewScratch\r\n );\r\n return modifiedModelViewScratch;\r\n },\r\n u_highlightColor: function () {\r\n return primitive._highlightColor;\r\n },\r\n };\r\n}\r\n\r\nfunction createRenderStates(primitive) {\r\n if (defined(primitive._rs)) {\r\n return;\r\n }\r\n\r\n var polygonOffset = {\r\n enabled: true,\r\n factor: -5.0,\r\n units: -5.0,\r\n };\r\n\r\n primitive._rs = RenderState.fromCache({\r\n blending: BlendingState.ALPHA_BLEND,\r\n depthMask: false,\r\n depthTest: {\r\n enabled: true,\r\n },\r\n polygonOffset: polygonOffset,\r\n });\r\n}\r\n\r\nvar PolylineFS =\r\n \"uniform vec4 u_highlightColor; \\n\" +\r\n \"void main()\\n\" +\r\n \"{\\n\" +\r\n \" gl_FragColor = u_highlightColor;\\n\" +\r\n \"}\\n\";\r\n\r\nfunction createShaders(primitive, context) {\r\n if (defined(primitive._sp)) {\r\n return;\r\n }\r\n\r\n var batchTable = primitive._batchTable;\r\n\r\n var vsSource = batchTable.getVertexShaderCallback(\r\n false,\r\n \"a_batchId\",\r\n undefined\r\n )(Vector3DTilePolylinesVS);\r\n var fsSource = batchTable.getFragmentShaderCallback(\r\n false,\r\n undefined,\r\n false\r\n )(PolylineFS);\r\n\r\n var vs = new ShaderSource({\r\n defines: [\r\n \"VECTOR_TILE\",\r\n !FeatureDetection.isInternetExplorer() ? \"CLIP_POLYLINE\" : \"\",\r\n ],\r\n sources: [PolylineCommon, vsSource],\r\n });\r\n var fs = new ShaderSource({\r\n defines: [\"VECTOR_TILE\"],\r\n sources: [fsSource],\r\n });\r\n\r\n primitive._sp = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n}\r\n\r\nfunction queueCommands(primitive, frameState) {\r\n if (!defined(primitive._command)) {\r\n var uniformMap = primitive._batchTable.getUniformMapCallback()(\r\n primitive._uniformMap\r\n );\r\n primitive._command = new DrawCommand({\r\n owner: primitive,\r\n vertexArray: primitive._va,\r\n renderState: primitive._rs,\r\n shaderProgram: primitive._sp,\r\n uniformMap: uniformMap,\r\n boundingVolume: primitive._boundingVolume,\r\n pass: Pass.TRANSLUCENT,\r\n pickId: primitive._batchTable.getPickId(),\r\n });\r\n }\r\n\r\n frameState.commandList.push(primitive._command);\r\n}\r\n\r\n/**\r\n * Creates features for each polyline and places it at the batch id index of features.\r\n *\r\n * @param {Vector3DTileContent} content The vector tile content.\r\n * @param {Cesium3DTileFeature[]} features An array of features where the polygon features will be placed.\r\n */\r\nVector3DTilePolylines.prototype.createFeatures = function (content, features) {\r\n var batchIds = this._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n features[batchId] = new Cesium3DTileFeature(content, batchId);\r\n }\r\n};\r\n\r\n/**\r\n * Colors the entire tile when enabled is true. The resulting color will be (polyline batch table color * color).\r\n *\r\n * @param {Boolean} enabled Whether to enable debug coloring.\r\n * @param {Color} color The debug color.\r\n */\r\nVector3DTilePolylines.prototype.applyDebugSettings = function (enabled, color) {\r\n this._highlightColor = enabled ? color : this._constantColor;\r\n};\r\n\r\nfunction clearStyle(polygons, features) {\r\n var batchIds = polygons._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n var feature = features[batchId];\r\n\r\n feature.show = true;\r\n feature.color = Color.WHITE;\r\n }\r\n}\r\n\r\nvar scratchColor = new Color();\r\n\r\nvar DEFAULT_COLOR_VALUE = Color.WHITE;\r\nvar DEFAULT_SHOW_VALUE = true;\r\n\r\n/**\r\n * Apply a style to the content.\r\n *\r\n * @param {Cesium3DTileStyle} style The style.\r\n * @param {Cesium3DTileFeature[]} features The array of features.\r\n */\r\nVector3DTilePolylines.prototype.applyStyle = function (style, features) {\r\n if (!defined(style)) {\r\n clearStyle(this, features);\r\n return;\r\n }\r\n\r\n var batchIds = this._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n var feature = features[batchId];\r\n\r\n feature.color = defined(style.color)\r\n ? style.color.evaluateColor(feature, scratchColor)\r\n : DEFAULT_COLOR_VALUE;\r\n feature.show = defined(style.show)\r\n ? style.show.evaluate(feature)\r\n : DEFAULT_SHOW_VALUE;\r\n }\r\n};\r\n\r\n/**\r\n * Updates the batches and queues the commands for rendering.\r\n *\r\n * @param {FrameState} frameState The current frame state.\r\n */\r\nVector3DTilePolylines.prototype.update = function (frameState) {\r\n var context = frameState.context;\r\n\r\n createVertexArray(this, context);\r\n createUniformMap(this, context);\r\n createShaders(this, context);\r\n createRenderStates(this);\r\n\r\n if (!this._ready) {\r\n return;\r\n }\r\n\r\n var passes = frameState.passes;\r\n if (passes.render || passes.pick) {\r\n queueCommands(this, frameState);\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n */\r\nVector3DTilePolylines.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nVector3DTilePolylines.prototype.destroy = function () {\r\n this._va = this._va && this._va.destroy();\r\n this._sp = this._sp && this._sp.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Vector3DTilePolylines;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"attribute vec3 startEllipsoidNormal;\\n\\\nattribute vec3 endEllipsoidNormal;\\n\\\nattribute vec4 startPositionAndHeight;\\n\\\nattribute vec4 endPositionAndHeight;\\n\\\nattribute vec4 startFaceNormalAndVertexCorner;\\n\\\nattribute vec4 endFaceNormalAndHalfWidth;\\n\\\nattribute float a_batchId;\\n\\\nuniform mat4 u_modifiedModelView;\\n\\\nuniform vec2 u_minimumMaximumVectorHeights;\\n\\\nvarying vec4 v_startPlaneEC;\\n\\\nvarying vec4 v_endPlaneEC;\\n\\\nvarying vec4 v_rightPlaneEC;\\n\\\nvarying float v_halfWidth;\\n\\\nvarying vec3 v_volumeUpEC;\\n\\\nvoid main()\\n\\\n{\\n\\\nfloat isEnd = floor(startFaceNormalAndVertexCorner.w * 0.251);\\n\\\nfloat isTop = floor(startFaceNormalAndVertexCorner.w * mix(0.51, 0.19, isEnd));\\n\\\nvec3 forward = endPositionAndHeight.xyz - startPositionAndHeight.xyz;\\n\\\nvec3 right = normalize(cross(forward, startEllipsoidNormal));\\n\\\nvec4 position = vec4(startPositionAndHeight.xyz, 1.0);\\n\\\nposition.xyz += forward * isEnd;\\n\\\nv_volumeUpEC = czm_normal * normalize(cross(right, forward));\\n\\\nfloat offset;\\n\\\nvec3 ellipsoidNormal = mix(startEllipsoidNormal, endEllipsoidNormal, isEnd);\\n\\\noffset = mix(startPositionAndHeight.w, endPositionAndHeight.w, isEnd);\\n\\\noffset = mix(u_minimumMaximumVectorHeights.y, u_minimumMaximumVectorHeights.x, isTop) - offset;\\n\\\nposition.xyz += offset * ellipsoidNormal;\\n\\\nposition = u_modifiedModelView * position;\\n\\\nright = czm_normal * right;\\n\\\nvec3 scratchNormal = mix(-startFaceNormalAndVertexCorner.xyz, endFaceNormalAndHalfWidth.xyz, isEnd);\\n\\\nscratchNormal = cross(scratchNormal, mix(startEllipsoidNormal, endEllipsoidNormal, isEnd));\\n\\\nvec3 miterPushNormal = czm_normal * normalize(scratchNormal);\\n\\\noffset = 2.0 * endFaceNormalAndHalfWidth.w * max(0.0, czm_metersPerPixel(position));\\n\\\noffset = offset / dot(miterPushNormal, right);\\n\\\nposition.xyz += miterPushNormal * (offset * sign(0.5 - mod(startFaceNormalAndVertexCorner.w, 2.0)));\\n\\\ngl_Position = czm_depthClamp(czm_projection * position);\\n\\\nposition = u_modifiedModelView * vec4(startPositionAndHeight.xyz, 1.0);\\n\\\nvec3 startNormalEC = czm_normal * startFaceNormalAndVertexCorner.xyz;\\n\\\nv_startPlaneEC = vec4(startNormalEC, -dot(startNormalEC, position.xyz));\\n\\\nv_rightPlaneEC = vec4(right, -dot(right, position.xyz));\\n\\\nposition = u_modifiedModelView * vec4(endPositionAndHeight.xyz, 1.0);\\n\\\nvec3 endNormalEC = czm_normal * endFaceNormalAndHalfWidth.xyz;\\n\\\nv_endPlaneEC = vec4(endNormalEC, -dot(endNormalEC, position.xyz));\\n\\\nv_halfWidth = endFaceNormalAndHalfWidth.w;\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"#ifdef GL_EXT_frag_depth\\n\\\n#extension GL_EXT_frag_depth : enable\\n\\\n#endif\\n\\\nvarying vec4 v_startPlaneEC;\\n\\\nvarying vec4 v_endPlaneEC;\\n\\\nvarying vec4 v_rightPlaneEC;\\n\\\nvarying float v_halfWidth;\\n\\\nvarying vec3 v_volumeUpEC;\\n\\\nuniform vec4 u_highlightColor;\\n\\\nvoid main()\\n\\\n{\\n\\\nfloat logDepthOrDepth = czm_branchFreeTernary(czm_sceneMode == czm_sceneMode2D, gl_FragCoord.z, czm_unpackDepth(texture2D(czm_globeDepthTexture, gl_FragCoord.xy / czm_viewport.zw)));\\n\\\nif (logDepthOrDepth == 0.0) {\\n\\\n#ifdef DEBUG_SHOW_VOLUME\\n\\\ngl_FragColor = vec4(0.0, 0.0, 1.0, 0.5);\\n\\\nreturn;\\n\\\n#else // DEBUG_SHOW_VOLUME\\n\\\ndiscard;\\n\\\n#endif // DEBUG_SHOW_VOLUME\\n\\\n}\\n\\\nvec4 eyeCoordinate = czm_windowToEyeCoordinates(gl_FragCoord.xy, logDepthOrDepth);\\n\\\neyeCoordinate /= eyeCoordinate.w;\\n\\\nfloat halfMaxWidth = v_halfWidth * czm_metersPerPixel(eyeCoordinate);\\n\\\nhalfMaxWidth += halfMaxWidth * (1.0 - dot(-normalize(eyeCoordinate.xyz), v_volumeUpEC));\\n\\\nfloat widthwiseDistance = czm_planeDistance(v_rightPlaneEC, eyeCoordinate.xyz);\\n\\\nfloat distanceFromStart = czm_planeDistance(v_startPlaneEC, eyeCoordinate.xyz);\\n\\\nfloat distanceFromEnd = czm_planeDistance(v_endPlaneEC, eyeCoordinate.xyz);\\n\\\nif (abs(widthwiseDistance) > halfMaxWidth || distanceFromStart < 0.0 || distanceFromEnd < 0.0) {\\n\\\n#ifdef DEBUG_SHOW_VOLUME\\n\\\ngl_FragColor = vec4(logDepthOrDepth, 0.0, 0.0, 0.5);\\n\\\nreturn;\\n\\\n#else // DEBUG_SHOW_VOLUME\\n\\\ndiscard;\\n\\\n#endif // DEBUG_SHOW_VOLUME\\n\\\n}\\n\\\ngl_FragColor = u_highlightColor;\\n\\\nczm_writeDepthClamp();\\n\\\n}\\n\\\n\";\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport arraySlice from \"../Core/arraySlice.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport FeatureDetection from \"../Core/FeatureDetection.js\";\r\nimport IndexDatatype from \"../Core/IndexDatatype.js\";\r\nimport OrientedBoundingBox from \"../Core/OrientedBoundingBox.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport TaskProcessor from \"../Core/TaskProcessor.js\";\r\nimport Buffer from \"../Renderer/Buffer.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport VertexArray from \"../Renderer/VertexArray.js\";\r\nimport PolylineCommon from \"../Shaders/PolylineCommon.js\";\r\nimport Vector3DTileClampedPolylinesVS from \"../Shaders/Vector3DTileClampedPolylinesVS.js\";\r\nimport Vector3DTileClampedPolylinesFS from \"../Shaders/Vector3DTileClampedPolylinesFS.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport Cesium3DTileFeature from \"./Cesium3DTileFeature.js\";\r\nimport ClassificationType from \"./ClassificationType.js\";\r\nimport CullFace from \"./CullFace.js\";\r\nimport StencilConstants from \"./StencilConstants.js\";\r\nimport StencilFunction from \"./StencilFunction.js\";\r\nimport StencilOperation from \"./StencilOperation.js\";\r\n\r\n/**\r\n * Creates a batch of polylines as volumes with shader-adjustable width.\r\n *\r\n * @alias Vector3DTileClampedPolylines\r\n * @constructor\r\n *\r\n * @param {Object} options An object with following properties:\r\n * @param {Uint16Array} options.positions The positions of the polylines\r\n * @param {Uint32Array} options.counts The number or positions in the each polyline.\r\n * @param {Uint16Array} options.widths The width of each polyline.\r\n * @param {Number} options.minimumHeight The minimum height of the tile's region.\r\n * @param {Number} options.maximumHeight The maximum height of the tile's region.\r\n * @param {Rectangle} options.rectangle The rectangle containing the tile.\r\n * @param {Cartesian3} [options.center=Cartesian3.ZERO] The RTC center.\r\n * @param {Cesium3DTileBatchTable} options.batchTable The batch table for the tile containing the batched polylines.\r\n * @param {Uint16Array} options.batchIds The batch ids for each polyline.\r\n * @param {Cesium3DTileset} options.tileset Tileset carrying minimum and maximum clamping heights.\r\n *\r\n * @private\r\n */\r\nfunction Vector3DTileClampedPolylines(options) {\r\n // these arrays hold data from the tile payload\r\n // and are all released after the first update.\r\n this._positions = options.positions;\r\n this._widths = options.widths;\r\n this._counts = options.counts;\r\n this._batchIds = options.batchIds;\r\n\r\n this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n this._minimumHeight = options.minimumHeight;\r\n this._maximumHeight = options.maximumHeight;\r\n this._center = options.center;\r\n this._rectangle = options.rectangle;\r\n\r\n this._batchTable = options.batchTable;\r\n\r\n this._va = undefined;\r\n this._sp = undefined;\r\n this._rs = undefined;\r\n this._uniformMap = undefined;\r\n this._command = undefined;\r\n\r\n this._transferrableBatchIds = undefined;\r\n this._packedBuffer = undefined;\r\n this._tileset = options.tileset;\r\n this._minimumMaximumVectorHeights = new Cartesian2(\r\n ApproximateTerrainHeights._defaultMinTerrainHeight,\r\n ApproximateTerrainHeights._defaultMaxTerrainHeight\r\n );\r\n this._boundingVolume = OrientedBoundingBox.fromRectangle(\r\n options.rectangle,\r\n ApproximateTerrainHeights._defaultMinTerrainHeight,\r\n ApproximateTerrainHeights._defaultMaxTerrainHeight,\r\n this._ellipsoid\r\n );\r\n\r\n // Fat vertices - all information for each volume packed to a vec3 and 5 vec4s\r\n this._startEllipsoidNormals = undefined;\r\n this._endEllipsoidNormals = undefined;\r\n this._startPositionAndHeights = undefined;\r\n this._startFaceNormalAndVertexCornerIds = undefined;\r\n this._endPositionAndHeights = undefined;\r\n this._endFaceNormalAndHalfWidths = undefined;\r\n this._vertexBatchIds = undefined;\r\n\r\n this._indices = undefined;\r\n\r\n this._constantColor = Color.clone(Color.WHITE);\r\n this._highlightColor = this._constantColor;\r\n\r\n this._trianglesLength = 0;\r\n this._geometryByteLength = 0;\r\n\r\n this._ready = false;\r\n this._readyPromise = when.defer();\r\n\r\n this._verticesPromise = undefined;\r\n\r\n var that = this;\r\n ApproximateTerrainHeights.initialize()\r\n .then(function () {\r\n updateMinimumMaximumHeights(that, that._rectangle, that._ellipsoid);\r\n })\r\n .otherwise(function (error) {\r\n this._readyPromise.reject(error);\r\n });\r\n}\r\n\r\nObject.defineProperties(Vector3DTileClampedPolylines.prototype, {\r\n /**\r\n * Gets the number of triangles.\r\n *\r\n * @memberof Vector3DTileClampedPolylines.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n trianglesLength: {\r\n get: function () {\r\n return this._trianglesLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the geometry memory in bytes.\r\n *\r\n * @memberof Vector3DTileClampedPolylines.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n geometryByteLength: {\r\n get: function () {\r\n return this._geometryByteLength;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a promise that resolves when the primitive is ready to render.\r\n * @memberof Vector3DTileClampedPolylines.prototype\r\n * @type {Promise}\r\n * @readonly\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n});\r\n\r\nfunction updateMinimumMaximumHeights(polylines, rectangle, ellipsoid) {\r\n var result = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n rectangle,\r\n ellipsoid\r\n );\r\n var min = result.minimumTerrainHeight;\r\n var max = result.maximumTerrainHeight;\r\n var minimumMaximumVectorHeights = polylines._minimumMaximumVectorHeights;\r\n minimumMaximumVectorHeights.x = min;\r\n minimumMaximumVectorHeights.y = max;\r\n\r\n var obb = polylines._boundingVolume;\r\n var rect = polylines._rectangle;\r\n OrientedBoundingBox.fromRectangle(rect, min, max, ellipsoid, obb);\r\n}\r\n\r\nfunction packBuffer(polylines) {\r\n var rectangle = polylines._rectangle;\r\n var minimumHeight = polylines._minimumHeight;\r\n var maximumHeight = polylines._maximumHeight;\r\n var ellipsoid = polylines._ellipsoid;\r\n var center = polylines._center;\r\n\r\n var packedLength =\r\n 2 +\r\n Rectangle.packedLength +\r\n Ellipsoid.packedLength +\r\n Cartesian3.packedLength;\r\n var packedBuffer = new Float64Array(packedLength);\r\n\r\n var offset = 0;\r\n packedBuffer[offset++] = minimumHeight;\r\n packedBuffer[offset++] = maximumHeight;\r\n\r\n Rectangle.pack(rectangle, packedBuffer, offset);\r\n offset += Rectangle.packedLength;\r\n\r\n Ellipsoid.pack(ellipsoid, packedBuffer, offset);\r\n offset += Ellipsoid.packedLength;\r\n\r\n Cartesian3.pack(center, packedBuffer, offset);\r\n\r\n return packedBuffer;\r\n}\r\n\r\nvar createVerticesTaskProcessor = new TaskProcessor(\r\n \"createVectorTileClampedPolylines\"\r\n);\r\nvar attributeLocations = {\r\n startEllipsoidNormal: 0,\r\n endEllipsoidNormal: 1,\r\n startPositionAndHeight: 2,\r\n endPositionAndHeight: 3,\r\n startFaceNormalAndVertexCorner: 4,\r\n endFaceNormalAndHalfWidth: 5,\r\n a_batchId: 6,\r\n};\r\n\r\nfunction createVertexArray(polylines, context) {\r\n if (defined(polylines._va)) {\r\n return;\r\n }\r\n\r\n if (!defined(polylines._verticesPromise)) {\r\n var positions = polylines._positions;\r\n var widths = polylines._widths;\r\n var counts = polylines._counts;\r\n var batchIds = polylines._transferrableBatchIds;\r\n\r\n var packedBuffer = polylines._packedBuffer;\r\n\r\n if (!defined(packedBuffer)) {\r\n // Copy because they may be the views on the same buffer.\r\n positions = polylines._positions = arraySlice(positions);\r\n widths = polylines._widths = arraySlice(widths);\r\n counts = polylines._counts = arraySlice(counts);\r\n\r\n batchIds = polylines._transferrableBatchIds = arraySlice(\r\n polylines._batchIds\r\n );\r\n\r\n packedBuffer = polylines._packedBuffer = packBuffer(polylines);\r\n }\r\n\r\n var transferrableObjects = [\r\n positions.buffer,\r\n widths.buffer,\r\n counts.buffer,\r\n batchIds.buffer,\r\n packedBuffer.buffer,\r\n ];\r\n var parameters = {\r\n positions: positions.buffer,\r\n widths: widths.buffer,\r\n counts: counts.buffer,\r\n batchIds: batchIds.buffer,\r\n packedBuffer: packedBuffer.buffer,\r\n };\r\n\r\n var verticesPromise = (polylines._verticesPromise = createVerticesTaskProcessor.scheduleTask(\r\n parameters,\r\n transferrableObjects\r\n ));\r\n if (!defined(verticesPromise)) {\r\n // Postponed\r\n return;\r\n }\r\n\r\n when(verticesPromise, function (result) {\r\n polylines._startEllipsoidNormals = new Float32Array(\r\n result.startEllipsoidNormals\r\n );\r\n polylines._endEllipsoidNormals = new Float32Array(\r\n result.endEllipsoidNormals\r\n );\r\n polylines._startPositionAndHeights = new Float32Array(\r\n result.startPositionAndHeights\r\n );\r\n polylines._startFaceNormalAndVertexCornerIds = new Float32Array(\r\n result.startFaceNormalAndVertexCornerIds\r\n );\r\n polylines._endPositionAndHeights = new Float32Array(\r\n result.endPositionAndHeights\r\n );\r\n polylines._endFaceNormalAndHalfWidths = new Float32Array(\r\n result.endFaceNormalAndHalfWidths\r\n );\r\n polylines._vertexBatchIds = new Uint16Array(result.vertexBatchIds);\r\n\r\n var indexDatatype = result.indexDatatype;\r\n polylines._indices =\r\n indexDatatype === IndexDatatype.UNSIGNED_SHORT\r\n ? new Uint16Array(result.indices)\r\n : new Uint32Array(result.indices);\r\n\r\n polylines._ready = true;\r\n }).otherwise(function (error) {\r\n polylines._readyPromise.reject(error);\r\n });\r\n }\r\n\r\n if (polylines._ready && !defined(polylines._va)) {\r\n var startEllipsoidNormals = polylines._startEllipsoidNormals;\r\n var endEllipsoidNormals = polylines._endEllipsoidNormals;\r\n var startPositionAndHeights = polylines._startPositionAndHeights;\r\n var endPositionAndHeights = polylines._endPositionAndHeights;\r\n var startFaceNormalAndVertexCornerIds =\r\n polylines._startFaceNormalAndVertexCornerIds;\r\n var endFaceNormalAndHalfWidths = polylines._endFaceNormalAndHalfWidths;\r\n var batchIdAttribute = polylines._vertexBatchIds;\r\n\r\n var indices = polylines._indices;\r\n\r\n var byteLength =\r\n startEllipsoidNormals.byteLength + endEllipsoidNormals.byteLength;\r\n byteLength +=\r\n startPositionAndHeights.byteLength + endPositionAndHeights.byteLength;\r\n byteLength +=\r\n startFaceNormalAndVertexCornerIds.byteLength +\r\n endFaceNormalAndHalfWidths.byteLength;\r\n byteLength += batchIdAttribute.byteLength + indices.byteLength;\r\n\r\n polylines._trianglesLength = indices.length / 3;\r\n polylines._geometryByteLength = byteLength;\r\n\r\n var startEllipsoidNormalsBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: startEllipsoidNormals,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var endEllipsoidNormalsBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: endEllipsoidNormals,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var startPositionAndHeightsBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: startPositionAndHeights,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var endPositionAndHeightsBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: endPositionAndHeights,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var startFaceNormalAndVertexCornerIdsBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: startFaceNormalAndVertexCornerIds,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var endFaceNormalAndHalfWidthsBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: endFaceNormalAndHalfWidths,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n var batchIdAttributeBuffer = Buffer.createVertexBuffer({\r\n context: context,\r\n typedArray: batchIdAttribute,\r\n usage: BufferUsage.STATIC_DRAW,\r\n });\r\n\r\n var indexBuffer = Buffer.createIndexBuffer({\r\n context: context,\r\n typedArray: indices,\r\n usage: BufferUsage.STATIC_DRAW,\r\n indexDatatype:\r\n indices.BYTES_PER_ELEMENT === 2\r\n ? IndexDatatype.UNSIGNED_SHORT\r\n : IndexDatatype.UNSIGNED_INT,\r\n });\r\n\r\n var vertexAttributes = [\r\n {\r\n index: attributeLocations.startEllipsoidNormal,\r\n vertexBuffer: startEllipsoidNormalsBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n index: attributeLocations.endEllipsoidNormal,\r\n vertexBuffer: endEllipsoidNormalsBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 3,\r\n },\r\n {\r\n index: attributeLocations.startPositionAndHeight,\r\n vertexBuffer: startPositionAndHeightsBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n },\r\n {\r\n index: attributeLocations.endPositionAndHeight,\r\n vertexBuffer: endPositionAndHeightsBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n },\r\n {\r\n index: attributeLocations.startFaceNormalAndVertexCorner,\r\n vertexBuffer: startFaceNormalAndVertexCornerIdsBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n },\r\n {\r\n index: attributeLocations.endFaceNormalAndHalfWidth,\r\n vertexBuffer: endFaceNormalAndHalfWidthsBuffer,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n componentsPerAttribute: 4,\r\n },\r\n {\r\n index: attributeLocations.a_batchId,\r\n vertexBuffer: batchIdAttributeBuffer,\r\n componentDatatype: ComponentDatatype.UNSIGNED_SHORT,\r\n componentsPerAttribute: 1,\r\n },\r\n ];\r\n\r\n polylines._va = new VertexArray({\r\n context: context,\r\n attributes: vertexAttributes,\r\n indexBuffer: indexBuffer,\r\n });\r\n\r\n polylines._positions = undefined;\r\n polylines._widths = undefined;\r\n polylines._counts = undefined;\r\n\r\n polylines._ellipsoid = undefined;\r\n polylines._minimumHeight = undefined;\r\n polylines._maximumHeight = undefined;\r\n polylines._rectangle = undefined;\r\n\r\n polylines._transferrableBatchIds = undefined;\r\n polylines._packedBuffer = undefined;\r\n\r\n polylines._startEllipsoidNormals = undefined;\r\n polylines._endEllipsoidNormals = undefined;\r\n polylines._startPositionAndHeights = undefined;\r\n polylines._startFaceNormalAndVertexCornerIds = undefined;\r\n polylines._endPositionAndHeights = undefined;\r\n polylines._endFaceNormalAndHalfWidths = undefined;\r\n polylines._vertexBatchIds = undefined;\r\n\r\n polylines._indices = undefined;\r\n\r\n polylines._readyPromise.resolve();\r\n }\r\n}\r\n\r\nvar modifiedModelViewScratch = new Matrix4();\r\nvar rtcScratch = new Cartesian3();\r\n\r\nfunction createUniformMap(primitive, context) {\r\n if (defined(primitive._uniformMap)) {\r\n return;\r\n }\r\n\r\n primitive._uniformMap = {\r\n u_modifiedModelView: function () {\r\n var viewMatrix = context.uniformState.view;\r\n Matrix4.clone(viewMatrix, modifiedModelViewScratch);\r\n Matrix4.multiplyByPoint(\r\n modifiedModelViewScratch,\r\n primitive._center,\r\n rtcScratch\r\n );\r\n Matrix4.setTranslation(\r\n modifiedModelViewScratch,\r\n rtcScratch,\r\n modifiedModelViewScratch\r\n );\r\n return modifiedModelViewScratch;\r\n },\r\n u_highlightColor: function () {\r\n return primitive._highlightColor;\r\n },\r\n u_minimumMaximumVectorHeights: function () {\r\n return primitive._minimumMaximumVectorHeights;\r\n },\r\n };\r\n}\r\n\r\nfunction getRenderState(mask3DTiles) {\r\n /**\r\n * Cull front faces of each volume (relative to camera) to prevent\r\n * classification drawing from both the front and back faces, double-draw.\r\n * The geometry is \"inverted\" (inside-out winding order for the indices) but\r\n * the vertex shader seems to re-invert so that the triangles face \"out\" again.\r\n * So cull FRONT faces.\r\n */\r\n return RenderState.fromCache({\r\n cull: {\r\n enabled: true,\r\n face: CullFace.FRONT,\r\n },\r\n blending: BlendingState.PRE_MULTIPLIED_ALPHA_BLEND,\r\n depthMask: false,\r\n stencilTest: {\r\n enabled: mask3DTiles,\r\n frontFunction: StencilFunction.EQUAL,\r\n frontOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.KEEP,\r\n zPass: StencilOperation.KEEP,\r\n },\r\n backFunction: StencilFunction.EQUAL,\r\n backOperation: {\r\n fail: StencilOperation.KEEP,\r\n zFail: StencilOperation.KEEP,\r\n zPass: StencilOperation.KEEP,\r\n },\r\n reference: StencilConstants.CESIUM_3D_TILE_MASK,\r\n mask: StencilConstants.CESIUM_3D_TILE_MASK,\r\n },\r\n });\r\n}\r\n\r\nfunction createRenderStates(primitive) {\r\n if (defined(primitive._rs)) {\r\n return;\r\n }\r\n\r\n primitive._rs = getRenderState(false);\r\n primitive._rs3DTiles = getRenderState(true);\r\n}\r\n\r\nfunction createShaders(primitive, context) {\r\n if (defined(primitive._sp)) {\r\n return;\r\n }\r\n\r\n var batchTable = primitive._batchTable;\r\n\r\n var vsSource = batchTable.getVertexShaderCallback(\r\n false,\r\n \"a_batchId\",\r\n undefined\r\n )(Vector3DTileClampedPolylinesVS);\r\n var fsSource = batchTable.getFragmentShaderCallback(\r\n false,\r\n undefined,\r\n true\r\n )(Vector3DTileClampedPolylinesFS);\r\n\r\n var vs = new ShaderSource({\r\n defines: [\r\n \"VECTOR_TILE\",\r\n !FeatureDetection.isInternetExplorer() ? \"CLIP_POLYLINE\" : \"\",\r\n ],\r\n sources: [PolylineCommon, vsSource],\r\n });\r\n var fs = new ShaderSource({\r\n defines: [\"VECTOR_TILE\"],\r\n sources: [fsSource],\r\n });\r\n\r\n primitive._sp = ShaderProgram.fromCache({\r\n context: context,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n}\r\n\r\nfunction queueCommands(primitive, frameState) {\r\n var command = primitive._command;\r\n if (!defined(primitive._command)) {\r\n var uniformMap = primitive._batchTable.getUniformMapCallback()(\r\n primitive._uniformMap\r\n );\r\n command = primitive._command = new DrawCommand({\r\n owner: primitive,\r\n vertexArray: primitive._va,\r\n renderState: primitive._rs,\r\n shaderProgram: primitive._sp,\r\n uniformMap: uniformMap,\r\n boundingVolume: primitive._boundingVolume,\r\n pass: Pass.TERRAIN_CLASSIFICATION,\r\n pickId: primitive._batchTable.getPickId(),\r\n });\r\n\r\n var derivedTilesetCommand = DrawCommand.shallowClone(\r\n command,\r\n command.derivedCommands.tileset\r\n );\r\n derivedTilesetCommand.renderState = primitive._rs3DTiles;\r\n derivedTilesetCommand.pass = Pass.CESIUM_3D_TILE_CLASSIFICATION;\r\n command.derivedCommands.tileset = derivedTilesetCommand;\r\n }\r\n\r\n var classificationType = primitive._tileset.classificationType;\r\n if (\r\n classificationType === ClassificationType.TERRAIN ||\r\n classificationType === ClassificationType.BOTH\r\n ) {\r\n frameState.commandList.push(command);\r\n }\r\n if (\r\n classificationType === ClassificationType.CESIUM_3D_TILE ||\r\n classificationType === ClassificationType.BOTH\r\n ) {\r\n frameState.commandList.push(command.derivedCommands.tileset);\r\n }\r\n}\r\n\r\n/**\r\n * Creates features for each polyline and places it at the batch id index of features.\r\n *\r\n * @param {Vector3DTileContent} content The vector tile content.\r\n * @param {Cesium3DTileFeature[]} features An array of features where the polygon features will be placed.\r\n */\r\nVector3DTileClampedPolylines.prototype.createFeatures = function (\r\n content,\r\n features\r\n) {\r\n var batchIds = this._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n features[batchId] = new Cesium3DTileFeature(content, batchId);\r\n }\r\n};\r\n\r\n/**\r\n * Colors the entire tile when enabled is true. The resulting color will be (polyline batch table color * color).\r\n *\r\n * @param {Boolean} enabled Whether to enable debug coloring.\r\n * @param {Color} color The debug color.\r\n */\r\nVector3DTileClampedPolylines.prototype.applyDebugSettings = function (\r\n enabled,\r\n color\r\n) {\r\n this._highlightColor = enabled ? color : this._constantColor;\r\n};\r\n\r\nfunction clearStyle(polygons, features) {\r\n var batchIds = polygons._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n var feature = features[batchId];\r\n\r\n feature.show = true;\r\n feature.color = Color.WHITE;\r\n }\r\n}\r\n\r\nvar scratchColor = new Color();\r\n\r\nvar DEFAULT_COLOR_VALUE = Color.WHITE;\r\nvar DEFAULT_SHOW_VALUE = true;\r\n\r\n/**\r\n * Apply a style to the content.\r\n *\r\n * @param {Cesium3DTileStyle} style The style.\r\n * @param {Cesium3DTileFeature[]} features The dictionary of features.\r\n */\r\nVector3DTileClampedPolylines.prototype.applyStyle = function (style, features) {\r\n if (!defined(style)) {\r\n clearStyle(this, features);\r\n return;\r\n }\r\n\r\n var batchIds = this._batchIds;\r\n var length = batchIds.length;\r\n for (var i = 0; i < length; ++i) {\r\n var batchId = batchIds[i];\r\n var feature = features[batchId];\r\n\r\n feature.color = defined(style.color)\r\n ? style.color.evaluateColor(feature, scratchColor)\r\n : DEFAULT_COLOR_VALUE;\r\n feature.show = defined(style.show)\r\n ? style.show.evaluate(feature)\r\n : DEFAULT_SHOW_VALUE;\r\n }\r\n};\r\n\r\n/**\r\n * Updates the batches and queues the commands for rendering.\r\n *\r\n * @param {FrameState} frameState The current frame state.\r\n */\r\nVector3DTileClampedPolylines.prototype.update = function (frameState) {\r\n var context = frameState.context;\r\n\r\n createVertexArray(this, context);\r\n createUniformMap(this, context);\r\n createShaders(this, context);\r\n createRenderStates(this);\r\n\r\n if (!this._ready) {\r\n return;\r\n }\r\n\r\n var passes = frameState.passes;\r\n if (passes.render || passes.pick) {\r\n queueCommands(this, frameState);\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *

\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n */\r\nVector3DTileClampedPolylines.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *

\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nVector3DTileClampedPolylines.prototype.destroy = function () {\r\n this._va = this._va && this._va.destroy();\r\n this._sp = this._sp && this._sp.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Vector3DTileClampedPolylines;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport getJsonFromTypedArray from \"../Core/getJsonFromTypedArray.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Cesium3DTileBatchTable from \"./Cesium3DTileBatchTable.js\";\r\nimport Cesium3DTileFeatureTable from \"./Cesium3DTileFeatureTable.js\";\r\nimport Vector3DTilePoints from \"./Vector3DTilePoints.js\";\r\nimport Vector3DTilePolygons from \"./Vector3DTilePolygons.js\";\r\nimport Vector3DTilePolylines from \"./Vector3DTilePolylines.js\";\r\nimport Vector3DTileClampedPolylines from \"./Vector3DTileClampedPolylines.js\";\r\nimport decodeVectorPolylinePositions from \"../Core/decodeVectorPolylinePositions.js\";\r\n\r\n/**\r\n * Represents the contents of a\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/vctr/TileFormats/VectorData|Vector}\r\n * tile in a {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles} tileset.\r\n *

\r\n * Implements the {@link Cesium3DTileContent} interface.\r\n *

\r\n *\r\n * @alias Vector3DTileContent\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction Vector3DTileContent(tileset, tile, resource, arrayBuffer, byteOffset) {\r\n this._tileset = tileset;\r\n this._tile = tile;\r\n this._resource = resource;\r\n\r\n this._polygons = undefined;\r\n this._polylines = undefined;\r\n this._points = undefined;\r\n\r\n this._contentReadyPromise = undefined;\r\n this._readyPromise = when.defer();\r\n\r\n this._batchTable = undefined;\r\n this._features = undefined;\r\n\r\n /**\r\n * Part of the {@link Cesium3DTileContent} interface.\r\n */\r\n this.featurePropertiesDirty = false;\r\n\r\n initialize(this, arrayBuffer, byteOffset);\r\n}\r\n\r\nObject.defineProperties(Vector3DTileContent.prototype, {\r\n featuresLength: {\r\n get: function () {\r\n return defined(this._batchTable) ? this._batchTable.featuresLength : 0;\r\n },\r\n },\r\n\r\n pointsLength: {\r\n get: function () {\r\n if (defined(this._points)) {\r\n return this._points.pointsLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n trianglesLength: {\r\n get: function () {\r\n var trianglesLength = 0;\r\n if (defined(this._polygons)) {\r\n trianglesLength += this._polygons.trianglesLength;\r\n }\r\n if (defined(this._polylines)) {\r\n trianglesLength += this._polylines.trianglesLength;\r\n }\r\n return trianglesLength;\r\n },\r\n },\r\n\r\n geometryByteLength: {\r\n get: function () {\r\n var geometryByteLength = 0;\r\n if (defined(this._polygons)) {\r\n geometryByteLength += this._polygons.geometryByteLength;\r\n }\r\n if (defined(this._polylines)) {\r\n geometryByteLength += this._polylines.geometryByteLength;\r\n }\r\n return geometryByteLength;\r\n },\r\n },\r\n\r\n texturesByteLength: {\r\n get: function () {\r\n if (defined(this._points)) {\r\n return this._points.texturesByteLength;\r\n }\r\n return 0;\r\n },\r\n },\r\n\r\n batchTableByteLength: {\r\n get: function () {\r\n return defined(this._batchTable) ? this._batchTable.memorySizeInBytes : 0;\r\n },\r\n },\r\n\r\n innerContents: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n tile: {\r\n get: function () {\r\n return this._tile;\r\n },\r\n },\r\n\r\n url: {\r\n get: function () {\r\n return this._resource.getUrlComponent(true);\r\n },\r\n },\r\n\r\n batchTable: {\r\n get: function () {\r\n return this._batchTable;\r\n },\r\n },\r\n});\r\n\r\nfunction createColorChangedCallback(content) {\r\n return function (batchId, color) {\r\n if (defined(content._polygons)) {\r\n content._polygons.updateCommands(batchId, color);\r\n }\r\n };\r\n}\r\n\r\nfunction getBatchIds(featureTableJson, featureTableBinary) {\r\n var polygonBatchIds;\r\n var polylineBatchIds;\r\n var pointBatchIds;\r\n var i;\r\n\r\n var numberOfPolygons = defaultValue(featureTableJson.POLYGONS_LENGTH, 0);\r\n var numberOfPolylines = defaultValue(featureTableJson.POLYLINES_LENGTH, 0);\r\n var numberOfPoints = defaultValue(featureTableJson.POINTS_LENGTH, 0);\r\n\r\n if (numberOfPolygons > 0 && defined(featureTableJson.POLYGON_BATCH_IDS)) {\r\n var polygonBatchIdsByteOffset =\r\n featureTableBinary.byteOffset +\r\n featureTableJson.POLYGON_BATCH_IDS.byteOffset;\r\n polygonBatchIds = new Uint16Array(\r\n featureTableBinary.buffer,\r\n polygonBatchIdsByteOffset,\r\n numberOfPolygons\r\n );\r\n }\r\n\r\n if (numberOfPolylines > 0 && defined(featureTableJson.POLYLINE_BATCH_IDS)) {\r\n var polylineBatchIdsByteOffset =\r\n featureTableBinary.byteOffset +\r\n featureTableJson.POLYLINE_BATCH_IDS.byteOffset;\r\n polylineBatchIds = new Uint16Array(\r\n featureTableBinary.buffer,\r\n polylineBatchIdsByteOffset,\r\n numberOfPolylines\r\n );\r\n }\r\n\r\n if (numberOfPoints > 0 && defined(featureTableJson.POINT_BATCH_IDS)) {\r\n var pointBatchIdsByteOffset =\r\n featureTableBinary.byteOffset +\r\n featureTableJson.POINT_BATCH_IDS.byteOffset;\r\n pointBatchIds = new Uint16Array(\r\n featureTableBinary.buffer,\r\n pointBatchIdsByteOffset,\r\n numberOfPoints\r\n );\r\n }\r\n\r\n var atLeastOneDefined =\r\n defined(polygonBatchIds) ||\r\n defined(polylineBatchIds) ||\r\n defined(pointBatchIds);\r\n var atLeastOneUndefined =\r\n (numberOfPolygons > 0 && !defined(polygonBatchIds)) ||\r\n (numberOfPolylines > 0 && !defined(polylineBatchIds)) ||\r\n (numberOfPoints > 0 && !defined(pointBatchIds));\r\n\r\n if (atLeastOneDefined && atLeastOneUndefined) {\r\n throw new RuntimeError(\r\n \"If one group of batch ids is defined, then all batch ids must be defined.\"\r\n );\r\n }\r\n\r\n var allUndefinedBatchIds =\r\n !defined(polygonBatchIds) &&\r\n !defined(polylineBatchIds) &&\r\n !defined(pointBatchIds);\r\n if (allUndefinedBatchIds) {\r\n var id = 0;\r\n if (!defined(polygonBatchIds) && numberOfPolygons > 0) {\r\n polygonBatchIds = new Uint16Array(numberOfPolygons);\r\n for (i = 0; i < numberOfPolygons; ++i) {\r\n polygonBatchIds[i] = id++;\r\n }\r\n }\r\n if (!defined(polylineBatchIds) && numberOfPolylines > 0) {\r\n polylineBatchIds = new Uint16Array(numberOfPolylines);\r\n for (i = 0; i < numberOfPolylines; ++i) {\r\n polylineBatchIds[i] = id++;\r\n }\r\n }\r\n if (!defined(pointBatchIds) && numberOfPoints > 0) {\r\n pointBatchIds = new Uint16Array(numberOfPoints);\r\n for (i = 0; i < numberOfPoints; ++i) {\r\n pointBatchIds[i] = id++;\r\n }\r\n }\r\n }\r\n\r\n return {\r\n polygons: polygonBatchIds,\r\n polylines: polylineBatchIds,\r\n points: pointBatchIds,\r\n };\r\n}\r\n\r\nvar sizeOfUint32 = Uint32Array.BYTES_PER_ELEMENT;\r\n\r\nfunction createFloatingPolylines(options) {\r\n return new Vector3DTilePolylines(options);\r\n}\r\n\r\nfunction createClampedPolylines(options) {\r\n return new Vector3DTileClampedPolylines(options);\r\n}\r\n\r\nfunction initialize(content, arrayBuffer, byteOffset) {\r\n byteOffset = defaultValue(byteOffset, 0);\r\n\r\n var uint8Array = new Uint8Array(arrayBuffer);\r\n var view = new DataView(arrayBuffer);\r\n byteOffset += sizeOfUint32; // Skip magic number\r\n\r\n var version = view.getUint32(byteOffset, true);\r\n if (version !== 1) {\r\n throw new RuntimeError(\r\n \"Only Vector tile version 1 is supported. Version \" +\r\n version +\r\n \" is not.\"\r\n );\r\n }\r\n byteOffset += sizeOfUint32;\r\n\r\n var byteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n if (byteLength === 0) {\r\n content._readyPromise.resolve(content);\r\n return;\r\n }\r\n\r\n var featureTableJSONByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n if (featureTableJSONByteLength === 0) {\r\n throw new RuntimeError(\r\n \"Feature table must have a byte length greater than zero\"\r\n );\r\n }\r\n\r\n var featureTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var batchTableJSONByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var batchTableBinaryByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var indicesByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var positionByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var polylinePositionByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n var pointsPositionByteLength = view.getUint32(byteOffset, true);\r\n byteOffset += sizeOfUint32;\r\n\r\n var featureTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n featureTableJSONByteLength\r\n );\r\n byteOffset += featureTableJSONByteLength;\r\n\r\n var featureTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n featureTableBinaryByteLength\r\n );\r\n byteOffset += featureTableBinaryByteLength;\r\n\r\n var batchTableJson;\r\n var batchTableBinary;\r\n if (batchTableJSONByteLength > 0) {\r\n // PERFORMANCE_IDEA: is it possible to allocate this on-demand? Perhaps keep the\r\n // arraybuffer/string compressed in memory and then decompress it when it is first accessed.\r\n //\r\n // We could also make another request for it, but that would make the property set/get\r\n // API async, and would double the number of numbers in some cases.\r\n batchTableJson = getJsonFromTypedArray(\r\n uint8Array,\r\n byteOffset,\r\n batchTableJSONByteLength\r\n );\r\n byteOffset += batchTableJSONByteLength;\r\n\r\n if (batchTableBinaryByteLength > 0) {\r\n // Has a batch table binary\r\n batchTableBinary = new Uint8Array(\r\n arrayBuffer,\r\n byteOffset,\r\n batchTableBinaryByteLength\r\n );\r\n // Copy the batchTableBinary section and let the underlying ArrayBuffer be freed\r\n batchTableBinary = new Uint8Array(batchTableBinary);\r\n byteOffset += batchTableBinaryByteLength;\r\n }\r\n }\r\n\r\n var numberOfPolygons = defaultValue(featureTableJson.POLYGONS_LENGTH, 0);\r\n var numberOfPolylines = defaultValue(featureTableJson.POLYLINES_LENGTH, 0);\r\n var numberOfPoints = defaultValue(featureTableJson.POINTS_LENGTH, 0);\r\n var totalPrimitives = numberOfPolygons + numberOfPolylines + numberOfPoints;\r\n\r\n var batchTable = new Cesium3DTileBatchTable(\r\n content,\r\n totalPrimitives,\r\n batchTableJson,\r\n batchTableBinary,\r\n createColorChangedCallback(content)\r\n );\r\n content._batchTable = batchTable;\r\n\r\n if (totalPrimitives === 0) {\r\n return;\r\n }\r\n\r\n var featureTable = new Cesium3DTileFeatureTable(\r\n featureTableJson,\r\n featureTableBinary\r\n );\r\n var region = featureTable.getGlobalProperty(\"REGION\");\r\n if (!defined(region)) {\r\n throw new RuntimeError(\r\n \"Feature table global property: REGION must be defined\"\r\n );\r\n }\r\n var rectangle = Rectangle.unpack(region);\r\n var minHeight = region[4];\r\n var maxHeight = region[5];\r\n\r\n var modelMatrix = content._tile.computedTransform;\r\n\r\n var center = featureTable.getGlobalProperty(\r\n \"RTC_CENTER\",\r\n ComponentDatatype.FLOAT,\r\n 3\r\n );\r\n if (defined(center)) {\r\n center = Cartesian3.unpack(center);\r\n Matrix4.multiplyByPoint(modelMatrix, center, center);\r\n } else {\r\n center = Rectangle.center(rectangle);\r\n center.height = CesiumMath.lerp(minHeight, maxHeight, 0.5);\r\n center = Ellipsoid.WGS84.cartographicToCartesian(center);\r\n }\r\n\r\n var batchIds = getBatchIds(featureTableJson, featureTableBinary);\r\n byteOffset += byteOffset % 4;\r\n\r\n if (numberOfPolygons > 0) {\r\n featureTable.featuresLength = numberOfPolygons;\r\n\r\n var polygonCounts = defaultValue(\r\n featureTable.getPropertyArray(\r\n \"POLYGON_COUNTS\",\r\n ComponentDatatype.UNSIGNED_INT,\r\n 1\r\n ),\r\n featureTable.getPropertyArray(\r\n \"POLYGON_COUNT\",\r\n ComponentDatatype.UNSIGNED_INT,\r\n 1\r\n ) // Workaround for old vector tilesets using the non-plural name\r\n );\r\n\r\n if (!defined(polygonCounts)) {\r\n throw new RuntimeError(\r\n \"Feature table property: POLYGON_COUNTS must be defined when POLYGONS_LENGTH is greater than 0\"\r\n );\r\n }\r\n\r\n var polygonIndexCounts = defaultValue(\r\n featureTable.getPropertyArray(\r\n \"POLYGON_INDEX_COUNTS\",\r\n ComponentDatatype.UNSIGNED_INT,\r\n 1\r\n ),\r\n featureTable.getPropertyArray(\r\n \"POLYGON_INDEX_COUNT\",\r\n ComponentDatatype.UNSIGNED_INT,\r\n 1\r\n ) // Workaround for old vector tilesets using the non-plural name\r\n );\r\n\r\n if (!defined(polygonIndexCounts)) {\r\n throw new RuntimeError(\r\n \"Feature table property: POLYGON_INDEX_COUNTS must be defined when POLYGONS_LENGTH is greater than 0\"\r\n );\r\n }\r\n\r\n // Use the counts array to determine how many position values we want. If we used the byte length then\r\n // zero padding values would be included and cause the delta zig-zag decoding to fail\r\n var numPolygonPositions = polygonCounts.reduce(function (total, count) {\r\n return total + count * 2;\r\n }, 0);\r\n\r\n var numPolygonIndices = polygonIndexCounts.reduce(function (total, count) {\r\n return total + count;\r\n }, 0);\r\n\r\n var indices = new Uint32Array(arrayBuffer, byteOffset, numPolygonIndices);\r\n byteOffset += indicesByteLength;\r\n\r\n var polygonPositions = new Uint16Array(\r\n arrayBuffer,\r\n byteOffset,\r\n numPolygonPositions\r\n );\r\n byteOffset += positionByteLength;\r\n\r\n var polygonMinimumHeights;\r\n var polygonMaximumHeights;\r\n if (\r\n defined(featureTableJson.POLYGON_MINIMUM_HEIGHTS) &&\r\n defined(featureTableJson.POLYGON_MAXIMUM_HEIGHTS)\r\n ) {\r\n polygonMinimumHeights = featureTable.getPropertyArray(\r\n \"POLYGON_MINIMUM_HEIGHTS\",\r\n ComponentDatatype.FLOAT,\r\n 1\r\n );\r\n polygonMaximumHeights = featureTable.getPropertyArray(\r\n \"POLYGON_MAXIMUM_HEIGHTS\",\r\n ComponentDatatype.FLOAT,\r\n 1\r\n );\r\n }\r\n\r\n content._polygons = new Vector3DTilePolygons({\r\n positions: polygonPositions,\r\n counts: polygonCounts,\r\n indexCounts: polygonIndexCounts,\r\n indices: indices,\r\n minimumHeight: minHeight,\r\n maximumHeight: maxHeight,\r\n polygonMinimumHeights: polygonMinimumHeights,\r\n polygonMaximumHeights: polygonMaximumHeights,\r\n center: center,\r\n rectangle: rectangle,\r\n boundingVolume: content.tile.boundingVolume.boundingVolume,\r\n batchTable: batchTable,\r\n batchIds: batchIds.polygons,\r\n modelMatrix: modelMatrix,\r\n });\r\n }\r\n\r\n if (numberOfPolylines > 0) {\r\n featureTable.featuresLength = numberOfPolylines;\r\n\r\n var polylineCounts = defaultValue(\r\n featureTable.getPropertyArray(\r\n \"POLYLINE_COUNTS\",\r\n ComponentDatatype.UNSIGNED_INT,\r\n 1\r\n ),\r\n featureTable.getPropertyArray(\r\n \"POLYLINE_COUNT\",\r\n ComponentDatatype.UNSIGNED_INT,\r\n 1\r\n ) // Workaround for old vector tilesets using the non-plural name\r\n );\r\n\r\n if (!defined(polylineCounts)) {\r\n throw new RuntimeError(\r\n \"Feature table property: POLYLINE_COUNTS must be defined when POLYLINES_LENGTH is greater than 0\"\r\n );\r\n }\r\n\r\n var widths = featureTable.getPropertyArray(\r\n \"POLYLINE_WIDTHS\",\r\n ComponentDatatype.UNSIGNED_SHORT,\r\n 1\r\n );\r\n if (!defined(widths)) {\r\n widths = new Uint16Array(numberOfPolylines);\r\n for (var i = 0; i < numberOfPolylines; ++i) {\r\n widths[i] = 2.0;\r\n }\r\n }\r\n\r\n // Use the counts array to determine how many position values we want. If we used the byte length then\r\n // zero padding values would be included and cause the delta zig-zag decoding to fail\r\n var numPolylinePositions = polylineCounts.reduce(function (total, count) {\r\n return total + count * 3;\r\n }, 0);\r\n var polylinePositions = new Uint16Array(\r\n arrayBuffer,\r\n byteOffset,\r\n numPolylinePositions\r\n );\r\n byteOffset += polylinePositionByteLength;\r\n\r\n var tileset = content._tileset;\r\n var examineVectorLinesFunction = tileset.examineVectorLinesFunction;\r\n if (defined(examineVectorLinesFunction)) {\r\n var decodedPositions = decodeVectorPolylinePositions(\r\n new Uint16Array(polylinePositions),\r\n rectangle,\r\n minHeight,\r\n maxHeight,\r\n Ellipsoid.WGS84\r\n );\r\n examineVectorLines(\r\n decodedPositions,\r\n polylineCounts,\r\n batchIds.polylines,\r\n batchTable,\r\n content.url,\r\n examineVectorLinesFunction\r\n );\r\n }\r\n\r\n var createPolylines = createFloatingPolylines;\r\n if (defined(tileset.classificationType)) {\r\n createPolylines = createClampedPolylines;\r\n }\r\n\r\n content._polylines = createPolylines({\r\n positions: polylinePositions,\r\n widths: widths,\r\n counts: polylineCounts,\r\n batchIds: batchIds.polylines,\r\n minimumHeight: minHeight,\r\n maximumHeight: maxHeight,\r\n center: center,\r\n rectangle: rectangle,\r\n boundingVolume: content.tile.boundingVolume.boundingVolume,\r\n batchTable: batchTable,\r\n tileset: tileset,\r\n });\r\n }\r\n\r\n if (numberOfPoints > 0) {\r\n var pointPositions = new Uint16Array(\r\n arrayBuffer,\r\n byteOffset,\r\n numberOfPoints * 3\r\n );\r\n byteOffset += pointsPositionByteLength;\r\n content._points = new Vector3DTilePoints({\r\n positions: pointPositions,\r\n batchIds: batchIds.points,\r\n minimumHeight: minHeight,\r\n maximumHeight: maxHeight,\r\n rectangle: rectangle,\r\n batchTable: batchTable,\r\n });\r\n }\r\n}\r\n\r\nfunction createFeatures(content) {\r\n var featuresLength = content.featuresLength;\r\n if (!defined(content._features) && featuresLength > 0) {\r\n var features = new Array(featuresLength);\r\n\r\n if (defined(content._polygons)) {\r\n content._polygons.createFeatures(content, features);\r\n }\r\n if (defined(content._polylines)) {\r\n content._polylines.createFeatures(content, features);\r\n }\r\n if (defined(content._points)) {\r\n content._points.createFeatures(content, features);\r\n }\r\n content._features = features;\r\n }\r\n}\r\n\r\nVector3DTileContent.prototype.hasProperty = function (batchId, name) {\r\n return this._batchTable.hasProperty(batchId, name);\r\n};\r\n\r\nVector3DTileContent.prototype.getFeature = function (batchId) {\r\n //>>includeStart('debug', pragmas.debug);\r\n var featuresLength = this.featuresLength;\r\n if (!defined(batchId) || batchId < 0 || batchId >= featuresLength) {\r\n throw new DeveloperError(\r\n \"batchId is required and between zero and featuresLength - 1 (\" +\r\n (featuresLength - 1) +\r\n \").\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n createFeatures(this);\r\n return this._features[batchId];\r\n};\r\n\r\nVector3DTileContent.prototype.applyDebugSettings = function (enabled, color) {\r\n if (defined(this._polygons)) {\r\n this._polygons.applyDebugSettings(enabled, color);\r\n }\r\n if (defined(this._polylines)) {\r\n this._polylines.applyDebugSettings(enabled, color);\r\n }\r\n if (defined(this._points)) {\r\n this._points.applyDebugSettings(enabled, color);\r\n }\r\n};\r\n\r\nVector3DTileContent.prototype.applyStyle = function (style) {\r\n createFeatures(this);\r\n if (defined(this._polygons)) {\r\n this._polygons.applyStyle(style, this._features);\r\n }\r\n if (defined(this._polylines)) {\r\n this._polylines.applyStyle(style, this._features);\r\n }\r\n if (defined(this._points)) {\r\n this._points.applyStyle(style, this._features);\r\n }\r\n};\r\n\r\nVector3DTileContent.prototype.update = function (tileset, frameState) {\r\n var ready = true;\r\n if (defined(this._polygons)) {\r\n this._polygons.classificationType = this._tileset.classificationType;\r\n this._polygons.debugWireframe = this._tileset.debugWireframe;\r\n this._polygons.update(frameState);\r\n ready = ready && this._polygons._ready;\r\n }\r\n if (defined(this._polylines)) {\r\n this._polylines.update(frameState);\r\n ready = ready && this._polylines._ready;\r\n }\r\n if (defined(this._points)) {\r\n this._points.update(frameState);\r\n ready = ready && this._points._ready;\r\n }\r\n if (defined(this._batchTable) && ready) {\r\n this._batchTable.update(tileset, frameState);\r\n }\r\n\r\n if (!defined(this._contentReadyPromise)) {\r\n var pointsPromise = defined(this._points)\r\n ? this._points.readyPromise\r\n : undefined;\r\n var polygonPromise = defined(this._polygons)\r\n ? this._polygons.readyPromise\r\n : undefined;\r\n var polylinePromise = defined(this._polylines)\r\n ? this._polylines.readyPromise\r\n : undefined;\r\n\r\n var that = this;\r\n this._contentReadyPromise = when\r\n .all([pointsPromise, polygonPromise, polylinePromise])\r\n .then(function () {\r\n that._readyPromise.resolve(that);\r\n })\r\n .otherwise(function (error) {\r\n that._readyPromise.reject(error);\r\n });\r\n }\r\n};\r\n\r\nVector3DTileContent.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nVector3DTileContent.prototype.destroy = function () {\r\n this._polygons = this._polygons && this._polygons.destroy();\r\n this._polylines = this._polylines && this._polylines.destroy();\r\n this._points = this._points && this._points.destroy();\r\n this._batchTable = this._batchTable && this._batchTable.destroy();\r\n return destroyObject(this);\r\n};\r\n\r\nfunction examineVectorLines(\r\n positions,\r\n counts,\r\n batchIds,\r\n batchTable,\r\n url,\r\n callback\r\n) {\r\n var countsLength = counts.length;\r\n var polylineStart = 0;\r\n for (var i = 0; i < countsLength; i++) {\r\n var count = counts[i] * 3;\r\n var linePositions = positions.slice(polylineStart, polylineStart + count);\r\n polylineStart += count;\r\n\r\n callback(linePositions, batchIds[i], url, batchTable);\r\n }\r\n}\r\n\r\nexport default Vector3DTileContent;\r\n","import Batched3DModel3DTileContent from \"./Batched3DModel3DTileContent.js\";\r\nimport Composite3DTileContent from \"./Composite3DTileContent.js\";\r\nimport Geometry3DTileContent from \"./Geometry3DTileContent.js\";\r\nimport Instanced3DModel3DTileContent from \"./Instanced3DModel3DTileContent.js\";\r\nimport PointCloud3DTileContent from \"./PointCloud3DTileContent.js\";\r\nimport Tileset3DTileContent from \"./Tileset3DTileContent.js\";\r\nimport Vector3DTileContent from \"./Vector3DTileContent.js\";\r\n\r\n/**\r\n * Maps a tile's magic field in its header to a new content object for the tile's payload.\r\n *\r\n * @private\r\n */\r\nvar Cesium3DTileContentFactory = {\r\n b3dm: function (tileset, tile, resource, arrayBuffer, byteOffset) {\r\n return new Batched3DModel3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n );\r\n },\r\n pnts: function (tileset, tile, resource, arrayBuffer, byteOffset) {\r\n return new PointCloud3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n );\r\n },\r\n i3dm: function (tileset, tile, resource, arrayBuffer, byteOffset) {\r\n return new Instanced3DModel3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n );\r\n },\r\n cmpt: function (tileset, tile, resource, arrayBuffer, byteOffset) {\r\n // Send in the factory in order to avoid a cyclical dependency\r\n return new Composite3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset,\r\n Cesium3DTileContentFactory\r\n );\r\n },\r\n json: function (tileset, tile, resource, arrayBuffer, byteOffset) {\r\n return new Tileset3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n );\r\n },\r\n geom: function (tileset, tile, resource, arrayBuffer, byteOffset) {\r\n return new Geometry3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n );\r\n },\r\n vctr: function (tileset, tile, resource, arrayBuffer, byteOffset) {\r\n return new Vector3DTileContent(\r\n tileset,\r\n tile,\r\n resource,\r\n arrayBuffer,\r\n byteOffset\r\n );\r\n },\r\n};\r\nexport default Cesium3DTileContentFactory;\r\n","/**\r\n * @private\r\n */\r\nvar Cesium3DTileContentState = {\r\n UNLOADED: 0, // Has never been requested\r\n LOADING: 1, // Is waiting on a pending request\r\n PROCESSING: 2, // Request received. Contents are being processed for rendering. Depending on the content, it might make its own requests for external data.\r\n READY: 3, // Ready to render.\r\n EXPIRED: 4, // Is expired and will be unloaded once new content is loaded.\r\n FAILED: 5, // Request failed.\r\n};\r\nexport default Object.freeze(Cesium3DTileContentState);\r\n","/**\r\n * Hint defining optimization support for a 3D tile\r\n *\r\n * @enum {Number}\r\n *\r\n * @private\r\n */\r\nvar Cesium3DTileOptimizationHint = {\r\n NOT_COMPUTED: -1,\r\n USE_OPTIMIZATION: 1,\r\n SKIP_OPTIMIZATION: 0,\r\n};\r\nexport default Object.freeze(Cesium3DTileOptimizationHint);\r\n","import Intersect from \"../Core/Intersect.js\";\r\nimport ManagedArray from \"../Core/ManagedArray.js\";\r\nimport Cesium3DTileRefine from \"./Cesium3DTileRefine.js\";\r\n\r\n/**\r\n * Traversal that loads all leaves that intersect the camera frustum.\r\n * Used to determine ray-tileset intersections during a pickFromRayMostDetailed call.\r\n *\r\n * @private\r\n */\r\nfunction Cesium3DTilesetMostDetailedTraversal() {}\r\n\r\nvar traversal = {\r\n stack: new ManagedArray(),\r\n stackMaximumLength: 0,\r\n};\r\n\r\nCesium3DTilesetMostDetailedTraversal.selectTiles = function (\r\n tileset,\r\n frameState\r\n) {\r\n tileset._selectedTiles.length = 0;\r\n tileset._requestedTiles.length = 0;\r\n tileset._hasMixedContent = false;\r\n\r\n var ready = true;\r\n\r\n var root = tileset.root;\r\n root.updateVisibility(frameState);\r\n\r\n if (!isVisible(root)) {\r\n return ready;\r\n }\r\n\r\n var stack = traversal.stack;\r\n stack.push(tileset.root);\r\n\r\n while (stack.length > 0) {\r\n traversal.stackMaximumLength = Math.max(\r\n traversal.stackMaximumLength,\r\n stack.length\r\n );\r\n\r\n var tile = stack.pop();\r\n var add = tile.refine === Cesium3DTileRefine.ADD;\r\n var replace = tile.refine === Cesium3DTileRefine.REPLACE;\r\n var traverse = canTraverse(tileset, tile);\r\n\r\n if (traverse) {\r\n updateAndPushChildren(tileset, tile, stack, frameState);\r\n }\r\n\r\n if (add || (replace && !traverse)) {\r\n loadTile(tileset, tile);\r\n touchTile(tileset, tile, frameState);\r\n selectDesiredTile(tileset, tile, frameState);\r\n\r\n if (!hasEmptyContent(tile) && !tile.contentAvailable) {\r\n ready = false;\r\n }\r\n }\r\n\r\n visitTile(tileset);\r\n }\r\n\r\n traversal.stack.trim(traversal.stackMaximumLength);\r\n\r\n return ready;\r\n};\r\n\r\nfunction isVisible(tile) {\r\n return tile._visible && tile._inRequestVolume;\r\n}\r\n\r\nfunction hasEmptyContent(tile) {\r\n return tile.hasEmptyContent || tile.hasTilesetContent;\r\n}\r\n\r\nfunction hasUnloadedContent(tile) {\r\n return !hasEmptyContent(tile) && tile.contentUnloaded;\r\n}\r\n\r\nfunction canTraverse(tileset, tile) {\r\n if (tile.children.length === 0) {\r\n return false;\r\n }\r\n\r\n if (tile.hasTilesetContent) {\r\n // Traverse external tileset to visit its root tile\r\n // Don't traverse if the subtree is expired because it will be destroyed\r\n return !tile.contentExpired;\r\n }\r\n\r\n if (tile.hasEmptyContent) {\r\n return true;\r\n }\r\n\r\n return true; // Keep traversing until a leave is hit\r\n}\r\n\r\nfunction updateAndPushChildren(tileset, tile, stack, frameState) {\r\n var children = tile.children;\r\n var length = children.length;\r\n\r\n for (var i = 0; i < length; ++i) {\r\n var child = children[i];\r\n child.updateVisibility(frameState);\r\n if (isVisible(child)) {\r\n stack.push(child);\r\n }\r\n }\r\n}\r\n\r\nfunction loadTile(tileset, tile) {\r\n if (hasUnloadedContent(tile) || tile.contentExpired) {\r\n tile._priority = 0.0; // Highest priority\r\n tileset._requestedTiles.push(tile);\r\n }\r\n}\r\n\r\nfunction touchTile(tileset, tile, frameState) {\r\n if (tile._touchedFrame === frameState.frameNumber) {\r\n // Prevents another pass from touching the frame again\r\n return;\r\n }\r\n tileset._cache.touch(tile);\r\n tile._touchedFrame = frameState.frameNumber;\r\n}\r\n\r\nfunction visitTile(tileset) {\r\n ++tileset.statistics.visited;\r\n}\r\n\r\nfunction selectDesiredTile(tileset, tile, frameState) {\r\n if (\r\n tile.contentAvailable &&\r\n tile.contentVisibility(frameState) !== Intersect.OUTSIDE\r\n ) {\r\n tileset._selectedTiles.push(tile);\r\n }\r\n}\r\nexport default Cesium3DTilesetMostDetailedTraversal;\r\n","import defined from \"../Core/defined.js\";\r\nimport Intersect from \"../Core/Intersect.js\";\r\nimport ManagedArray from \"../Core/ManagedArray.js\";\r\nimport Cesium3DTileOptimizationHint from \"./Cesium3DTileOptimizationHint.js\";\r\nimport Cesium3DTileRefine from \"./Cesium3DTileRefine.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Cesium3DTilesetTraversal() {}\r\n\r\nfunction isVisible(tile) {\r\n return tile._visible && tile._inRequestVolume;\r\n}\r\n\r\nvar traversal = {\r\n stack: new ManagedArray(),\r\n stackMaximumLength: 0,\r\n};\r\n\r\nvar emptyTraversal = {\r\n stack: new ManagedArray(),\r\n stackMaximumLength: 0,\r\n};\r\n\r\nvar descendantTraversal = {\r\n stack: new ManagedArray(),\r\n stackMaximumLength: 0,\r\n};\r\n\r\nvar selectionTraversal = {\r\n stack: new ManagedArray(),\r\n stackMaximumLength: 0,\r\n ancestorStack: new ManagedArray(),\r\n ancestorStackMaximumLength: 0,\r\n};\r\n\r\nvar descendantSelectionDepth = 2;\r\n\r\nCesium3DTilesetTraversal.selectTiles = function (tileset, frameState) {\r\n tileset._requestedTiles.length = 0;\r\n\r\n if (tileset.debugFreezeFrame) {\r\n return;\r\n }\r\n\r\n tileset._selectedTiles.length = 0;\r\n tileset._selectedTilesToStyle.length = 0;\r\n tileset._emptyTiles.length = 0;\r\n tileset._hasMixedContent = false;\r\n\r\n var root = tileset.root;\r\n updateTile(tileset, root, frameState);\r\n\r\n // The root tile is not visible\r\n if (!isVisible(root)) {\r\n return;\r\n }\r\n\r\n // The tileset doesn't meet the SSE requirement, therefore the tree does not need to be rendered\r\n if (\r\n root.getScreenSpaceError(frameState, true) <=\r\n tileset._maximumScreenSpaceError\r\n ) {\r\n return;\r\n }\r\n\r\n if (!skipLevelOfDetail(tileset)) {\r\n executeBaseTraversal(tileset, root, frameState);\r\n } else if (tileset.immediatelyLoadDesiredLevelOfDetail) {\r\n executeSkipTraversal(tileset, root, frameState);\r\n } else {\r\n executeBaseAndSkipTraversal(tileset, root, frameState);\r\n }\r\n\r\n traversal.stack.trim(traversal.stackMaximumLength);\r\n emptyTraversal.stack.trim(emptyTraversal.stackMaximumLength);\r\n descendantTraversal.stack.trim(descendantTraversal.stackMaximumLength);\r\n selectionTraversal.stack.trim(selectionTraversal.stackMaximumLength);\r\n selectionTraversal.ancestorStack.trim(\r\n selectionTraversal.ancestorStackMaximumLength\r\n );\r\n\r\n // Update the priority for any requests found during traversal\r\n // Update after traversal so that min and max values can be used to normalize priority values\r\n var requestedTiles = tileset._requestedTiles;\r\n var length = requestedTiles.length;\r\n for (var i = 0; i < length; ++i) {\r\n requestedTiles[i].updatePriority();\r\n }\r\n};\r\n\r\nfunction executeBaseTraversal(tileset, root, frameState) {\r\n var baseScreenSpaceError = tileset._maximumScreenSpaceError;\r\n var maximumScreenSpaceError = tileset._maximumScreenSpaceError;\r\n executeTraversal(\r\n tileset,\r\n root,\r\n baseScreenSpaceError,\r\n maximumScreenSpaceError,\r\n frameState\r\n );\r\n}\r\n\r\nfunction executeSkipTraversal(tileset, root, frameState) {\r\n var baseScreenSpaceError = Number.MAX_VALUE;\r\n var maximumScreenSpaceError = tileset._maximumScreenSpaceError;\r\n executeTraversal(\r\n tileset,\r\n root,\r\n baseScreenSpaceError,\r\n maximumScreenSpaceError,\r\n frameState\r\n );\r\n traverseAndSelect(tileset, root, frameState);\r\n}\r\n\r\nfunction executeBaseAndSkipTraversal(tileset, root, frameState) {\r\n var baseScreenSpaceError = Math.max(\r\n tileset.baseScreenSpaceError,\r\n tileset.maximumScreenSpaceError\r\n );\r\n var maximumScreenSpaceError = tileset.maximumScreenSpaceError;\r\n executeTraversal(\r\n tileset,\r\n root,\r\n baseScreenSpaceError,\r\n maximumScreenSpaceError,\r\n frameState\r\n );\r\n traverseAndSelect(tileset, root, frameState);\r\n}\r\n\r\nfunction skipLevelOfDetail(tileset) {\r\n return tileset._skipLevelOfDetail;\r\n}\r\n\r\nfunction addEmptyTile(tileset, tile) {\r\n tileset._emptyTiles.push(tile);\r\n}\r\n\r\nfunction selectTile(tileset, tile, frameState) {\r\n if (tile.contentVisibility(frameState) !== Intersect.OUTSIDE) {\r\n var tileContent = tile.content;\r\n if (tileContent.featurePropertiesDirty) {\r\n // A feature's property in this tile changed, the tile needs to be re-styled.\r\n tileContent.featurePropertiesDirty = false;\r\n tile.lastStyleTime = 0; // Force applying the style to this tile\r\n tileset._selectedTilesToStyle.push(tile);\r\n } else if (tile._selectedFrame < frameState.frameNumber - 1) {\r\n // Tile is newly selected; it is selected this frame, but was not selected last frame.\r\n tileset._selectedTilesToStyle.push(tile);\r\n }\r\n tile._selectedFrame = frameState.frameNumber;\r\n tileset._selectedTiles.push(tile);\r\n }\r\n}\r\n\r\nfunction selectDescendants(tileset, root, frameState) {\r\n var stack = descendantTraversal.stack;\r\n stack.push(root);\r\n while (stack.length > 0) {\r\n descendantTraversal.stackMaximumLength = Math.max(\r\n descendantTraversal.stackMaximumLength,\r\n stack.length\r\n );\r\n var tile = stack.pop();\r\n var children = tile.children;\r\n var childrenLength = children.length;\r\n for (var i = 0; i < childrenLength; ++i) {\r\n var child = children[i];\r\n if (isVisible(child)) {\r\n if (child.contentAvailable) {\r\n updateTile(tileset, child, frameState);\r\n touchTile(tileset, child, frameState);\r\n selectTile(tileset, child, frameState);\r\n } else if (child._depth - root._depth < descendantSelectionDepth) {\r\n // Continue traversing, but not too far\r\n stack.push(child);\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction selectDesiredTile(tileset, tile, frameState) {\r\n if (!skipLevelOfDetail(tileset)) {\r\n if (tile.contentAvailable) {\r\n // The tile can be selected right away and does not require traverseAndSelect\r\n selectTile(tileset, tile, frameState);\r\n }\r\n return;\r\n }\r\n\r\n // If this tile is not loaded attempt to select its ancestor instead\r\n var loadedTile = tile.contentAvailable\r\n ? tile\r\n : tile._ancestorWithContentAvailable;\r\n if (defined(loadedTile)) {\r\n // Tiles will actually be selected in traverseAndSelect\r\n loadedTile._shouldSelect = true;\r\n } else {\r\n // If no ancestors are ready traverse down and select tiles to minimize empty regions.\r\n // This happens often for immediatelyLoadDesiredLevelOfDetail where parent tiles are not necessarily loaded before zooming out.\r\n selectDescendants(tileset, tile, frameState);\r\n }\r\n}\r\n\r\nfunction visitTile(tileset, tile, frameState) {\r\n ++tileset._statistics.visited;\r\n tile._visitedFrame = frameState.frameNumber;\r\n}\r\n\r\nfunction touchTile(tileset, tile, frameState) {\r\n if (tile._touchedFrame === frameState.frameNumber) {\r\n // Prevents another pass from touching the frame again\r\n return;\r\n }\r\n tileset._cache.touch(tile);\r\n tile._touchedFrame = frameState.frameNumber;\r\n}\r\n\r\nfunction updateMinimumMaximumPriority(tileset, tile) {\r\n tileset._maximumPriority.distance = Math.max(\r\n tile._priorityHolder._distanceToCamera,\r\n tileset._maximumPriority.distance\r\n );\r\n tileset._minimumPriority.distance = Math.min(\r\n tile._priorityHolder._distanceToCamera,\r\n tileset._minimumPriority.distance\r\n );\r\n tileset._maximumPriority.depth = Math.max(\r\n tile._depth,\r\n tileset._maximumPriority.depth\r\n );\r\n tileset._minimumPriority.depth = Math.min(\r\n tile._depth,\r\n tileset._minimumPriority.depth\r\n );\r\n tileset._maximumPriority.foveatedFactor = Math.max(\r\n tile._priorityHolder._foveatedFactor,\r\n tileset._maximumPriority.foveatedFactor\r\n );\r\n tileset._minimumPriority.foveatedFactor = Math.min(\r\n tile._priorityHolder._foveatedFactor,\r\n tileset._minimumPriority.foveatedFactor\r\n );\r\n tileset._maximumPriority.reverseScreenSpaceError = Math.max(\r\n tile._priorityReverseScreenSpaceError,\r\n tileset._maximumPriority.reverseScreenSpaceError\r\n );\r\n tileset._minimumPriority.reverseScreenSpaceError = Math.min(\r\n tile._priorityReverseScreenSpaceError,\r\n tileset._minimumPriority.reverseScreenSpaceError\r\n );\r\n}\r\n\r\nfunction isOnScreenLongEnough(tileset, tile, frameState) {\r\n // Prevent unnecessary loads while camera is moving by getting the ratio of travel distance to tile size.\r\n if (!tileset._cullRequestsWhileMoving) {\r\n return true;\r\n }\r\n\r\n var sphere = tile.boundingSphere;\r\n var diameter = Math.max(sphere.radius * 2.0, 1.0);\r\n\r\n var camera = frameState.camera;\r\n var deltaMagnitude =\r\n camera.positionWCDeltaMagnitude !== 0.0\r\n ? camera.positionWCDeltaMagnitude\r\n : camera.positionWCDeltaMagnitudeLastFrame;\r\n var movementRatio =\r\n (tileset.cullRequestsWhileMovingMultiplier * deltaMagnitude) / diameter; // How do n frames of this movement compare to the tile's physical size.\r\n return movementRatio < 1.0;\r\n}\r\n\r\nfunction loadTile(tileset, tile, frameState) {\r\n if (\r\n tile._requestedFrame === frameState.frameNumber ||\r\n (!hasUnloadedContent(tile) && !tile.contentExpired)\r\n ) {\r\n return;\r\n }\r\n\r\n if (!isOnScreenLongEnough(tileset, tile, frameState)) {\r\n return;\r\n }\r\n\r\n var cameraHasNotStoppedMovingLongEnough =\r\n frameState.camera.timeSinceMoved < tileset.foveatedTimeDelay;\r\n if (tile.priorityDeferred && cameraHasNotStoppedMovingLongEnough) {\r\n return;\r\n }\r\n\r\n tile._requestedFrame = frameState.frameNumber;\r\n tileset._requestedTiles.push(tile);\r\n}\r\n\r\nfunction updateVisibility(tileset, tile, frameState) {\r\n if (tile._updatedVisibilityFrame === tileset._updatedVisibilityFrame) {\r\n // Return early if visibility has already been checked during the traversal.\r\n // The visibility may have already been checked if the cullWithChildrenBounds optimization is used.\r\n return;\r\n }\r\n\r\n tile.updateVisibility(frameState);\r\n tile._updatedVisibilityFrame = tileset._updatedVisibilityFrame;\r\n}\r\n\r\nfunction anyChildrenVisible(tileset, tile, frameState) {\r\n var anyVisible = false;\r\n var children = tile.children;\r\n var length = children.length;\r\n for (var i = 0; i < length; ++i) {\r\n var child = children[i];\r\n updateVisibility(tileset, child, frameState);\r\n anyVisible = anyVisible || isVisible(child);\r\n }\r\n return anyVisible;\r\n}\r\n\r\nfunction meetsScreenSpaceErrorEarly(tileset, tile, frameState) {\r\n var parent = tile.parent;\r\n if (\r\n !defined(parent) ||\r\n parent.hasTilesetContent ||\r\n parent.refine !== Cesium3DTileRefine.ADD\r\n ) {\r\n return false;\r\n }\r\n\r\n // Use parent's geometric error with child's box to see if the tile already meet the SSE\r\n return (\r\n tile.getScreenSpaceError(frameState, true) <=\r\n tileset._maximumScreenSpaceError\r\n );\r\n}\r\n\r\nfunction updateTileVisibility(tileset, tile, frameState) {\r\n updateVisibility(tileset, tile, frameState);\r\n\r\n if (!isVisible(tile)) {\r\n return;\r\n }\r\n\r\n var hasChildren = tile.children.length > 0;\r\n if (tile.hasTilesetContent && hasChildren) {\r\n // Use the root tile's visibility instead of this tile's visibility.\r\n // The root tile may be culled by the children bounds optimization in which\r\n // case this tile should also be culled.\r\n var child = tile.children[0];\r\n updateTileVisibility(tileset, child, frameState);\r\n tile._visible = child._visible;\r\n return;\r\n }\r\n\r\n if (meetsScreenSpaceErrorEarly(tileset, tile, frameState)) {\r\n tile._visible = false;\r\n return;\r\n }\r\n\r\n // Optimization - if none of the tile's children are visible then this tile isn't visible\r\n var replace = tile.refine === Cesium3DTileRefine.REPLACE;\r\n var useOptimization =\r\n tile._optimChildrenWithinParent ===\r\n Cesium3DTileOptimizationHint.USE_OPTIMIZATION;\r\n if (replace && useOptimization && hasChildren) {\r\n if (!anyChildrenVisible(tileset, tile, frameState)) {\r\n ++tileset._statistics.numberOfTilesCulledWithChildrenUnion;\r\n tile._visible = false;\r\n return;\r\n }\r\n }\r\n}\r\n\r\nfunction updateTile(tileset, tile, frameState) {\r\n // Reset some of the tile's flags and re-evaluate visibility\r\n updateTileVisibility(tileset, tile, frameState);\r\n tile.updateExpiration();\r\n\r\n // Request priority\r\n tile._wasMinPriorityChild = false;\r\n tile._priorityHolder = tile;\r\n updateMinimumMaximumPriority(tileset, tile);\r\n\r\n // SkipLOD\r\n tile._shouldSelect = false;\r\n tile._finalResolution = true;\r\n}\r\n\r\nfunction updateTileAncestorContentLinks(tile, frameState) {\r\n tile._ancestorWithContent = undefined;\r\n tile._ancestorWithContentAvailable = undefined;\r\n\r\n var parent = tile.parent;\r\n if (defined(parent)) {\r\n // ancestorWithContent is an ancestor that has content or has the potential to have\r\n // content. Used in conjunction with tileset.skipLevels to know when to skip a tile.\r\n // ancestorWithContentAvailable is an ancestor that is rendered if a desired tile is not loaded.\r\n var hasContent =\r\n !hasUnloadedContent(parent) ||\r\n parent._requestedFrame === frameState.frameNumber;\r\n tile._ancestorWithContent = hasContent\r\n ? parent\r\n : parent._ancestorWithContent;\r\n tile._ancestorWithContentAvailable = parent.contentAvailable\r\n ? parent\r\n : parent._ancestorWithContentAvailable; // Links a descendant up to its contentAvailable ancestor as the traversal progresses.\r\n }\r\n}\r\n\r\nfunction hasEmptyContent(tile) {\r\n return tile.hasEmptyContent || tile.hasTilesetContent;\r\n}\r\n\r\nfunction hasUnloadedContent(tile) {\r\n return !hasEmptyContent(tile) && tile.contentUnloaded;\r\n}\r\n\r\nfunction reachedSkippingThreshold(tileset, tile) {\r\n var ancestor = tile._ancestorWithContent;\r\n return (\r\n !tileset.immediatelyLoadDesiredLevelOfDetail &&\r\n (tile._priorityProgressiveResolutionScreenSpaceErrorLeaf ||\r\n (defined(ancestor) &&\r\n tile._screenSpaceError <\r\n ancestor._screenSpaceError / tileset.skipScreenSpaceErrorFactor &&\r\n tile._depth > ancestor._depth + tileset.skipLevels))\r\n );\r\n}\r\n\r\nfunction sortChildrenByDistanceToCamera(a, b) {\r\n // Sort by farthest child first since this is going on a stack\r\n if (b._distanceToCamera === 0 && a._distanceToCamera === 0) {\r\n return b._centerZDepth - a._centerZDepth;\r\n }\r\n\r\n return b._distanceToCamera - a._distanceToCamera;\r\n}\r\n\r\nfunction updateAndPushChildren(tileset, tile, stack, frameState) {\r\n var i;\r\n var replace = tile.refine === Cesium3DTileRefine.REPLACE;\r\n var children = tile.children;\r\n var length = children.length;\r\n\r\n for (i = 0; i < length; ++i) {\r\n updateTile(tileset, children[i], frameState);\r\n }\r\n\r\n // Sort by distance to take advantage of early Z and reduce artifacts for skipLevelOfDetail\r\n children.sort(sortChildrenByDistanceToCamera);\r\n\r\n // For traditional replacement refinement only refine if all children are loaded.\r\n // Empty tiles are exempt since it looks better if children stream in as they are loaded to fill the empty space.\r\n var checkRefines =\r\n !skipLevelOfDetail(tileset) && replace && !hasEmptyContent(tile);\r\n var refines = true;\r\n\r\n var anyChildrenVisible = false;\r\n\r\n // Determining min child\r\n var minIndex = -1;\r\n var minimumPriority = Number.MAX_VALUE;\r\n\r\n var child;\r\n for (i = 0; i < length; ++i) {\r\n child = children[i];\r\n if (isVisible(child)) {\r\n stack.push(child);\r\n if (child._foveatedFactor < minimumPriority) {\r\n minIndex = i;\r\n minimumPriority = child._foveatedFactor;\r\n }\r\n anyChildrenVisible = true;\r\n } else if (checkRefines || tileset.loadSiblings) {\r\n // Keep non-visible children loaded since they are still needed before the parent can refine.\r\n // Or loadSiblings is true so always load tiles regardless of visibility.\r\n if (child._foveatedFactor < minimumPriority) {\r\n minIndex = i;\r\n minimumPriority = child._foveatedFactor;\r\n }\r\n loadTile(tileset, child, frameState);\r\n touchTile(tileset, child, frameState);\r\n }\r\n if (checkRefines) {\r\n var childRefines;\r\n if (!child._inRequestVolume) {\r\n childRefines = false;\r\n } else if (hasEmptyContent(child)) {\r\n childRefines = executeEmptyTraversal(tileset, child, frameState);\r\n } else {\r\n childRefines = child.contentAvailable;\r\n }\r\n refines = refines && childRefines;\r\n }\r\n }\r\n\r\n if (!anyChildrenVisible) {\r\n refines = false;\r\n }\r\n\r\n if (minIndex !== -1 && !skipLevelOfDetail(tileset) && replace) {\r\n // An ancestor will hold the _foveatedFactor and _distanceToCamera for descendants between itself and its highest priority descendant. Siblings of a min children along the way use this ancestor as their priority holder as well.\r\n // Priority of all tiles that refer to the _foveatedFactor and _distanceToCamera stored in the common ancestor will be differentiated based on their _depth.\r\n var minPriorityChild = children[minIndex];\r\n minPriorityChild._wasMinPriorityChild = true;\r\n var priorityHolder =\r\n (tile._wasMinPriorityChild || tile === tileset.root) &&\r\n minimumPriority <= tile._priorityHolder._foveatedFactor\r\n ? tile._priorityHolder\r\n : tile; // This is where priority dependency chains are wired up or started anew.\r\n priorityHolder._foveatedFactor = Math.min(\r\n minPriorityChild._foveatedFactor,\r\n priorityHolder._foveatedFactor\r\n );\r\n priorityHolder._distanceToCamera = Math.min(\r\n minPriorityChild._distanceToCamera,\r\n priorityHolder._distanceToCamera\r\n );\r\n\r\n for (i = 0; i < length; ++i) {\r\n child = children[i];\r\n child._priorityHolder = priorityHolder;\r\n }\r\n }\r\n\r\n return refines;\r\n}\r\n\r\nfunction inBaseTraversal(tileset, tile, baseScreenSpaceError) {\r\n if (!skipLevelOfDetail(tileset)) {\r\n return true;\r\n }\r\n if (tileset.immediatelyLoadDesiredLevelOfDetail) {\r\n return false;\r\n }\r\n if (!defined(tile._ancestorWithContent)) {\r\n // Include root or near-root tiles in the base traversal so there is something to select up to\r\n return true;\r\n }\r\n if (tile._screenSpaceError === 0.0) {\r\n // If a leaf, use parent's SSE\r\n return tile.parent._screenSpaceError > baseScreenSpaceError;\r\n }\r\n return tile._screenSpaceError > baseScreenSpaceError;\r\n}\r\n\r\nfunction canTraverse(tileset, tile) {\r\n if (tile.children.length === 0) {\r\n return false;\r\n }\r\n if (tile.hasTilesetContent) {\r\n // Traverse external tileset to visit its root tile\r\n // Don't traverse if the subtree is expired because it will be destroyed\r\n return !tile.contentExpired;\r\n }\r\n return tile._screenSpaceError > tileset._maximumScreenSpaceError;\r\n}\r\n\r\nfunction executeTraversal(\r\n tileset,\r\n root,\r\n baseScreenSpaceError,\r\n maximumScreenSpaceError,\r\n frameState\r\n) {\r\n // Depth-first traversal that traverses all visible tiles and marks tiles for selection.\r\n // If skipLevelOfDetail is off then a tile does not refine until all children are loaded.\r\n // This is the traditional replacement refinement approach and is called the base traversal.\r\n // Tiles that have a greater screen space error than the base screen space error are part of the base traversal,\r\n // all other tiles are part of the skip traversal. The skip traversal allows for skipping levels of the tree\r\n // and rendering children and parent tiles simultaneously.\r\n var stack = traversal.stack;\r\n stack.push(root);\r\n\r\n while (stack.length > 0) {\r\n traversal.stackMaximumLength = Math.max(\r\n traversal.stackMaximumLength,\r\n stack.length\r\n );\r\n\r\n var tile = stack.pop();\r\n\r\n updateTileAncestorContentLinks(tile, frameState);\r\n var baseTraversal = inBaseTraversal(tileset, tile, baseScreenSpaceError);\r\n var add = tile.refine === Cesium3DTileRefine.ADD;\r\n var replace = tile.refine === Cesium3DTileRefine.REPLACE;\r\n var parent = tile.parent;\r\n var parentRefines = !defined(parent) || parent._refines;\r\n var refines = false;\r\n\r\n if (canTraverse(tileset, tile)) {\r\n refines =\r\n updateAndPushChildren(tileset, tile, stack, frameState) &&\r\n parentRefines;\r\n }\r\n\r\n var stoppedRefining = !refines && parentRefines;\r\n\r\n if (hasEmptyContent(tile)) {\r\n // Add empty tile just to show its debug bounding volume\r\n // If the tile has tileset content load the external tileset\r\n // If the tile cannot refine further select its nearest loaded ancestor\r\n addEmptyTile(tileset, tile, frameState);\r\n loadTile(tileset, tile, frameState);\r\n if (stoppedRefining) {\r\n selectDesiredTile(tileset, tile, frameState);\r\n }\r\n } else if (add) {\r\n // Additive tiles are always loaded and selected\r\n selectDesiredTile(tileset, tile, frameState);\r\n loadTile(tileset, tile, frameState);\r\n } else if (replace) {\r\n if (baseTraversal) {\r\n // Always load tiles in the base traversal\r\n // Select tiles that can't refine further\r\n loadTile(tileset, tile, frameState);\r\n if (stoppedRefining) {\r\n selectDesiredTile(tileset, tile, frameState);\r\n }\r\n } else if (stoppedRefining) {\r\n // In skip traversal, load and select tiles that can't refine further\r\n selectDesiredTile(tileset, tile, frameState);\r\n loadTile(tileset, tile, frameState);\r\n } else if (reachedSkippingThreshold(tileset, tile)) {\r\n // In skip traversal, load tiles that aren't skipped. In practice roughly half the tiles stay unloaded.\r\n loadTile(tileset, tile, frameState);\r\n }\r\n }\r\n\r\n visitTile(tileset, tile, frameState);\r\n touchTile(tileset, tile, frameState);\r\n tile._refines = refines;\r\n }\r\n}\r\n\r\nfunction executeEmptyTraversal(tileset, root, frameState) {\r\n // Depth-first traversal that checks if all nearest descendants with content are loaded. Ignores visibility.\r\n var allDescendantsLoaded = true;\r\n var stack = emptyTraversal.stack;\r\n stack.push(root);\r\n\r\n while (stack.length > 0) {\r\n emptyTraversal.stackMaximumLength = Math.max(\r\n emptyTraversal.stackMaximumLength,\r\n stack.length\r\n );\r\n\r\n var tile = stack.pop();\r\n var children = tile.children;\r\n var childrenLength = children.length;\r\n\r\n // Only traverse if the tile is empty - traversal stop at descendants with content\r\n var emptyContent = hasEmptyContent(tile);\r\n var traverse = emptyContent && canTraverse(tileset, tile);\r\n var emptyLeaf = emptyContent && tile.children.length === 0;\r\n\r\n // Traversal stops but the tile does not have content yet\r\n // There will be holes if the parent tries to refine to its children, so don't refine\r\n // One exception: a parent may refine even if one of its descendants is an empty leaf\r\n if (!traverse && !tile.contentAvailable && !emptyLeaf) {\r\n allDescendantsLoaded = false;\r\n }\r\n\r\n updateTile(tileset, tile, frameState);\r\n if (!isVisible(tile)) {\r\n // Load tiles that aren't visible since they are still needed for the parent to refine\r\n loadTile(tileset, tile, frameState);\r\n touchTile(tileset, tile, frameState);\r\n }\r\n\r\n if (traverse) {\r\n for (var i = 0; i < childrenLength; ++i) {\r\n var child = children[i];\r\n stack.push(child);\r\n }\r\n }\r\n }\r\n\r\n return allDescendantsLoaded;\r\n}\r\n\r\n/**\r\n * Traverse the tree and check if their selected frame is the current frame. If so, add it to a selection queue.\r\n * This is a preorder traversal so children tiles are selected before ancestor tiles.\r\n *\r\n * The reason for the preorder traversal is so that tiles can easily be marked with their\r\n * selection depth. A tile's _selectionDepth is its depth in the tree where all non-selected tiles are removed.\r\n * This property is important for use in the stencil test because we want to render deeper tiles on top of their\r\n * ancestors. If a tileset is very deep, the depth is unlikely to fit into the stencil buffer.\r\n *\r\n * We want to select children before their ancestors because there is no guarantee on the relationship between\r\n * the children's z-depth and the ancestor's z-depth. We cannot rely on Z because we want the child to appear on top\r\n * of ancestor regardless of true depth. The stencil tests used require children to be drawn first.\r\n *\r\n * NOTE: 3D Tiles uses 3 bits from the stencil buffer meaning this will not work when there is a chain of\r\n * selected tiles that is deeper than 7. This is not very likely.\r\n * @private\r\n */\r\nfunction traverseAndSelect(tileset, root, frameState) {\r\n var stack = selectionTraversal.stack;\r\n var ancestorStack = selectionTraversal.ancestorStack;\r\n var lastAncestor;\r\n\r\n stack.push(root);\r\n\r\n while (stack.length > 0 || ancestorStack.length > 0) {\r\n selectionTraversal.stackMaximumLength = Math.max(\r\n selectionTraversal.stackMaximumLength,\r\n stack.length\r\n );\r\n selectionTraversal.ancestorStackMaximumLength = Math.max(\r\n selectionTraversal.ancestorStackMaximumLength,\r\n ancestorStack.length\r\n );\r\n\r\n if (ancestorStack.length > 0) {\r\n var waitingTile = ancestorStack.peek();\r\n if (waitingTile._stackLength === stack.length) {\r\n ancestorStack.pop();\r\n if (waitingTile !== lastAncestor) {\r\n waitingTile._finalResolution = false;\r\n }\r\n selectTile(tileset, waitingTile, frameState);\r\n continue;\r\n }\r\n }\r\n\r\n var tile = stack.pop();\r\n if (!defined(tile)) {\r\n // stack is empty but ancestorStack isn't\r\n continue;\r\n }\r\n\r\n var add = tile.refine === Cesium3DTileRefine.ADD;\r\n var shouldSelect = tile._shouldSelect;\r\n var children = tile.children;\r\n var childrenLength = children.length;\r\n var traverse = canTraverse(tileset, tile);\r\n\r\n if (shouldSelect) {\r\n if (add) {\r\n selectTile(tileset, tile, frameState);\r\n } else {\r\n tile._selectionDepth = ancestorStack.length;\r\n if (tile._selectionDepth > 0) {\r\n tileset._hasMixedContent = true;\r\n }\r\n lastAncestor = tile;\r\n if (!traverse) {\r\n selectTile(tileset, tile, frameState);\r\n continue;\r\n }\r\n ancestorStack.push(tile);\r\n tile._stackLength = stack.length;\r\n }\r\n }\r\n\r\n if (traverse) {\r\n for (var i = 0; i < childrenLength; ++i) {\r\n var child = children[i];\r\n if (isVisible(child)) {\r\n stack.push(child);\r\n }\r\n }\r\n }\r\n }\r\n}\r\nexport default Cesium3DTilesetTraversal;\r\n","import Cesium3DTilesetMostDetailedTraversal from \"./Cesium3DTilesetMostDetailedTraversal.js\";\r\nimport Cesium3DTilesetTraversal from \"./Cesium3DTilesetTraversal.js\";\r\n\r\n/**\r\n * The pass in which a 3D Tileset is updated.\r\n *\r\n * @private\r\n */\r\nvar Cesium3DTilePass = {\r\n RENDER: 0,\r\n PICK: 1,\r\n SHADOW: 2,\r\n PRELOAD: 3,\r\n PRELOAD_FLIGHT: 4,\r\n REQUEST_RENDER_MODE_DEFER_CHECK: 5,\r\n MOST_DETAILED_PRELOAD: 6,\r\n MOST_DETAILED_PICK: 7,\r\n NUMBER_OF_PASSES: 8,\r\n};\r\n\r\nvar passOptions = new Array(Cesium3DTilePass.NUMBER_OF_PASSES);\r\n\r\npassOptions[Cesium3DTilePass.RENDER] = Object.freeze({\r\n traversal: Cesium3DTilesetTraversal,\r\n isRender: true,\r\n requestTiles: true,\r\n ignoreCommands: false,\r\n});\r\n\r\npassOptions[Cesium3DTilePass.PICK] = Object.freeze({\r\n traversal: Cesium3DTilesetTraversal,\r\n isRender: false,\r\n requestTiles: false,\r\n ignoreCommands: false,\r\n});\r\n\r\npassOptions[Cesium3DTilePass.SHADOW] = Object.freeze({\r\n traversal: Cesium3DTilesetTraversal,\r\n isRender: false,\r\n requestTiles: true,\r\n ignoreCommands: false,\r\n});\r\n\r\npassOptions[Cesium3DTilePass.PRELOAD] = Object.freeze({\r\n traversal: Cesium3DTilesetTraversal,\r\n isRender: false,\r\n requestTiles: true,\r\n ignoreCommands: true,\r\n});\r\n\r\npassOptions[Cesium3DTilePass.PRELOAD_FLIGHT] = Object.freeze({\r\n traversal: Cesium3DTilesetTraversal,\r\n isRender: false,\r\n requestTiles: true,\r\n ignoreCommands: true,\r\n});\r\n\r\npassOptions[Cesium3DTilePass.REQUEST_RENDER_MODE_DEFER_CHECK] = Object.freeze({\r\n traversal: Cesium3DTilesetTraversal,\r\n isRender: false,\r\n requestTiles: true,\r\n ignoreCommands: true,\r\n});\r\n\r\npassOptions[Cesium3DTilePass.MOST_DETAILED_PRELOAD] = Object.freeze({\r\n traversal: Cesium3DTilesetMostDetailedTraversal,\r\n isRender: false,\r\n requestTiles: true,\r\n ignoreCommands: true,\r\n});\r\n\r\npassOptions[Cesium3DTilePass.MOST_DETAILED_PICK] = Object.freeze({\r\n traversal: Cesium3DTilesetMostDetailedTraversal,\r\n isRender: false,\r\n requestTiles: false,\r\n ignoreCommands: false,\r\n});\r\n\r\nCesium3DTilePass.getPassOptions = function (pass) {\r\n return passOptions[pass];\r\n};\r\nexport default Object.freeze(Cesium3DTilePass);\r\n","import destroyObject from \"../Core/destroyObject.js\";\r\n\r\n/**\r\n * Represents empty content for tiles in a\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles} tileset that\r\n * do not have content, e.g., because they are used to optimize hierarchical culling.\r\n *

\r\n * Implements the {@link Cesium3DTileContent} interface.\r\n *

\r\n *\r\n * @alias Empty3DTileContent\r\n * @constructor\r\n *\r\n * @private\r\n */\r\nfunction Empty3DTileContent(tileset, tile) {\r\n this._tileset = tileset;\r\n this._tile = tile;\r\n\r\n this.featurePropertiesDirty = false;\r\n}\r\n\r\nObject.defineProperties(Empty3DTileContent.prototype, {\r\n featuresLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n pointsLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n trianglesLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n geometryByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n texturesByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n batchTableByteLength: {\r\n get: function () {\r\n return 0;\r\n },\r\n },\r\n\r\n innerContents: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n readyPromise: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n tile: {\r\n get: function () {\r\n return this._tile;\r\n },\r\n },\r\n\r\n url: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n\r\n batchTable: {\r\n get: function () {\r\n return undefined;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Part of the {@link Cesium3DTileContent} interface. Empty3DTileContent\r\n * always returns false since a tile of this type does not have any features.\r\n */\r\nEmpty3DTileContent.prototype.hasProperty = function (batchId, name) {\r\n return false;\r\n};\r\n\r\n/**\r\n * Part of the {@link Cesium3DTileContent} interface. Empty3DTileContent\r\n * always returns undefined since a tile of this type does not have any features.\r\n */\r\nEmpty3DTileContent.prototype.getFeature = function (batchId) {\r\n return undefined;\r\n};\r\n\r\nEmpty3DTileContent.prototype.applyDebugSettings = function (enabled, color) {};\r\n\r\nEmpty3DTileContent.prototype.applyStyle = function (style) {};\r\n\r\nEmpty3DTileContent.prototype.update = function (tileset, frameState) {};\r\n\r\nEmpty3DTileContent.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nEmpty3DTileContent.prototype.destroy = function () {\r\n return destroyObject(this);\r\n};\r\nexport default Empty3DTileContent;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport IntersectionTests from \"../Core/IntersectionTests.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport OrientedBoundingBox from \"../Core/OrientedBoundingBox.js\";\r\nimport Plane from \"../Core/Plane.js\";\r\nimport Ray from \"../Core/Ray.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport RectangleOutlineGeometry from \"../Core/RectangleOutlineGeometry.js\";\r\nimport PerInstanceColorAppearance from \"./PerInstanceColorAppearance.js\";\r\nimport Primitive from \"./Primitive.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\n\r\n/**\r\n * A tile bounding volume specified as a longitude/latitude/height region.\r\n * @alias TileBoundingRegion\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Rectangle} options.rectangle The rectangle specifying the longitude and latitude range of the region.\r\n * @param {Number} [options.minimumHeight=0.0] The minimum height of the region.\r\n * @param {Number} [options.maximumHeight=0.0] The maximum height of the region.\r\n * @param {Ellipsoid} [options.ellipsoid=Cesium.Ellipsoid.WGS84] The ellipsoid.\r\n * @param {Boolean} [options.computeBoundingVolumes=true] True to compute the {@link TileBoundingRegion#boundingVolume} and\r\n * {@link TileBoundingVolume#boundingSphere}. If false, these properties will be undefined.\r\n *\r\n * @private\r\n */\r\nfunction TileBoundingRegion(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.object(\"options.rectangle\", options.rectangle);\r\n //>>includeEnd('debug');\r\n\r\n this.rectangle = Rectangle.clone(options.rectangle);\r\n this.minimumHeight = defaultValue(options.minimumHeight, 0.0);\r\n this.maximumHeight = defaultValue(options.maximumHeight, 0.0);\r\n\r\n /**\r\n * The world coordinates of the southwest corner of the tile's rectangle.\r\n *\r\n * @type {Cartesian3}\r\n * @default Cartesian3()\r\n */\r\n this.southwestCornerCartesian = new Cartesian3();\r\n\r\n /**\r\n * The world coordinates of the northeast corner of the tile's rectangle.\r\n *\r\n * @type {Cartesian3}\r\n * @default Cartesian3()\r\n */\r\n this.northeastCornerCartesian = new Cartesian3();\r\n\r\n /**\r\n * A normal that, along with southwestCornerCartesian, defines a plane at the western edge of\r\n * the tile. Any position above (in the direction of the normal) this plane is outside the tile.\r\n *\r\n * @type {Cartesian3}\r\n * @default Cartesian3()\r\n */\r\n this.westNormal = new Cartesian3();\r\n\r\n /**\r\n * A normal that, along with southwestCornerCartesian, defines a plane at the southern edge of\r\n * the tile. Any position above (in the direction of the normal) this plane is outside the tile.\r\n * Because points of constant latitude do not necessary lie in a plane, positions below this\r\n * plane are not necessarily inside the tile, but they are close.\r\n *\r\n * @type {Cartesian3}\r\n * @default Cartesian3()\r\n */\r\n this.southNormal = new Cartesian3();\r\n\r\n /**\r\n * A normal that, along with northeastCornerCartesian, defines a plane at the eastern edge of\r\n * the tile. Any position above (in the direction of the normal) this plane is outside the tile.\r\n *\r\n * @type {Cartesian3}\r\n * @default Cartesian3()\r\n */\r\n this.eastNormal = new Cartesian3();\r\n\r\n /**\r\n * A normal that, along with northeastCornerCartesian, defines a plane at the eastern edge of\r\n * the tile. Any position above (in the direction of the normal) this plane is outside the tile.\r\n * Because points of constant latitude do not necessary lie in a plane, positions below this\r\n * plane are not necessarily inside the tile, but they are close.\r\n *\r\n * @type {Cartesian3}\r\n * @default Cartesian3()\r\n */\r\n this.northNormal = new Cartesian3();\r\n\r\n var ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n computeBox(this, options.rectangle, ellipsoid);\r\n\r\n if (defaultValue(options.computeBoundingVolumes, true)) {\r\n // An oriented bounding box that encloses this tile's region. This is used to calculate tile visibility.\r\n this._orientedBoundingBox = OrientedBoundingBox.fromRectangle(\r\n this.rectangle,\r\n this.minimumHeight,\r\n this.maximumHeight,\r\n ellipsoid\r\n );\r\n\r\n this._boundingSphere = BoundingSphere.fromOrientedBoundingBox(\r\n this._orientedBoundingBox\r\n );\r\n }\r\n}\r\n\r\nObject.defineProperties(TileBoundingRegion.prototype, {\r\n /**\r\n * The underlying bounding volume\r\n *\r\n * @memberof TileBoundingRegion.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n boundingVolume: {\r\n get: function () {\r\n return this._orientedBoundingBox;\r\n },\r\n },\r\n /**\r\n * The underlying bounding sphere\r\n *\r\n * @memberof TileBoundingRegion.prototype\r\n *\r\n * @type {BoundingSphere}\r\n * @readonly\r\n */\r\n boundingSphere: {\r\n get: function () {\r\n return this._boundingSphere;\r\n },\r\n },\r\n});\r\n\r\nvar cartesian3Scratch = new Cartesian3();\r\nvar cartesian3Scratch2 = new Cartesian3();\r\nvar cartesian3Scratch3 = new Cartesian3();\r\nvar eastWestNormalScratch = new Cartesian3();\r\nvar westernMidpointScratch = new Cartesian3();\r\nvar easternMidpointScratch = new Cartesian3();\r\nvar cartographicScratch = new Cartographic();\r\nvar planeScratch = new Plane(Cartesian3.UNIT_X, 0.0);\r\nvar rayScratch = new Ray();\r\n\r\nfunction computeBox(tileBB, rectangle, ellipsoid) {\r\n ellipsoid.cartographicToCartesian(\r\n Rectangle.southwest(rectangle),\r\n tileBB.southwestCornerCartesian\r\n );\r\n ellipsoid.cartographicToCartesian(\r\n Rectangle.northeast(rectangle),\r\n tileBB.northeastCornerCartesian\r\n );\r\n\r\n // The middle latitude on the western edge.\r\n cartographicScratch.longitude = rectangle.west;\r\n cartographicScratch.latitude = (rectangle.south + rectangle.north) * 0.5;\r\n cartographicScratch.height = 0.0;\r\n var westernMidpointCartesian = ellipsoid.cartographicToCartesian(\r\n cartographicScratch,\r\n westernMidpointScratch\r\n );\r\n\r\n // Compute the normal of the plane on the western edge of the tile.\r\n var westNormal = Cartesian3.cross(\r\n westernMidpointCartesian,\r\n Cartesian3.UNIT_Z,\r\n cartesian3Scratch\r\n );\r\n Cartesian3.normalize(westNormal, tileBB.westNormal);\r\n\r\n // The middle latitude on the eastern edge.\r\n cartographicScratch.longitude = rectangle.east;\r\n var easternMidpointCartesian = ellipsoid.cartographicToCartesian(\r\n cartographicScratch,\r\n easternMidpointScratch\r\n );\r\n\r\n // Compute the normal of the plane on the eastern edge of the tile.\r\n var eastNormal = Cartesian3.cross(\r\n Cartesian3.UNIT_Z,\r\n easternMidpointCartesian,\r\n cartesian3Scratch\r\n );\r\n Cartesian3.normalize(eastNormal, tileBB.eastNormal);\r\n\r\n // Compute the normal of the plane bounding the southern edge of the tile.\r\n var westVector = Cartesian3.subtract(\r\n westernMidpointCartesian,\r\n easternMidpointCartesian,\r\n cartesian3Scratch\r\n );\r\n var eastWestNormal = Cartesian3.normalize(westVector, eastWestNormalScratch);\r\n\r\n var south = rectangle.south;\r\n var southSurfaceNormal;\r\n\r\n if (south > 0.0) {\r\n // Compute a plane that doesn't cut through the tile.\r\n cartographicScratch.longitude = (rectangle.west + rectangle.east) * 0.5;\r\n cartographicScratch.latitude = south;\r\n var southCenterCartesian = ellipsoid.cartographicToCartesian(\r\n cartographicScratch,\r\n rayScratch.origin\r\n );\r\n Cartesian3.clone(eastWestNormal, rayScratch.direction);\r\n var westPlane = Plane.fromPointNormal(\r\n tileBB.southwestCornerCartesian,\r\n tileBB.westNormal,\r\n planeScratch\r\n );\r\n // Find a point that is on the west and the south planes\r\n IntersectionTests.rayPlane(\r\n rayScratch,\r\n westPlane,\r\n tileBB.southwestCornerCartesian\r\n );\r\n southSurfaceNormal = ellipsoid.geodeticSurfaceNormal(\r\n southCenterCartesian,\r\n cartesian3Scratch2\r\n );\r\n } else {\r\n southSurfaceNormal = ellipsoid.geodeticSurfaceNormalCartographic(\r\n Rectangle.southeast(rectangle),\r\n cartesian3Scratch2\r\n );\r\n }\r\n var southNormal = Cartesian3.cross(\r\n southSurfaceNormal,\r\n westVector,\r\n cartesian3Scratch3\r\n );\r\n Cartesian3.normalize(southNormal, tileBB.southNormal);\r\n\r\n // Compute the normal of the plane bounding the northern edge of the tile.\r\n var north = rectangle.north;\r\n var northSurfaceNormal;\r\n if (north < 0.0) {\r\n // Compute a plane that doesn't cut through the tile.\r\n cartographicScratch.longitude = (rectangle.west + rectangle.east) * 0.5;\r\n cartographicScratch.latitude = north;\r\n var northCenterCartesian = ellipsoid.cartographicToCartesian(\r\n cartographicScratch,\r\n rayScratch.origin\r\n );\r\n Cartesian3.negate(eastWestNormal, rayScratch.direction);\r\n var eastPlane = Plane.fromPointNormal(\r\n tileBB.northeastCornerCartesian,\r\n tileBB.eastNormal,\r\n planeScratch\r\n );\r\n // Find a point that is on the east and the north planes\r\n IntersectionTests.rayPlane(\r\n rayScratch,\r\n eastPlane,\r\n tileBB.northeastCornerCartesian\r\n );\r\n northSurfaceNormal = ellipsoid.geodeticSurfaceNormal(\r\n northCenterCartesian,\r\n cartesian3Scratch2\r\n );\r\n } else {\r\n northSurfaceNormal = ellipsoid.geodeticSurfaceNormalCartographic(\r\n Rectangle.northwest(rectangle),\r\n cartesian3Scratch2\r\n );\r\n }\r\n var northNormal = Cartesian3.cross(\r\n westVector,\r\n northSurfaceNormal,\r\n cartesian3Scratch3\r\n );\r\n Cartesian3.normalize(northNormal, tileBB.northNormal);\r\n}\r\n\r\nvar southwestCornerScratch = new Cartesian3();\r\nvar northeastCornerScratch = new Cartesian3();\r\nvar negativeUnitY = new Cartesian3(0.0, -1.0, 0.0);\r\nvar negativeUnitZ = new Cartesian3(0.0, 0.0, -1.0);\r\nvar vectorScratch = new Cartesian3();\r\n\r\n/**\r\n * Gets the distance from the camera to the closest point on the tile. This is used for level of detail selection.\r\n *\r\n * @param {FrameState} frameState The state information of the current rendering frame.\r\n * @returns {Number} The distance from the camera to the closest point on the tile, in meters.\r\n */\r\nTileBoundingRegion.prototype.distanceToCamera = function (frameState) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"frameState\", frameState);\r\n //>>includeEnd('debug');\r\n var camera = frameState.camera;\r\n var cameraCartesianPosition = camera.positionWC;\r\n var cameraCartographicPosition = camera.positionCartographic;\r\n\r\n var result = 0.0;\r\n if (!Rectangle.contains(this.rectangle, cameraCartographicPosition)) {\r\n var southwestCornerCartesian = this.southwestCornerCartesian;\r\n var northeastCornerCartesian = this.northeastCornerCartesian;\r\n var westNormal = this.westNormal;\r\n var southNormal = this.southNormal;\r\n var eastNormal = this.eastNormal;\r\n var northNormal = this.northNormal;\r\n\r\n if (frameState.mode !== SceneMode.SCENE3D) {\r\n southwestCornerCartesian = frameState.mapProjection.project(\r\n Rectangle.southwest(this.rectangle),\r\n southwestCornerScratch\r\n );\r\n southwestCornerCartesian.z = southwestCornerCartesian.y;\r\n southwestCornerCartesian.y = southwestCornerCartesian.x;\r\n southwestCornerCartesian.x = 0.0;\r\n northeastCornerCartesian = frameState.mapProjection.project(\r\n Rectangle.northeast(this.rectangle),\r\n northeastCornerScratch\r\n );\r\n northeastCornerCartesian.z = northeastCornerCartesian.y;\r\n northeastCornerCartesian.y = northeastCornerCartesian.x;\r\n northeastCornerCartesian.x = 0.0;\r\n westNormal = negativeUnitY;\r\n eastNormal = Cartesian3.UNIT_Y;\r\n southNormal = negativeUnitZ;\r\n northNormal = Cartesian3.UNIT_Z;\r\n }\r\n\r\n var vectorFromSouthwestCorner = Cartesian3.subtract(\r\n cameraCartesianPosition,\r\n southwestCornerCartesian,\r\n vectorScratch\r\n );\r\n var distanceToWestPlane = Cartesian3.dot(\r\n vectorFromSouthwestCorner,\r\n westNormal\r\n );\r\n var distanceToSouthPlane = Cartesian3.dot(\r\n vectorFromSouthwestCorner,\r\n southNormal\r\n );\r\n\r\n var vectorFromNortheastCorner = Cartesian3.subtract(\r\n cameraCartesianPosition,\r\n northeastCornerCartesian,\r\n vectorScratch\r\n );\r\n var distanceToEastPlane = Cartesian3.dot(\r\n vectorFromNortheastCorner,\r\n eastNormal\r\n );\r\n var distanceToNorthPlane = Cartesian3.dot(\r\n vectorFromNortheastCorner,\r\n northNormal\r\n );\r\n\r\n if (distanceToWestPlane > 0.0) {\r\n result += distanceToWestPlane * distanceToWestPlane;\r\n } else if (distanceToEastPlane > 0.0) {\r\n result += distanceToEastPlane * distanceToEastPlane;\r\n }\r\n\r\n if (distanceToSouthPlane > 0.0) {\r\n result += distanceToSouthPlane * distanceToSouthPlane;\r\n } else if (distanceToNorthPlane > 0.0) {\r\n result += distanceToNorthPlane * distanceToNorthPlane;\r\n }\r\n }\r\n\r\n var cameraHeight;\r\n var minimumHeight;\r\n var maximumHeight;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n cameraHeight = cameraCartographicPosition.height;\r\n minimumHeight = this.minimumHeight;\r\n maximumHeight = this.maximumHeight;\r\n } else {\r\n cameraHeight = cameraCartesianPosition.x;\r\n minimumHeight = 0.0;\r\n maximumHeight = 0.0;\r\n }\r\n\r\n if (cameraHeight > maximumHeight) {\r\n var distanceAboveTop = cameraHeight - maximumHeight;\r\n result += distanceAboveTop * distanceAboveTop;\r\n } else if (cameraHeight < minimumHeight) {\r\n var distanceBelowBottom = minimumHeight - cameraHeight;\r\n result += distanceBelowBottom * distanceBelowBottom;\r\n }\r\n\r\n return Math.sqrt(result);\r\n};\r\n\r\n/**\r\n * Determines which side of a plane this box is located.\r\n *\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the box\r\n * intersects the plane.\r\n */\r\nTileBoundingRegion.prototype.intersectPlane = function (plane) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"plane\", plane);\r\n //>>includeEnd('debug');\r\n return this._orientedBoundingBox.intersectPlane(plane);\r\n};\r\n\r\n/**\r\n * Creates a debug primitive that shows the outline of the tile bounding region.\r\n *\r\n * @param {Color} color The desired color of the primitive's mesh\r\n * @return {Primitive}\r\n *\r\n * @private\r\n */\r\nTileBoundingRegion.prototype.createDebugVolume = function (color) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"color\", color);\r\n //>>includeEnd('debug');\r\n\r\n var modelMatrix = new Matrix4.clone(Matrix4.IDENTITY);\r\n var geometry = new RectangleOutlineGeometry({\r\n rectangle: this.rectangle,\r\n height: this.minimumHeight,\r\n extrudedHeight: this.maximumHeight,\r\n });\r\n var instance = new GeometryInstance({\r\n geometry: geometry,\r\n id: \"outline\",\r\n modelMatrix: modelMatrix,\r\n attributes: {\r\n color: ColorGeometryInstanceAttribute.fromColor(color),\r\n },\r\n });\r\n\r\n return new Primitive({\r\n geometryInstances: instance,\r\n appearance: new PerInstanceColorAppearance({\r\n translucent: false,\r\n flat: true,\r\n }),\r\n asynchronous: false,\r\n });\r\n};\r\nexport default TileBoundingRegion;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport SphereOutlineGeometry from \"../Core/SphereOutlineGeometry.js\";\r\nimport PerInstanceColorAppearance from \"./PerInstanceColorAppearance.js\";\r\nimport Primitive from \"./Primitive.js\";\r\n\r\n/**\r\n * A tile bounding volume specified as a sphere.\r\n * @alias TileBoundingSphere\r\n * @constructor\r\n *\r\n * @param {Cartesian3} [center=Cartesian3.ZERO] The center of the bounding sphere.\r\n * @param {Number} [radius=0.0] The radius of the bounding sphere.\r\n *\r\n * @private\r\n */\r\nfunction TileBoundingSphere(center, radius) {\r\n if (radius === 0) {\r\n radius = CesiumMath.EPSILON7;\r\n }\r\n this._boundingSphere = new BoundingSphere(center, radius);\r\n}\r\n\r\nObject.defineProperties(TileBoundingSphere.prototype, {\r\n /**\r\n * The center of the bounding sphere\r\n *\r\n * @memberof TileBoundingSphere.prototype\r\n *\r\n * @type {Cartesian3}\r\n * @readonly\r\n */\r\n center: {\r\n get: function () {\r\n return this._boundingSphere.center;\r\n },\r\n },\r\n\r\n /**\r\n * The radius of the bounding sphere\r\n *\r\n * @memberof TileBoundingSphere.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n radius: {\r\n get: function () {\r\n return this._boundingSphere.radius;\r\n },\r\n },\r\n\r\n /**\r\n * The underlying bounding volume\r\n *\r\n * @memberof TileBoundingSphere.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n boundingVolume: {\r\n get: function () {\r\n return this._boundingSphere;\r\n },\r\n },\r\n /**\r\n * The underlying bounding sphere\r\n *\r\n * @memberof TileBoundingSphere.prototype\r\n *\r\n * @type {BoundingSphere}\r\n * @readonly\r\n */\r\n boundingSphere: {\r\n get: function () {\r\n return this._boundingSphere;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Computes the distance between this bounding sphere and the camera attached to frameState.\r\n *\r\n * @param {FrameState} frameState The frameState to which the camera is attached.\r\n * @returns {Number} The distance between the camera and the bounding sphere in meters. Returns 0 if the camera is inside the bounding volume.\r\n *\r\n */\r\nTileBoundingSphere.prototype.distanceToCamera = function (frameState) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"frameState\", frameState);\r\n //>>includeEnd('debug');\r\n var boundingSphere = this._boundingSphere;\r\n return Math.max(\r\n 0.0,\r\n Cartesian3.distance(boundingSphere.center, frameState.camera.positionWC) -\r\n boundingSphere.radius\r\n );\r\n};\r\n\r\n/**\r\n * Determines which side of a plane this sphere is located.\r\n *\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire sphere is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire sphere is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the sphere\r\n * intersects the plane.\r\n */\r\nTileBoundingSphere.prototype.intersectPlane = function (plane) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"plane\", plane);\r\n //>>includeEnd('debug');\r\n return BoundingSphere.intersectPlane(this._boundingSphere, plane);\r\n};\r\n\r\n/**\r\n * Update the bounding sphere after the tile is transformed.\r\n *\r\n * @param {Cartesian3} center The center of the bounding sphere.\r\n * @param {Number} radius The radius of the bounding sphere.\r\n */\r\nTileBoundingSphere.prototype.update = function (center, radius) {\r\n Cartesian3.clone(center, this._boundingSphere.center);\r\n this._boundingSphere.radius = radius;\r\n};\r\n\r\n/**\r\n * Creates a debug primitive that shows the outline of the sphere.\r\n *\r\n * @param {Color} color The desired color of the primitive's mesh\r\n * @return {Primitive}\r\n */\r\nTileBoundingSphere.prototype.createDebugVolume = function (color) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"color\", color);\r\n //>>includeEnd('debug');\r\n var geometry = new SphereOutlineGeometry({\r\n radius: this.radius,\r\n });\r\n var modelMatrix = Matrix4.fromTranslation(\r\n this.center,\r\n new Matrix4.clone(Matrix4.IDENTITY)\r\n );\r\n var instance = new GeometryInstance({\r\n geometry: geometry,\r\n id: \"outline\",\r\n modelMatrix: modelMatrix,\r\n attributes: {\r\n color: ColorGeometryInstanceAttribute.fromColor(color),\r\n },\r\n });\r\n\r\n return new Primitive({\r\n geometryInstances: instance,\r\n appearance: new PerInstanceColorAppearance({\r\n translucent: false,\r\n flat: true,\r\n }),\r\n asynchronous: false,\r\n });\r\n};\r\nexport default TileBoundingSphere;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport BoxOutlineGeometry from \"../Core/BoxOutlineGeometry.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport OrientedBoundingBox from \"../Core/OrientedBoundingBox.js\";\r\nimport PerInstanceColorAppearance from \"./PerInstanceColorAppearance.js\";\r\nimport Primitive from \"./Primitive.js\";\r\n\r\nvar scratchU = new Cartesian3();\r\nvar scratchV = new Cartesian3();\r\nvar scratchW = new Cartesian3();\r\nvar scratchCartesian = new Cartesian3();\r\n\r\nfunction computeMissingVector(a, b, result) {\r\n result = Cartesian3.cross(a, b, result);\r\n var magnitude = Cartesian3.magnitude(result);\r\n return Cartesian3.multiplyByScalar(\r\n result,\r\n CesiumMath.EPSILON7 / magnitude,\r\n result\r\n );\r\n}\r\n\r\nfunction findOrthogonalVector(a, result) {\r\n var temp = Cartesian3.normalize(a, scratchCartesian);\r\n var b = Cartesian3.equalsEpsilon(temp, Cartesian3.UNIT_X, CesiumMath.EPSILON6)\r\n ? Cartesian3.UNIT_Y\r\n : Cartesian3.UNIT_X;\r\n return computeMissingVector(a, b, result);\r\n}\r\n\r\nfunction checkHalfAxes(halfAxes) {\r\n var u = Matrix3.getColumn(halfAxes, 0, scratchU);\r\n var v = Matrix3.getColumn(halfAxes, 1, scratchV);\r\n var w = Matrix3.getColumn(halfAxes, 2, scratchW);\r\n\r\n var uZero = Cartesian3.equals(u, Cartesian3.ZERO);\r\n var vZero = Cartesian3.equals(v, Cartesian3.ZERO);\r\n var wZero = Cartesian3.equals(w, Cartesian3.ZERO);\r\n\r\n if (!uZero && !vZero && !wZero) {\r\n return halfAxes;\r\n }\r\n if (uZero && vZero && wZero) {\r\n halfAxes[0] = CesiumMath.EPSILON7;\r\n halfAxes[4] = CesiumMath.EPSILON7;\r\n halfAxes[8] = CesiumMath.EPSILON7;\r\n return halfAxes;\r\n }\r\n if (uZero && !vZero && !wZero) {\r\n u = computeMissingVector(v, w, u);\r\n } else if (!uZero && vZero && !wZero) {\r\n v = computeMissingVector(u, w, v);\r\n } else if (!uZero && !vZero && wZero) {\r\n w = computeMissingVector(v, u, w);\r\n } else if (!uZero) {\r\n v = findOrthogonalVector(u, v);\r\n w = computeMissingVector(v, u, w);\r\n } else if (!vZero) {\r\n u = findOrthogonalVector(v, u);\r\n w = computeMissingVector(v, u, w);\r\n } else if (!wZero) {\r\n u = findOrthogonalVector(w, u);\r\n v = computeMissingVector(w, u, v);\r\n }\r\n\r\n Matrix3.setColumn(halfAxes, 0, u, halfAxes);\r\n Matrix3.setColumn(halfAxes, 1, v, halfAxes);\r\n Matrix3.setColumn(halfAxes, 2, w, halfAxes);\r\n\r\n return halfAxes;\r\n}\r\n\r\n/**\r\n * A tile bounding volume specified as an oriented bounding box.\r\n * @alias TileOrientedBoundingBox\r\n * @constructor\r\n *\r\n * @param {Cartesian3} [center=Cartesian3.ZERO] The center of the box.\r\n * @param {Matrix3} [halfAxes=Matrix3.ZERO] The three orthogonal half-axes of the bounding box.\r\n * Equivalently, the transformation matrix, to rotate and scale a 2x2x2\r\n * cube centered at the origin.\r\n *\r\n * @private\r\n */\r\nfunction TileOrientedBoundingBox(center, halfAxes) {\r\n halfAxes = checkHalfAxes(halfAxes);\r\n this._orientedBoundingBox = new OrientedBoundingBox(center, halfAxes);\r\n this._boundingSphere = BoundingSphere.fromOrientedBoundingBox(\r\n this._orientedBoundingBox\r\n );\r\n}\r\n\r\nObject.defineProperties(TileOrientedBoundingBox.prototype, {\r\n /**\r\n * The underlying bounding volume.\r\n *\r\n * @memberof TileOrientedBoundingBox.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n */\r\n boundingVolume: {\r\n get: function () {\r\n return this._orientedBoundingBox;\r\n },\r\n },\r\n /**\r\n * The underlying bounding sphere.\r\n *\r\n * @memberof TileOrientedBoundingBox.prototype\r\n *\r\n * @type {BoundingSphere}\r\n * @readonly\r\n */\r\n boundingSphere: {\r\n get: function () {\r\n return this._boundingSphere;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Computes the distance between this bounding box and the camera attached to frameState.\r\n *\r\n * @param {FrameState} frameState The frameState to which the camera is attached.\r\n * @returns {Number} The distance between the camera and the bounding box in meters. Returns 0 if the camera is inside the bounding volume.\r\n */\r\nTileOrientedBoundingBox.prototype.distanceToCamera = function (frameState) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"frameState\", frameState);\r\n //>>includeEnd('debug');\r\n return Math.sqrt(\r\n this._orientedBoundingBox.distanceSquaredTo(frameState.camera.positionWC)\r\n );\r\n};\r\n\r\n/**\r\n * Determines which side of a plane this box is located.\r\n *\r\n * @param {Plane} plane The plane to test against.\r\n * @returns {Intersect} {@link Intersect.INSIDE} if the entire box is on the side of the plane\r\n * the normal is pointing, {@link Intersect.OUTSIDE} if the entire box is\r\n * on the opposite side, and {@link Intersect.INTERSECTING} if the box\r\n * intersects the plane.\r\n */\r\nTileOrientedBoundingBox.prototype.intersectPlane = function (plane) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"plane\", plane);\r\n //>>includeEnd('debug');\r\n return this._orientedBoundingBox.intersectPlane(plane);\r\n};\r\n\r\n/**\r\n * Update the bounding box after the tile is transformed.\r\n *\r\n * @param {Cartesian3} center The center of the box.\r\n * @param {Matrix3} halfAxes The three orthogonal half-axes of the bounding box.\r\n * Equivalently, the transformation matrix, to rotate and scale a 2x2x2\r\n * cube centered at the origin.\r\n */\r\nTileOrientedBoundingBox.prototype.update = function (center, halfAxes) {\r\n Cartesian3.clone(center, this._orientedBoundingBox.center);\r\n halfAxes = checkHalfAxes(halfAxes);\r\n Matrix3.clone(halfAxes, this._orientedBoundingBox.halfAxes);\r\n BoundingSphere.fromOrientedBoundingBox(\r\n this._orientedBoundingBox,\r\n this._boundingSphere\r\n );\r\n};\r\n\r\n/**\r\n * Creates a debug primitive that shows the outline of the box.\r\n *\r\n * @param {Color} color The desired color of the primitive's mesh\r\n * @return {Primitive}\r\n */\r\nTileOrientedBoundingBox.prototype.createDebugVolume = function (color) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"color\", color);\r\n //>>includeEnd('debug');\r\n\r\n var geometry = new BoxOutlineGeometry({\r\n // Make a 2x2x2 cube\r\n minimum: new Cartesian3(-1.0, -1.0, -1.0),\r\n maximum: new Cartesian3(1.0, 1.0, 1.0),\r\n });\r\n var modelMatrix = Matrix4.fromRotationTranslation(\r\n this.boundingVolume.halfAxes,\r\n this.boundingVolume.center\r\n );\r\n var instance = new GeometryInstance({\r\n geometry: geometry,\r\n id: \"outline\",\r\n modelMatrix: modelMatrix,\r\n attributes: {\r\n color: ColorGeometryInstanceAttribute.fromColor(color),\r\n },\r\n });\r\n\r\n return new Primitive({\r\n geometryInstances: instance,\r\n appearance: new PerInstanceColorAppearance({\r\n translucent: false,\r\n flat: true,\r\n }),\r\n asynchronous: false,\r\n });\r\n};\r\nexport default TileOrientedBoundingBox;\r\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport CullingVolume from \"../Core/CullingVolume.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport deprecationWarning from \"../Core/deprecationWarning.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport getMagic from \"../Core/getMagic.js\";\r\nimport Intersect from \"../Core/Intersect.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport OrientedBoundingBox from \"../Core/OrientedBoundingBox.js\";\r\nimport OrthographicFrustum from \"../Core/OrthographicFrustum.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport Request from \"../Core/Request.js\";\r\nimport RequestScheduler from \"../Core/RequestScheduler.js\";\r\nimport RequestState from \"../Core/RequestState.js\";\r\nimport RequestType from \"../Core/RequestType.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Cesium3DTileContentFactory from \"./Cesium3DTileContentFactory.js\";\r\nimport Cesium3DTileContentState from \"./Cesium3DTileContentState.js\";\r\nimport Cesium3DTileOptimizationHint from \"./Cesium3DTileOptimizationHint.js\";\r\nimport Cesium3DTilePass from \"./Cesium3DTilePass.js\";\r\nimport Cesium3DTileRefine from \"./Cesium3DTileRefine.js\";\r\nimport Empty3DTileContent from \"./Empty3DTileContent.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport TileBoundingRegion from \"./TileBoundingRegion.js\";\r\nimport TileBoundingSphere from \"./TileBoundingSphere.js\";\r\nimport TileOrientedBoundingBox from \"./TileOrientedBoundingBox.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\n\r\n/**\r\n * A tile in a {@link Cesium3DTileset}. When a tile is first created, its content is not loaded;\r\n * the content is loaded on-demand when needed based on the view.\r\n *

\r\n * Do not construct this directly, instead access tiles through {@link Cesium3DTileset#tileVisible}.\r\n *

\r\n *\r\n * @alias Cesium3DTile\r\n * @constructor\r\n */\r\nfunction Cesium3DTile(tileset, baseResource, header, parent) {\r\n this._tileset = tileset;\r\n this._header = header;\r\n var contentHeader = header.content;\r\n\r\n /**\r\n * The local transform of this tile.\r\n * @type {Matrix4}\r\n */\r\n this.transform = defined(header.transform)\r\n ? Matrix4.unpack(header.transform)\r\n : Matrix4.clone(Matrix4.IDENTITY);\r\n\r\n var parentTransform = defined(parent)\r\n ? parent.computedTransform\r\n : tileset.modelMatrix;\r\n var computedTransform = Matrix4.multiply(\r\n parentTransform,\r\n this.transform,\r\n new Matrix4()\r\n );\r\n\r\n var parentInitialTransform = defined(parent)\r\n ? parent._initialTransform\r\n : Matrix4.IDENTITY;\r\n this._initialTransform = Matrix4.multiply(\r\n parentInitialTransform,\r\n this.transform,\r\n new Matrix4()\r\n );\r\n\r\n /**\r\n * The final computed transform of this tile.\r\n * @type {Matrix4}\r\n * @readonly\r\n */\r\n this.computedTransform = computedTransform;\r\n\r\n this._boundingVolume = this.createBoundingVolume(\r\n header.boundingVolume,\r\n computedTransform\r\n );\r\n this._boundingVolume2D = undefined;\r\n\r\n var contentBoundingVolume;\r\n\r\n if (defined(contentHeader) && defined(contentHeader.boundingVolume)) {\r\n // Non-leaf tiles may have a content bounding-volume, which is a tight-fit bounding volume\r\n // around only the features in the tile. This box is useful for culling for rendering,\r\n // but not for culling for traversing the tree since it does not guarantee spatial coherence, i.e.,\r\n // since it only bounds features in the tile, not the entire tile, children may be\r\n // outside of this box.\r\n contentBoundingVolume = this.createBoundingVolume(\r\n contentHeader.boundingVolume,\r\n computedTransform\r\n );\r\n }\r\n this._contentBoundingVolume = contentBoundingVolume;\r\n this._contentBoundingVolume2D = undefined;\r\n\r\n var viewerRequestVolume;\r\n if (defined(header.viewerRequestVolume)) {\r\n viewerRequestVolume = this.createBoundingVolume(\r\n header.viewerRequestVolume,\r\n computedTransform\r\n );\r\n }\r\n this._viewerRequestVolume = viewerRequestVolume;\r\n\r\n /**\r\n * The error, in meters, introduced if this tile is rendered and its children are not.\r\n * This is used to compute screen space error, i.e., the error measured in pixels.\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n this.geometricError = header.geometricError;\r\n this._geometricError = header.geometricError;\r\n\r\n if (!defined(this._geometricError)) {\r\n this._geometricError = defined(parent)\r\n ? parent.geometricError\r\n : tileset._geometricError;\r\n Cesium3DTile._deprecationWarning(\r\n \"geometricErrorUndefined\",\r\n \"Required property geometricError is undefined for this tile. Using parent's geometric error instead.\"\r\n );\r\n }\r\n\r\n this.updateGeometricErrorScale();\r\n\r\n var refine;\r\n if (defined(header.refine)) {\r\n if (header.refine === \"replace\" || header.refine === \"add\") {\r\n Cesium3DTile._deprecationWarning(\r\n \"lowercase-refine\",\r\n 'This tile uses a lowercase refine \"' +\r\n header.refine +\r\n '\". Instead use \"' +\r\n header.refine.toUpperCase() +\r\n '\".'\r\n );\r\n }\r\n refine =\r\n header.refine.toUpperCase() === \"REPLACE\"\r\n ? Cesium3DTileRefine.REPLACE\r\n : Cesium3DTileRefine.ADD;\r\n } else if (defined(parent)) {\r\n // Inherit from parent tile if omitted.\r\n refine = parent.refine;\r\n } else {\r\n refine = Cesium3DTileRefine.REPLACE;\r\n }\r\n\r\n /**\r\n * Specifies the type of refinement that is used when traversing this tile for rendering.\r\n *\r\n * @type {Cesium3DTileRefine}\r\n * @readonly\r\n * @private\r\n */\r\n this.refine = refine;\r\n\r\n /**\r\n * Gets the tile's children.\r\n *\r\n * @type {Cesium3DTile[]}\r\n * @readonly\r\n */\r\n this.children = [];\r\n\r\n /**\r\n * This tile's parent or undefined if this tile is the root.\r\n *

\r\n * When a tile's content points to an external tileset JSON file, the external tileset's\r\n * root tile's parent is not undefined; instead, the parent references\r\n * the tile (with its content pointing to an external tileset JSON file) as if the two tilesets were merged.\r\n *

\r\n *\r\n * @type {Cesium3DTile}\r\n * @readonly\r\n */\r\n this.parent = parent;\r\n\r\n var content;\r\n var hasEmptyContent;\r\n var contentState;\r\n var contentResource;\r\n var serverKey;\r\n\r\n baseResource = Resource.createIfNeeded(baseResource);\r\n\r\n if (defined(contentHeader)) {\r\n var contentHeaderUri = contentHeader.uri;\r\n if (defined(contentHeader.url)) {\r\n Cesium3DTile._deprecationWarning(\r\n \"contentUrl\",\r\n 'This tileset JSON uses the \"content.url\" property which has been deprecated. Use \"content.uri\" instead.'\r\n );\r\n contentHeaderUri = contentHeader.url;\r\n }\r\n hasEmptyContent = false;\r\n contentState = Cesium3DTileContentState.UNLOADED;\r\n contentResource = baseResource.getDerivedResource({\r\n url: contentHeaderUri,\r\n });\r\n serverKey = RequestScheduler.getServerKey(\r\n contentResource.getUrlComponent()\r\n );\r\n } else {\r\n content = new Empty3DTileContent(tileset, this);\r\n hasEmptyContent = true;\r\n contentState = Cesium3DTileContentState.READY;\r\n }\r\n\r\n this._content = content;\r\n this._contentResource = contentResource;\r\n this._contentState = contentState;\r\n this._contentReadyToProcessPromise = undefined;\r\n this._contentReadyPromise = undefined;\r\n this._expiredContent = undefined;\r\n\r\n this._serverKey = serverKey;\r\n\r\n /**\r\n * When true, the tile has no content.\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n this.hasEmptyContent = hasEmptyContent;\r\n\r\n /**\r\n * When true, the tile's content points to an external tileset.\r\n *

\r\n * This is false until the tile's content is loaded.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n this.hasTilesetContent = false;\r\n\r\n /**\r\n * The node in the tileset's LRU cache, used to determine when to unload a tile's content.\r\n *\r\n * See {@link Cesium3DTilesetCache}\r\n *\r\n * @type {DoublyLinkedListNode}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n this.cacheNode = undefined;\r\n\r\n var expire = header.expire;\r\n var expireDuration;\r\n var expireDate;\r\n if (defined(expire)) {\r\n expireDuration = expire.duration;\r\n if (defined(expire.date)) {\r\n expireDate = JulianDate.fromIso8601(expire.date);\r\n }\r\n }\r\n\r\n /**\r\n * The time in seconds after the tile's content is ready when the content expires and new content is requested.\r\n *\r\n * @type {Number}\r\n */\r\n this.expireDuration = expireDuration;\r\n\r\n /**\r\n * The date when the content expires and new content is requested.\r\n *\r\n * @type {JulianDate}\r\n */\r\n this.expireDate = expireDate;\r\n\r\n /**\r\n * The time when a style was last applied to this tile.\r\n *\r\n * @type {Number}\r\n *\r\n * @private\r\n */\r\n this.lastStyleTime = 0.0;\r\n\r\n /**\r\n * Marks whether the tile's children bounds are fully contained within the tile's bounds\r\n *\r\n * @type {Cesium3DTileOptimizationHint}\r\n *\r\n * @private\r\n */\r\n this._optimChildrenWithinParent = Cesium3DTileOptimizationHint.NOT_COMPUTED;\r\n\r\n /**\r\n * Tracks if the tile's relationship with a ClippingPlaneCollection has changed with regards\r\n * to the ClippingPlaneCollection's state.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @private\r\n */\r\n this.clippingPlanesDirty = false;\r\n\r\n /**\r\n * Tracks if the tile's request should be deferred until all non-deferred\r\n * tiles load.\r\n *\r\n * @type {Boolean}\r\n *\r\n * @private\r\n */\r\n this.priorityDeferred = false;\r\n\r\n // Members that are updated every frame for tree traversal and rendering optimizations:\r\n this._distanceToCamera = 0.0;\r\n this._centerZDepth = 0.0;\r\n this._screenSpaceError = 0.0;\r\n this._screenSpaceErrorProgressiveResolution = 0.0; // The screen space error at a given screen height of tileset.progressiveResolutionHeightFraction * screenHeight\r\n this._visibilityPlaneMask = 0;\r\n this._visible = false;\r\n this._inRequestVolume = false;\r\n\r\n this._finalResolution = true;\r\n this._depth = 0;\r\n this._stackLength = 0;\r\n this._selectionDepth = 0;\r\n\r\n this._updatedVisibilityFrame = 0;\r\n this._touchedFrame = 0;\r\n this._visitedFrame = 0;\r\n this._selectedFrame = 0;\r\n this._requestedFrame = 0;\r\n this._ancestorWithContent = undefined;\r\n this._ancestorWithContentAvailable = undefined;\r\n this._refines = false;\r\n this._shouldSelect = false;\r\n this._isClipped = true;\r\n this._clippingPlanesState = 0; // encapsulates (_isClipped, clippingPlanes.enabled) and number/function\r\n this._debugBoundingVolume = undefined;\r\n this._debugContentBoundingVolume = undefined;\r\n this._debugViewerRequestVolume = undefined;\r\n this._debugColor = Color.fromRandom({ alpha: 1.0 });\r\n this._debugColorizeTiles = false;\r\n\r\n this._priority = 0.0; // The priority used for request sorting\r\n this._priorityHolder = this; // Reference to the ancestor up the tree that holds the _foveatedFactor and _distanceToCamera for all tiles in the refinement chain.\r\n this._priorityProgressiveResolution = false;\r\n this._priorityProgressiveResolutionScreenSpaceErrorLeaf = false;\r\n this._priorityReverseScreenSpaceError = 0.0;\r\n this._foveatedFactor = 0.0;\r\n this._wasMinPriorityChild = false; // Needed for knowing when to continue a refinement chain. Gets reset in updateTile in traversal and gets set in updateAndPushChildren in traversal.\r\n\r\n this._loadTimestamp = new JulianDate();\r\n\r\n this._commandsLength = 0;\r\n\r\n this._color = undefined;\r\n this._colorDirty = false;\r\n\r\n this._request = undefined;\r\n}\r\n\r\n// This can be overridden for testing purposes\r\nCesium3DTile._deprecationWarning = deprecationWarning;\r\n\r\nObject.defineProperties(Cesium3DTile.prototype, {\r\n /**\r\n * The tileset containing this tile.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {Cesium3DTileset}\r\n * @readonly\r\n */\r\n tileset: {\r\n get: function () {\r\n return this._tileset;\r\n },\r\n },\r\n\r\n /**\r\n * The tile's content. This represents the actual tile's payload,\r\n * not the content's metadata in the tileset JSON file.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {Cesium3DTileContent}\r\n * @readonly\r\n */\r\n content: {\r\n get: function () {\r\n return this._content;\r\n },\r\n },\r\n\r\n /**\r\n * Get the tile's bounding volume.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {TileBoundingVolume}\r\n * @readonly\r\n * @private\r\n */\r\n boundingVolume: {\r\n get: function () {\r\n return this._boundingVolume;\r\n },\r\n },\r\n\r\n /**\r\n * Get the bounding volume of the tile's contents. This defaults to the\r\n * tile's bounding volume when the content's bounding volume is\r\n * undefined.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {TileBoundingVolume}\r\n * @readonly\r\n * @private\r\n */\r\n contentBoundingVolume: {\r\n get: function () {\r\n return defaultValue(this._contentBoundingVolume, this._boundingVolume);\r\n },\r\n },\r\n\r\n /**\r\n * Get the bounding sphere derived from the tile's bounding volume.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {BoundingSphere}\r\n * @readonly\r\n */\r\n boundingSphere: {\r\n get: function () {\r\n return this._boundingVolume.boundingSphere;\r\n },\r\n },\r\n\r\n /**\r\n * Returns the extras property in the tileset JSON for this tile, which contains application specific metadata.\r\n * Returns undefined if extras does not exist.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {*}\r\n * @readonly\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification#specifying-extensions-and-application-specific-extras|Extras in the 3D Tiles specification.}\r\n */\r\n extras: {\r\n get: function () {\r\n return this._header.extras;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the tile's highlight color.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {Color}\r\n *\r\n * @default {@link Color.WHITE}\r\n *\r\n * @private\r\n */\r\n color: {\r\n get: function () {\r\n if (!defined(this._color)) {\r\n this._color = new Color();\r\n }\r\n return Color.clone(this._color);\r\n },\r\n set: function (value) {\r\n this._color = Color.clone(value, this._color);\r\n this._colorDirty = true;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the tile has available content to render. true if the tile's\r\n * content is ready or if it has expired content that renders while new content loads; otherwise,\r\n * false.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n contentAvailable: {\r\n get: function () {\r\n return (\r\n (this.contentReady &&\r\n !this.hasEmptyContent &&\r\n !this.hasTilesetContent) ||\r\n (defined(this._expiredContent) && !this.contentFailed)\r\n );\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the tile's content is ready. This is automatically true for\r\n * tile's with empty content.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n contentReady: {\r\n get: function () {\r\n return this._contentState === Cesium3DTileContentState.READY;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the tile's content has not be requested. true if tile's\r\n * content has not be requested; otherwise, false.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n contentUnloaded: {\r\n get: function () {\r\n return this._contentState === Cesium3DTileContentState.UNLOADED;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the tile's content is expired. true if tile's\r\n * content is expired; otherwise, false.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n contentExpired: {\r\n get: function () {\r\n return this._contentState === Cesium3DTileContentState.EXPIRED;\r\n },\r\n },\r\n\r\n /**\r\n * Determines if the tile's content failed to load. true if the tile's\r\n * content failed to load; otherwise, false.\r\n *\r\n * @memberof Cesium3DTile.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n contentFailed: {\r\n get: function () {\r\n return this._contentState === Cesium3DTileContentState.FAILED;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the promise that will be resolved when the tile's content is ready to process.\r\n * This happens after the content is downloaded but before the content is ready\r\n * to render.\r\n *

\r\n * The promise remains undefined until the tile's content is requested.\r\n *

\r\n *\r\n * @type {Promise.}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n contentReadyToProcessPromise: {\r\n get: function () {\r\n if (defined(this._contentReadyToProcessPromise)) {\r\n return this._contentReadyToProcessPromise.promise;\r\n }\r\n return undefined;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the promise that will be resolved when the tile's content is ready to render.\r\n *

\r\n * The promise remains undefined until the tile's content is requested.\r\n *

\r\n *\r\n * @type {Promise.}\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n contentReadyPromise: {\r\n get: function () {\r\n if (defined(this._contentReadyPromise)) {\r\n return this._contentReadyPromise.promise;\r\n }\r\n return undefined;\r\n },\r\n },\r\n\r\n /**\r\n * Returns the number of draw commands used by this tile.\r\n *\r\n * @readonly\r\n *\r\n * @private\r\n */\r\n commandsLength: {\r\n get: function () {\r\n return this._commandsLength;\r\n },\r\n },\r\n});\r\n\r\nvar scratchCartesian = new Cartesian3();\r\nfunction isPriorityDeferred(tile, frameState) {\r\n var tileset = tile._tileset;\r\n\r\n // If closest point on line is inside the sphere then set foveatedFactor to 0. Otherwise, the dot product is with the line from camera to the point on the sphere that is closest to the line.\r\n var camera = frameState.camera;\r\n var boundingSphere = tile.boundingSphere;\r\n var radius = boundingSphere.radius;\r\n var scaledCameraDirection = Cartesian3.multiplyByScalar(\r\n camera.directionWC,\r\n tile._centerZDepth,\r\n scratchCartesian\r\n );\r\n var closestPointOnLine = Cartesian3.add(\r\n camera.positionWC,\r\n scaledCameraDirection,\r\n scratchCartesian\r\n );\r\n // The distance from the camera's view direction to the tile.\r\n var toLine = Cartesian3.subtract(\r\n closestPointOnLine,\r\n boundingSphere.center,\r\n scratchCartesian\r\n );\r\n var distanceToCenterLine = Cartesian3.magnitude(toLine);\r\n var notTouchingSphere = distanceToCenterLine > radius;\r\n\r\n // If camera's direction vector is inside the bounding sphere then consider\r\n // this tile right along the line of sight and set _foveatedFactor to 0.\r\n // Otherwise,_foveatedFactor is one minus the dot product of the camera's direction\r\n // and the vector between the camera and the point on the bounding sphere closest to the view line.\r\n if (notTouchingSphere) {\r\n var toLineNormalized = Cartesian3.normalize(toLine, scratchCartesian);\r\n var scaledToLine = Cartesian3.multiplyByScalar(\r\n toLineNormalized,\r\n radius,\r\n scratchCartesian\r\n );\r\n var closestOnSphere = Cartesian3.add(\r\n boundingSphere.center,\r\n scaledToLine,\r\n scratchCartesian\r\n );\r\n var toClosestOnSphere = Cartesian3.subtract(\r\n closestOnSphere,\r\n camera.positionWC,\r\n scratchCartesian\r\n );\r\n var toClosestOnSphereNormalize = Cartesian3.normalize(\r\n toClosestOnSphere,\r\n scratchCartesian\r\n );\r\n tile._foveatedFactor =\r\n 1.0 -\r\n Math.abs(Cartesian3.dot(camera.directionWC, toClosestOnSphereNormalize));\r\n } else {\r\n tile._foveatedFactor = 0.0;\r\n }\r\n\r\n // Skip this feature if: non-skipLevelOfDetail and replace refine, if the foveated settings are turned off, if tile is progressive resolution and replace refine and skipLevelOfDetail (will help get rid of ancestor artifacts faster)\r\n // Or if the tile is a preload of any kind\r\n var replace = tile.refine === Cesium3DTileRefine.REPLACE;\r\n var skipLevelOfDetail = tileset._skipLevelOfDetail;\r\n if (\r\n (replace && !skipLevelOfDetail) ||\r\n !tileset.foveatedScreenSpaceError ||\r\n tileset.foveatedConeSize === 1.0 ||\r\n (tile._priorityProgressiveResolution && replace && skipLevelOfDetail) ||\r\n tileset._pass === Cesium3DTilePass.PRELOAD_FLIGHT ||\r\n tileset._pass === Cesium3DTilePass.PRELOAD\r\n ) {\r\n return false;\r\n }\r\n\r\n var maximumFovatedFactor = 1.0 - Math.cos(camera.frustum.fov * 0.5); // 0.14 for fov = 60. NOTE very hard to defer vertically foveated tiles since max is based on fovy (which is fov). Lowering the 0.5 to a smaller fraction of the screen height will start to defer vertically foveated tiles.\r\n var foveatedConeFactor = tileset.foveatedConeSize * maximumFovatedFactor;\r\n\r\n // If it's inside the user-defined view cone, then it should not be deferred.\r\n if (tile._foveatedFactor <= foveatedConeFactor) {\r\n return false;\r\n }\r\n\r\n // Relax SSE based on how big the angle is between the tile and the edge of the foveated cone.\r\n var range = maximumFovatedFactor - foveatedConeFactor;\r\n var normalizedFoveatedFactor = CesiumMath.clamp(\r\n (tile._foveatedFactor - foveatedConeFactor) / range,\r\n 0.0,\r\n 1.0\r\n );\r\n var sseRelaxation = tileset.foveatedInterpolationCallback(\r\n tileset.foveatedMinimumScreenSpaceErrorRelaxation,\r\n tileset.maximumScreenSpaceError,\r\n normalizedFoveatedFactor\r\n );\r\n var sse =\r\n tile._screenSpaceError === 0.0 && defined(tile.parent)\r\n ? tile.parent._screenSpaceError * 0.5\r\n : tile._screenSpaceError;\r\n\r\n return tileset.maximumScreenSpaceError - sseRelaxation <= sse;\r\n}\r\n\r\nvar scratchJulianDate = new JulianDate();\r\n\r\n/**\r\n * Get the tile's screen space error.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.getScreenSpaceError = function (\r\n frameState,\r\n useParentGeometricError,\r\n progressiveResolutionHeightFraction\r\n) {\r\n var tileset = this._tileset;\r\n var heightFraction = defaultValue(progressiveResolutionHeightFraction, 1.0);\r\n var parentGeometricError = defined(this.parent)\r\n ? this.parent.geometricError\r\n : tileset._geometricError;\r\n var geometricError = useParentGeometricError\r\n ? parentGeometricError\r\n : this.geometricError;\r\n if (geometricError === 0.0) {\r\n // Leaf tiles do not have any error so save the computation\r\n return 0.0;\r\n }\r\n var camera = frameState.camera;\r\n var frustum = camera.frustum;\r\n var context = frameState.context;\r\n var width = context.drawingBufferWidth;\r\n var height = context.drawingBufferHeight * heightFraction;\r\n var error;\r\n if (\r\n frameState.mode === SceneMode.SCENE2D ||\r\n frustum instanceof OrthographicFrustum\r\n ) {\r\n if (defined(frustum._offCenterFrustum)) {\r\n frustum = frustum._offCenterFrustum;\r\n }\r\n var pixelSize =\r\n Math.max(frustum.top - frustum.bottom, frustum.right - frustum.left) /\r\n Math.max(width, height);\r\n error = geometricError / pixelSize;\r\n } else {\r\n // Avoid divide by zero when viewer is inside the tile\r\n var distance = Math.max(this._distanceToCamera, CesiumMath.EPSILON7);\r\n var sseDenominator = camera.frustum.sseDenominator;\r\n error = (geometricError * height) / (distance * sseDenominator);\r\n if (tileset.dynamicScreenSpaceError) {\r\n var density = tileset._dynamicScreenSpaceErrorComputedDensity;\r\n var factor = tileset.dynamicScreenSpaceErrorFactor;\r\n var dynamicError = CesiumMath.fog(distance, density) * factor;\r\n error -= dynamicError;\r\n }\r\n }\r\n\r\n error /= frameState.pixelRatio;\r\n\r\n return error;\r\n};\r\n\r\nfunction isPriorityProgressiveResolution(tileset, tile) {\r\n if (\r\n tileset.progressiveResolutionHeightFraction <= 0.0 ||\r\n tileset.progressiveResolutionHeightFraction > 0.5\r\n ) {\r\n return false;\r\n }\r\n\r\n var isProgressiveResolutionTile =\r\n tile._screenSpaceErrorProgressiveResolution >\r\n tileset._maximumScreenSpaceError; // Mark non-SSE leaves\r\n tile._priorityProgressiveResolutionScreenSpaceErrorLeaf = false; // Needed for skipLOD\r\n var parent = tile.parent;\r\n var maximumScreenSpaceError = tileset._maximumScreenSpaceError;\r\n var tilePasses =\r\n tile._screenSpaceErrorProgressiveResolution <= maximumScreenSpaceError;\r\n var parentFails =\r\n defined(parent) &&\r\n parent._screenSpaceErrorProgressiveResolution > maximumScreenSpaceError;\r\n if (tilePasses && parentFails) {\r\n // A progressive resolution SSE leaf, promote its priority as well\r\n tile._priorityProgressiveResolutionScreenSpaceErrorLeaf = true;\r\n isProgressiveResolutionTile = true;\r\n }\r\n return isProgressiveResolutionTile;\r\n}\r\n\r\nfunction getPriorityReverseScreenSpaceError(tileset, tile) {\r\n var parent = tile.parent;\r\n var useParentScreenSpaceError =\r\n defined(parent) &&\r\n (!tileset._skipLevelOfDetail ||\r\n tile._screenSpaceError === 0.0 ||\r\n parent.hasTilesetContent);\r\n var screenSpaceError = useParentScreenSpaceError\r\n ? parent._screenSpaceError\r\n : tile._screenSpaceError;\r\n return tileset.root._screenSpaceError - screenSpaceError;\r\n}\r\n\r\n/**\r\n * Update the tile's visibility.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.updateVisibility = function (frameState) {\r\n var parent = this.parent;\r\n var tileset = this._tileset;\r\n var parentTransform = defined(parent)\r\n ? parent.computedTransform\r\n : tileset.modelMatrix;\r\n var parentVisibilityPlaneMask = defined(parent)\r\n ? parent._visibilityPlaneMask\r\n : CullingVolume.MASK_INDETERMINATE;\r\n this.updateTransform(parentTransform);\r\n this._distanceToCamera = this.distanceToTile(frameState);\r\n this._centerZDepth = this.distanceToTileCenter(frameState);\r\n this._screenSpaceError = this.getScreenSpaceError(frameState, false);\r\n this._screenSpaceErrorProgressiveResolution = this.getScreenSpaceError(\r\n frameState,\r\n false,\r\n tileset.progressiveResolutionHeightFraction\r\n );\r\n this._visibilityPlaneMask = this.visibility(\r\n frameState,\r\n parentVisibilityPlaneMask\r\n ); // Use parent's plane mask to speed up visibility test\r\n this._visible = this._visibilityPlaneMask !== CullingVolume.MASK_OUTSIDE;\r\n this._inRequestVolume = this.insideViewerRequestVolume(frameState);\r\n this._priorityReverseScreenSpaceError = getPriorityReverseScreenSpaceError(\r\n tileset,\r\n this\r\n );\r\n this._priorityProgressiveResolution = isPriorityProgressiveResolution(\r\n tileset,\r\n this\r\n );\r\n this.priorityDeferred = isPriorityDeferred(this, frameState);\r\n};\r\n\r\n/**\r\n * Update whether the tile has expired.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.updateExpiration = function () {\r\n if (defined(this.expireDate) && this.contentReady && !this.hasEmptyContent) {\r\n var now = JulianDate.now(scratchJulianDate);\r\n if (JulianDate.lessThan(this.expireDate, now)) {\r\n this._contentState = Cesium3DTileContentState.EXPIRED;\r\n this._expiredContent = this._content;\r\n }\r\n }\r\n};\r\n\r\nfunction updateExpireDate(tile) {\r\n if (defined(tile.expireDuration)) {\r\n var expireDurationDate = JulianDate.now(scratchJulianDate);\r\n JulianDate.addSeconds(\r\n expireDurationDate,\r\n tile.expireDuration,\r\n expireDurationDate\r\n );\r\n\r\n if (defined(tile.expireDate)) {\r\n if (JulianDate.lessThan(tile.expireDate, expireDurationDate)) {\r\n JulianDate.clone(expireDurationDate, tile.expireDate);\r\n }\r\n } else {\r\n tile.expireDate = JulianDate.clone(expireDurationDate);\r\n }\r\n }\r\n}\r\n\r\nfunction getContentFailedFunction(tile, tileset) {\r\n return function (error) {\r\n if (tile._contentState === Cesium3DTileContentState.PROCESSING) {\r\n --tileset.statistics.numberOfTilesProcessing;\r\n } else {\r\n --tileset.statistics.numberOfPendingRequests;\r\n }\r\n tile._contentState = Cesium3DTileContentState.FAILED;\r\n tile._contentReadyPromise.reject(error);\r\n tile._contentReadyToProcessPromise.reject(error);\r\n };\r\n}\r\n\r\nfunction createPriorityFunction(tile) {\r\n return function () {\r\n return tile._priority;\r\n };\r\n}\r\n\r\n/**\r\n * Requests the tile's content.\r\n *

\r\n * The request may not be made if the Cesium Request Scheduler can't prioritize it.\r\n *

\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.requestContent = function () {\r\n var that = this;\r\n var tileset = this._tileset;\r\n\r\n if (this.hasEmptyContent) {\r\n return false;\r\n }\r\n\r\n var resource = this._contentResource.clone();\r\n var expired = this.contentExpired;\r\n if (expired) {\r\n // Append a query parameter of the tile expiration date to prevent caching\r\n resource.setQueryParameters({\r\n expired: this.expireDate.toString(),\r\n });\r\n }\r\n\r\n var request = new Request({\r\n throttle: true,\r\n throttleByServer: true,\r\n type: RequestType.TILES3D,\r\n priorityFunction: createPriorityFunction(this),\r\n serverKey: this._serverKey,\r\n });\r\n\r\n this._request = request;\r\n resource.request = request;\r\n\r\n var promise = resource.fetchArrayBuffer();\r\n\r\n if (!defined(promise)) {\r\n return false;\r\n }\r\n\r\n var contentState = this._contentState;\r\n this._contentState = Cesium3DTileContentState.LOADING;\r\n this._contentReadyToProcessPromise = when.defer();\r\n this._contentReadyPromise = when.defer();\r\n\r\n var contentFailedFunction = getContentFailedFunction(this, tileset);\r\n promise\r\n .then(function (arrayBuffer) {\r\n if (that.isDestroyed()) {\r\n // Tile is unloaded before the content finishes loading\r\n contentFailedFunction();\r\n return;\r\n }\r\n var uint8Array = new Uint8Array(arrayBuffer);\r\n var magic = getMagic(uint8Array);\r\n var contentFactory = Cesium3DTileContentFactory[magic];\r\n var content;\r\n\r\n // Vector and Geometry tile rendering do not support the skip LOD optimization.\r\n tileset._disableSkipLevelOfDetail =\r\n tileset._disableSkipLevelOfDetail ||\r\n magic === \"vctr\" ||\r\n magic === \"geom\";\r\n\r\n if (defined(contentFactory)) {\r\n content = contentFactory(\r\n tileset,\r\n that,\r\n that._contentResource,\r\n arrayBuffer,\r\n 0\r\n );\r\n } else {\r\n // The content may be json instead\r\n content = Cesium3DTileContentFactory.json(\r\n tileset,\r\n that,\r\n that._contentResource,\r\n arrayBuffer,\r\n 0\r\n );\r\n that.hasTilesetContent = true;\r\n }\r\n\r\n if (expired) {\r\n that.expireDate = undefined;\r\n }\r\n\r\n that._content = content;\r\n that._contentState = Cesium3DTileContentState.PROCESSING;\r\n that._contentReadyToProcessPromise.resolve(content);\r\n\r\n return content.readyPromise.then(function (content) {\r\n if (that.isDestroyed()) {\r\n // Tile is unloaded before the content finishes processing\r\n contentFailedFunction();\r\n return;\r\n }\r\n updateExpireDate(that);\r\n\r\n // Refresh style for expired content\r\n that._selectedFrame = 0;\r\n that.lastStyleTime = 0.0;\r\n\r\n JulianDate.now(that._loadTimestamp);\r\n that._contentState = Cesium3DTileContentState.READY;\r\n that._contentReadyPromise.resolve(content);\r\n });\r\n })\r\n .otherwise(function (error) {\r\n if (request.state === RequestState.CANCELLED) {\r\n // Cancelled due to low priority - try again later.\r\n that._contentState = contentState;\r\n --tileset.statistics.numberOfPendingRequests;\r\n ++tileset.statistics.numberOfAttemptedRequests;\r\n return;\r\n }\r\n contentFailedFunction(error);\r\n });\r\n\r\n return true;\r\n};\r\n\r\n/**\r\n * Unloads the tile's content.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.unloadContent = function () {\r\n if (this.hasEmptyContent || this.hasTilesetContent) {\r\n return;\r\n }\r\n\r\n this._content = this._content && this._content.destroy();\r\n this._contentState = Cesium3DTileContentState.UNLOADED;\r\n this._contentReadyToProcessPromise = undefined;\r\n this._contentReadyPromise = undefined;\r\n\r\n this.lastStyleTime = 0.0;\r\n this.clippingPlanesDirty = this._clippingPlanesState === 0;\r\n this._clippingPlanesState = 0;\r\n\r\n this._debugColorizeTiles = false;\r\n\r\n this._debugBoundingVolume =\r\n this._debugBoundingVolume && this._debugBoundingVolume.destroy();\r\n this._debugContentBoundingVolume =\r\n this._debugContentBoundingVolume &&\r\n this._debugContentBoundingVolume.destroy();\r\n this._debugViewerRequestVolume =\r\n this._debugViewerRequestVolume && this._debugViewerRequestVolume.destroy();\r\n};\r\n\r\nvar scratchProjectedBoundingSphere = new BoundingSphere();\r\n\r\nfunction getBoundingVolume(tile, frameState) {\r\n if (\r\n frameState.mode !== SceneMode.SCENE3D &&\r\n !defined(tile._boundingVolume2D)\r\n ) {\r\n var boundingSphere = tile._boundingVolume.boundingSphere;\r\n var sphere = BoundingSphere.projectTo2D(\r\n boundingSphere,\r\n frameState.mapProjection,\r\n scratchProjectedBoundingSphere\r\n );\r\n tile._boundingVolume2D = new TileBoundingSphere(\r\n sphere.center,\r\n sphere.radius\r\n );\r\n }\r\n\r\n return frameState.mode !== SceneMode.SCENE3D\r\n ? tile._boundingVolume2D\r\n : tile._boundingVolume;\r\n}\r\n\r\nfunction getContentBoundingVolume(tile, frameState) {\r\n if (\r\n frameState.mode !== SceneMode.SCENE3D &&\r\n !defined(tile._contentBoundingVolume2D)\r\n ) {\r\n var boundingSphere = tile._contentBoundingVolume.boundingSphere;\r\n var sphere = BoundingSphere.projectTo2D(\r\n boundingSphere,\r\n frameState.mapProjection,\r\n scratchProjectedBoundingSphere\r\n );\r\n tile._contentBoundingVolume2D = new TileBoundingSphere(\r\n sphere.center,\r\n sphere.radius\r\n );\r\n }\r\n return frameState.mode !== SceneMode.SCENE3D\r\n ? tile._contentBoundingVolume2D\r\n : tile._contentBoundingVolume;\r\n}\r\n\r\n/**\r\n * Determines whether the tile's bounding volume intersects the culling volume.\r\n *\r\n * @param {FrameState} frameState The frame state.\r\n * @param {Number} parentVisibilityPlaneMask The parent's plane mask to speed up the visibility check.\r\n * @returns {Number} A plane mask as described above in {@link CullingVolume#computeVisibilityWithPlaneMask}.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.visibility = function (\r\n frameState,\r\n parentVisibilityPlaneMask\r\n) {\r\n var cullingVolume = frameState.cullingVolume;\r\n var boundingVolume = getBoundingVolume(this, frameState);\r\n\r\n var tileset = this._tileset;\r\n var clippingPlanes = tileset.clippingPlanes;\r\n if (defined(clippingPlanes) && clippingPlanes.enabled) {\r\n var intersection = clippingPlanes.computeIntersectionWithBoundingVolume(\r\n boundingVolume,\r\n tileset.clippingPlanesOriginMatrix\r\n );\r\n this._isClipped = intersection !== Intersect.INSIDE;\r\n if (intersection === Intersect.OUTSIDE) {\r\n return CullingVolume.MASK_OUTSIDE;\r\n }\r\n }\r\n\r\n return cullingVolume.computeVisibilityWithPlaneMask(\r\n boundingVolume,\r\n parentVisibilityPlaneMask\r\n );\r\n};\r\n\r\n/**\r\n * Assuming the tile's bounding volume intersects the culling volume, determines\r\n * whether the tile's content's bounding volume intersects the culling volume.\r\n *\r\n * @param {FrameState} frameState The frame state.\r\n * @returns {Intersect} The result of the intersection: the tile's content is completely outside, completely inside, or intersecting the culling volume.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.contentVisibility = function (frameState) {\r\n // Assumes the tile's bounding volume intersects the culling volume already, so\r\n // just return Intersect.INSIDE if there is no content bounding volume.\r\n if (!defined(this._contentBoundingVolume)) {\r\n return Intersect.INSIDE;\r\n }\r\n\r\n if (this._visibilityPlaneMask === CullingVolume.MASK_INSIDE) {\r\n // The tile's bounding volume is completely inside the culling volume so\r\n // the content bounding volume must also be inside.\r\n return Intersect.INSIDE;\r\n }\r\n\r\n // PERFORMANCE_IDEA: is it possible to burn less CPU on this test since we know the\r\n // tile's (not the content's) bounding volume intersects the culling volume?\r\n var cullingVolume = frameState.cullingVolume;\r\n var boundingVolume = getContentBoundingVolume(this, frameState);\r\n\r\n var tileset = this._tileset;\r\n var clippingPlanes = tileset.clippingPlanes;\r\n if (defined(clippingPlanes) && clippingPlanes.enabled) {\r\n var intersection = clippingPlanes.computeIntersectionWithBoundingVolume(\r\n boundingVolume,\r\n tileset.clippingPlanesOriginMatrix\r\n );\r\n this._isClipped = intersection !== Intersect.INSIDE;\r\n if (intersection === Intersect.OUTSIDE) {\r\n return Intersect.OUTSIDE;\r\n }\r\n }\r\n\r\n return cullingVolume.computeVisibility(boundingVolume);\r\n};\r\n\r\n/**\r\n * Computes the (potentially approximate) distance from the closest point of the tile's bounding volume to the camera.\r\n *\r\n * @param {FrameState} frameState The frame state.\r\n * @returns {Number} The distance, in meters, or zero if the camera is inside the bounding volume.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.distanceToTile = function (frameState) {\r\n var boundingVolume = getBoundingVolume(this, frameState);\r\n return boundingVolume.distanceToCamera(frameState);\r\n};\r\n\r\nvar scratchToTileCenter = new Cartesian3();\r\n\r\n/**\r\n * Computes the distance from the center of the tile's bounding volume to the camera's plane defined by its position and view direction.\r\n *\r\n * @param {FrameState} frameState The frame state.\r\n * @returns {Number} The distance, in meters.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.distanceToTileCenter = function (frameState) {\r\n var tileBoundingVolume = getBoundingVolume(this, frameState);\r\n var boundingVolume = tileBoundingVolume.boundingVolume; // Gets the underlying OrientedBoundingBox or BoundingSphere\r\n var toCenter = Cartesian3.subtract(\r\n boundingVolume.center,\r\n frameState.camera.positionWC,\r\n scratchToTileCenter\r\n );\r\n return Cartesian3.dot(frameState.camera.directionWC, toCenter);\r\n};\r\n\r\n/**\r\n * Checks if the camera is inside the viewer request volume.\r\n *\r\n * @param {FrameState} frameState The frame state.\r\n * @returns {Boolean} Whether the camera is inside the volume.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.insideViewerRequestVolume = function (frameState) {\r\n var viewerRequestVolume = this._viewerRequestVolume;\r\n return (\r\n !defined(viewerRequestVolume) ||\r\n viewerRequestVolume.distanceToCamera(frameState) === 0.0\r\n );\r\n};\r\n\r\nvar scratchMatrix = new Matrix3();\r\nvar scratchScale = new Cartesian3();\r\nvar scratchHalfAxes = new Matrix3();\r\nvar scratchCenter = new Cartesian3();\r\nvar scratchRectangle = new Rectangle();\r\nvar scratchOrientedBoundingBox = new OrientedBoundingBox();\r\nvar scratchTransform = new Matrix4();\r\n\r\nfunction createBox(box, transform, result) {\r\n var center = Cartesian3.fromElements(box[0], box[1], box[2], scratchCenter);\r\n var halfAxes = Matrix3.fromArray(box, 3, scratchHalfAxes);\r\n\r\n // Find the transformed center and halfAxes\r\n center = Matrix4.multiplyByPoint(transform, center, center);\r\n var rotationScale = Matrix4.getMatrix3(transform, scratchMatrix);\r\n halfAxes = Matrix3.multiply(rotationScale, halfAxes, halfAxes);\r\n\r\n if (defined(result)) {\r\n result.update(center, halfAxes);\r\n return result;\r\n }\r\n return new TileOrientedBoundingBox(center, halfAxes);\r\n}\r\n\r\nfunction createBoxFromTransformedRegion(\r\n region,\r\n transform,\r\n initialTransform,\r\n result\r\n) {\r\n var rectangle = Rectangle.unpack(region, 0, scratchRectangle);\r\n var minimumHeight = region[4];\r\n var maximumHeight = region[5];\r\n\r\n var orientedBoundingBox = OrientedBoundingBox.fromRectangle(\r\n rectangle,\r\n minimumHeight,\r\n maximumHeight,\r\n Ellipsoid.WGS84,\r\n scratchOrientedBoundingBox\r\n );\r\n var center = orientedBoundingBox.center;\r\n var halfAxes = orientedBoundingBox.halfAxes;\r\n\r\n // A region bounding volume is not transformed by the transform in the tileset JSON,\r\n // but may be transformed by additional transforms applied in Cesium.\r\n // This is why the transform is calculated as the difference between the initial transform and the current transform.\r\n transform = Matrix4.multiplyTransformation(\r\n transform,\r\n Matrix4.inverseTransformation(initialTransform, scratchTransform),\r\n scratchTransform\r\n );\r\n center = Matrix4.multiplyByPoint(transform, center, center);\r\n var rotationScale = Matrix4.getMatrix3(transform, scratchMatrix);\r\n halfAxes = Matrix3.multiply(rotationScale, halfAxes, halfAxes);\r\n\r\n if (defined(result) && result instanceof TileOrientedBoundingBox) {\r\n result.update(center, halfAxes);\r\n return result;\r\n }\r\n\r\n return new TileOrientedBoundingBox(center, halfAxes);\r\n}\r\n\r\nfunction createRegion(region, transform, initialTransform, result) {\r\n if (\r\n !Matrix4.equalsEpsilon(transform, initialTransform, CesiumMath.EPSILON8)\r\n ) {\r\n return createBoxFromTransformedRegion(\r\n region,\r\n transform,\r\n initialTransform,\r\n result\r\n );\r\n }\r\n\r\n if (defined(result)) {\r\n return result;\r\n }\r\n\r\n var rectangleRegion = Rectangle.unpack(region, 0, scratchRectangle);\r\n\r\n return new TileBoundingRegion({\r\n rectangle: rectangleRegion,\r\n minimumHeight: region[4],\r\n maximumHeight: region[5],\r\n });\r\n}\r\n\r\nfunction createSphere(sphere, transform, result) {\r\n var center = Cartesian3.fromElements(\r\n sphere[0],\r\n sphere[1],\r\n sphere[2],\r\n scratchCenter\r\n );\r\n var radius = sphere[3];\r\n\r\n // Find the transformed center and radius\r\n center = Matrix4.multiplyByPoint(transform, center, center);\r\n var scale = Matrix4.getScale(transform, scratchScale);\r\n var uniformScale = Cartesian3.maximumComponent(scale);\r\n radius *= uniformScale;\r\n\r\n if (defined(result)) {\r\n result.update(center, radius);\r\n return result;\r\n }\r\n return new TileBoundingSphere(center, radius);\r\n}\r\n\r\n/**\r\n * Create a bounding volume from the tile's bounding volume header.\r\n *\r\n * @param {Object} boundingVolumeHeader The tile's bounding volume header.\r\n * @param {Matrix4} transform The transform to apply to the bounding volume.\r\n * @param {TileBoundingVolume} [result] The object onto which to store the result.\r\n *\r\n * @returns {TileBoundingVolume} The modified result parameter or a new TileBoundingVolume instance if none was provided.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.createBoundingVolume = function (\r\n boundingVolumeHeader,\r\n transform,\r\n result\r\n) {\r\n if (!defined(boundingVolumeHeader)) {\r\n throw new RuntimeError(\"boundingVolume must be defined\");\r\n }\r\n if (defined(boundingVolumeHeader.box)) {\r\n return createBox(boundingVolumeHeader.box, transform, result);\r\n }\r\n if (defined(boundingVolumeHeader.region)) {\r\n return createRegion(\r\n boundingVolumeHeader.region,\r\n transform,\r\n this._initialTransform,\r\n result\r\n );\r\n }\r\n if (defined(boundingVolumeHeader.sphere)) {\r\n return createSphere(boundingVolumeHeader.sphere, transform, result);\r\n }\r\n throw new RuntimeError(\r\n \"boundingVolume must contain a sphere, region, or box\"\r\n );\r\n};\r\n\r\n/**\r\n * Update the tile's transform. The transform is applied to the tile's bounding volumes.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.updateTransform = function (parentTransform) {\r\n parentTransform = defaultValue(parentTransform, Matrix4.IDENTITY);\r\n var computedTransform = Matrix4.multiply(\r\n parentTransform,\r\n this.transform,\r\n scratchTransform\r\n );\r\n var transformChanged = !Matrix4.equals(\r\n computedTransform,\r\n this.computedTransform\r\n );\r\n\r\n if (!transformChanged) {\r\n return;\r\n }\r\n\r\n Matrix4.clone(computedTransform, this.computedTransform);\r\n\r\n // Update the bounding volumes\r\n var header = this._header;\r\n var content = this._header.content;\r\n this._boundingVolume = this.createBoundingVolume(\r\n header.boundingVolume,\r\n this.computedTransform,\r\n this._boundingVolume\r\n );\r\n if (defined(this._contentBoundingVolume)) {\r\n this._contentBoundingVolume = this.createBoundingVolume(\r\n content.boundingVolume,\r\n this.computedTransform,\r\n this._contentBoundingVolume\r\n );\r\n }\r\n if (defined(this._viewerRequestVolume)) {\r\n this._viewerRequestVolume = this.createBoundingVolume(\r\n header.viewerRequestVolume,\r\n this.computedTransform,\r\n this._viewerRequestVolume\r\n );\r\n }\r\n\r\n this.updateGeometricErrorScale();\r\n\r\n // Destroy the debug bounding volumes. They will be generated fresh.\r\n this._debugBoundingVolume =\r\n this._debugBoundingVolume && this._debugBoundingVolume.destroy();\r\n this._debugContentBoundingVolume =\r\n this._debugContentBoundingVolume &&\r\n this._debugContentBoundingVolume.destroy();\r\n this._debugViewerRequestVolume =\r\n this._debugViewerRequestVolume && this._debugViewerRequestVolume.destroy();\r\n};\r\n\r\nCesium3DTile.prototype.updateGeometricErrorScale = function () {\r\n var scale = Matrix4.getScale(this.computedTransform, scratchScale);\r\n var uniformScale = Cartesian3.maximumComponent(scale);\r\n this.geometricError = this._geometricError * uniformScale;\r\n};\r\n\r\nfunction applyDebugSettings(tile, tileset, frameState, passOptions) {\r\n if (!passOptions.isRender) {\r\n return;\r\n }\r\n\r\n var hasContentBoundingVolume =\r\n defined(tile._header.content) &&\r\n defined(tile._header.content.boundingVolume);\r\n var empty = tile.hasEmptyContent || tile.hasTilesetContent;\r\n\r\n var showVolume =\r\n tileset.debugShowBoundingVolume ||\r\n (tileset.debugShowContentBoundingVolume && !hasContentBoundingVolume);\r\n if (showVolume) {\r\n var color;\r\n if (!tile._finalResolution) {\r\n color = Color.YELLOW;\r\n } else if (empty) {\r\n color = Color.DARKGRAY;\r\n } else {\r\n color = Color.WHITE;\r\n }\r\n if (!defined(tile._debugBoundingVolume)) {\r\n tile._debugBoundingVolume = tile._boundingVolume.createDebugVolume(color);\r\n }\r\n tile._debugBoundingVolume.update(frameState);\r\n var attributes = tile._debugBoundingVolume.getGeometryInstanceAttributes(\r\n \"outline\"\r\n );\r\n attributes.color = ColorGeometryInstanceAttribute.toValue(\r\n color,\r\n attributes.color\r\n );\r\n } else if (!showVolume && defined(tile._debugBoundingVolume)) {\r\n tile._debugBoundingVolume = tile._debugBoundingVolume.destroy();\r\n }\r\n\r\n if (tileset.debugShowContentBoundingVolume && hasContentBoundingVolume) {\r\n if (!defined(tile._debugContentBoundingVolume)) {\r\n tile._debugContentBoundingVolume = tile._contentBoundingVolume.createDebugVolume(\r\n Color.BLUE\r\n );\r\n }\r\n tile._debugContentBoundingVolume.update(frameState);\r\n } else if (\r\n !tileset.debugShowContentBoundingVolume &&\r\n defined(tile._debugContentBoundingVolume)\r\n ) {\r\n tile._debugContentBoundingVolume = tile._debugContentBoundingVolume.destroy();\r\n }\r\n\r\n if (\r\n tileset.debugShowViewerRequestVolume &&\r\n defined(tile._viewerRequestVolume)\r\n ) {\r\n if (!defined(tile._debugViewerRequestVolume)) {\r\n tile._debugViewerRequestVolume = tile._viewerRequestVolume.createDebugVolume(\r\n Color.YELLOW\r\n );\r\n }\r\n tile._debugViewerRequestVolume.update(frameState);\r\n } else if (\r\n !tileset.debugShowViewerRequestVolume &&\r\n defined(tile._debugViewerRequestVolume)\r\n ) {\r\n tile._debugViewerRequestVolume = tile._debugViewerRequestVolume.destroy();\r\n }\r\n\r\n var debugColorizeTilesOn =\r\n (tileset.debugColorizeTiles && !tile._debugColorizeTiles) ||\r\n defined(tileset._heatmap.tilePropertyName);\r\n var debugColorizeTilesOff =\r\n !tileset.debugColorizeTiles && tile._debugColorizeTiles;\r\n\r\n if (debugColorizeTilesOn) {\r\n tileset._heatmap.colorize(tile, frameState); // Skipped if tileset._heatmap.tilePropertyName is undefined\r\n tile._debugColorizeTiles = true;\r\n tile.color = tile._debugColor;\r\n } else if (debugColorizeTilesOff) {\r\n tile._debugColorizeTiles = false;\r\n tile.color = Color.WHITE;\r\n }\r\n\r\n if (tile._colorDirty) {\r\n tile._colorDirty = false;\r\n tile._content.applyDebugSettings(true, tile._color);\r\n }\r\n\r\n if (debugColorizeTilesOff) {\r\n tileset.makeStyleDirty(); // Re-apply style now that colorize is switched off\r\n }\r\n}\r\n\r\nfunction updateContent(tile, tileset, frameState) {\r\n var content = tile._content;\r\n var expiredContent = tile._expiredContent;\r\n\r\n if (defined(expiredContent)) {\r\n if (!tile.contentReady) {\r\n // Render the expired content while the content loads\r\n expiredContent.update(tileset, frameState);\r\n return;\r\n }\r\n\r\n // New content is ready, destroy expired content\r\n tile._expiredContent.destroy();\r\n tile._expiredContent = undefined;\r\n }\r\n\r\n content.update(tileset, frameState);\r\n}\r\n\r\nfunction updateClippingPlanes(tile, tileset) {\r\n // Compute and compare ClippingPlanes state:\r\n // - enabled-ness - are clipping planes enabled? is this tile clipped?\r\n // - clipping plane count\r\n // - clipping function (union v. intersection)\r\n var clippingPlanes = tileset.clippingPlanes;\r\n var currentClippingPlanesState = 0;\r\n if (defined(clippingPlanes) && tile._isClipped && clippingPlanes.enabled) {\r\n currentClippingPlanesState = clippingPlanes.clippingPlanesState;\r\n }\r\n // If clippingPlaneState for tile changed, mark clippingPlanesDirty so content can update\r\n if (currentClippingPlanesState !== tile._clippingPlanesState) {\r\n tile._clippingPlanesState = currentClippingPlanesState;\r\n tile.clippingPlanesDirty = true;\r\n }\r\n}\r\n\r\n/**\r\n * Get the draw commands needed to render this tile.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.update = function (tileset, frameState, passOptions) {\r\n var commandStart = frameState.commandList.length;\r\n\r\n updateClippingPlanes(this, tileset);\r\n applyDebugSettings(this, tileset, frameState, passOptions);\r\n updateContent(this, tileset, frameState);\r\n\r\n var commandEnd = frameState.commandList.length;\r\n var commandsLength = commandEnd - commandStart;\r\n this._commandsLength = commandsLength;\r\n\r\n for (var i = 0; i < commandsLength; ++i) {\r\n var command = frameState.commandList[commandStart + i];\r\n var translucent = command.pass === Pass.TRANSLUCENT;\r\n command.depthForTranslucentClassification = translucent;\r\n }\r\n\r\n this.clippingPlanesDirty = false; // reset after content update\r\n};\r\n\r\nvar scratchCommandList = [];\r\n\r\n/**\r\n * Processes the tile's content, e.g., create WebGL resources, to move from the PROCESSING to READY state.\r\n *\r\n * @param {Cesium3DTileset} tileset The tileset containing this tile.\r\n * @param {FrameState} frameState The frame state.\r\n *\r\n * @private\r\n */\r\nCesium3DTile.prototype.process = function (tileset, frameState) {\r\n var savedCommandList = frameState.commandList;\r\n frameState.commandList = scratchCommandList;\r\n\r\n this._content.update(tileset, frameState);\r\n\r\n scratchCommandList.length = 0;\r\n frameState.commandList = savedCommandList;\r\n};\r\n\r\nfunction isolateDigits(normalizedValue, numberOfDigits, leftShift) {\r\n var scaled = normalizedValue * Math.pow(10, numberOfDigits);\r\n var integer = parseInt(scaled);\r\n return integer * Math.pow(10, leftShift);\r\n}\r\n\r\nfunction priorityNormalizeAndClamp(value, minimum, maximum) {\r\n return Math.max(\r\n CesiumMath.normalize(value, minimum, maximum) - CesiumMath.EPSILON7,\r\n 0.0\r\n ); // Subtract epsilon since we only want decimal digits present in the output.\r\n}\r\n\r\n/**\r\n * Sets the priority of the tile based on distance and depth\r\n * @private\r\n */\r\nCesium3DTile.prototype.updatePriority = function () {\r\n var tileset = this.tileset;\r\n var preferLeaves = tileset.preferLeaves;\r\n var minimumPriority = tileset._minimumPriority;\r\n var maximumPriority = tileset._maximumPriority;\r\n\r\n // Combine priority systems together by mapping them into a base 10 number where each priority controls a specific set of digits in the number.\r\n // For number priorities, map them to a 0.xxxxx number then left shift it up into a set number of digits before the decimal point. Chop of the fractional part then left shift again into the position it needs to go.\r\n // For blending number priorities, normalize them to 0-1 and interpolate to get a combined 0-1 number, then proceed as normal.\r\n // Booleans can just be 0 or 10^leftshift.\r\n // Think of digits as penalties since smaller numbers are higher priority. If a tile has some large quantity or has a flag raised it's (usually) penalized for it, expressed as a higher number for the digit.\r\n // Priority number format: preloadFlightDigits(1) | foveatedDeferDigits(1) | foveatedDigits(4) | preloadProgressiveResolutionDigits(1) | preferredSortingDigits(4) . depthDigits(the decimal digits)\r\n // Certain flags like preferLeaves will flip / turn off certain digits to get desired load order.\r\n\r\n // Setup leftShifts, digit counts, and scales (for booleans)\r\n var digitsForANumber = 4;\r\n var digitsForABoolean = 1;\r\n\r\n var preferredSortingLeftShift = 0;\r\n var preferredSortingDigitsCount = digitsForANumber;\r\n\r\n var foveatedLeftShift =\r\n preferredSortingLeftShift + preferredSortingDigitsCount;\r\n var foveatedDigitsCount = digitsForANumber;\r\n\r\n var preloadProgressiveResolutionLeftShift =\r\n foveatedLeftShift + foveatedDigitsCount;\r\n var preloadProgressiveResolutionDigitsCount = digitsForABoolean;\r\n var preloadProgressiveResolutionScale = Math.pow(\r\n 10,\r\n preloadProgressiveResolutionLeftShift\r\n );\r\n\r\n var foveatedDeferLeftShift =\r\n preloadProgressiveResolutionLeftShift +\r\n preloadProgressiveResolutionDigitsCount;\r\n var foveatedDeferDigitsCount = digitsForABoolean;\r\n var foveatedDeferScale = Math.pow(10, foveatedDeferLeftShift);\r\n\r\n var preloadFlightLeftShift =\r\n foveatedDeferLeftShift + foveatedDeferDigitsCount;\r\n var preloadFlightScale = Math.pow(10, preloadFlightLeftShift);\r\n\r\n // Compute the digits for each priority\r\n var depthDigits = priorityNormalizeAndClamp(\r\n this._depth,\r\n minimumPriority.depth,\r\n maximumPriority.depth\r\n );\r\n depthDigits = preferLeaves ? 1.0 - depthDigits : depthDigits;\r\n\r\n // Map 0-1 then convert to digit. Include a distance sort when doing non-skipLOD and replacement refinement, helps things like non-skipLOD photogrammetry\r\n var useDistance =\r\n !tileset._skipLevelOfDetail && this.refine === Cesium3DTileRefine.REPLACE;\r\n var normalizedPreferredSorting = useDistance\r\n ? priorityNormalizeAndClamp(\r\n this._priorityHolder._distanceToCamera,\r\n minimumPriority.distance,\r\n maximumPriority.distance\r\n )\r\n : priorityNormalizeAndClamp(\r\n this._priorityReverseScreenSpaceError,\r\n minimumPriority.reverseScreenSpaceError,\r\n maximumPriority.reverseScreenSpaceError\r\n );\r\n var preferredSortingDigits = isolateDigits(\r\n normalizedPreferredSorting,\r\n preferredSortingDigitsCount,\r\n preferredSortingLeftShift\r\n );\r\n\r\n var preloadProgressiveResolutionDigits = this._priorityProgressiveResolution\r\n ? 0\r\n : preloadProgressiveResolutionScale;\r\n\r\n var normalizedFoveatedFactor = priorityNormalizeAndClamp(\r\n this._priorityHolder._foveatedFactor,\r\n minimumPriority.foveatedFactor,\r\n maximumPriority.foveatedFactor\r\n );\r\n var foveatedDigits = isolateDigits(\r\n normalizedFoveatedFactor,\r\n foveatedDigitsCount,\r\n foveatedLeftShift\r\n );\r\n\r\n var foveatedDeferDigits = this.priorityDeferred ? foveatedDeferScale : 0;\r\n\r\n var preloadFlightDigits =\r\n tileset._pass === Cesium3DTilePass.PRELOAD_FLIGHT ? 0 : preloadFlightScale;\r\n\r\n // Get the final base 10 number\r\n this._priority =\r\n depthDigits +\r\n preferredSortingDigits +\r\n preloadProgressiveResolutionDigits +\r\n foveatedDigits +\r\n foveatedDeferDigits +\r\n preloadFlightDigits;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCesium3DTile.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCesium3DTile.prototype.destroy = function () {\r\n // For the interval between new content being requested and downloaded, expiredContent === content, so don't destroy twice\r\n this._content = this._content && this._content.destroy();\r\n this._expiredContent =\r\n this._expiredContent &&\r\n !this._expiredContent.isDestroyed() &&\r\n this._expiredContent.destroy();\r\n this._debugBoundingVolume =\r\n this._debugBoundingVolume && this._debugBoundingVolume.destroy();\r\n this._debugContentBoundingVolume =\r\n this._debugContentBoundingVolume &&\r\n this._debugContentBoundingVolume.destroy();\r\n this._debugViewerRequestVolume =\r\n this._debugViewerRequestVolume && this._debugViewerRequestVolume.destroy();\r\n return destroyObject(this);\r\n};\r\nexport default Cesium3DTile;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Cesium3DTileOptimizationHint from \"./Cesium3DTileOptimizationHint.js\";\r\nimport TileBoundingRegion from \"./TileBoundingRegion.js\";\r\nimport TileOrientedBoundingBox from \"./TileOrientedBoundingBox.js\";\r\n\r\n/**\r\n * Utility functions for computing optimization hints for a {@link Cesium3DTileset}.\r\n *\r\n * @namespace Cesium3DTileOptimizations\r\n *\r\n * @private\r\n */\r\nvar Cesium3DTileOptimizations = {};\r\n\r\nvar scratchAxis = new Cartesian3();\r\n\r\n/**\r\n * Evaluates support for the childrenWithinParent optimization. This is used to more tightly cull tilesets if\r\n * children bounds are fully contained within the parent. Currently, support for the optimization only works for\r\n * oriented bounding boxes, so both the child and parent tile must be either a {@link TileOrientedBoundingBox} or\r\n * {@link TileBoundingRegion}. The purpose of this check is to prevent use of a culling optimization when the child\r\n * bounds exceed those of the parent. If the child bounds are greater, it is more likely that the optimization will\r\n * waste CPU cycles. Bounding spheres are not supported for the reason that the child bounds can very often be\r\n * partially outside of the parent bounds.\r\n *\r\n * @param {Cesium3DTile} tile The tile to check.\r\n * @returns {Boolean} Whether the childrenWithinParent optimization is supported.\r\n */\r\nCesium3DTileOptimizations.checkChildrenWithinParent = function (tile) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"tile\", tile);\r\n //>>includeEnd('debug');\r\n\r\n var children = tile.children;\r\n var length = children.length;\r\n\r\n // Check if the parent has an oriented bounding box.\r\n var boundingVolume = tile.boundingVolume;\r\n if (\r\n boundingVolume instanceof TileOrientedBoundingBox ||\r\n boundingVolume instanceof TileBoundingRegion\r\n ) {\r\n var orientedBoundingBox = boundingVolume._orientedBoundingBox;\r\n tile._optimChildrenWithinParent =\r\n Cesium3DTileOptimizationHint.USE_OPTIMIZATION;\r\n for (var i = 0; i < length; ++i) {\r\n var child = children[i];\r\n\r\n // Check if the child has an oriented bounding box.\r\n var childBoundingVolume = child.boundingVolume;\r\n if (\r\n !(\r\n childBoundingVolume instanceof TileOrientedBoundingBox ||\r\n childBoundingVolume instanceof TileBoundingRegion\r\n )\r\n ) {\r\n // Do not support if the parent and child both do not have oriented bounding boxes.\r\n tile._optimChildrenWithinParent =\r\n Cesium3DTileOptimizationHint.SKIP_OPTIMIZATION;\r\n break;\r\n }\r\n\r\n var childOrientedBoundingBox = childBoundingVolume._orientedBoundingBox;\r\n\r\n // Compute the axis from the parent to the child.\r\n var axis = Cartesian3.subtract(\r\n childOrientedBoundingBox.center,\r\n orientedBoundingBox.center,\r\n scratchAxis\r\n );\r\n var axisLength = Cartesian3.magnitude(axis);\r\n Cartesian3.divideByScalar(axis, axisLength, axis);\r\n\r\n // Project the bounding box of the parent onto the axis. Because the axis is a ray from the parent\r\n // to the child, the projection parameterized along the ray will be (+/- proj1).\r\n var proj1 =\r\n Math.abs(orientedBoundingBox.halfAxes[0] * axis.x) +\r\n Math.abs(orientedBoundingBox.halfAxes[1] * axis.y) +\r\n Math.abs(orientedBoundingBox.halfAxes[2] * axis.z) +\r\n Math.abs(orientedBoundingBox.halfAxes[3] * axis.x) +\r\n Math.abs(orientedBoundingBox.halfAxes[4] * axis.y) +\r\n Math.abs(orientedBoundingBox.halfAxes[5] * axis.z) +\r\n Math.abs(orientedBoundingBox.halfAxes[6] * axis.x) +\r\n Math.abs(orientedBoundingBox.halfAxes[7] * axis.y) +\r\n Math.abs(orientedBoundingBox.halfAxes[8] * axis.z);\r\n\r\n // Project the bounding box of the child onto the axis. Because the axis is a ray from the parent\r\n // to the child, the projection parameterized along the ray will be (+/- proj2) + axis.length.\r\n var proj2 =\r\n Math.abs(childOrientedBoundingBox.halfAxes[0] * axis.x) +\r\n Math.abs(childOrientedBoundingBox.halfAxes[1] * axis.y) +\r\n Math.abs(childOrientedBoundingBox.halfAxes[2] * axis.z) +\r\n Math.abs(childOrientedBoundingBox.halfAxes[3] * axis.x) +\r\n Math.abs(childOrientedBoundingBox.halfAxes[4] * axis.y) +\r\n Math.abs(childOrientedBoundingBox.halfAxes[5] * axis.z) +\r\n Math.abs(childOrientedBoundingBox.halfAxes[6] * axis.x) +\r\n Math.abs(childOrientedBoundingBox.halfAxes[7] * axis.y) +\r\n Math.abs(childOrientedBoundingBox.halfAxes[8] * axis.z);\r\n\r\n // If the child extends the parent's bounds, the optimization is not valid and we skip it.\r\n if (proj1 <= proj2 + axisLength) {\r\n tile._optimChildrenWithinParent =\r\n Cesium3DTileOptimizationHint.SKIP_OPTIMIZATION;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return (\r\n tile._optimChildrenWithinParent ===\r\n Cesium3DTileOptimizationHint.USE_OPTIMIZATION\r\n );\r\n};\r\nexport default Cesium3DTileOptimizations;\r\n","import defined from \"../Core/defined.js\";\r\nimport DoublyLinkedList from \"../Core/DoublyLinkedList.js\";\r\n\r\n/**\r\n * Stores tiles with content loaded.\r\n *\r\n * @private\r\n */\r\nfunction Cesium3DTilesetCache() {\r\n // [head, sentinel) -> tiles that weren't selected this frame and may be removed from the cache\r\n // (sentinel, tail] -> tiles that were selected this frame\r\n this._list = new DoublyLinkedList();\r\n this._sentinel = this._list.add();\r\n this._trimTiles = false;\r\n}\r\n\r\nCesium3DTilesetCache.prototype.reset = function () {\r\n // Move sentinel node to the tail so, at the start of the frame, all tiles\r\n // may be potentially replaced. Tiles are moved to the right of the sentinel\r\n // when they are selected so they will not be replaced.\r\n this._list.splice(this._list.tail, this._sentinel);\r\n};\r\n\r\nCesium3DTilesetCache.prototype.touch = function (tile) {\r\n var node = tile.cacheNode;\r\n if (defined(node)) {\r\n this._list.splice(this._sentinel, node);\r\n }\r\n};\r\n\r\nCesium3DTilesetCache.prototype.add = function (tile) {\r\n if (!defined(tile.cacheNode)) {\r\n tile.cacheNode = this._list.add(tile);\r\n }\r\n};\r\n\r\nCesium3DTilesetCache.prototype.unloadTile = function (\r\n tileset,\r\n tile,\r\n unloadCallback\r\n) {\r\n var node = tile.cacheNode;\r\n if (!defined(node)) {\r\n return;\r\n }\r\n\r\n this._list.remove(node);\r\n tile.cacheNode = undefined;\r\n unloadCallback(tileset, tile);\r\n};\r\n\r\nCesium3DTilesetCache.prototype.unloadTiles = function (\r\n tileset,\r\n unloadCallback\r\n) {\r\n var trimTiles = this._trimTiles;\r\n this._trimTiles = false;\r\n\r\n var list = this._list;\r\n\r\n var maximumMemoryUsageInBytes = tileset.maximumMemoryUsage * 1024 * 1024;\r\n\r\n // Traverse the list only to the sentinel since tiles/nodes to the\r\n // right of the sentinel were used this frame.\r\n //\r\n // The sub-list to the left of the sentinel is ordered from LRU to MRU.\r\n var sentinel = this._sentinel;\r\n var node = list.head;\r\n while (\r\n node !== sentinel &&\r\n (tileset.totalMemoryUsageInBytes > maximumMemoryUsageInBytes || trimTiles)\r\n ) {\r\n var tile = node.item;\r\n node = node.next;\r\n this.unloadTile(tileset, tile, unloadCallback);\r\n }\r\n};\r\n\r\nCesium3DTilesetCache.prototype.trim = function () {\r\n this._trimTiles = true;\r\n};\r\nexport default Cesium3DTilesetCache;\r\n","import Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\n\r\n/**\r\n * A heatmap colorizer in a {@link Cesium3DTileset}. A tileset can colorize its visible tiles in a heatmap style.\r\n *\r\n * @alias Cesium3DTilesetHeatmap\r\n * @constructor\r\n * @private\r\n */\r\nfunction Cesium3DTilesetHeatmap(tilePropertyName) {\r\n /**\r\n * The tile variable to track for heatmap colorization.\r\n * Tile's will be colorized relative to the other visible tile's values for this variable.\r\n *\r\n * @type {String}\r\n */\r\n this.tilePropertyName = tilePropertyName;\r\n\r\n // Members that are updated every time a tile is colorized\r\n this._minimum = Number.MAX_VALUE;\r\n this._maximum = -Number.MAX_VALUE;\r\n\r\n // Members that are updated once every frame\r\n this._previousMinimum = Number.MAX_VALUE;\r\n this._previousMaximum = -Number.MAX_VALUE;\r\n\r\n // If defined uses a reference minimum maximum to colorize by instead of using last frames minimum maximum of rendered tiles.\r\n // For example, the _loadTimestamp can get a better colorization using setReferenceMinimumMaximum in order to take accurate colored timing diffs of various scenes.\r\n this._referenceMinimum = {};\r\n this._referenceMaximum = {};\r\n}\r\n\r\n/**\r\n * Convert to a usable heatmap value (i.e. a number). Ensures that tile values that aren't stored as numbers can be used for colorization.\r\n * @private\r\n */\r\nfunction getHeatmapValue(tileValue, tilePropertyName) {\r\n var value;\r\n if (tilePropertyName === \"_loadTimestamp\") {\r\n value = JulianDate.toDate(tileValue).getTime();\r\n } else {\r\n value = tileValue;\r\n }\r\n return value;\r\n}\r\n\r\n/**\r\n * Sets the reference minimum and maximum for the variable name. Converted to numbers before they are stored.\r\n *\r\n * @param {Object} minimum The minimum reference value.\r\n * @param {Object} maximum The maximum reference value.\r\n * @param {String} tilePropertyName The tile variable that will use these reference values when it is colorized.\r\n */\r\nCesium3DTilesetHeatmap.prototype.setReferenceMinimumMaximum = function (\r\n minimum,\r\n maximum,\r\n tilePropertyName\r\n) {\r\n this._referenceMinimum[tilePropertyName] = getHeatmapValue(\r\n minimum,\r\n tilePropertyName\r\n );\r\n this._referenceMaximum[tilePropertyName] = getHeatmapValue(\r\n maximum,\r\n tilePropertyName\r\n );\r\n};\r\n\r\nfunction getHeatmapValueAndUpdateMinimumMaximum(heatmap, tile) {\r\n var tilePropertyName = heatmap.tilePropertyName;\r\n if (defined(tilePropertyName)) {\r\n var heatmapValue = getHeatmapValue(\r\n tile[tilePropertyName],\r\n tilePropertyName\r\n );\r\n if (!defined(heatmapValue)) {\r\n heatmap.tilePropertyName = undefined;\r\n return heatmapValue;\r\n }\r\n heatmap._maximum = Math.max(heatmapValue, heatmap._maximum);\r\n heatmap._minimum = Math.min(heatmapValue, heatmap._minimum);\r\n return heatmapValue;\r\n }\r\n}\r\n\r\nvar heatmapColors = [\r\n new Color(0.1, 0.1, 0.1, 1), // Dark Gray\r\n new Color(0.153, 0.278, 0.878, 1), // Blue\r\n new Color(0.827, 0.231, 0.49, 1), // Pink\r\n new Color(0.827, 0.188, 0.22, 1), // Red\r\n new Color(1.0, 0.592, 0.259, 1), // Orange\r\n new Color(1.0, 0.843, 0.0, 1),\r\n]; // Yellow\r\n/**\r\n * Colorize the tile in heat map style based on where it lies within the minimum maximum window.\r\n * Heatmap colors are black, blue, pink, red, orange, yellow. 'Cold' or low numbers will be black and blue, 'Hot' or high numbers will be orange and yellow,\r\n * @param {Cesium3DTile} tile The tile to colorize relative to last frame's minimum and maximum values of all visible tiles.\r\n * @param {FrameState} frameState The frame state.\r\n */\r\nCesium3DTilesetHeatmap.prototype.colorize = function (tile, frameState) {\r\n var tilePropertyName = this.tilePropertyName;\r\n if (\r\n !defined(tilePropertyName) ||\r\n !tile.contentAvailable ||\r\n tile._selectedFrame !== frameState.frameNumber\r\n ) {\r\n return;\r\n }\r\n\r\n var heatmapValue = getHeatmapValueAndUpdateMinimumMaximum(this, tile);\r\n var minimum = this._previousMinimum;\r\n var maximum = this._previousMaximum;\r\n\r\n if (minimum === Number.MAX_VALUE || maximum === -Number.MAX_VALUE) {\r\n return;\r\n }\r\n\r\n // Shift the minimum maximum window down to 0\r\n var shiftedMax = maximum - minimum + CesiumMath.EPSILON7; // Prevent divide by 0\r\n var shiftedValue = CesiumMath.clamp(heatmapValue - minimum, 0.0, shiftedMax);\r\n\r\n // Get position between minimum and maximum and convert that to a position in the color array\r\n var zeroToOne = shiftedValue / shiftedMax;\r\n var lastIndex = heatmapColors.length - 1.0;\r\n var colorPosition = zeroToOne * lastIndex;\r\n\r\n // Take floor and ceil of the value to get the two colors to lerp between, lerp using the fractional portion\r\n var colorPositionFloor = Math.floor(colorPosition);\r\n var colorPositionCeil = Math.ceil(colorPosition);\r\n var t = colorPosition - colorPositionFloor;\r\n var colorZero = heatmapColors[colorPositionFloor];\r\n var colorOne = heatmapColors[colorPositionCeil];\r\n\r\n // Perform the lerp\r\n var finalColor = Color.clone(Color.WHITE);\r\n finalColor.red = CesiumMath.lerp(colorZero.red, colorOne.red, t);\r\n finalColor.green = CesiumMath.lerp(colorZero.green, colorOne.green, t);\r\n finalColor.blue = CesiumMath.lerp(colorZero.blue, colorOne.blue, t);\r\n tile._debugColor = finalColor;\r\n};\r\n\r\n/**\r\n * Resets the tracked minimum maximum values for heatmap colorization. Happens right before tileset traversal.\r\n */\r\nCesium3DTilesetHeatmap.prototype.resetMinimumMaximum = function () {\r\n // For heat map colorization\r\n var tilePropertyName = this.tilePropertyName;\r\n if (defined(tilePropertyName)) {\r\n var referenceMinimum = this._referenceMinimum[tilePropertyName];\r\n var referenceMaximum = this._referenceMaximum[tilePropertyName];\r\n var useReference = defined(referenceMinimum) && defined(referenceMaximum);\r\n this._previousMinimum = useReference ? referenceMinimum : this._minimum;\r\n this._previousMaximum = useReference ? referenceMaximum : this._maximum;\r\n this._minimum = Number.MAX_VALUE;\r\n this._maximum = -Number.MAX_VALUE;\r\n }\r\n};\r\nexport default Cesium3DTilesetHeatmap;\r\n","import defined from \"../Core/defined.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Cesium3DTilesetStatistics() {\r\n // Rendering statistics\r\n this.selected = 0;\r\n this.visited = 0;\r\n // Loading statistics\r\n this.numberOfCommands = 0;\r\n this.numberOfAttemptedRequests = 0;\r\n this.numberOfPendingRequests = 0;\r\n this.numberOfTilesProcessing = 0;\r\n this.numberOfTilesWithContentReady = 0; // Number of tiles with content loaded, does not include empty tiles\r\n this.numberOfTilesTotal = 0; // Number of tiles in tileset JSON (and other tileset JSON files as they are loaded)\r\n this.numberOfLoadedTilesTotal = 0; // Running total of loaded tiles for the lifetime of the session\r\n // Features statistics\r\n this.numberOfFeaturesSelected = 0; // Number of features rendered\r\n this.numberOfFeaturesLoaded = 0; // Number of features in memory\r\n this.numberOfPointsSelected = 0;\r\n this.numberOfPointsLoaded = 0;\r\n this.numberOfTrianglesSelected = 0;\r\n // Styling statistics\r\n this.numberOfTilesStyled = 0;\r\n this.numberOfFeaturesStyled = 0;\r\n // Optimization statistics\r\n this.numberOfTilesCulledWithChildrenUnion = 0;\r\n // Memory statistics\r\n this.geometryByteLength = 0;\r\n this.texturesByteLength = 0;\r\n this.batchTableByteLength = 0;\r\n}\r\n\r\nCesium3DTilesetStatistics.prototype.clear = function () {\r\n this.selected = 0;\r\n this.visited = 0;\r\n this.numberOfCommands = 0;\r\n this.numberOfAttemptedRequests = 0;\r\n this.numberOfFeaturesSelected = 0;\r\n this.numberOfPointsSelected = 0;\r\n this.numberOfTrianglesSelected = 0;\r\n this.numberOfTilesStyled = 0;\r\n this.numberOfFeaturesStyled = 0;\r\n this.numberOfTilesCulledWithChildrenUnion = 0;\r\n};\r\n\r\nfunction updatePointAndFeatureCounts(statistics, content, decrement, load) {\r\n var contents = content.innerContents;\r\n var pointsLength = content.pointsLength;\r\n var trianglesLength = content.trianglesLength;\r\n var featuresLength = content.featuresLength;\r\n var geometryByteLength = content.geometryByteLength;\r\n var texturesByteLength = content.texturesByteLength;\r\n var batchTableByteLength = content.batchTableByteLength;\r\n\r\n if (load) {\r\n statistics.numberOfFeaturesLoaded += decrement\r\n ? -featuresLength\r\n : featuresLength;\r\n statistics.numberOfPointsLoaded += decrement ? -pointsLength : pointsLength;\r\n statistics.geometryByteLength += decrement\r\n ? -geometryByteLength\r\n : geometryByteLength;\r\n statistics.texturesByteLength += decrement\r\n ? -texturesByteLength\r\n : texturesByteLength;\r\n statistics.batchTableByteLength += decrement\r\n ? -batchTableByteLength\r\n : batchTableByteLength;\r\n } else {\r\n statistics.numberOfFeaturesSelected += decrement\r\n ? -featuresLength\r\n : featuresLength;\r\n statistics.numberOfPointsSelected += decrement\r\n ? -pointsLength\r\n : pointsLength;\r\n statistics.numberOfTrianglesSelected += decrement\r\n ? -trianglesLength\r\n : trianglesLength;\r\n }\r\n\r\n if (defined(contents)) {\r\n var length = contents.length;\r\n for (var i = 0; i < length; ++i) {\r\n updatePointAndFeatureCounts(statistics, contents[i], decrement, load);\r\n }\r\n }\r\n}\r\n\r\nCesium3DTilesetStatistics.prototype.incrementSelectionCounts = function (\r\n content\r\n) {\r\n updatePointAndFeatureCounts(this, content, false, false);\r\n};\r\n\r\nCesium3DTilesetStatistics.prototype.incrementLoadCounts = function (content) {\r\n updatePointAndFeatureCounts(this, content, false, true);\r\n};\r\n\r\nCesium3DTilesetStatistics.prototype.decrementLoadCounts = function (content) {\r\n updatePointAndFeatureCounts(this, content, true, true);\r\n};\r\n\r\nCesium3DTilesetStatistics.clone = function (statistics, result) {\r\n result.selected = statistics.selected;\r\n result.visited = statistics.visited;\r\n result.numberOfCommands = statistics.numberOfCommands;\r\n result.selected = statistics.selected;\r\n result.numberOfAttemptedRequests = statistics.numberOfAttemptedRequests;\r\n result.numberOfPendingRequests = statistics.numberOfPendingRequests;\r\n result.numberOfTilesProcessing = statistics.numberOfTilesProcessing;\r\n result.numberOfTilesWithContentReady =\r\n statistics.numberOfTilesWithContentReady;\r\n result.numberOfTilesTotal = statistics.numberOfTilesTotal;\r\n result.numberOfFeaturesSelected = statistics.numberOfFeaturesSelected;\r\n result.numberOfFeaturesLoaded = statistics.numberOfFeaturesLoaded;\r\n result.numberOfPointsSelected = statistics.numberOfPointsSelected;\r\n result.numberOfPointsLoaded = statistics.numberOfPointsLoaded;\r\n result.numberOfTrianglesSelected = statistics.numberOfTrianglesSelected;\r\n result.numberOfTilesStyled = statistics.numberOfTilesStyled;\r\n result.numberOfFeaturesStyled = statistics.numberOfFeaturesStyled;\r\n result.numberOfTilesCulledWithChildrenUnion =\r\n statistics.numberOfTilesCulledWithChildrenUnion;\r\n result.geometryByteLength = statistics.geometryByteLength;\r\n result.texturesByteLength = statistics.texturesByteLength;\r\n result.batchTableByteLength = statistics.batchTableByteLength;\r\n};\r\nexport default Cesium3DTilesetStatistics;\r\n","import defined from \"../Core/defined.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction Cesium3DTileStyleEngine() {\r\n this._style = undefined; // The style provided by the user\r\n this._styleDirty = false; // true when the style is reassigned\r\n this._lastStyleTime = 0; // The \"time\" when the last style was assigned\r\n}\r\n\r\nObject.defineProperties(Cesium3DTileStyleEngine.prototype, {\r\n style: {\r\n get: function () {\r\n return this._style;\r\n },\r\n set: function (value) {\r\n if (value === this._style) {\r\n return;\r\n }\r\n this._style = value;\r\n this._styleDirty = true;\r\n },\r\n },\r\n});\r\n\r\nCesium3DTileStyleEngine.prototype.makeDirty = function () {\r\n this._styleDirty = true;\r\n};\r\n\r\nCesium3DTileStyleEngine.prototype.resetDirty = function () {\r\n this._styleDirty = false;\r\n};\r\n\r\nCesium3DTileStyleEngine.prototype.applyStyle = function (tileset) {\r\n if (!tileset.ready) {\r\n return;\r\n }\r\n\r\n if (defined(this._style) && !this._style.ready) {\r\n return;\r\n }\r\n\r\n var styleDirty = this._styleDirty;\r\n\r\n if (styleDirty) {\r\n // Increase \"time\", so the style is applied to all visible tiles\r\n ++this._lastStyleTime;\r\n }\r\n\r\n var lastStyleTime = this._lastStyleTime;\r\n var statistics = tileset._statistics;\r\n\r\n // If a new style was assigned, loop through all the visible tiles; otherwise, loop through\r\n // only the tiles that are newly visible, i.e., they are visible this frame, but were not\r\n // visible last frame. In many cases, the newly selected tiles list will be short or empty.\r\n var tiles = styleDirty\r\n ? tileset._selectedTiles\r\n : tileset._selectedTilesToStyle;\r\n // PERFORMANCE_IDEA: does mouse-over picking basically trash this? We need to style on\r\n // pick, for example, because a feature's show may be false.\r\n\r\n var length = tiles.length;\r\n for (var i = 0; i < length; ++i) {\r\n var tile = tiles[i];\r\n if (tile.lastStyleTime !== lastStyleTime) {\r\n // Apply the style to this tile if it wasn't already applied because:\r\n // 1) the user assigned a new style to the tileset\r\n // 2) this tile is now visible, but it wasn't visible when the style was first assigned\r\n var content = tile.content;\r\n tile.lastStyleTime = lastStyleTime;\r\n content.applyStyle(this._style);\r\n statistics.numberOfFeaturesStyled += content.featuresLength;\r\n ++statistics.numberOfTilesStyled;\r\n }\r\n }\r\n};\r\nexport default Cesium3DTileStyleEngine;\r\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Credit from \"../Core/Credit.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport deprecationWarning from \"../Core/deprecationWarning.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport ManagedArray from \"../Core/ManagedArray.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport ClearCommand from \"../Renderer/ClearCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport Axis from \"./Axis.js\";\r\nimport Cesium3DTile from \"./Cesium3DTile.js\";\r\nimport Cesium3DTileColorBlendMode from \"./Cesium3DTileColorBlendMode.js\";\r\nimport Cesium3DTileContentState from \"./Cesium3DTileContentState.js\";\r\nimport Cesium3DTileOptimizations from \"./Cesium3DTileOptimizations.js\";\r\nimport Cesium3DTilePass from \"./Cesium3DTilePass.js\";\r\nimport Cesium3DTileRefine from \"./Cesium3DTileRefine.js\";\r\nimport Cesium3DTilesetCache from \"./Cesium3DTilesetCache.js\";\r\nimport Cesium3DTilesetHeatmap from \"./Cesium3DTilesetHeatmap.js\";\r\nimport Cesium3DTilesetStatistics from \"./Cesium3DTilesetStatistics.js\";\r\nimport Cesium3DTileStyleEngine from \"./Cesium3DTileStyleEngine.js\";\r\nimport ClippingPlaneCollection from \"./ClippingPlaneCollection.js\";\r\nimport LabelCollection from \"./LabelCollection.js\";\r\nimport PointCloudEyeDomeLighting from \"./PointCloudEyeDomeLighting.js\";\r\nimport PointCloudShading from \"./PointCloudShading.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport ShadowMode from \"./ShadowMode.js\";\r\nimport StencilConstants from \"./StencilConstants.js\";\r\nimport TileBoundingRegion from \"./TileBoundingRegion.js\";\r\nimport TileBoundingSphere from \"./TileBoundingSphere.js\";\r\nimport TileOrientedBoundingBox from \"./TileOrientedBoundingBox.js\";\r\n\r\n/**\r\n * A {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles tileset},\r\n * used for streaming massive heterogeneous 3D geospatial datasets.\r\n *\r\n * @alias Cesium3DTileset\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Resource|String|Promise|Promise} options.url The url to a tileset JSON file.\r\n * @param {Boolean} [options.show=true] Determines if the tileset will be shown.\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] A 4x4 transformation matrix that transforms the tileset's root tile.\r\n * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the tileset casts or receives shadows from light sources.\r\n * @param {Number} [options.maximumScreenSpaceError=16] The maximum screen space error used to drive level of detail refinement.\r\n * @param {Number} [options.maximumMemoryUsage=512] The maximum amount of memory in MB that can be used by the tileset.\r\n * @param {Boolean} [options.cullWithChildrenBounds=true] Optimization option. Whether to cull tiles using the union of their children bounding volumes.\r\n * @param {Boolean} [options.cullRequestsWhileMoving=true] Optimization option. Don't request tiles that will likely be unused when they come back because of the camera's movement. This optimization only applies to stationary tilesets.\r\n * @param {Number} [options.cullRequestsWhileMovingMultiplier=60.0] Optimization option. Multiplier used in culling requests while moving. Larger is more aggressive culling, smaller less aggressive culling.\r\n * @param {Boolean} [options.preloadWhenHidden=false] Preload tiles when tileset.show is false. Loads tiles as if the tileset is visible but does not render them.\r\n * @param {Boolean} [options.preloadFlightDestinations=true] Optimization option. Preload tiles at the camera's flight destination while the camera is in flight.\r\n * @param {Boolean} [options.preferLeaves=false] Optimization option. Prefer loading of leaves first.\r\n * @param {Boolean} [options.dynamicScreenSpaceError=false] Optimization option. Reduce the screen space error for tiles that are further away from the camera.\r\n * @param {Number} [options.dynamicScreenSpaceErrorDensity=0.00278] Density used to adjust the dynamic screen space error, similar to fog density.\r\n * @param {Number} [options.dynamicScreenSpaceErrorFactor=4.0] A factor used to increase the computed dynamic screen space error.\r\n * @param {Number} [options.dynamicScreenSpaceErrorHeightFalloff=0.25] A ratio of the tileset's height at which the density starts to falloff.\r\n * @param {Number} [options.progressiveResolutionHeightFraction=0.3] Optimization option. If between (0.0, 0.5], tiles at or above the screen space error for the reduced screen resolution of progressiveResolutionHeightFraction*screenHeight will be prioritized first. This can help get a quick layer of tiles down while full resolution tiles continue to load.\r\n * @param {Boolean} [options.foveatedScreenSpaceError=true] Optimization option. Prioritize loading tiles in the center of the screen by temporarily raising the screen space error for tiles around the edge of the screen. Screen space error returns to normal once all the tiles in the center of the screen as determined by the {@link Cesium3DTileset#foveatedConeSize} are loaded.\r\n * @param {Number} [options.foveatedConeSize=0.1] Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control the cone size that determines which tiles are deferred. Tiles that are inside this cone are loaded immediately. Tiles outside the cone are potentially deferred based on how far outside the cone they are and their screen space error. This is controlled by {@link Cesium3DTileset#foveatedInterpolationCallback} and {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation}. Setting this to 0.0 means the cone will be the line formed by the camera position and its view direction. Setting this to 1.0 means the cone encompasses the entire field of view of the camera, disabling the effect.\r\n * @param {Number} [options.foveatedMinimumScreenSpaceErrorRelaxation=0.0] Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control the starting screen space error relaxation for tiles outside the foveated cone. The screen space error will be raised starting with tileset value up to {@link Cesium3DTileset#maximumScreenSpaceError} based on the provided {@link Cesium3DTileset#foveatedInterpolationCallback}.\r\n * @param {Cesium3DTileset.foveatedInterpolationCallback} [options.foveatedInterpolationCallback=Math.lerp] Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control how much to raise the screen space error for tiles outside the foveated cone, interpolating between {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation} and {@link Cesium3DTileset#maximumScreenSpaceError}\r\n * @param {Number} [options.foveatedTimeDelay=0.2] Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control how long in seconds to wait after the camera stops moving before deferred tiles start loading in. This time delay prevents requesting tiles around the edges of the screen when the camera is moving. Setting this to 0.0 will immediately request all tiles in any given view.\r\n * @param {Boolean} [options.skipLevelOfDetail=false] Optimization option. Determines if level of detail skipping should be applied during the traversal.\r\n * @param {Number} [options.baseScreenSpaceError=1024] When skipLevelOfDetail is true, the screen space error that must be reached before skipping levels of detail.\r\n * @param {Number} [options.skipScreenSpaceErrorFactor=16] When skipLevelOfDetail is true, a multiplier defining the minimum screen space error to skip. Used in conjunction with skipLevels to determine which tiles to load.\r\n * @param {Number} [options.skipLevels=1] When skipLevelOfDetail is true, a constant defining the minimum number of levels to skip when loading tiles. When it is 0, no levels are skipped. Used in conjunction with skipScreenSpaceErrorFactor to determine which tiles to load.\r\n * @param {Boolean} [options.immediatelyLoadDesiredLevelOfDetail=false] When skipLevelOfDetail is true, only tiles that meet the maximum screen space error will ever be downloaded. Skipping factors are ignored and just the desired tiles are loaded.\r\n * @param {Boolean} [options.loadSiblings=false] When skipLevelOfDetail is true, determines whether siblings of visible tiles are always downloaded during traversal.\r\n * @param {ClippingPlaneCollection} [options.clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the tileset.\r\n * @param {ClassificationType} [options.classificationType] Determines whether terrain, 3D Tiles or both will be classified by this tileset. See {@link Cesium3DTileset#classificationType} for details about restrictions and limitations.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid determining the size and shape of the globe.\r\n * @param {Object} [options.pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting.\r\n * @param {Cartesian2} [options.imageBasedLightingFactor=new Cartesian2(1.0, 1.0)] Scales the diffuse and specular image-based lighting from the earth, sky, atmosphere and star skybox.\r\n * @param {Cartesian3} [options.lightColor] The light color when shading models. When undefined the scene's light color is used instead.\r\n * @param {Number} [options.luminanceAtZenith=0.2] The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map.\r\n * @param {Cartesian3[]} [options.sphericalHarmonicCoefficients] The third order spherical harmonic coefficients used for the diffuse color of image-based lighting.\r\n * @param {String} [options.specularEnvironmentMaps] A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.\r\n * @param {Boolean} [options.backFaceCulling=true] Whether to cull back-facing geometry. When true, back face culling is determined by the glTF material's doubleSided property; when false, back face culling is disabled.\r\n * @param {Boolean} [options.vectorClassificationOnly=false] Indicates that only the tileset's vector tiles should be used for classification.\r\n * @param {String} [options.debugHeatmapTilePropertyName] The tile variable to colorize as a heatmap. All rendered tiles will be colorized relative to each other's specified variable value.\r\n * @param {Boolean} [options.debugFreezeFrame=false] For debugging only. Determines if only the tiles from last frame should be used for rendering.\r\n * @param {Boolean} [options.debugColorizeTiles=false] For debugging only. When true, assigns a random color to each tile.\r\n * @param {Boolean} [options.debugWireframe=false] For debugging only. When true, render's each tile's content as a wireframe.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. When true, renders the bounding volume for each tile.\r\n * @param {Boolean} [options.debugShowContentBoundingVolume=false] For debugging only. When true, renders the bounding volume for each tile's content.\r\n * @param {Boolean} [options.debugShowViewerRequestVolume=false] For debugging only. When true, renders the viewer request volume for each tile.\r\n * @param {Boolean} [options.debugShowGeometricError=false] For debugging only. When true, draws labels to indicate the geometric error of each tile.\r\n * @param {Boolean} [options.debugShowRenderingStatistics=false] For debugging only. When true, draws labels to indicate the number of commands, points, triangles and features for each tile.\r\n * @param {Boolean} [options.debugShowMemoryUsage=false] For debugging only. When true, draws labels to indicate the texture and geometry memory in megabytes used by each tile.\r\n * @param {Boolean} [options.debugShowUrl=false] For debugging only. When true, draws labels to indicate the url of each tile.\r\n *\r\n * @exception {DeveloperError} The tileset must be 3D Tiles version 0.0 or 1.0.\r\n *\r\n * @example\r\n * var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({\r\n * url : 'http://localhost:8002/tilesets/Seattle/tileset.json'\r\n * }));\r\n *\r\n * @example\r\n * // Common setting for the skipLevelOfDetail optimization\r\n * var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({\r\n * url : 'http://localhost:8002/tilesets/Seattle/tileset.json',\r\n * skipLevelOfDetail : true,\r\n * baseScreenSpaceError : 1024,\r\n * skipScreenSpaceErrorFactor : 16,\r\n * skipLevels : 1,\r\n * immediatelyLoadDesiredLevelOfDetail : false,\r\n * loadSiblings : false,\r\n * cullWithChildrenBounds : true\r\n * }));\r\n *\r\n * @example\r\n * // Common settings for the dynamicScreenSpaceError optimization\r\n * var tileset = scene.primitives.add(new Cesium.Cesium3DTileset({\r\n * url : 'http://localhost:8002/tilesets/Seattle/tileset.json',\r\n * dynamicScreenSpaceError : true,\r\n * dynamicScreenSpaceErrorDensity : 0.00278,\r\n * dynamicScreenSpaceErrorFactor : 4.0,\r\n * dynamicScreenSpaceErrorHeightFalloff : 0.25\r\n * }));\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification|3D Tiles specification}\r\n */\r\nfunction Cesium3DTileset(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"options.url\", options.url);\r\n //>>includeEnd('debug');\r\n\r\n this._url = undefined;\r\n this._basePath = undefined;\r\n this._root = undefined;\r\n this._resource = undefined;\r\n this._asset = undefined; // Metadata for the entire tileset\r\n this._properties = undefined; // Metadata for per-model/point/etc properties\r\n this._geometricError = undefined; // Geometric error when the tree is not rendered at all\r\n this._extensionsUsed = undefined;\r\n this._extensions = undefined;\r\n this._gltfUpAxis = undefined;\r\n this._cache = new Cesium3DTilesetCache();\r\n this._processingQueue = [];\r\n this._selectedTiles = [];\r\n this._emptyTiles = [];\r\n this._requestedTiles = [];\r\n this._selectedTilesToStyle = [];\r\n this._loadTimestamp = undefined;\r\n this._timeSinceLoad = 0.0;\r\n this._updatedVisibilityFrame = 0;\r\n this._updatedModelMatrixFrame = 0;\r\n this._modelMatrixChanged = false;\r\n this._previousModelMatrix = undefined;\r\n this._extras = undefined;\r\n this._credits = undefined;\r\n\r\n this._cullWithChildrenBounds = defaultValue(\r\n options.cullWithChildrenBounds,\r\n true\r\n );\r\n this._allTilesAdditive = true;\r\n\r\n this._hasMixedContent = false;\r\n\r\n this._stencilClearCommand = undefined;\r\n this._backfaceCommands = new ManagedArray();\r\n\r\n this._maximumScreenSpaceError = defaultValue(\r\n options.maximumScreenSpaceError,\r\n 16\r\n );\r\n this._maximumMemoryUsage = defaultValue(options.maximumMemoryUsage, 512);\r\n\r\n this._styleEngine = new Cesium3DTileStyleEngine();\r\n\r\n this._modelMatrix = defined(options.modelMatrix)\r\n ? Matrix4.clone(options.modelMatrix)\r\n : Matrix4.clone(Matrix4.IDENTITY);\r\n\r\n this._statistics = new Cesium3DTilesetStatistics();\r\n this._statisticsLast = new Cesium3DTilesetStatistics();\r\n this._statisticsPerPass = new Array(Cesium3DTilePass.NUMBER_OF_PASSES);\r\n\r\n for (var i = 0; i < Cesium3DTilePass.NUMBER_OF_PASSES; ++i) {\r\n this._statisticsPerPass[i] = new Cesium3DTilesetStatistics();\r\n }\r\n\r\n this._requestedTilesInFlight = [];\r\n\r\n this._maximumPriority = {\r\n foveatedFactor: -Number.MAX_VALUE,\r\n depth: -Number.MAX_VALUE,\r\n distance: -Number.MAX_VALUE,\r\n reverseScreenSpaceError: -Number.MAX_VALUE,\r\n };\r\n this._minimumPriority = {\r\n foveatedFactor: Number.MAX_VALUE,\r\n depth: Number.MAX_VALUE,\r\n distance: Number.MAX_VALUE,\r\n reverseScreenSpaceError: Number.MAX_VALUE,\r\n };\r\n this._heatmap = new Cesium3DTilesetHeatmap(\r\n options.debugHeatmapTilePropertyName\r\n );\r\n\r\n /**\r\n * Optimization option. Don't request tiles that will likely be unused when they come back because of the camera's movement. This optimization only applies to stationary tilesets.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.cullRequestsWhileMoving = defaultValue(\r\n options.cullRequestsWhileMoving,\r\n true\r\n );\r\n this._cullRequestsWhileMoving = false;\r\n\r\n /**\r\n * Optimization option. Multiplier used in culling requests while moving. Larger is more aggressive culling, smaller less aggressive culling.\r\n *\r\n * @type {Number}\r\n * @default 60.0\r\n */\r\n this.cullRequestsWhileMovingMultiplier = defaultValue(\r\n options.cullRequestsWhileMovingMultiplier,\r\n 60.0\r\n );\r\n\r\n /**\r\n * Optimization option. If between (0.0, 0.5], tiles at or above the screen space error for the reduced screen resolution of progressiveResolutionHeightFraction*screenHeight will be prioritized first. This can help get a quick layer of tiles down while full resolution tiles continue to load.\r\n *\r\n * @type {Number}\r\n * @default 0.3\r\n */\r\n this.progressiveResolutionHeightFraction = CesiumMath.clamp(\r\n defaultValue(options.progressiveResolutionHeightFraction, 0.3),\r\n 0.0,\r\n 0.5\r\n );\r\n\r\n /**\r\n * Optimization option. Prefer loading of leaves first.\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.preferLeaves = defaultValue(options.preferLeaves, false);\r\n\r\n this._tilesLoaded = false;\r\n this._initialTilesLoaded = false;\r\n\r\n this._tileDebugLabels = undefined;\r\n\r\n this._readyPromise = when.defer();\r\n\r\n this._classificationType = options.classificationType;\r\n\r\n this._ellipsoid = defaultValue(options.ellipsoid, Ellipsoid.WGS84);\r\n\r\n this._initialClippingPlanesOriginMatrix = Matrix4.IDENTITY; // Computed from the tileset JSON.\r\n this._clippingPlanesOriginMatrix = undefined; // Combines the above with any run-time transforms.\r\n this._clippingPlanesOriginMatrixDirty = true;\r\n\r\n this._vectorClassificationOnly = defaultValue(\r\n options.vectorClassificationOnly,\r\n false\r\n );\r\n\r\n /**\r\n * Preload tiles when tileset.show is false. Loads tiles as if the tileset is visible but does not render them.\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.preloadWhenHidden = defaultValue(options.preloadWhenHidden, false);\r\n\r\n /**\r\n * Optimization option. Fetch tiles at the camera's flight destination while the camera is in flight.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.preloadFlightDestinations = defaultValue(\r\n options.preloadFlightDestinations,\r\n true\r\n );\r\n this._pass = undefined; // Cesium3DTilePass\r\n\r\n /**\r\n * Optimization option. Whether the tileset should refine based on a dynamic screen space error. Tiles that are further\r\n * away will be rendered with lower detail than closer tiles. This improves performance by rendering fewer\r\n * tiles and making less requests, but may result in a slight drop in visual quality for tiles in the distance.\r\n * The algorithm is biased towards \"street views\" where the camera is close to the ground plane of the tileset and looking\r\n * at the horizon. In addition results are more accurate for tightly fitting bounding volumes like box and region.\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.dynamicScreenSpaceError = defaultValue(\r\n options.dynamicScreenSpaceError,\r\n false\r\n );\r\n\r\n /**\r\n * Optimization option. Prioritize loading tiles in the center of the screen by temporarily raising the\r\n * screen space error for tiles around the edge of the screen. Screen space error returns to normal once all\r\n * the tiles in the center of the screen as determined by the {@link Cesium3DTileset#foveatedConeSize} are loaded.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.foveatedScreenSpaceError = defaultValue(\r\n options.foveatedScreenSpaceError,\r\n true\r\n );\r\n this._foveatedConeSize = defaultValue(options.foveatedConeSize, 0.1);\r\n this._foveatedMinimumScreenSpaceErrorRelaxation = defaultValue(\r\n options.foveatedMinimumScreenSpaceErrorRelaxation,\r\n 0.0\r\n );\r\n\r\n /**\r\n * Gets or sets a callback to control how much to raise the screen space error for tiles outside the foveated cone,\r\n * interpolating between {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation} and {@link Cesium3DTileset#maximumScreenSpaceError}.\r\n *\r\n * @type {Cesium3DTileset.foveatedInterpolationCallback}\r\n */\r\n this.foveatedInterpolationCallback = defaultValue(\r\n options.foveatedInterpolationCallback,\r\n CesiumMath.lerp\r\n );\r\n\r\n /**\r\n * Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control\r\n * how long in seconds to wait after the camera stops moving before deferred tiles start loading in.\r\n * This time delay prevents requesting tiles around the edges of the screen when the camera is moving.\r\n * Setting this to 0.0 will immediately request all tiles in any given view.\r\n *\r\n * @type {Number}\r\n * @default 0.2\r\n */\r\n this.foveatedTimeDelay = defaultValue(options.foveatedTimeDelay, 0.2);\r\n\r\n /**\r\n * A scalar that determines the density used to adjust the dynamic screen space error, similar to {@link Fog}. Increasing this\r\n * value has the effect of increasing the maximum screen space error for all tiles, but in a non-linear fashion.\r\n * The error starts at 0.0 and increases exponentially until a midpoint is reached, and then approaches 1.0 asymptotically.\r\n * This has the effect of keeping high detail in the closer tiles and lower detail in the further tiles, with all tiles\r\n * beyond a certain distance all roughly having an error of 1.0.\r\n *

\r\n * The dynamic error is in the range [0.0, 1.0) and is multiplied by dynamicScreenSpaceErrorFactor to produce the\r\n * final dynamic error. This dynamic error is then subtracted from the tile's actual screen space error.\r\n *

\r\n *

\r\n * Increasing dynamicScreenSpaceErrorDensity has the effect of moving the error midpoint closer to the camera.\r\n * It is analogous to moving fog closer to the camera.\r\n *

\r\n *\r\n * @type {Number}\r\n * @default 0.00278\r\n */\r\n this.dynamicScreenSpaceErrorDensity = 0.00278;\r\n\r\n /**\r\n * A factor used to increase the screen space error of tiles for dynamic screen space error. As this value increases less tiles\r\n * are requested for rendering and tiles in the distance will have lower detail. If set to zero, the feature will be disabled.\r\n *\r\n * @type {Number}\r\n * @default 4.0\r\n */\r\n this.dynamicScreenSpaceErrorFactor = 4.0;\r\n\r\n /**\r\n * A ratio of the tileset's height at which the density starts to falloff. If the camera is below this height the\r\n * full computed density is applied, otherwise the density falls off. This has the effect of higher density at\r\n * street level views.\r\n *

\r\n * Valid values are between 0.0 and 1.0.\r\n *

\r\n *\r\n * @type {Number}\r\n * @default 0.25\r\n */\r\n this.dynamicScreenSpaceErrorHeightFalloff = 0.25;\r\n\r\n this._dynamicScreenSpaceErrorComputedDensity = 0.0; // Updated based on the camera position and direction\r\n\r\n /**\r\n * Determines whether the tileset casts or receives shadows from light sources.\r\n *

\r\n * Enabling shadows has a performance impact. A tileset that casts shadows must be rendered twice, once from the camera and again from the light's point of view.\r\n *

\r\n *

\r\n * Shadows are rendered only when {@link Viewer#shadows} is true.\r\n *

\r\n *\r\n * @type {ShadowMode}\r\n * @default ShadowMode.ENABLED\r\n */\r\n this.shadows = defaultValue(options.shadows, ShadowMode.ENABLED);\r\n\r\n /**\r\n * Determines if the tileset will be shown.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * Defines how per-feature colors set from the Cesium API or declarative styling blend with the source colors from\r\n * the original feature, e.g. glTF material or per-point color in the tile.\r\n *\r\n * @type {Cesium3DTileColorBlendMode}\r\n * @default Cesium3DTileColorBlendMode.HIGHLIGHT\r\n */\r\n this.colorBlendMode = Cesium3DTileColorBlendMode.HIGHLIGHT;\r\n\r\n /**\r\n * Defines the value used to linearly interpolate between the source color and feature color when the {@link Cesium3DTileset#colorBlendMode} is MIX.\r\n * A value of 0.0 results in the source color while a value of 1.0 results in the feature color, with any value in-between\r\n * resulting in a mix of the source color and feature color.\r\n *\r\n * @type {Number}\r\n * @default 0.5\r\n */\r\n this.colorBlendAmount = 0.5;\r\n\r\n /**\r\n * Options for controlling point size based on geometric error and eye dome lighting.\r\n * @type {PointCloudShading}\r\n */\r\n this.pointCloudShading = new PointCloudShading(options.pointCloudShading);\r\n\r\n this._pointCloudEyeDomeLighting = new PointCloudEyeDomeLighting();\r\n\r\n /**\r\n * The event fired to indicate progress of loading new tiles. This event is fired when a new tile\r\n * is requested, when a requested tile is finished downloading, and when a downloaded tile has been\r\n * processed and is ready to render.\r\n *

\r\n * The number of pending tile requests, numberOfPendingRequests, and number of tiles\r\n * processing, numberOfTilesProcessing are passed to the event listener.\r\n *

\r\n *

\r\n * This event is fired at the end of the frame after the scene is rendered.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * tileset.loadProgress.addEventListener(function(numberOfPendingRequests, numberOfTilesProcessing) {\r\n * if ((numberOfPendingRequests === 0) && (numberOfTilesProcessing === 0)) {\r\n * console.log('Stopped loading');\r\n * return;\r\n * }\r\n *\r\n * console.log('Loading: requests: ' + numberOfPendingRequests + ', processing: ' + numberOfTilesProcessing);\r\n * });\r\n */\r\n this.loadProgress = new Event();\r\n\r\n /**\r\n * The event fired to indicate that all tiles that meet the screen space error this frame are loaded. The tileset\r\n * is completely loaded for this view.\r\n *

\r\n * This event is fired at the end of the frame after the scene is rendered.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * tileset.allTilesLoaded.addEventListener(function() {\r\n * console.log('All tiles are loaded');\r\n * });\r\n *\r\n * @see Cesium3DTileset#tilesLoaded\r\n */\r\n this.allTilesLoaded = new Event();\r\n\r\n /**\r\n * The event fired to indicate that all tiles that meet the screen space error this frame are loaded. This event\r\n * is fired once when all tiles in the initial view are loaded.\r\n *

\r\n * This event is fired at the end of the frame after the scene is rendered.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * tileset.initialTilesLoaded.addEventListener(function() {\r\n * console.log('Initial tiles are loaded');\r\n * });\r\n *\r\n * @see Cesium3DTileset#allTilesLoaded\r\n */\r\n this.initialTilesLoaded = new Event();\r\n\r\n /**\r\n * The event fired to indicate that a tile's content was loaded.\r\n *

\r\n * The loaded {@link Cesium3DTile} is passed to the event listener.\r\n *

\r\n *

\r\n * This event is fired during the tileset traversal while the frame is being rendered\r\n * so that updates to the tile take effect in the same frame. Do not create or modify\r\n * Cesium entities or primitives during the event listener.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * tileset.tileLoad.addEventListener(function(tile) {\r\n * console.log('A tile was loaded.');\r\n * });\r\n */\r\n this.tileLoad = new Event();\r\n\r\n /**\r\n * The event fired to indicate that a tile's content was unloaded.\r\n *

\r\n * The unloaded {@link Cesium3DTile} is passed to the event listener.\r\n *

\r\n *

\r\n * This event is fired immediately before the tile's content is unloaded while the frame is being\r\n * rendered so that the event listener has access to the tile's content. Do not create\r\n * or modify Cesium entities or primitives during the event listener.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * tileset.tileUnload.addEventListener(function(tile) {\r\n * console.log('A tile was unloaded from the cache.');\r\n * });\r\n *\r\n * @see Cesium3DTileset#maximumMemoryUsage\r\n * @see Cesium3DTileset#trimLoadedTiles\r\n */\r\n this.tileUnload = new Event();\r\n\r\n /**\r\n * The event fired to indicate that a tile's content failed to load.\r\n *

\r\n * If there are no event listeners, error messages will be logged to the console.\r\n *

\r\n *

\r\n * The error object passed to the listener contains two properties:\r\n *

    \r\n *
  • url: the url of the failed tile.
  • \r\n *
  • message: the error message.
  • \r\n *
\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * tileset.tileFailed.addEventListener(function(error) {\r\n * console.log('An error occurred loading tile: ' + error.url);\r\n * console.log('Error: ' + error.message);\r\n * });\r\n */\r\n this.tileFailed = new Event();\r\n\r\n /**\r\n * This event fires once for each visible tile in a frame. This can be used to manually\r\n * style a tileset.\r\n *

\r\n * The visible {@link Cesium3DTile} is passed to the event listener.\r\n *

\r\n *

\r\n * This event is fired during the tileset traversal while the frame is being rendered\r\n * so that updates to the tile take effect in the same frame. Do not create or modify\r\n * Cesium entities or primitives during the event listener.\r\n *

\r\n *\r\n * @type {Event}\r\n * @default new Event()\r\n *\r\n * @example\r\n * tileset.tileVisible.addEventListener(function(tile) {\r\n * if (tile.content instanceof Cesium.Batched3DModel3DTileContent) {\r\n * console.log('A Batched 3D Model tile is visible.');\r\n * }\r\n * });\r\n *\r\n * @example\r\n * // Apply a red style and then manually set random colors for every other feature when the tile becomes visible.\r\n * tileset.style = new Cesium.Cesium3DTileStyle({\r\n * color : 'color(\"red\")'\r\n * });\r\n * tileset.tileVisible.addEventListener(function(tile) {\r\n * var content = tile.content;\r\n * var featuresLength = content.featuresLength;\r\n * for (var i = 0; i < featuresLength; i+=2) {\r\n * content.getFeature(i).color = Cesium.Color.fromRandom();\r\n * }\r\n * });\r\n */\r\n this.tileVisible = new Event();\r\n\r\n /**\r\n * Optimization option. Determines if level of detail skipping should be applied during the traversal.\r\n *

\r\n * The common strategy for replacement-refinement traversal is to store all levels of the tree in memory and require\r\n * all children to be loaded before the parent can refine. With this optimization levels of the tree can be skipped\r\n * entirely and children can be rendered alongside their parents. The tileset requires significantly less memory when\r\n * using this optimization.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.skipLevelOfDetail = defaultValue(options.skipLevelOfDetail, false);\r\n this._skipLevelOfDetail = this.skipLevelOfDetail;\r\n this._disableSkipLevelOfDetail = false;\r\n\r\n /**\r\n * The screen space error that must be reached before skipping levels of detail.\r\n *

\r\n * Only used when {@link Cesium3DTileset#skipLevelOfDetail} is true.\r\n *

\r\n *\r\n * @type {Number}\r\n * @default 1024\r\n */\r\n this.baseScreenSpaceError = defaultValue(options.baseScreenSpaceError, 1024);\r\n\r\n /**\r\n * Multiplier defining the minimum screen space error to skip.\r\n * For example, if a tile has screen space error of 100, no tiles will be loaded unless they\r\n * are leaves or have a screen space error <= 100 / skipScreenSpaceErrorFactor.\r\n *

\r\n * Only used when {@link Cesium3DTileset#skipLevelOfDetail} is true.\r\n *

\r\n *\r\n * @type {Number}\r\n * @default 16\r\n */\r\n this.skipScreenSpaceErrorFactor = defaultValue(\r\n options.skipScreenSpaceErrorFactor,\r\n 16\r\n );\r\n\r\n /**\r\n * Constant defining the minimum number of levels to skip when loading tiles. When it is 0, no levels are skipped.\r\n * For example, if a tile is level 1, no tiles will be loaded unless they are at level greater than 2.\r\n *

\r\n * Only used when {@link Cesium3DTileset#skipLevelOfDetail} is true.\r\n *

\r\n *\r\n * @type {Number}\r\n * @default 1\r\n */\r\n this.skipLevels = defaultValue(options.skipLevels, 1);\r\n\r\n /**\r\n * When true, only tiles that meet the maximum screen space error will ever be downloaded.\r\n * Skipping factors are ignored and just the desired tiles are loaded.\r\n *

\r\n * Only used when {@link Cesium3DTileset#skipLevelOfDetail} is true.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.immediatelyLoadDesiredLevelOfDetail = defaultValue(\r\n options.immediatelyLoadDesiredLevelOfDetail,\r\n false\r\n );\r\n\r\n /**\r\n * Determines whether siblings of visible tiles are always downloaded during traversal.\r\n * This may be useful for ensuring that tiles are already available when the viewer turns left/right.\r\n *

\r\n * Only used when {@link Cesium3DTileset#skipLevelOfDetail} is true.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.loadSiblings = defaultValue(options.loadSiblings, false);\r\n\r\n this._clippingPlanes = undefined;\r\n this.clippingPlanes = options.clippingPlanes;\r\n\r\n this._imageBasedLightingFactor = new Cartesian2(1.0, 1.0);\r\n Cartesian2.clone(\r\n options.imageBasedLightingFactor,\r\n this._imageBasedLightingFactor\r\n );\r\n\r\n /**\r\n * The light color when shading models. When undefined the scene's light color is used instead.\r\n *

\r\n * For example, disabling additional light sources by setting model.imageBasedLightingFactor = new Cartesian2(0.0, 0.0) will make the\r\n * model much darker. Here, increasing the intensity of the light source will make the model brighter.\r\n *

\r\n *\r\n * @type {Cartesian3}\r\n * @default undefined\r\n */\r\n this.lightColor = options.lightColor;\r\n\r\n /**\r\n * The sun's luminance at the zenith in kilo candela per meter squared to use for this model's procedural environment map.\r\n * This is used when {@link Cesium3DTileset#specularEnvironmentMaps} and {@link Cesium3DTileset#sphericalHarmonicCoefficients} are not defined.\r\n *\r\n * @type Number\r\n *\r\n * @default 0.2\r\n *\r\n */\r\n this.luminanceAtZenith = defaultValue(options.luminanceAtZenith, 0.2);\r\n\r\n /**\r\n * The third order spherical harmonic coefficients used for the diffuse color of image-based lighting. When undefined, a diffuse irradiance\r\n * computed from the atmosphere color is used.\r\n *

\r\n * There are nine Cartesian3 coefficients.\r\n * The order of the coefficients is: L00, L1-1, L10, L11, L2-2, L2-1, L20, L21, L22\r\n *

\r\n *\r\n * These values can be obtained by preprocessing the environment map using the cmgen tool of\r\n * {@link https://github.com/google/filament/releases|Google's Filament project}. This will also generate a KTX file that can be\r\n * supplied to {@link Cesium3DTileset#specularEnvironmentMaps}.\r\n *\r\n * @type {Cartesian3[]}\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Image-Based Lighting.html|Sandcastle Image Based Lighting Demo}\r\n * @see {@link https://graphics.stanford.edu/papers/envmap/envmap.pdf|An Efficient Representation for Irradiance Environment Maps}\r\n */\r\n this.sphericalHarmonicCoefficients = options.sphericalHarmonicCoefficients;\r\n\r\n /**\r\n * A URL to a KTX file that contains a cube map of the specular lighting and the convoluted specular mipmaps.\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Image-Based Lighting.html|Sandcastle Image Based Lighting Demo}\r\n * @type {String}\r\n * @see Cesium3DTileset#sphericalHarmonicCoefficients\r\n */\r\n this.specularEnvironmentMaps = options.specularEnvironmentMaps;\r\n\r\n /**\r\n * Whether to cull back-facing geometry. When true, back face culling is determined\r\n * by the glTF material's doubleSided property; when false, back face culling is disabled.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.backFaceCulling = defaultValue(options.backFaceCulling, true);\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * Determines if only the tiles from last frame should be used for rendering. This\r\n * effectively \"freezes\" the tileset to the previous frame so it is possible to zoom\r\n * out and see what was rendered.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugFreezeFrame = defaultValue(options.debugFreezeFrame, false);\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, assigns a random color to each tile. This is useful for visualizing\r\n * what features belong to what tiles, especially with additive refinement where features\r\n * from parent tiles may be interleaved with features from child tiles.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugColorizeTiles = defaultValue(options.debugColorizeTiles, false);\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, renders each tile's content as a wireframe.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugWireframe = defaultValue(options.debugWireframe, false);\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, renders the bounding volume for each visible tile. The bounding volume is\r\n * white if the tile has a content bounding volume or is empty; otherwise, it is red. Tiles that don't meet the\r\n * screen space error and are still refining to their descendants are yellow.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, renders the bounding volume for each visible tile's content. The bounding volume is\r\n * blue if the tile has a content bounding volume; otherwise it is red.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugShowContentBoundingVolume = defaultValue(\r\n options.debugShowContentBoundingVolume,\r\n false\r\n );\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, renders the viewer request volume for each tile.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugShowViewerRequestVolume = defaultValue(\r\n options.debugShowViewerRequestVolume,\r\n false\r\n );\r\n\r\n this._tileDebugLabels = undefined;\r\n this.debugPickedTileLabelOnly = false;\r\n this.debugPickedTile = undefined;\r\n this.debugPickPosition = undefined;\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, draws labels to indicate the geometric error of each tile.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugShowGeometricError = defaultValue(\r\n options.debugShowGeometricError,\r\n false\r\n );\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, draws labels to indicate the number of commands, points, triangles and features of each tile.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugShowRenderingStatistics = defaultValue(\r\n options.debugShowRenderingStatistics,\r\n false\r\n );\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, draws labels to indicate the geometry and texture memory usage of each tile.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugShowMemoryUsage = defaultValue(options.debugShowMemoryUsage, false);\r\n\r\n /**\r\n * This property is for debugging only; it is not optimized for production use.\r\n *

\r\n * When true, draws labels to indicate the url of each tile.\r\n *

\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n this.debugShowUrl = defaultValue(options.debugShowUrl, false);\r\n\r\n /**\r\n * Function for examining vector lines as they are being streamed.\r\n *\r\n * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.\r\n *\r\n * @type {Function}\r\n */\r\n this.examineVectorLinesFunction = undefined;\r\n\r\n var that = this;\r\n var resource;\r\n when(options.url)\r\n .then(function (url) {\r\n var basePath;\r\n resource = Resource.createIfNeeded(url);\r\n that._resource = resource;\r\n\r\n // ion resources have a credits property we can use for additional attribution.\r\n that._credits = resource.credits;\r\n\r\n if (resource.extension === \"json\") {\r\n basePath = resource.getBaseUri(true);\r\n } else if (resource.isDataUri) {\r\n basePath = \"\";\r\n }\r\n\r\n that._url = resource.url;\r\n that._basePath = basePath;\r\n\r\n return Cesium3DTileset.loadJson(resource);\r\n })\r\n .then(function (tilesetJson) {\r\n that._root = that.loadTileset(resource, tilesetJson);\r\n var gltfUpAxis = defined(tilesetJson.asset.gltfUpAxis)\r\n ? Axis.fromName(tilesetJson.asset.gltfUpAxis)\r\n : Axis.Y;\r\n var asset = tilesetJson.asset;\r\n that._asset = asset;\r\n that._properties = tilesetJson.properties;\r\n that._geometricError = tilesetJson.geometricError;\r\n that._extensionsUsed = tilesetJson.extensionsUsed;\r\n that._extensions = tilesetJson.extensions;\r\n that._gltfUpAxis = gltfUpAxis;\r\n that._extras = tilesetJson.extras;\r\n\r\n var extras = asset.extras;\r\n if (\r\n defined(extras) &&\r\n defined(extras.cesium) &&\r\n defined(extras.cesium.credits)\r\n ) {\r\n var extraCredits = extras.cesium.credits;\r\n var credits = that._credits;\r\n if (!defined(credits)) {\r\n credits = [];\r\n that._credits = credits;\r\n }\r\n for (var i = 0; i < extraCredits.length; ++i) {\r\n var credit = extraCredits[i];\r\n credits.push(new Credit(credit.html, credit.showOnScreen));\r\n }\r\n }\r\n\r\n // Save the original, untransformed bounding volume position so we can apply\r\n // the tile transform and model matrix at run time\r\n var boundingVolume = that._root.createBoundingVolume(\r\n tilesetJson.root.boundingVolume,\r\n Matrix4.IDENTITY\r\n );\r\n var clippingPlanesOrigin = boundingVolume.boundingSphere.center;\r\n // If this origin is above the surface of the earth\r\n // we want to apply an ENU orientation as our best guess of orientation.\r\n // Otherwise, we assume it gets its position/orientation completely from the\r\n // root tile transform and the tileset's model matrix\r\n var originCartographic = that._ellipsoid.cartesianToCartographic(\r\n clippingPlanesOrigin\r\n );\r\n if (\r\n defined(originCartographic) &&\r\n originCartographic.height >\r\n ApproximateTerrainHeights._defaultMinTerrainHeight\r\n ) {\r\n that._initialClippingPlanesOriginMatrix = Transforms.eastNorthUpToFixedFrame(\r\n clippingPlanesOrigin\r\n );\r\n }\r\n that._clippingPlanesOriginMatrix = Matrix4.clone(\r\n that._initialClippingPlanesOriginMatrix\r\n );\r\n that._readyPromise.resolve(that);\r\n })\r\n .otherwise(function (error) {\r\n that._readyPromise.reject(error);\r\n });\r\n}\r\n\r\nObject.defineProperties(Cesium3DTileset.prototype, {\r\n /**\r\n * NOTE: This getter exists so that `Picking.js` can differentiate between\r\n * PrimitiveCollection and Cesium3DTileset objects without inflating\r\n * the size of the module via `instanceof Cesium3DTileset`\r\n * @private\r\n */\r\n isCesium3DTileset: {\r\n get: function () {\r\n return true;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tileset's asset object property, which contains metadata about the tileset.\r\n *

\r\n * See the {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification#reference-asset|asset schema reference}\r\n * in the 3D Tiles spec for the full set of properties.\r\n *

\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n *\r\n * @exception {DeveloperError} The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\r\n */\r\n asset: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._asset;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tileset's extensions object property.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n *\r\n * @exception {DeveloperError} The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\r\n */\r\n extensions: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._extensions;\r\n },\r\n },\r\n\r\n /**\r\n * The {@link ClippingPlaneCollection} used to selectively disable rendering the tileset.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {ClippingPlaneCollection}\r\n */\r\n clippingPlanes: {\r\n get: function () {\r\n return this._clippingPlanes;\r\n },\r\n set: function (value) {\r\n ClippingPlaneCollection.setOwner(value, this, \"_clippingPlanes\");\r\n },\r\n },\r\n\r\n /**\r\n * Gets the tileset's properties dictionary object, which contains metadata about per-feature properties.\r\n *

\r\n * See the {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification#reference-properties|properties schema reference}\r\n * in the 3D Tiles spec for the full set of properties.\r\n *

\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Object}\r\n * @readonly\r\n *\r\n * @exception {DeveloperError} The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\r\n *\r\n * @example\r\n * console.log('Maximum building height: ' + tileset.properties.height.maximum);\r\n * console.log('Minimum building height: ' + tileset.properties.height.minimum);\r\n *\r\n * @see Cesium3DTileFeature#getProperty\r\n * @see Cesium3DTileFeature#setProperty\r\n */\r\n properties: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._properties;\r\n },\r\n },\r\n\r\n /**\r\n * When true, the tileset's root tile is loaded and the tileset is ready to render.\r\n * This is set to true right before {@link Cesium3DTileset#readyPromise} is resolved.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n */\r\n ready: {\r\n get: function () {\r\n return defined(this._root);\r\n },\r\n },\r\n\r\n /**\r\n * Gets the promise that will be resolved when the tileset's root tile is loaded and the tileset is ready to render.\r\n *

\r\n * This promise is resolved at the end of the frame before the first frame the tileset is rendered in.\r\n *

\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Promise.}\r\n * @readonly\r\n *\r\n * @example\r\n * tileset.readyPromise.then(function(tileset) {\r\n * // tile.properties is not defined until readyPromise resolves.\r\n * var properties = tileset.properties;\r\n * if (Cesium.defined(properties)) {\r\n * for (var name in properties) {\r\n * console.log(properties[name]);\r\n * }\r\n * }\r\n * });\r\n */\r\n readyPromise: {\r\n get: function () {\r\n return this._readyPromise.promise;\r\n },\r\n },\r\n\r\n /**\r\n * When true, all tiles that meet the screen space error this frame are loaded. The tileset is\r\n * completely loaded for this view.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n *\r\n * @default false\r\n *\r\n * @see Cesium3DTileset#allTilesLoaded\r\n */\r\n tilesLoaded: {\r\n get: function () {\r\n return this._tilesLoaded;\r\n },\r\n },\r\n\r\n /**\r\n * The resource used to fetch the tileset JSON file\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Resource}\r\n * @readonly\r\n */\r\n resource: {\r\n get: function () {\r\n return this._resource;\r\n },\r\n },\r\n\r\n /**\r\n * The base path that non-absolute paths in tileset JSON file are relative to.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {String}\r\n * @readonly\r\n * @deprecated\r\n */\r\n basePath: {\r\n get: function () {\r\n deprecationWarning(\r\n \"Cesium3DTileset.basePath\",\r\n \"Cesium3DTileset.basePath has been deprecated. All tiles are relative to the url of the tileset JSON file that contains them. Use the url property instead.\"\r\n );\r\n return this._basePath;\r\n },\r\n },\r\n\r\n /**\r\n * The style, defined using the\r\n * {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/Styling|3D Tiles Styling language},\r\n * applied to each feature in the tileset.\r\n *

\r\n * Assign undefined to remove the style, which will restore the visual\r\n * appearance of the tileset to its default when no style was applied.\r\n *

\r\n *

\r\n * The style is applied to a tile before the {@link Cesium3DTileset#tileVisible}\r\n * event is raised, so code in tileVisible can manually set a feature's\r\n * properties (e.g. color and show) after the style is applied. When\r\n * a new style is assigned any manually set properties are overwritten.\r\n *

\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Cesium3DTileStyle|undefined}\r\n *\r\n * @default undefined\r\n *\r\n * @example\r\n * tileset.style = new Cesium.Cesium3DTileStyle({\r\n * color : {\r\n * conditions : [\r\n * ['${Height} >= 100', 'color(\"purple\", 0.5)'],\r\n * ['${Height} >= 50', 'color(\"red\")'],\r\n * ['true', 'color(\"blue\")']\r\n * ]\r\n * },\r\n * show : '${Height} > 0',\r\n * meta : {\r\n * description : '\"Building id ${id} has height ${Height}.\"'\r\n * }\r\n * });\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification/Styling|3D Tiles Styling language}\r\n */\r\n style: {\r\n get: function () {\r\n return this._styleEngine.style;\r\n },\r\n set: function (value) {\r\n this._styleEngine.style = value;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum screen space error used to drive level of detail refinement. This value helps determine when a tile\r\n * refines to its descendants, and therefore plays a major role in balancing performance with visual quality.\r\n *

\r\n * A tile's screen space error is roughly equivalent to the number of pixels wide that would be drawn if a sphere with a\r\n * radius equal to the tile's geometric error were rendered at the tile's position. If this value exceeds\r\n * maximumScreenSpaceError the tile refines to its descendants.\r\n *

\r\n *

\r\n * Depending on the tileset, maximumScreenSpaceError may need to be tweaked to achieve the right balance.\r\n * Higher values provide better performance but lower visual quality.\r\n *

\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Number}\r\n * @default 16\r\n *\r\n * @exception {DeveloperError} maximumScreenSpaceError must be greater than or equal to zero.\r\n */\r\n maximumScreenSpaceError: {\r\n get: function () {\r\n return this._maximumScreenSpaceError;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"maximumScreenSpaceError\",\r\n value,\r\n 0\r\n );\r\n //>>includeEnd('debug');\r\n\r\n this._maximumScreenSpaceError = value;\r\n },\r\n },\r\n\r\n /**\r\n * The maximum amount of GPU memory (in MB) that may be used to cache tiles. This value is estimated from\r\n * geometry, textures, and batch table textures of loaded tiles. For point clouds, this value also\r\n * includes per-point metadata.\r\n *

\r\n * Tiles not in view are unloaded to enforce this.\r\n *

\r\n *

\r\n * If decreasing this value results in unloading tiles, the tiles are unloaded the next frame.\r\n *

\r\n *

\r\n * If tiles sized more than maximumMemoryUsage are needed\r\n * to meet the desired screen space error, determined by {@link Cesium3DTileset#maximumScreenSpaceError},\r\n * for the current view, then the memory usage of the tiles loaded will exceed\r\n * maximumMemoryUsage. For example, if the maximum is 256 MB, but\r\n * 300 MB of tiles are needed to meet the screen space error, then 300 MB of tiles may be loaded. When\r\n * these tiles go out of view, they will be unloaded.\r\n *

\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Number}\r\n * @default 512\r\n *\r\n * @exception {DeveloperError} maximumMemoryUsage must be greater than or equal to zero.\r\n * @see Cesium3DTileset#totalMemoryUsageInBytes\r\n */\r\n maximumMemoryUsage: {\r\n get: function () {\r\n return this._maximumMemoryUsage;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"value\", value, 0);\r\n //>>includeEnd('debug');\r\n\r\n this._maximumMemoryUsage = value;\r\n },\r\n },\r\n\r\n /**\r\n * The root tile.\r\n *\r\n * @memberOf Cesium3DTileset.prototype\r\n *\r\n * @type {Cesium3DTile}\r\n * @readonly\r\n *\r\n * @exception {DeveloperError} The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\r\n */\r\n root: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._root;\r\n },\r\n },\r\n\r\n /**\r\n * The tileset's bounding sphere.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {BoundingSphere}\r\n * @readonly\r\n *\r\n * @exception {DeveloperError} The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\r\n *\r\n * @example\r\n * var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({\r\n * url : 'http://localhost:8002/tilesets/Seattle/tileset.json'\r\n * }));\r\n *\r\n * tileset.readyPromise.then(function(tileset) {\r\n * // Set the camera to view the newly added tileset\r\n * viewer.camera.viewBoundingSphere(tileset.boundingSphere, new Cesium.HeadingPitchRange(0, -0.5, 0));\r\n * });\r\n */\r\n boundingSphere: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._root.updateTransform(this._modelMatrix);\r\n return this._root.boundingSphere;\r\n },\r\n },\r\n\r\n /**\r\n * A 4x4 transformation matrix that transforms the entire tileset.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Matrix4}\r\n * @default Matrix4.IDENTITY\r\n *\r\n * @example\r\n * // Adjust a tileset's height from the globe's surface.\r\n * var heightOffset = 20.0;\r\n * var boundingSphere = tileset.boundingSphere;\r\n * var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);\r\n * var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);\r\n * var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);\r\n * var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());\r\n * tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);\r\n */\r\n modelMatrix: {\r\n get: function () {\r\n return this._modelMatrix;\r\n },\r\n set: function (value) {\r\n this._modelMatrix = Matrix4.clone(value, this._modelMatrix);\r\n },\r\n },\r\n\r\n /**\r\n * Returns the time, in milliseconds, since the tileset was loaded and first updated.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n timeSinceLoad: {\r\n get: function () {\r\n return this._timeSinceLoad;\r\n },\r\n },\r\n\r\n /**\r\n * The total amount of GPU memory in bytes used by the tileset. This value is estimated from\r\n * geometry, texture, and batch table textures of loaded tiles. For point clouds, this value also\r\n * includes per-point metadata.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n *\r\n * @see Cesium3DTileset#maximumMemoryUsage\r\n */\r\n totalMemoryUsageInBytes: {\r\n get: function () {\r\n var statistics = this._statistics;\r\n return (\r\n statistics.texturesByteLength +\r\n statistics.geometryByteLength +\r\n statistics.batchTableByteLength\r\n );\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n clippingPlanesOriginMatrix: {\r\n get: function () {\r\n if (!defined(this._clippingPlanesOriginMatrix)) {\r\n return Matrix4.IDENTITY;\r\n }\r\n\r\n if (this._clippingPlanesOriginMatrixDirty) {\r\n Matrix4.multiply(\r\n this.root.computedTransform,\r\n this._initialClippingPlanesOriginMatrix,\r\n this._clippingPlanesOriginMatrix\r\n );\r\n this._clippingPlanesOriginMatrixDirty = false;\r\n }\r\n\r\n return this._clippingPlanesOriginMatrix;\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n styleEngine: {\r\n get: function () {\r\n return this._styleEngine;\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n statistics: {\r\n get: function () {\r\n return this._statistics;\r\n },\r\n },\r\n\r\n /**\r\n * Determines whether terrain, 3D Tiles or both will be classified by this tileset.\r\n *

\r\n * This option is only applied to tilesets containing batched 3D models, geometry data, or vector data. Even when undefined, vector data and geometry data\r\n * must render as classifications and will default to rendering on both terrain and other 3D Tiles tilesets.\r\n *

\r\n *

\r\n * When enabled for batched 3D model tilesets, there are a few requirements/limitations on the glTF:\r\n *

    \r\n *
  • POSITION and _BATCHID semantics are required.
  • \r\n *
  • All indices with the same batch id must occupy contiguous sections of the index buffer.
  • \r\n *
  • All shaders and techniques are ignored. The generated shader simply multiplies the position by the model-view-projection matrix.
  • \r\n *
  • The only supported extensions are CESIUM_RTC and WEB3D_quantized_attributes.
  • \r\n *
  • Only one node is supported.
  • \r\n *
  • Only one mesh per node is supported.
  • \r\n *
  • Only one primitive per mesh is supported.
  • \r\n *
\r\n *

\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {ClassificationType}\r\n * @default undefined\r\n *\r\n * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.\r\n * @readonly\r\n */\r\n classificationType: {\r\n get: function () {\r\n return this._classificationType;\r\n },\r\n },\r\n\r\n /**\r\n * Gets an ellipsoid describing the shape of the globe.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Ellipsoid}\r\n * @readonly\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n },\r\n\r\n /**\r\n * Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control the cone size that determines which tiles are deferred.\r\n * Tiles that are inside this cone are loaded immediately. Tiles outside the cone are potentially deferred based on how far outside the cone they are and {@link Cesium3DTileset#foveatedInterpolationCallback} and {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation}.\r\n * Setting this to 0.0 means the cone will be the line formed by the camera position and its view direction. Setting this to 1.0 means the cone encompasses the entire field of view of the camera, essentially disabling the effect.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Number}\r\n * @default 0.3\r\n */\r\n foveatedConeSize: {\r\n get: function () {\r\n return this._foveatedConeSize;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\"foveatedConeSize\", value, 0.0);\r\n Check.typeOf.number.lessThanOrEquals(\"foveatedConeSize\", value, 1.0);\r\n //>>includeEnd('debug');\r\n\r\n this._foveatedConeSize = value;\r\n },\r\n },\r\n\r\n /**\r\n * Optimization option. Used when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control the starting screen space error relaxation for tiles outside the foveated cone.\r\n * The screen space error will be raised starting with this value up to {@link Cesium3DTileset#maximumScreenSpaceError} based on the provided {@link Cesium3DTileset#foveatedInterpolationCallback}.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n foveatedMinimumScreenSpaceErrorRelaxation: {\r\n get: function () {\r\n return this._foveatedMinimumScreenSpaceErrorRelaxation;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"foveatedMinimumScreenSpaceErrorRelaxation\",\r\n value,\r\n 0.0\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"foveatedMinimumScreenSpaceErrorRelaxation\",\r\n value,\r\n this.maximumScreenSpaceError\r\n );\r\n //>>includeEnd('debug');\r\n\r\n this._foveatedMinimumScreenSpaceErrorRelaxation = value;\r\n },\r\n },\r\n\r\n /**\r\n * Returns the extras property at the top-level of the tileset JSON, which contains application specific metadata.\r\n * Returns undefined if extras does not exist.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @exception {DeveloperError} The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\r\n *\r\n * @type {*}\r\n * @readonly\r\n *\r\n * @see {@link https://github.com/CesiumGS/3d-tiles/tree/master/specification#specifying-extensions-and-application-specific-extras|Extras in the 3D Tiles specification.}\r\n */\r\n extras: {\r\n get: function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!this.ready) {\r\n throw new DeveloperError(\r\n \"The tileset is not loaded. Use Cesium3DTileset.readyPromise or wait for Cesium3DTileset.ready to be true.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._extras;\r\n },\r\n },\r\n\r\n /**\r\n * Cesium adds lighting from the earth, sky, atmosphere, and star skybox. This cartesian is used to scale the final\r\n * diffuse and specular lighting contribution from those sources to the final color. A value of 0.0 will disable those light sources.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @type {Cartesian2}\r\n * @default Cartesian2(1.0, 1.0)\r\n */\r\n imageBasedLightingFactor: {\r\n get: function () {\r\n return this._imageBasedLightingFactor;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"imageBasedLightingFactor\", value);\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"imageBasedLightingFactor.x\",\r\n value.x,\r\n 0.0\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"imageBasedLightingFactor.x\",\r\n value.x,\r\n 1.0\r\n );\r\n Check.typeOf.number.greaterThanOrEquals(\r\n \"imageBasedLightingFactor.y\",\r\n value.y,\r\n 0.0\r\n );\r\n Check.typeOf.number.lessThanOrEquals(\r\n \"imageBasedLightingFactor.y\",\r\n value.y,\r\n 1.0\r\n );\r\n //>>includeEnd('debug');\r\n Cartesian2.clone(value, this._imageBasedLightingFactor);\r\n },\r\n },\r\n\r\n /**\r\n * Indicates that only the tileset's vector tiles should be used for classification.\r\n *\r\n * @memberof Cesium3DTileset.prototype\r\n *\r\n * @experimental This feature is using part of the 3D Tiles spec that is not final and is subject to change without Cesium's standard deprecation policy.\r\n *\r\n * @type {Boolean}\r\n * @default false\r\n */\r\n vectorClassificationOnly: {\r\n get: function () {\r\n return this._vectorClassificationOnly;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Provides a hook to override the method used to request the tileset json\r\n * useful when fetching tilesets from remote servers\r\n * @param {Resource|String} tilesetUrl The url of the json file to be fetched\r\n * @returns {Promise.} A promise that resolves with the fetched json data\r\n */\r\nCesium3DTileset.loadJson = function (tilesetUrl) {\r\n var resource = Resource.createIfNeeded(tilesetUrl);\r\n return resource.fetchJson();\r\n};\r\n\r\n/**\r\n * Marks the tileset's {@link Cesium3DTileset#style} as dirty, which forces all\r\n * features to re-evaluate the style in the next frame each is visible.\r\n */\r\nCesium3DTileset.prototype.makeStyleDirty = function () {\r\n this._styleEngine.makeDirty();\r\n};\r\n\r\n/**\r\n * Loads the main tileset JSON file or a tileset JSON file referenced from a tile.\r\n *\r\n * @private\r\n */\r\nCesium3DTileset.prototype.loadTileset = function (\r\n resource,\r\n tilesetJson,\r\n parentTile\r\n) {\r\n var asset = tilesetJson.asset;\r\n if (!defined(asset)) {\r\n throw new RuntimeError(\"Tileset must have an asset property.\");\r\n }\r\n if (asset.version !== \"0.0\" && asset.version !== \"1.0\") {\r\n throw new RuntimeError(\"The tileset must be 3D Tiles version 0.0 or 1.0.\");\r\n }\r\n\r\n var statistics = this._statistics;\r\n\r\n var tilesetVersion = asset.tilesetVersion;\r\n if (defined(tilesetVersion)) {\r\n // Append the tileset version to the resource\r\n this._basePath += \"?v=\" + tilesetVersion;\r\n resource = resource.clone();\r\n resource.setQueryParameters({ v: tilesetVersion });\r\n }\r\n\r\n // A tileset JSON file referenced from a tile may exist in a different directory than the root tileset.\r\n // Get the basePath relative to the external tileset.\r\n var rootTile = new Cesium3DTile(this, resource, tilesetJson.root, parentTile);\r\n\r\n // If there is a parentTile, add the root of the currently loading tileset\r\n // to parentTile's children, and update its _depth.\r\n if (defined(parentTile)) {\r\n parentTile.children.push(rootTile);\r\n rootTile._depth = parentTile._depth + 1;\r\n }\r\n\r\n var stack = [];\r\n stack.push(rootTile);\r\n\r\n while (stack.length > 0) {\r\n var tile = stack.pop();\r\n ++statistics.numberOfTilesTotal;\r\n this._allTilesAdditive =\r\n this._allTilesAdditive && tile.refine === Cesium3DTileRefine.ADD;\r\n var children = tile._header.children;\r\n if (defined(children)) {\r\n var length = children.length;\r\n for (var i = 0; i < length; ++i) {\r\n var childHeader = children[i];\r\n var childTile = new Cesium3DTile(this, resource, childHeader, tile);\r\n tile.children.push(childTile);\r\n childTile._depth = tile._depth + 1;\r\n stack.push(childTile);\r\n }\r\n }\r\n\r\n if (this._cullWithChildrenBounds) {\r\n Cesium3DTileOptimizations.checkChildrenWithinParent(tile);\r\n }\r\n }\r\n\r\n return rootTile;\r\n};\r\n\r\nvar scratchPositionNormal = new Cartesian3();\r\nvar scratchCartographic = new Cartographic();\r\nvar scratchMatrix = new Matrix4();\r\nvar scratchCenter = new Cartesian3();\r\nvar scratchPosition = new Cartesian3();\r\nvar scratchDirection = new Cartesian3();\r\n\r\nfunction updateDynamicScreenSpaceError(tileset, frameState) {\r\n var up;\r\n var direction;\r\n var height;\r\n var minimumHeight;\r\n var maximumHeight;\r\n\r\n var camera = frameState.camera;\r\n var root = tileset._root;\r\n var tileBoundingVolume = root.contentBoundingVolume;\r\n\r\n if (tileBoundingVolume instanceof TileBoundingRegion) {\r\n up = Cartesian3.normalize(camera.positionWC, scratchPositionNormal);\r\n direction = camera.directionWC;\r\n height = camera.positionCartographic.height;\r\n minimumHeight = tileBoundingVolume.minimumHeight;\r\n maximumHeight = tileBoundingVolume.maximumHeight;\r\n } else {\r\n // Transform camera position and direction into the local coordinate system of the tileset\r\n var transformLocal = Matrix4.inverseTransformation(\r\n root.computedTransform,\r\n scratchMatrix\r\n );\r\n var ellipsoid = frameState.mapProjection.ellipsoid;\r\n var boundingVolume = tileBoundingVolume.boundingVolume;\r\n var centerLocal = Matrix4.multiplyByPoint(\r\n transformLocal,\r\n boundingVolume.center,\r\n scratchCenter\r\n );\r\n if (Cartesian3.magnitude(centerLocal) > ellipsoid.minimumRadius) {\r\n // The tileset is defined in WGS84. Approximate the minimum and maximum height.\r\n var centerCartographic = Cartographic.fromCartesian(\r\n centerLocal,\r\n ellipsoid,\r\n scratchCartographic\r\n );\r\n up = Cartesian3.normalize(camera.positionWC, scratchPositionNormal);\r\n direction = camera.directionWC;\r\n height = camera.positionCartographic.height;\r\n minimumHeight = 0.0;\r\n maximumHeight = centerCartographic.height * 2.0;\r\n } else {\r\n // The tileset is defined in local coordinates (z-up)\r\n var positionLocal = Matrix4.multiplyByPoint(\r\n transformLocal,\r\n camera.positionWC,\r\n scratchPosition\r\n );\r\n up = Cartesian3.UNIT_Z;\r\n direction = Matrix4.multiplyByPointAsVector(\r\n transformLocal,\r\n camera.directionWC,\r\n scratchDirection\r\n );\r\n direction = Cartesian3.normalize(direction, direction);\r\n height = positionLocal.z;\r\n if (tileBoundingVolume instanceof TileOrientedBoundingBox) {\r\n // Assuming z-up, the last component stores the half-height of the box\r\n var boxHeight = root._header.boundingVolume.box[11];\r\n minimumHeight = centerLocal.z - boxHeight;\r\n maximumHeight = centerLocal.z + boxHeight;\r\n } else if (tileBoundingVolume instanceof TileBoundingSphere) {\r\n var radius = boundingVolume.radius;\r\n minimumHeight = centerLocal.z - radius;\r\n maximumHeight = centerLocal.z + radius;\r\n }\r\n }\r\n }\r\n\r\n // The range where the density starts to lessen. Start at the quarter height of the tileset.\r\n var heightFalloff = tileset.dynamicScreenSpaceErrorHeightFalloff;\r\n var heightClose =\r\n minimumHeight + (maximumHeight - minimumHeight) * heightFalloff;\r\n var heightFar = maximumHeight;\r\n\r\n var t = CesiumMath.clamp(\r\n (height - heightClose) / (heightFar - heightClose),\r\n 0.0,\r\n 1.0\r\n );\r\n\r\n // Increase density as the camera tilts towards the horizon\r\n var dot = Math.abs(Cartesian3.dot(direction, up));\r\n var horizonFactor = 1.0 - dot;\r\n\r\n // Weaken the horizon factor as the camera height increases, implying the camera is further away from the tileset.\r\n // The goal is to increase density for the \"street view\", not when viewing the tileset from a distance.\r\n horizonFactor = horizonFactor * (1.0 - t);\r\n\r\n var density = tileset.dynamicScreenSpaceErrorDensity;\r\n density *= horizonFactor;\r\n\r\n tileset._dynamicScreenSpaceErrorComputedDensity = density;\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction requestContent(tileset, tile) {\r\n if (tile.hasEmptyContent) {\r\n return;\r\n }\r\n\r\n var statistics = tileset._statistics;\r\n var expired = tile.contentExpired;\r\n var requested = tile.requestContent();\r\n\r\n if (!requested) {\r\n ++statistics.numberOfAttemptedRequests;\r\n return;\r\n }\r\n\r\n if (expired) {\r\n if (tile.hasTilesetContent) {\r\n destroySubtree(tileset, tile);\r\n } else {\r\n statistics.decrementLoadCounts(tile.content);\r\n --statistics.numberOfTilesWithContentReady;\r\n }\r\n }\r\n\r\n ++statistics.numberOfPendingRequests;\r\n tileset._requestedTilesInFlight.push(tile);\r\n\r\n tile.contentReadyToProcessPromise.then(addToProcessingQueue(tileset, tile));\r\n tile.contentReadyPromise\r\n .then(handleTileSuccess(tileset, tile))\r\n .otherwise(handleTileFailure(tileset, tile));\r\n}\r\n\r\nfunction sortRequestByPriority(a, b) {\r\n return a._priority - b._priority;\r\n}\r\n\r\n/**\r\n * Perform any pass invariant tasks here. Called after the render pass.\r\n * @private\r\n */\r\nCesium3DTileset.prototype.postPassesUpdate = function (frameState) {\r\n if (!this.ready) {\r\n return;\r\n }\r\n\r\n cancelOutOfViewRequests(this, frameState);\r\n raiseLoadProgressEvent(this, frameState);\r\n this._cache.unloadTiles(this, unloadTile);\r\n this._styleEngine.resetDirty();\r\n};\r\n\r\n/**\r\n * Perform any pass invariant tasks here. Called before any passes are executed.\r\n * @private\r\n */\r\nCesium3DTileset.prototype.prePassesUpdate = function (frameState) {\r\n if (!this.ready) {\r\n return;\r\n }\r\n\r\n processTiles(this, frameState);\r\n\r\n // Update clipping planes\r\n var clippingPlanes = this._clippingPlanes;\r\n this._clippingPlanesOriginMatrixDirty = true;\r\n if (defined(clippingPlanes) && clippingPlanes.enabled) {\r\n clippingPlanes.update(frameState);\r\n }\r\n\r\n if (!defined(this._loadTimestamp)) {\r\n this._loadTimestamp = JulianDate.clone(frameState.time);\r\n }\r\n this._timeSinceLoad = Math.max(\r\n JulianDate.secondsDifference(frameState.time, this._loadTimestamp) * 1000,\r\n 0.0\r\n );\r\n\r\n this._skipLevelOfDetail =\r\n this.skipLevelOfDetail &&\r\n !defined(this._classificationType) &&\r\n !this._disableSkipLevelOfDetail &&\r\n !this._allTilesAdditive;\r\n\r\n if (this.dynamicScreenSpaceError) {\r\n updateDynamicScreenSpaceError(this, frameState);\r\n }\r\n\r\n if (frameState.newFrame) {\r\n this._cache.reset();\r\n }\r\n};\r\n\r\nfunction cancelOutOfViewRequests(tileset, frameState) {\r\n var requestedTilesInFlight = tileset._requestedTilesInFlight;\r\n var removeCount = 0;\r\n var length = requestedTilesInFlight.length;\r\n for (var i = 0; i < length; ++i) {\r\n var tile = requestedTilesInFlight[i];\r\n\r\n // NOTE: This is framerate dependant so make sure the threshold check is small\r\n var outOfView = frameState.frameNumber - tile._touchedFrame >= 1;\r\n if (tile._contentState !== Cesium3DTileContentState.LOADING) {\r\n // No longer fetching from host, don't need to track it anymore. Gets marked as LOADING in Cesium3DTile::requestContent().\r\n ++removeCount;\r\n continue;\r\n } else if (outOfView) {\r\n // RequestScheduler will take care of cancelling it\r\n tile._request.cancel();\r\n ++removeCount;\r\n continue;\r\n }\r\n\r\n if (removeCount > 0) {\r\n requestedTilesInFlight[i - removeCount] = tile;\r\n }\r\n }\r\n\r\n requestedTilesInFlight.length -= removeCount;\r\n}\r\n\r\nfunction requestTiles(tileset, isAsync) {\r\n // Sort requests by priority before making any requests.\r\n // This makes it less likely that requests will be cancelled after being issued.\r\n var requestedTiles = tileset._requestedTiles;\r\n var length = requestedTiles.length;\r\n requestedTiles.sort(sortRequestByPriority);\r\n for (var i = 0; i < length; ++i) {\r\n requestContent(tileset, requestedTiles[i]);\r\n }\r\n}\r\n\r\nfunction addToProcessingQueue(tileset, tile) {\r\n return function () {\r\n tileset._processingQueue.push(tile);\r\n\r\n --tileset._statistics.numberOfPendingRequests;\r\n ++tileset._statistics.numberOfTilesProcessing;\r\n };\r\n}\r\n\r\nfunction handleTileFailure(tileset, tile) {\r\n return function (error) {\r\n var url = tile._contentResource.url;\r\n var message = defined(error.message) ? error.message : error.toString();\r\n if (tileset.tileFailed.numberOfListeners > 0) {\r\n tileset.tileFailed.raiseEvent({\r\n url: url,\r\n message: message,\r\n });\r\n } else {\r\n console.log(\"A 3D tile failed to load: \" + url);\r\n console.log(\"Error: \" + message);\r\n }\r\n };\r\n}\r\n\r\nfunction handleTileSuccess(tileset, tile) {\r\n return function () {\r\n --tileset._statistics.numberOfTilesProcessing;\r\n\r\n if (!tile.hasTilesetContent) {\r\n // RESEARCH_IDEA: ability to unload tiles (without content) for an\r\n // external tileset when all the tiles are unloaded.\r\n tileset._statistics.incrementLoadCounts(tile.content);\r\n ++tileset._statistics.numberOfTilesWithContentReady;\r\n ++tileset._statistics.numberOfLoadedTilesTotal;\r\n\r\n // Add to the tile cache. Previously expired tiles are already in the cache and won't get re-added.\r\n tileset._cache.add(tile);\r\n }\r\n\r\n tileset.tileLoad.raiseEvent(tile);\r\n };\r\n}\r\n\r\nfunction filterProcessingQueue(tileset) {\r\n var tiles = tileset._processingQueue;\r\n var length = tiles.length;\r\n\r\n var removeCount = 0;\r\n for (var i = 0; i < length; ++i) {\r\n var tile = tiles[i];\r\n if (tile._contentState !== Cesium3DTileContentState.PROCESSING) {\r\n ++removeCount;\r\n continue;\r\n }\r\n if (removeCount > 0) {\r\n tiles[i - removeCount] = tile;\r\n }\r\n }\r\n tiles.length -= removeCount;\r\n}\r\n\r\nfunction processTiles(tileset, frameState) {\r\n filterProcessingQueue(tileset);\r\n var tiles = tileset._processingQueue;\r\n var length = tiles.length;\r\n // Process tiles in the PROCESSING state so they will eventually move to the READY state.\r\n for (var i = 0; i < length; ++i) {\r\n tiles[i].process(tileset, frameState);\r\n }\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nvar scratchCartesian = new Cartesian3();\r\n\r\nvar stringOptions = {\r\n maximumFractionDigits: 3,\r\n};\r\n\r\nfunction formatMemoryString(memorySizeInBytes) {\r\n var memoryInMegabytes = memorySizeInBytes / 1048576;\r\n if (memoryInMegabytes < 1.0) {\r\n return memoryInMegabytes.toLocaleString(undefined, stringOptions);\r\n }\r\n return Math.round(memoryInMegabytes).toLocaleString();\r\n}\r\n\r\nfunction computeTileLabelPosition(tile) {\r\n var boundingVolume = tile.boundingVolume.boundingVolume;\r\n var halfAxes = boundingVolume.halfAxes;\r\n var radius = boundingVolume.radius;\r\n\r\n var position = Cartesian3.clone(boundingVolume.center, scratchCartesian);\r\n if (defined(halfAxes)) {\r\n position.x += 0.75 * (halfAxes[0] + halfAxes[3] + halfAxes[6]);\r\n position.y += 0.75 * (halfAxes[1] + halfAxes[4] + halfAxes[7]);\r\n position.z += 0.75 * (halfAxes[2] + halfAxes[5] + halfAxes[8]);\r\n } else if (defined(radius)) {\r\n var normal = Cartesian3.normalize(boundingVolume.center, scratchCartesian);\r\n normal = Cartesian3.multiplyByScalar(\r\n normal,\r\n 0.75 * radius,\r\n scratchCartesian\r\n );\r\n position = Cartesian3.add(normal, boundingVolume.center, scratchCartesian);\r\n }\r\n return position;\r\n}\r\n\r\nfunction addTileDebugLabel(tile, tileset, position) {\r\n var labelString = \"\";\r\n var attributes = 0;\r\n\r\n if (tileset.debugShowGeometricError) {\r\n labelString += \"\\nGeometric error: \" + tile.geometricError;\r\n attributes++;\r\n }\r\n\r\n if (tileset.debugShowRenderingStatistics) {\r\n labelString += \"\\nCommands: \" + tile.commandsLength;\r\n attributes++;\r\n\r\n // Don't display number of points or triangles if 0.\r\n var numberOfPoints = tile.content.pointsLength;\r\n if (numberOfPoints > 0) {\r\n labelString += \"\\nPoints: \" + tile.content.pointsLength;\r\n attributes++;\r\n }\r\n\r\n var numberOfTriangles = tile.content.trianglesLength;\r\n if (numberOfTriangles > 0) {\r\n labelString += \"\\nTriangles: \" + tile.content.trianglesLength;\r\n attributes++;\r\n }\r\n\r\n labelString += \"\\nFeatures: \" + tile.content.featuresLength;\r\n attributes++;\r\n }\r\n\r\n if (tileset.debugShowMemoryUsage) {\r\n labelString +=\r\n \"\\nTexture Memory: \" +\r\n formatMemoryString(tile.content.texturesByteLength);\r\n labelString +=\r\n \"\\nGeometry Memory: \" +\r\n formatMemoryString(tile.content.geometryByteLength);\r\n attributes += 2;\r\n }\r\n\r\n if (tileset.debugShowUrl) {\r\n labelString += \"\\nUrl: \" + tile._header.content.uri;\r\n attributes++;\r\n }\r\n\r\n var newLabel = {\r\n text: labelString.substring(1),\r\n position: position,\r\n font: 19 - attributes + \"px sans-serif\",\r\n showBackground: true,\r\n disableDepthTestDistance: Number.POSITIVE_INFINITY,\r\n };\r\n\r\n return tileset._tileDebugLabels.add(newLabel);\r\n}\r\n\r\nfunction updateTileDebugLabels(tileset, frameState) {\r\n var i;\r\n var tile;\r\n var selectedTiles = tileset._selectedTiles;\r\n var selectedLength = selectedTiles.length;\r\n var emptyTiles = tileset._emptyTiles;\r\n var emptyLength = emptyTiles.length;\r\n tileset._tileDebugLabels.removeAll();\r\n\r\n if (tileset.debugPickedTileLabelOnly) {\r\n if (defined(tileset.debugPickedTile)) {\r\n var position = defined(tileset.debugPickPosition)\r\n ? tileset.debugPickPosition\r\n : computeTileLabelPosition(tileset.debugPickedTile);\r\n var label = addTileDebugLabel(tileset.debugPickedTile, tileset, position);\r\n label.pixelOffset = new Cartesian2(15, -15); // Offset to avoid picking the label.\r\n }\r\n } else {\r\n for (i = 0; i < selectedLength; ++i) {\r\n tile = selectedTiles[i];\r\n addTileDebugLabel(tile, tileset, computeTileLabelPosition(tile));\r\n }\r\n for (i = 0; i < emptyLength; ++i) {\r\n tile = emptyTiles[i];\r\n if (tile.hasTilesetContent) {\r\n addTileDebugLabel(tile, tileset, computeTileLabelPosition(tile));\r\n }\r\n }\r\n }\r\n tileset._tileDebugLabels.update(frameState);\r\n}\r\n\r\nfunction updateTiles(tileset, frameState, passOptions) {\r\n tileset._styleEngine.applyStyle(tileset);\r\n\r\n var isRender = passOptions.isRender;\r\n var statistics = tileset._statistics;\r\n var commandList = frameState.commandList;\r\n var numberOfInitialCommands = commandList.length;\r\n var selectedTiles = tileset._selectedTiles;\r\n var selectedLength = selectedTiles.length;\r\n var emptyTiles = tileset._emptyTiles;\r\n var emptyLength = emptyTiles.length;\r\n var tileVisible = tileset.tileVisible;\r\n var i;\r\n var tile;\r\n\r\n var bivariateVisibilityTest =\r\n tileset._skipLevelOfDetail &&\r\n tileset._hasMixedContent &&\r\n frameState.context.stencilBuffer &&\r\n selectedLength > 0;\r\n\r\n tileset._backfaceCommands.length = 0;\r\n\r\n if (bivariateVisibilityTest) {\r\n if (!defined(tileset._stencilClearCommand)) {\r\n tileset._stencilClearCommand = new ClearCommand({\r\n stencil: 0,\r\n pass: Pass.CESIUM_3D_TILE,\r\n renderState: RenderState.fromCache({\r\n stencilMask: StencilConstants.SKIP_LOD_MASK,\r\n }),\r\n });\r\n }\r\n commandList.push(tileset._stencilClearCommand);\r\n }\r\n\r\n var lengthBeforeUpdate = commandList.length;\r\n for (i = 0; i < selectedLength; ++i) {\r\n tile = selectedTiles[i];\r\n // Raise the tileVisible event before update in case the tileVisible event\r\n // handler makes changes that update needs to apply to WebGL resources\r\n if (isRender) {\r\n tileVisible.raiseEvent(tile);\r\n }\r\n tile.update(tileset, frameState, passOptions);\r\n statistics.incrementSelectionCounts(tile.content);\r\n ++statistics.selected;\r\n }\r\n for (i = 0; i < emptyLength; ++i) {\r\n tile = emptyTiles[i];\r\n tile.update(tileset, frameState, passOptions);\r\n }\r\n\r\n var addedCommandsLength = commandList.length - lengthBeforeUpdate;\r\n\r\n tileset._backfaceCommands.trim();\r\n\r\n if (bivariateVisibilityTest) {\r\n /*\r\n * Consider 'effective leaf' tiles as selected tiles that have no selected descendants. They may have children,\r\n * but they are currently our effective leaves because they do not have selected descendants. These tiles\r\n * are those where with tile._finalResolution === true.\r\n * Let 'unresolved' tiles be those with tile._finalResolution === false.\r\n *\r\n * 1. Render just the backfaces of unresolved tiles in order to lay down z\r\n * 2. Render all frontfaces wherever tile._selectionDepth > stencilBuffer.\r\n * Replace stencilBuffer with tile._selectionDepth, when passing the z test.\r\n * Because children are always drawn before ancestors {@link Cesium3DTilesetTraversal#traverseAndSelect},\r\n * this effectively draws children first and does not draw ancestors if a descendant has already\r\n * been drawn at that pixel.\r\n * Step 1 prevents child tiles from appearing on top when they are truly behind ancestor content.\r\n * If they are behind the backfaces of the ancestor, then they will not be drawn.\r\n *\r\n * NOTE: Step 2 sometimes causes visual artifacts when backfacing child content has some faces that\r\n * partially face the camera and are inside of the ancestor content. Because they are inside, they will\r\n * not be culled by the depth writes in Step 1, and because they partially face the camera, the stencil tests\r\n * will draw them on top of the ancestor content.\r\n *\r\n * NOTE: Because we always render backfaces of unresolved tiles, if the camera is looking at the backfaces\r\n * of an object, they will always be drawn while loading, even if backface culling is enabled.\r\n */\r\n\r\n var backfaceCommands = tileset._backfaceCommands.values;\r\n var backfaceCommandsLength = backfaceCommands.length;\r\n\r\n commandList.length += backfaceCommandsLength;\r\n\r\n // copy commands to the back of the commandList\r\n for (i = addedCommandsLength - 1; i >= 0; --i) {\r\n commandList[lengthBeforeUpdate + backfaceCommandsLength + i] =\r\n commandList[lengthBeforeUpdate + i];\r\n }\r\n\r\n // move backface commands to the front of the commandList\r\n for (i = 0; i < backfaceCommandsLength; ++i) {\r\n commandList[lengthBeforeUpdate + i] = backfaceCommands[i];\r\n }\r\n }\r\n\r\n // Number of commands added by each update above\r\n addedCommandsLength = commandList.length - numberOfInitialCommands;\r\n statistics.numberOfCommands = addedCommandsLength;\r\n\r\n // Only run EDL if simple attenuation is on\r\n if (\r\n isRender &&\r\n tileset.pointCloudShading.attenuation &&\r\n tileset.pointCloudShading.eyeDomeLighting &&\r\n addedCommandsLength > 0\r\n ) {\r\n tileset._pointCloudEyeDomeLighting.update(\r\n frameState,\r\n numberOfInitialCommands,\r\n tileset.pointCloudShading,\r\n tileset.boundingSphere\r\n );\r\n }\r\n\r\n if (isRender) {\r\n if (\r\n tileset.debugShowGeometricError ||\r\n tileset.debugShowRenderingStatistics ||\r\n tileset.debugShowMemoryUsage ||\r\n tileset.debugShowUrl\r\n ) {\r\n if (!defined(tileset._tileDebugLabels)) {\r\n tileset._tileDebugLabels = new LabelCollection();\r\n }\r\n updateTileDebugLabels(tileset, frameState);\r\n } else {\r\n tileset._tileDebugLabels =\r\n tileset._tileDebugLabels && tileset._tileDebugLabels.destroy();\r\n }\r\n }\r\n}\r\n\r\nvar scratchStack = [];\r\n\r\nfunction destroySubtree(tileset, tile) {\r\n var root = tile;\r\n var stack = scratchStack;\r\n stack.push(tile);\r\n while (stack.length > 0) {\r\n tile = stack.pop();\r\n var children = tile.children;\r\n var length = children.length;\r\n for (var i = 0; i < length; ++i) {\r\n stack.push(children[i]);\r\n }\r\n if (tile !== root) {\r\n destroyTile(tileset, tile);\r\n --tileset._statistics.numberOfTilesTotal;\r\n }\r\n }\r\n root.children = [];\r\n}\r\n\r\nfunction unloadTile(tileset, tile) {\r\n tileset.tileUnload.raiseEvent(tile);\r\n tileset._statistics.decrementLoadCounts(tile.content);\r\n --tileset._statistics.numberOfTilesWithContentReady;\r\n tile.unloadContent();\r\n}\r\n\r\nfunction destroyTile(tileset, tile) {\r\n tileset._cache.unloadTile(tileset, tile, unloadTile);\r\n tile.destroy();\r\n}\r\n\r\n/**\r\n * Unloads all tiles that weren't selected the previous frame. This can be used to\r\n * explicitly manage the tile cache and reduce the total number of tiles loaded below\r\n * {@link Cesium3DTileset#maximumMemoryUsage}.\r\n *

\r\n * Tile unloads occur at the next frame to keep all the WebGL delete calls\r\n * within the render loop.\r\n *

\r\n */\r\nCesium3DTileset.prototype.trimLoadedTiles = function () {\r\n this._cache.trim();\r\n};\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction raiseLoadProgressEvent(tileset, frameState) {\r\n var statistics = tileset._statistics;\r\n var statisticsLast = tileset._statisticsLast;\r\n\r\n var numberOfPendingRequests = statistics.numberOfPendingRequests;\r\n var numberOfTilesProcessing = statistics.numberOfTilesProcessing;\r\n var lastNumberOfPendingRequest = statisticsLast.numberOfPendingRequests;\r\n var lastNumberOfTilesProcessing = statisticsLast.numberOfTilesProcessing;\r\n\r\n Cesium3DTilesetStatistics.clone(statistics, statisticsLast);\r\n\r\n var progressChanged =\r\n numberOfPendingRequests !== lastNumberOfPendingRequest ||\r\n numberOfTilesProcessing !== lastNumberOfTilesProcessing;\r\n\r\n if (progressChanged) {\r\n frameState.afterRender.push(function () {\r\n tileset.loadProgress.raiseEvent(\r\n numberOfPendingRequests,\r\n numberOfTilesProcessing\r\n );\r\n });\r\n }\r\n\r\n tileset._tilesLoaded =\r\n statistics.numberOfPendingRequests === 0 &&\r\n statistics.numberOfTilesProcessing === 0 &&\r\n statistics.numberOfAttemptedRequests === 0;\r\n\r\n // Events are raised (added to the afterRender queue) here since promises\r\n // may resolve outside of the update loop that then raise events, e.g.,\r\n // model's readyPromise.\r\n if (progressChanged && tileset._tilesLoaded) {\r\n frameState.afterRender.push(function () {\r\n tileset.allTilesLoaded.raiseEvent();\r\n });\r\n if (!tileset._initialTilesLoaded) {\r\n tileset._initialTilesLoaded = true;\r\n frameState.afterRender.push(function () {\r\n tileset.initialTilesLoaded.raiseEvent();\r\n });\r\n }\r\n }\r\n}\r\n\r\nfunction resetMinimumMaximum(tileset) {\r\n tileset._heatmap.resetMinimumMaximum();\r\n tileset._minimumPriority.depth = Number.MAX_VALUE;\r\n tileset._maximumPriority.depth = -Number.MAX_VALUE;\r\n tileset._minimumPriority.foveatedFactor = Number.MAX_VALUE;\r\n tileset._maximumPriority.foveatedFactor = -Number.MAX_VALUE;\r\n tileset._minimumPriority.distance = Number.MAX_VALUE;\r\n tileset._maximumPriority.distance = -Number.MAX_VALUE;\r\n tileset._minimumPriority.reverseScreenSpaceError = Number.MAX_VALUE;\r\n tileset._maximumPriority.reverseScreenSpaceError = -Number.MAX_VALUE;\r\n}\r\n\r\nfunction detectModelMatrixChanged(tileset, frameState) {\r\n if (\r\n frameState.frameNumber !== tileset._updatedModelMatrixFrame ||\r\n !defined(tileset._previousModelMatrix)\r\n ) {\r\n tileset._updatedModelMatrixFrame = frameState.frameNumber;\r\n tileset._modelMatrixChanged = !Matrix4.equals(\r\n tileset.modelMatrix,\r\n tileset._previousModelMatrix\r\n );\r\n if (tileset._modelMatrixChanged) {\r\n tileset._previousModelMatrix = Matrix4.clone(\r\n tileset.modelMatrix,\r\n tileset._previousModelMatrix\r\n );\r\n }\r\n }\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\nfunction update(tileset, frameState, passStatistics, passOptions) {\r\n if (frameState.mode === SceneMode.MORPHING) {\r\n return false;\r\n }\r\n\r\n if (!tileset.ready) {\r\n return false;\r\n }\r\n\r\n var statistics = tileset._statistics;\r\n statistics.clear();\r\n\r\n var isRender = passOptions.isRender;\r\n\r\n // Resets the visibility check for each pass\r\n ++tileset._updatedVisibilityFrame;\r\n\r\n // Update any tracked min max values\r\n resetMinimumMaximum(tileset);\r\n\r\n detectModelMatrixChanged(tileset, frameState);\r\n tileset._cullRequestsWhileMoving =\r\n tileset.cullRequestsWhileMoving && !tileset._modelMatrixChanged;\r\n\r\n var ready = passOptions.traversal.selectTiles(tileset, frameState);\r\n\r\n if (passOptions.requestTiles) {\r\n requestTiles(tileset);\r\n }\r\n\r\n updateTiles(tileset, frameState, passOptions);\r\n\r\n // Update pass statistics\r\n Cesium3DTilesetStatistics.clone(statistics, passStatistics);\r\n\r\n if (isRender) {\r\n var credits = tileset._credits;\r\n if (defined(credits) && statistics.selected !== 0) {\r\n var length = credits.length;\r\n for (var i = 0; i < length; ++i) {\r\n frameState.creditDisplay.addCredit(credits[i]);\r\n }\r\n }\r\n }\r\n\r\n return ready;\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nCesium3DTileset.prototype.update = function (frameState) {\r\n this.updateForPass(frameState, frameState.tilesetPassState);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCesium3DTileset.prototype.updateForPass = function (\r\n frameState,\r\n tilesetPassState\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"frameState\", frameState);\r\n Check.typeOf.object(\"tilesetPassState\", tilesetPassState);\r\n //>>includeEnd('debug');\r\n\r\n var pass = tilesetPassState.pass;\r\n if (\r\n (pass === Cesium3DTilePass.PRELOAD &&\r\n (!this.preloadWhenHidden || this.show)) ||\r\n (pass === Cesium3DTilePass.PRELOAD_FLIGHT &&\r\n (!this.preloadFlightDestinations ||\r\n (!this.show && !this.preloadWhenHidden))) ||\r\n (pass === Cesium3DTilePass.REQUEST_RENDER_MODE_DEFER_CHECK &&\r\n ((!this._cullRequestsWhileMoving && this.foveatedTimeDelay <= 0) ||\r\n !this.show))\r\n ) {\r\n return;\r\n }\r\n\r\n var originalCommandList = frameState.commandList;\r\n var originalCamera = frameState.camera;\r\n var originalCullingVolume = frameState.cullingVolume;\r\n\r\n tilesetPassState.ready = false;\r\n\r\n var passOptions = Cesium3DTilePass.getPassOptions(pass);\r\n var ignoreCommands = passOptions.ignoreCommands;\r\n\r\n var commandList = defaultValue(\r\n tilesetPassState.commandList,\r\n originalCommandList\r\n );\r\n var commandStart = commandList.length;\r\n\r\n frameState.commandList = commandList;\r\n frameState.camera = defaultValue(tilesetPassState.camera, originalCamera);\r\n frameState.cullingVolume = defaultValue(\r\n tilesetPassState.cullingVolume,\r\n originalCullingVolume\r\n );\r\n\r\n var passStatistics = this._statisticsPerPass[pass];\r\n\r\n if (this.show || ignoreCommands) {\r\n this._pass = pass;\r\n tilesetPassState.ready = update(\r\n this,\r\n frameState,\r\n passStatistics,\r\n passOptions\r\n );\r\n }\r\n\r\n if (ignoreCommands) {\r\n commandList.length = commandStart;\r\n }\r\n\r\n frameState.commandList = originalCommandList;\r\n frameState.camera = originalCamera;\r\n frameState.cullingVolume = originalCullingVolume;\r\n};\r\n\r\n/**\r\n * true if the tileset JSON file lists the extension in extensionsUsed; otherwise, false.\r\n * @param {String} extensionName The name of the extension to check.\r\n *\r\n * @returns {Boolean} true if the tileset JSON file lists the extension in extensionsUsed; otherwise, false.\r\n */\r\nCesium3DTileset.prototype.hasExtension = function (extensionName) {\r\n if (!defined(this._extensionsUsed)) {\r\n return false;\r\n }\r\n\r\n return this._extensionsUsed.indexOf(extensionName) > -1;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see Cesium3DTileset#destroy\r\n */\r\nCesium3DTileset.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * tileset = tileset && tileset.destroy();\r\n *\r\n * @see Cesium3DTileset#isDestroyed\r\n */\r\nCesium3DTileset.prototype.destroy = function () {\r\n this._tileDebugLabels =\r\n this._tileDebugLabels && this._tileDebugLabels.destroy();\r\n this._clippingPlanes = this._clippingPlanes && this._clippingPlanes.destroy();\r\n\r\n // Traverse the tree and destroy all tiles\r\n if (defined(this._root)) {\r\n var stack = scratchStack;\r\n stack.push(this._root);\r\n\r\n while (stack.length > 0) {\r\n var tile = stack.pop();\r\n tile.destroy();\r\n\r\n var children = tile.children;\r\n var length = children.length;\r\n for (var i = 0; i < length; ++i) {\r\n stack.push(children[i]);\r\n }\r\n }\r\n }\r\n\r\n this._root = undefined;\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * Optimization option. Used as a callback when {@link Cesium3DTileset#foveatedScreenSpaceError} is true to control how much to raise the screen space error for tiles outside the foveated cone,\r\n * interpolating between {@link Cesium3DTileset#foveatedMinimumScreenSpaceErrorRelaxation} and {@link Cesium3DTileset#maximumScreenSpaceError}.\r\n *\r\n * @callback Cesium3DTileset.foveatedInterpolationCallback\r\n * @default Math.lerp\r\n *\r\n * @param {Number} p The start value to interpolate.\r\n * @param {Number} q The end value to interpolate.\r\n * @param {Number} time The time of interpolation generally in the range [0.0, 1.0].\r\n * @returns {Number} The interpolated value.\r\n */\r\nexport default Cesium3DTileset;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport Cesium3DTileset from \"../Scene/Cesium3DTileset.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar modelMatrixScratch = new Matrix4();\r\n\r\n/**\r\n * A {@link Visualizer} which maps {@link Entity#tileset} to a {@link Cesium3DTileset}.\r\n * @alias Cesium3DTilesetVisualizer\r\n * @constructor\r\n *\r\n * @param {Scene} scene The scene the primitives will be rendered in.\r\n * @param {EntityCollection} entityCollection The entityCollection to visualize.\r\n */\r\nfunction Cesium3DTilesetVisualizer(scene, entityCollection) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(scene)) {\r\n throw new DeveloperError(\"scene is required.\");\r\n }\r\n if (!defined(entityCollection)) {\r\n throw new DeveloperError(\"entityCollection is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n entityCollection.collectionChanged.addEventListener(\r\n Cesium3DTilesetVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n\r\n this._scene = scene;\r\n this._primitives = scene.primitives;\r\n this._entityCollection = entityCollection;\r\n this._tilesetHash = {};\r\n this._entitiesToVisualize = new AssociativeArray();\r\n this._onCollectionChanged(entityCollection, entityCollection.values, [], []);\r\n}\r\n\r\n/**\r\n * Updates models created this visualizer to match their\r\n * Entity counterpart at the given time.\r\n *\r\n * @param {JulianDate} time The time to update to.\r\n * @returns {Boolean} This function always returns true.\r\n */\r\nCesium3DTilesetVisualizer.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entities = this._entitiesToVisualize.values;\r\n var tilesetHash = this._tilesetHash;\r\n var primitives = this._primitives;\r\n\r\n for (var i = 0, len = entities.length; i < len; i++) {\r\n var entity = entities[i];\r\n var tilesetGraphics = entity._tileset;\r\n\r\n var resource;\r\n var tilesetData = tilesetHash[entity.id];\r\n var show =\r\n entity.isShowing &&\r\n entity.isAvailable(time) &&\r\n Property.getValueOrDefault(tilesetGraphics._show, time, true);\r\n\r\n var modelMatrix;\r\n if (show) {\r\n modelMatrix = entity.computeModelMatrix(time, modelMatrixScratch);\r\n resource = Resource.createIfNeeded(\r\n Property.getValueOrUndefined(tilesetGraphics._uri, time)\r\n );\r\n }\r\n\r\n if (!show) {\r\n if (defined(tilesetData)) {\r\n tilesetData.tilesetPrimitive.show = false;\r\n }\r\n continue;\r\n }\r\n\r\n var tileset = defined(tilesetData)\r\n ? tilesetData.tilesetPrimitive\r\n : undefined;\r\n if (!defined(tileset) || resource.url !== tilesetData.url) {\r\n if (defined(tileset)) {\r\n primitives.removeAndDestroy(tileset);\r\n delete tilesetHash[entity.id];\r\n }\r\n tileset = new Cesium3DTileset({\r\n url: resource,\r\n });\r\n tileset.id = entity;\r\n primitives.add(tileset);\r\n\r\n tilesetData = {\r\n tilesetPrimitive: tileset,\r\n url: resource.url,\r\n loadFail: false,\r\n };\r\n tilesetHash[entity.id] = tilesetData;\r\n\r\n checkLoad(tileset, entity, tilesetHash);\r\n }\r\n\r\n tileset.show = true;\r\n if (defined(modelMatrix)) {\r\n tileset.modelMatrix = modelMatrix;\r\n }\r\n tileset.maximumScreenSpaceError = Property.getValueOrDefault(\r\n tilesetGraphics.maximumScreenSpaceError,\r\n time,\r\n tileset.maximumScreenSpaceError\r\n );\r\n }\r\n\r\n return true;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nCesium3DTilesetVisualizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys all primitives created by this instance.\r\n */\r\nCesium3DTilesetVisualizer.prototype.destroy = function () {\r\n this._entityCollection.collectionChanged.removeEventListener(\r\n Cesium3DTilesetVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n var entities = this._entitiesToVisualize.values;\r\n var tilesetHash = this._tilesetHash;\r\n var primitives = this._primitives;\r\n for (var i = entities.length - 1; i > -1; i--) {\r\n removeTileset(this, entities[i], tilesetHash, primitives);\r\n }\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n *\r\n * @param {Entity} entity The entity whose bounding sphere to compute.\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nCesium3DTilesetVisualizer.prototype.getBoundingSphere = function (\r\n entity,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entity)) {\r\n throw new DeveloperError(\"entity is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var tilesetData = this._tilesetHash[entity.id];\r\n if (!defined(tilesetData) || tilesetData.loadFail) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n var primitive = tilesetData.tilesetPrimitive;\r\n if (!defined(primitive) || !primitive.show) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n if (!primitive.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n\r\n BoundingSphere.clone(primitive.boundingSphere, result);\r\n\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCesium3DTilesetVisualizer.prototype._onCollectionChanged = function (\r\n entityCollection,\r\n added,\r\n removed,\r\n changed\r\n) {\r\n var i;\r\n var entity;\r\n var entities = this._entitiesToVisualize;\r\n var tilesetHash = this._tilesetHash;\r\n var primitives = this._primitives;\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n if (defined(entity._tileset)) {\r\n entities.set(entity.id, entity);\r\n }\r\n }\r\n\r\n for (i = changed.length - 1; i > -1; i--) {\r\n entity = changed[i];\r\n if (defined(entity._tileset)) {\r\n entities.set(entity.id, entity);\r\n } else {\r\n removeTileset(this, entity, tilesetHash, primitives);\r\n entities.remove(entity.id);\r\n }\r\n }\r\n\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n removeTileset(this, entity, tilesetHash, primitives);\r\n entities.remove(entity.id);\r\n }\r\n};\r\n\r\nfunction removeTileset(visualizer, entity, tilesetHash, primitives) {\r\n var tilesetData = tilesetHash[entity.id];\r\n if (defined(tilesetData)) {\r\n primitives.removeAndDestroy(tilesetData.tilesetPrimitive);\r\n delete tilesetHash[entity.id];\r\n }\r\n}\r\n\r\nfunction checkLoad(primitive, entity, tilesetHash) {\r\n primitive.readyPromise.otherwise(function (error) {\r\n console.error(error);\r\n tilesetHash[entity.id].loadFail = true;\r\n });\r\n}\r\nexport default Cesium3DTilesetVisualizer;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultEvenColor = Color.WHITE;\r\nvar defaultOddColor = Color.BLACK;\r\nvar defaultRepeat = new Cartesian2(2.0, 2.0);\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to checkerboard {@link Material} uniforms.\r\n * @alias CheckerboardMaterialProperty\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Property|Color} [options.evenColor=Color.WHITE] A Property specifying the first {@link Color}.\r\n * @param {Property|Color} [options.oddColor=Color.BLACK] A Property specifying the second {@link Color}.\r\n * @param {Property|Cartesian2} [options.repeat=new Cartesian2(2.0, 2.0)] A {@link Cartesian2} Property specifying how many times the tiles repeat in each direction.\r\n */\r\nfunction CheckerboardMaterialProperty(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._definitionChanged = new Event();\r\n this._evenColor = undefined;\r\n this._evenColorSubscription = undefined;\r\n this._oddColor = undefined;\r\n this._oddColorSubscription = undefined;\r\n this._repeat = undefined;\r\n this._repeatSubscription = undefined;\r\n\r\n this.evenColor = options.evenColor;\r\n this.oddColor = options.oddColor;\r\n this.repeat = options.repeat;\r\n}\r\n\r\nObject.defineProperties(CheckerboardMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof CheckerboardMaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n Property.isConstant(this._evenColor) && //\r\n Property.isConstant(this._oddColor) && //\r\n Property.isConstant(this._repeat)\r\n );\r\n },\r\n },\r\n\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof CheckerboardMaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the Property specifying the first {@link Color}.\r\n * @memberof CheckerboardMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n evenColor: createPropertyDescriptor(\"evenColor\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the second {@link Color}.\r\n * @memberof CheckerboardMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n oddColor: createPropertyDescriptor(\"oddColor\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying how many times the tiles repeat in each direction.\r\n * @memberof CheckerboardMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default new Cartesian2(2.0, 2.0)\r\n */\r\n repeat: createPropertyDescriptor(\"repeat\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nCheckerboardMaterialProperty.prototype.getType = function (time) {\r\n return \"Checkerboard\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nCheckerboardMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n result.lightColor = Property.getValueOrClonedDefault(\r\n this._evenColor,\r\n time,\r\n defaultEvenColor,\r\n result.lightColor\r\n );\r\n result.darkColor = Property.getValueOrClonedDefault(\r\n this._oddColor,\r\n time,\r\n defaultOddColor,\r\n result.darkColor\r\n );\r\n result.repeat = Property.getValueOrDefault(this._repeat, time, defaultRepeat);\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCheckerboardMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof CheckerboardMaterialProperty && //\r\n Property.equals(this._evenColor, other._evenColor) && //\r\n Property.equals(this._oddColor, other._oddColor) && //\r\n Property.equals(this._repeat, other._repeat))\r\n );\r\n};\r\nexport default CheckerboardMaterialProperty;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport TimeInterval from \"../Core/TimeInterval.js\";\r\nimport Entity from \"./Entity.js\";\r\n\r\nvar entityOptionsScratch = {\r\n id: undefined,\r\n};\r\n\r\nfunction fireChangedEvent(collection) {\r\n if (collection._firing) {\r\n collection._refire = true;\r\n return;\r\n }\r\n\r\n if (collection._suspendCount === 0) {\r\n var added = collection._addedEntities;\r\n var removed = collection._removedEntities;\r\n var changed = collection._changedEntities;\r\n if (changed.length !== 0 || added.length !== 0 || removed.length !== 0) {\r\n collection._firing = true;\r\n do {\r\n collection._refire = false;\r\n var addedArray = added.values.slice(0);\r\n var removedArray = removed.values.slice(0);\r\n var changedArray = changed.values.slice(0);\r\n\r\n added.removeAll();\r\n removed.removeAll();\r\n changed.removeAll();\r\n collection._collectionChanged.raiseEvent(\r\n collection,\r\n addedArray,\r\n removedArray,\r\n changedArray\r\n );\r\n } while (collection._refire);\r\n collection._firing = false;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * An observable collection of {@link Entity} instances where each entity has a unique id.\r\n * @alias EntityCollection\r\n * @constructor\r\n *\r\n * @param {DataSource|CompositeEntityCollection} [owner] The data source (or composite entity collection) which created this collection.\r\n */\r\nfunction EntityCollection(owner) {\r\n this._owner = owner;\r\n this._entities = new AssociativeArray();\r\n this._addedEntities = new AssociativeArray();\r\n this._removedEntities = new AssociativeArray();\r\n this._changedEntities = new AssociativeArray();\r\n this._suspendCount = 0;\r\n this._collectionChanged = new Event();\r\n this._id = createGuid();\r\n this._show = true;\r\n this._firing = false;\r\n this._refire = false;\r\n}\r\n\r\n/**\r\n * Prevents {@link EntityCollection#collectionChanged} events from being raised\r\n * until a corresponding call is made to {@link EntityCollection#resumeEvents}, at which\r\n * point a single event will be raised that covers all suspended operations.\r\n * This allows for many items to be added and removed efficiently.\r\n * This function can be safely called multiple times as long as there\r\n * are corresponding calls to {@link EntityCollection#resumeEvents}.\r\n */\r\nEntityCollection.prototype.suspendEvents = function () {\r\n this._suspendCount++;\r\n};\r\n\r\n/**\r\n * Resumes raising {@link EntityCollection#collectionChanged} events immediately\r\n * when an item is added or removed. Any modifications made while while events were suspended\r\n * will be triggered as a single event when this function is called.\r\n * This function is reference counted and can safely be called multiple times as long as there\r\n * are corresponding calls to {@link EntityCollection#resumeEvents}.\r\n *\r\n * @exception {DeveloperError} resumeEvents can not be called before suspendEvents.\r\n */\r\nEntityCollection.prototype.resumeEvents = function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (this._suspendCount === 0) {\r\n throw new DeveloperError(\r\n \"resumeEvents can not be called before suspendEvents.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._suspendCount--;\r\n fireChangedEvent(this);\r\n};\r\n\r\n/**\r\n * The signature of the event generated by {@link EntityCollection#collectionChanged}.\r\n * @function\r\n *\r\n * @param {EntityCollection} collection The collection that triggered the event.\r\n * @param {Entity[]} added The array of {@link Entity} instances that have been added to the collection.\r\n * @param {Entity[]} removed The array of {@link Entity} instances that have been removed from the collection.\r\n * @param {Entity[]} changed The array of {@link Entity} instances that have been modified.\r\n */\r\nEntityCollection.collectionChangedEventCallback = undefined;\r\n\r\nObject.defineProperties(EntityCollection.prototype, {\r\n /**\r\n * Gets the event that is fired when entities are added or removed from the collection.\r\n * The generated event is a {@link EntityCollection.collectionChangedEventCallback}.\r\n * @memberof EntityCollection.prototype\r\n * @readonly\r\n * @type {Event}\r\n */\r\n collectionChanged: {\r\n get: function () {\r\n return this._collectionChanged;\r\n },\r\n },\r\n /**\r\n * Gets a globally unique identifier for this collection.\r\n * @memberof EntityCollection.prototype\r\n * @readonly\r\n * @type {String}\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n /**\r\n * Gets the array of Entity instances in the collection.\r\n * This array should not be modified directly.\r\n * @memberof EntityCollection.prototype\r\n * @readonly\r\n * @type {Entity[]}\r\n */\r\n values: {\r\n get: function () {\r\n return this._entities.values;\r\n },\r\n },\r\n /**\r\n * Gets whether or not this entity collection should be\r\n * displayed. When true, each entity is only displayed if\r\n * its own show property is also true.\r\n * @memberof EntityCollection.prototype\r\n * @type {Boolean}\r\n */\r\n show: {\r\n get: function () {\r\n return this._show;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (value === this._show) {\r\n return;\r\n }\r\n\r\n //Since entity.isShowing includes the EntityCollection.show state\r\n //in its calculation, we need to loop over the entities array\r\n //twice, once to get the old showing value and a second time\r\n //to raise the changed event.\r\n this.suspendEvents();\r\n\r\n var i;\r\n var oldShows = [];\r\n var entities = this._entities.values;\r\n var entitiesLength = entities.length;\r\n\r\n for (i = 0; i < entitiesLength; i++) {\r\n oldShows.push(entities[i].isShowing);\r\n }\r\n\r\n this._show = value;\r\n\r\n for (i = 0; i < entitiesLength; i++) {\r\n var oldShow = oldShows[i];\r\n var entity = entities[i];\r\n if (oldShow !== entity.isShowing) {\r\n entity.definitionChanged.raiseEvent(\r\n entity,\r\n \"isShowing\",\r\n entity.isShowing,\r\n oldShow\r\n );\r\n }\r\n }\r\n\r\n this.resumeEvents();\r\n },\r\n },\r\n /**\r\n * Gets the owner of this entity collection, ie. the data source or composite entity collection which created it.\r\n * @memberof EntityCollection.prototype\r\n * @readonly\r\n * @type {DataSource|CompositeEntityCollection}\r\n */\r\n owner: {\r\n get: function () {\r\n return this._owner;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Computes the maximum availability of the entities in the collection.\r\n * If the collection contains a mix of infinitely available data and non-infinite data,\r\n * it will return the interval pertaining to the non-infinite data only. If all\r\n * data is infinite, an infinite interval will be returned.\r\n *\r\n * @returns {TimeInterval} The availability of entities in the collection.\r\n */\r\nEntityCollection.prototype.computeAvailability = function () {\r\n var startTime = Iso8601.MAXIMUM_VALUE;\r\n var stopTime = Iso8601.MINIMUM_VALUE;\r\n var entities = this._entities.values;\r\n for (var i = 0, len = entities.length; i < len; i++) {\r\n var entity = entities[i];\r\n var availability = entity.availability;\r\n if (defined(availability)) {\r\n var start = availability.start;\r\n var stop = availability.stop;\r\n if (\r\n JulianDate.lessThan(start, startTime) &&\r\n !start.equals(Iso8601.MINIMUM_VALUE)\r\n ) {\r\n startTime = start;\r\n }\r\n if (\r\n JulianDate.greaterThan(stop, stopTime) &&\r\n !stop.equals(Iso8601.MAXIMUM_VALUE)\r\n ) {\r\n stopTime = stop;\r\n }\r\n }\r\n }\r\n\r\n if (Iso8601.MAXIMUM_VALUE.equals(startTime)) {\r\n startTime = Iso8601.MINIMUM_VALUE;\r\n }\r\n if (Iso8601.MINIMUM_VALUE.equals(stopTime)) {\r\n stopTime = Iso8601.MAXIMUM_VALUE;\r\n }\r\n return new TimeInterval({\r\n start: startTime,\r\n stop: stopTime,\r\n });\r\n};\r\n\r\n/**\r\n * Add an entity to the collection.\r\n *\r\n * @param {Entity | Entity.ConstructorOptions} entity The entity to be added.\r\n * @returns {Entity} The entity that was added.\r\n * @exception {DeveloperError} An entity with already exists in this collection.\r\n */\r\nEntityCollection.prototype.add = function (entity) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entity)) {\r\n throw new DeveloperError(\"entity is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!(entity instanceof Entity)) {\r\n entity = new Entity(entity);\r\n }\r\n\r\n var id = entity.id;\r\n var entities = this._entities;\r\n if (entities.contains(id)) {\r\n throw new RuntimeError(\r\n \"An entity with id \" + id + \" already exists in this collection.\"\r\n );\r\n }\r\n\r\n entity.entityCollection = this;\r\n entities.set(id, entity);\r\n\r\n if (!this._removedEntities.remove(id)) {\r\n this._addedEntities.set(id, entity);\r\n }\r\n entity.definitionChanged.addEventListener(\r\n EntityCollection.prototype._onEntityDefinitionChanged,\r\n this\r\n );\r\n\r\n fireChangedEvent(this);\r\n return entity;\r\n};\r\n\r\n/**\r\n * Removes an entity from the collection.\r\n *\r\n * @param {Entity} entity The entity to be removed.\r\n * @returns {Boolean} true if the item was removed, false if it did not exist in the collection.\r\n */\r\nEntityCollection.prototype.remove = function (entity) {\r\n if (!defined(entity)) {\r\n return false;\r\n }\r\n return this.removeById(entity.id);\r\n};\r\n\r\n/**\r\n * Returns true if the provided entity is in this collection, false otherwise.\r\n *\r\n * @param {Entity} entity The entity.\r\n * @returns {Boolean} true if the provided entity is in this collection, false otherwise.\r\n */\r\nEntityCollection.prototype.contains = function (entity) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entity)) {\r\n throw new DeveloperError(\"entity is required\");\r\n }\r\n //>>includeEnd('debug');\r\n return this._entities.get(entity.id) === entity;\r\n};\r\n\r\n/**\r\n * Removes an entity with the provided id from the collection.\r\n *\r\n * @param {String} id The id of the entity to remove.\r\n * @returns {Boolean} true if the item was removed, false if no item with the provided id existed in the collection.\r\n */\r\nEntityCollection.prototype.removeById = function (id) {\r\n if (!defined(id)) {\r\n return false;\r\n }\r\n\r\n var entities = this._entities;\r\n var entity = entities.get(id);\r\n if (!this._entities.remove(id)) {\r\n return false;\r\n }\r\n\r\n if (!this._addedEntities.remove(id)) {\r\n this._removedEntities.set(id, entity);\r\n this._changedEntities.remove(id);\r\n }\r\n this._entities.remove(id);\r\n entity.definitionChanged.removeEventListener(\r\n EntityCollection.prototype._onEntityDefinitionChanged,\r\n this\r\n );\r\n fireChangedEvent(this);\r\n\r\n return true;\r\n};\r\n\r\n/**\r\n * Removes all Entities from the collection.\r\n */\r\nEntityCollection.prototype.removeAll = function () {\r\n //The event should only contain items added before events were suspended\r\n //and the contents of the collection.\r\n var entities = this._entities;\r\n var entitiesLength = entities.length;\r\n var array = entities.values;\r\n\r\n var addedEntities = this._addedEntities;\r\n var removed = this._removedEntities;\r\n\r\n for (var i = 0; i < entitiesLength; i++) {\r\n var existingItem = array[i];\r\n var existingItemId = existingItem.id;\r\n var addedItem = addedEntities.get(existingItemId);\r\n if (!defined(addedItem)) {\r\n existingItem.definitionChanged.removeEventListener(\r\n EntityCollection.prototype._onEntityDefinitionChanged,\r\n this\r\n );\r\n removed.set(existingItemId, existingItem);\r\n }\r\n }\r\n\r\n entities.removeAll();\r\n addedEntities.removeAll();\r\n this._changedEntities.removeAll();\r\n fireChangedEvent(this);\r\n};\r\n\r\n/**\r\n * Gets an entity with the specified id.\r\n *\r\n * @param {String} id The id of the entity to retrieve.\r\n * @returns {Entity|undefined} The entity with the provided id or undefined if the id did not exist in the collection.\r\n */\r\nEntityCollection.prototype.getById = function (id) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(id)) {\r\n throw new DeveloperError(\"id is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._entities.get(id);\r\n};\r\n\r\n/**\r\n * Gets an entity with the specified id or creates it and adds it to the collection if it does not exist.\r\n *\r\n * @param {String} id The id of the entity to retrieve or create.\r\n * @returns {Entity} The new or existing object.\r\n */\r\nEntityCollection.prototype.getOrCreateEntity = function (id) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(id)) {\r\n throw new DeveloperError(\"id is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entities.get(id);\r\n if (!defined(entity)) {\r\n entityOptionsScratch.id = id;\r\n entity = new Entity(entityOptionsScratch);\r\n this.add(entity);\r\n }\r\n return entity;\r\n};\r\n\r\nEntityCollection.prototype._onEntityDefinitionChanged = function (entity) {\r\n var id = entity.id;\r\n if (!this._addedEntities.contains(id)) {\r\n this._changedEntities.set(id, entity);\r\n }\r\n fireChangedEvent(this);\r\n};\r\nexport default EntityCollection;\r\n","import createGuid from \"../Core/createGuid.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Entity from \"./Entity.js\";\r\nimport EntityCollection from \"./EntityCollection.js\";\r\n\r\nvar entityOptionsScratch = {\r\n id: undefined,\r\n};\r\nvar entityIdScratch = new Array(2);\r\n\r\nfunction clean(entity) {\r\n var propertyNames = entity.propertyNames;\r\n var propertyNamesLength = propertyNames.length;\r\n for (var i = 0; i < propertyNamesLength; i++) {\r\n entity[propertyNames[i]] = undefined;\r\n }\r\n entity._name = undefined;\r\n entity._availability = undefined;\r\n}\r\n\r\nfunction subscribeToEntity(that, eventHash, collectionId, entity) {\r\n entityIdScratch[0] = collectionId;\r\n entityIdScratch[1] = entity.id;\r\n eventHash[\r\n JSON.stringify(entityIdScratch)\r\n ] = entity.definitionChanged.addEventListener(\r\n CompositeEntityCollection.prototype._onDefinitionChanged,\r\n that\r\n );\r\n}\r\n\r\nfunction unsubscribeFromEntity(that, eventHash, collectionId, entity) {\r\n entityIdScratch[0] = collectionId;\r\n entityIdScratch[1] = entity.id;\r\n var id = JSON.stringify(entityIdScratch);\r\n eventHash[id]();\r\n eventHash[id] = undefined;\r\n}\r\n\r\nfunction recomposite(that) {\r\n that._shouldRecomposite = true;\r\n if (that._suspendCount !== 0) {\r\n return;\r\n }\r\n\r\n var collections = that._collections;\r\n var collectionsLength = collections.length;\r\n\r\n var collectionsCopy = that._collectionsCopy;\r\n var collectionsCopyLength = collectionsCopy.length;\r\n\r\n var i;\r\n var entity;\r\n var entities;\r\n var iEntities;\r\n var collection;\r\n var composite = that._composite;\r\n var newEntities = new EntityCollection(that);\r\n var eventHash = that._eventHash;\r\n var collectionId;\r\n\r\n for (i = 0; i < collectionsCopyLength; i++) {\r\n collection = collectionsCopy[i];\r\n collection.collectionChanged.removeEventListener(\r\n CompositeEntityCollection.prototype._onCollectionChanged,\r\n that\r\n );\r\n entities = collection.values;\r\n collectionId = collection.id;\r\n for (iEntities = entities.length - 1; iEntities > -1; iEntities--) {\r\n entity = entities[iEntities];\r\n unsubscribeFromEntity(that, eventHash, collectionId, entity);\r\n }\r\n }\r\n\r\n for (i = collectionsLength - 1; i >= 0; i--) {\r\n collection = collections[i];\r\n collection.collectionChanged.addEventListener(\r\n CompositeEntityCollection.prototype._onCollectionChanged,\r\n that\r\n );\r\n\r\n //Merge all of the existing entities.\r\n entities = collection.values;\r\n collectionId = collection.id;\r\n for (iEntities = entities.length - 1; iEntities > -1; iEntities--) {\r\n entity = entities[iEntities];\r\n subscribeToEntity(that, eventHash, collectionId, entity);\r\n\r\n var compositeEntity = newEntities.getById(entity.id);\r\n if (!defined(compositeEntity)) {\r\n compositeEntity = composite.getById(entity.id);\r\n if (!defined(compositeEntity)) {\r\n entityOptionsScratch.id = entity.id;\r\n compositeEntity = new Entity(entityOptionsScratch);\r\n } else {\r\n clean(compositeEntity);\r\n }\r\n newEntities.add(compositeEntity);\r\n }\r\n compositeEntity.merge(entity);\r\n }\r\n }\r\n that._collectionsCopy = collections.slice(0);\r\n\r\n composite.suspendEvents();\r\n composite.removeAll();\r\n var newEntitiesArray = newEntities.values;\r\n for (i = 0; i < newEntitiesArray.length; i++) {\r\n composite.add(newEntitiesArray[i]);\r\n }\r\n composite.resumeEvents();\r\n}\r\n\r\n/**\r\n * Non-destructively composites multiple {@link EntityCollection} instances into a single collection.\r\n * If a Entity with the same ID exists in multiple collections, it is non-destructively\r\n * merged into a single new entity instance. If an entity has the same property in multiple\r\n * collections, the property of the Entity in the last collection of the list it\r\n * belongs to is used. CompositeEntityCollection can be used almost anywhere that a\r\n * EntityCollection is used.\r\n *\r\n * @alias CompositeEntityCollection\r\n * @constructor\r\n *\r\n * @param {EntityCollection[]} [collections] The initial list of EntityCollection instances to merge.\r\n * @param {DataSource|CompositeEntityCollection} [owner] The data source (or composite entity collection) which created this collection.\r\n */\r\nfunction CompositeEntityCollection(collections, owner) {\r\n this._owner = owner;\r\n this._composite = new EntityCollection(this);\r\n this._suspendCount = 0;\r\n this._collections = defined(collections) ? collections.slice() : [];\r\n this._collectionsCopy = [];\r\n this._id = createGuid();\r\n this._eventHash = {};\r\n recomposite(this);\r\n this._shouldRecomposite = false;\r\n}\r\n\r\nObject.defineProperties(CompositeEntityCollection.prototype, {\r\n /**\r\n * Gets the event that is fired when entities are added or removed from the collection.\r\n * The generated event is a {@link EntityCollection.collectionChangedEventCallback}.\r\n * @memberof CompositeEntityCollection.prototype\r\n * @readonly\r\n * @type {Event}\r\n */\r\n collectionChanged: {\r\n get: function () {\r\n return this._composite._collectionChanged;\r\n },\r\n },\r\n /**\r\n * Gets a globally unique identifier for this collection.\r\n * @memberof CompositeEntityCollection.prototype\r\n * @readonly\r\n * @type {String}\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n /**\r\n * Gets the array of Entity instances in the collection.\r\n * This array should not be modified directly.\r\n * @memberof CompositeEntityCollection.prototype\r\n * @readonly\r\n * @type {Entity[]}\r\n */\r\n values: {\r\n get: function () {\r\n return this._composite.values;\r\n },\r\n },\r\n /**\r\n * Gets the owner of this composite entity collection, ie. the data source or composite entity collection which created it.\r\n * @memberof CompositeEntityCollection.prototype\r\n * @readonly\r\n * @type {DataSource|CompositeEntityCollection}\r\n */\r\n owner: {\r\n get: function () {\r\n return this._owner;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Adds a collection to the composite.\r\n *\r\n * @param {EntityCollection} collection the collection to add.\r\n * @param {Number} [index] the index to add the collection at. If omitted, the collection will\r\n * added on top of all existing collections.\r\n *\r\n * @exception {DeveloperError} index, if supplied, must be greater than or equal to zero and less than or equal to the number of collections.\r\n */\r\nCompositeEntityCollection.prototype.addCollection = function (\r\n collection,\r\n index\r\n) {\r\n var hasIndex = defined(index);\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(collection)) {\r\n throw new DeveloperError(\"collection is required.\");\r\n }\r\n if (hasIndex) {\r\n if (index < 0) {\r\n throw new DeveloperError(\"index must be greater than or equal to zero.\");\r\n } else if (index > this._collections.length) {\r\n throw new DeveloperError(\r\n \"index must be less than or equal to the number of collections.\"\r\n );\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!hasIndex) {\r\n index = this._collections.length;\r\n this._collections.push(collection);\r\n } else {\r\n this._collections.splice(index, 0, collection);\r\n }\r\n\r\n recomposite(this);\r\n};\r\n\r\n/**\r\n * Removes a collection from this composite, if present.\r\n *\r\n * @param {EntityCollection} collection The collection to remove.\r\n * @returns {Boolean} true if the collection was in the composite and was removed,\r\n * false if the collection was not in the composite.\r\n */\r\nCompositeEntityCollection.prototype.removeCollection = function (collection) {\r\n var index = this._collections.indexOf(collection);\r\n if (index !== -1) {\r\n this._collections.splice(index, 1);\r\n recomposite(this);\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes all collections from this composite.\r\n */\r\nCompositeEntityCollection.prototype.removeAllCollections = function () {\r\n this._collections.length = 0;\r\n recomposite(this);\r\n};\r\n\r\n/**\r\n * Checks to see if the composite contains a given collection.\r\n *\r\n * @param {EntityCollection} collection the collection to check for.\r\n * @returns {Boolean} true if the composite contains the collection, false otherwise.\r\n */\r\nCompositeEntityCollection.prototype.containsCollection = function (collection) {\r\n return this._collections.indexOf(collection) !== -1;\r\n};\r\n\r\n/**\r\n * Returns true if the provided entity is in this collection, false otherwise.\r\n *\r\n * @param {Entity} entity The entity.\r\n * @returns {Boolean} true if the provided entity is in this collection, false otherwise.\r\n */\r\nCompositeEntityCollection.prototype.contains = function (entity) {\r\n return this._composite.contains(entity);\r\n};\r\n\r\n/**\r\n * Determines the index of a given collection in the composite.\r\n *\r\n * @param {EntityCollection} collection The collection to find the index of.\r\n * @returns {Number} The index of the collection in the composite, or -1 if the collection does not exist in the composite.\r\n */\r\nCompositeEntityCollection.prototype.indexOfCollection = function (collection) {\r\n return this._collections.indexOf(collection);\r\n};\r\n\r\n/**\r\n * Gets a collection by index from the composite.\r\n *\r\n * @param {Number} index the index to retrieve.\r\n */\r\nCompositeEntityCollection.prototype.getCollection = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\", \"index\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._collections[index];\r\n};\r\n\r\n/**\r\n * Gets the number of collections in this composite.\r\n */\r\nCompositeEntityCollection.prototype.getCollectionsLength = function () {\r\n return this._collections.length;\r\n};\r\n\r\nfunction getCollectionIndex(collections, collection) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(collection)) {\r\n throw new DeveloperError(\"collection is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var index = collections.indexOf(collection);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (index === -1) {\r\n throw new DeveloperError(\"collection is not in this composite.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return index;\r\n}\r\n\r\nfunction swapCollections(composite, i, j) {\r\n var arr = composite._collections;\r\n i = CesiumMath.clamp(i, 0, arr.length - 1);\r\n j = CesiumMath.clamp(j, 0, arr.length - 1);\r\n\r\n if (i === j) {\r\n return;\r\n }\r\n\r\n var temp = arr[i];\r\n arr[i] = arr[j];\r\n arr[j] = temp;\r\n\r\n recomposite(composite);\r\n}\r\n\r\n/**\r\n * Raises a collection up one position in the composite.\r\n *\r\n * @param {EntityCollection} collection the collection to move.\r\n *\r\n * @exception {DeveloperError} collection is not in this composite.\r\n */\r\nCompositeEntityCollection.prototype.raiseCollection = function (collection) {\r\n var index = getCollectionIndex(this._collections, collection);\r\n swapCollections(this, index, index + 1);\r\n};\r\n\r\n/**\r\n * Lowers a collection down one position in the composite.\r\n *\r\n * @param {EntityCollection} collection the collection to move.\r\n *\r\n * @exception {DeveloperError} collection is not in this composite.\r\n */\r\nCompositeEntityCollection.prototype.lowerCollection = function (collection) {\r\n var index = getCollectionIndex(this._collections, collection);\r\n swapCollections(this, index, index - 1);\r\n};\r\n\r\n/**\r\n * Raises a collection to the top of the composite.\r\n *\r\n * @param {EntityCollection} collection the collection to move.\r\n *\r\n * @exception {DeveloperError} collection is not in this composite.\r\n */\r\nCompositeEntityCollection.prototype.raiseCollectionToTop = function (\r\n collection\r\n) {\r\n var index = getCollectionIndex(this._collections, collection);\r\n if (index === this._collections.length - 1) {\r\n return;\r\n }\r\n this._collections.splice(index, 1);\r\n this._collections.push(collection);\r\n\r\n recomposite(this);\r\n};\r\n\r\n/**\r\n * Lowers a collection to the bottom of the composite.\r\n *\r\n * @param {EntityCollection} collection the collection to move.\r\n *\r\n * @exception {DeveloperError} collection is not in this composite.\r\n */\r\nCompositeEntityCollection.prototype.lowerCollectionToBottom = function (\r\n collection\r\n) {\r\n var index = getCollectionIndex(this._collections, collection);\r\n if (index === 0) {\r\n return;\r\n }\r\n this._collections.splice(index, 1);\r\n this._collections.splice(0, 0, collection);\r\n\r\n recomposite(this);\r\n};\r\n\r\n/**\r\n * Prevents {@link EntityCollection#collectionChanged} events from being raised\r\n * until a corresponding call is made to {@link EntityCollection#resumeEvents}, at which\r\n * point a single event will be raised that covers all suspended operations.\r\n * This allows for many items to be added and removed efficiently.\r\n * While events are suspended, recompositing of the collections will\r\n * also be suspended, as this can be a costly operation.\r\n * This function can be safely called multiple times as long as there\r\n * are corresponding calls to {@link EntityCollection#resumeEvents}.\r\n */\r\nCompositeEntityCollection.prototype.suspendEvents = function () {\r\n this._suspendCount++;\r\n this._composite.suspendEvents();\r\n};\r\n\r\n/**\r\n * Resumes raising {@link EntityCollection#collectionChanged} events immediately\r\n * when an item is added or removed. Any modifications made while while events were suspended\r\n * will be triggered as a single event when this function is called. This function also ensures\r\n * the collection is recomposited if events are also resumed.\r\n * This function is reference counted and can safely be called multiple times as long as there\r\n * are corresponding calls to {@link EntityCollection#resumeEvents}.\r\n *\r\n * @exception {DeveloperError} resumeEvents can not be called before suspendEvents.\r\n */\r\nCompositeEntityCollection.prototype.resumeEvents = function () {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (this._suspendCount === 0) {\r\n throw new DeveloperError(\r\n \"resumeEvents can not be called before suspendEvents.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._suspendCount--;\r\n // recomposite before triggering events (but only if required for performance) that might depend on a composited collection\r\n if (this._shouldRecomposite && this._suspendCount === 0) {\r\n recomposite(this);\r\n this._shouldRecomposite = false;\r\n }\r\n\r\n this._composite.resumeEvents();\r\n};\r\n\r\n/**\r\n * Computes the maximum availability of the entities in the collection.\r\n * If the collection contains a mix of infinitely available data and non-infinite data,\r\n * It will return the interval pertaining to the non-infinite data only. If all\r\n * data is infinite, an infinite interval will be returned.\r\n *\r\n * @returns {TimeInterval} The availability of entities in the collection.\r\n */\r\nCompositeEntityCollection.prototype.computeAvailability = function () {\r\n return this._composite.computeAvailability();\r\n};\r\n\r\n/**\r\n * Gets an entity with the specified id.\r\n *\r\n * @param {String} id The id of the entity to retrieve.\r\n * @returns {Entity|undefined} The entity with the provided id or undefined if the id did not exist in the collection.\r\n */\r\nCompositeEntityCollection.prototype.getById = function (id) {\r\n return this._composite.getById(id);\r\n};\r\n\r\nCompositeEntityCollection.prototype._onCollectionChanged = function (\r\n collection,\r\n added,\r\n removed\r\n) {\r\n var collections = this._collectionsCopy;\r\n var collectionsLength = collections.length;\r\n var composite = this._composite;\r\n composite.suspendEvents();\r\n\r\n var i;\r\n var q;\r\n var entity;\r\n var compositeEntity;\r\n var removedLength = removed.length;\r\n var eventHash = this._eventHash;\r\n var collectionId = collection.id;\r\n for (i = 0; i < removedLength; i++) {\r\n var removedEntity = removed[i];\r\n unsubscribeFromEntity(this, eventHash, collectionId, removedEntity);\r\n\r\n var removedId = removedEntity.id;\r\n //Check if the removed entity exists in any of the remaining collections\r\n //If so, we clean and remerge it.\r\n for (q = collectionsLength - 1; q >= 0; q--) {\r\n entity = collections[q].getById(removedId);\r\n if (defined(entity)) {\r\n if (!defined(compositeEntity)) {\r\n compositeEntity = composite.getById(removedId);\r\n clean(compositeEntity);\r\n }\r\n compositeEntity.merge(entity);\r\n }\r\n }\r\n //We never retrieved the compositeEntity, which means it no longer\r\n //exists in any of the collections, remove it from the composite.\r\n if (!defined(compositeEntity)) {\r\n composite.removeById(removedId);\r\n }\r\n compositeEntity = undefined;\r\n }\r\n\r\n var addedLength = added.length;\r\n for (i = 0; i < addedLength; i++) {\r\n var addedEntity = added[i];\r\n subscribeToEntity(this, eventHash, collectionId, addedEntity);\r\n\r\n var addedId = addedEntity.id;\r\n //We know the added entity exists in at least one collection,\r\n //but we need to check all collections and re-merge in order\r\n //to maintain the priority of properties.\r\n for (q = collectionsLength - 1; q >= 0; q--) {\r\n entity = collections[q].getById(addedId);\r\n if (defined(entity)) {\r\n if (!defined(compositeEntity)) {\r\n compositeEntity = composite.getById(addedId);\r\n if (!defined(compositeEntity)) {\r\n entityOptionsScratch.id = addedId;\r\n compositeEntity = new Entity(entityOptionsScratch);\r\n composite.add(compositeEntity);\r\n } else {\r\n clean(compositeEntity);\r\n }\r\n }\r\n compositeEntity.merge(entity);\r\n }\r\n }\r\n compositeEntity = undefined;\r\n }\r\n\r\n composite.resumeEvents();\r\n};\r\n\r\nCompositeEntityCollection.prototype._onDefinitionChanged = function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n) {\r\n var collections = this._collections;\r\n var composite = this._composite;\r\n\r\n var collectionsLength = collections.length;\r\n var id = entity.id;\r\n var compositeEntity = composite.getById(id);\r\n var compositeProperty = compositeEntity[propertyName];\r\n var newProperty = !defined(compositeProperty);\r\n\r\n var firstTime = true;\r\n for (var q = collectionsLength - 1; q >= 0; q--) {\r\n var innerEntity = collections[q].getById(entity.id);\r\n if (defined(innerEntity)) {\r\n var property = innerEntity[propertyName];\r\n if (defined(property)) {\r\n if (firstTime) {\r\n firstTime = false;\r\n //We only want to clone if the property is also mergeable.\r\n //This ensures that leaf properties are referenced and not copied,\r\n //which is the entire point of compositing.\r\n if (defined(property.merge) && defined(property.clone)) {\r\n compositeProperty = property.clone(compositeProperty);\r\n } else {\r\n compositeProperty = property;\r\n break;\r\n }\r\n }\r\n compositeProperty.merge(property);\r\n }\r\n }\r\n }\r\n\r\n if (\r\n newProperty &&\r\n compositeEntity.propertyNames.indexOf(propertyName) === -1\r\n ) {\r\n compositeEntity.addProperty(propertyName);\r\n }\r\n\r\n compositeEntity[propertyName] = compositeProperty;\r\n};\r\nexport default CompositeEntityCollection;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport EventHelper from \"../Core/EventHelper.js\";\r\nimport TimeIntervalCollection from \"../Core/TimeIntervalCollection.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nfunction subscribeAll(property, eventHelper, definitionChanged, intervals) {\r\n function callback() {\r\n definitionChanged.raiseEvent(property);\r\n }\r\n var items = [];\r\n eventHelper.removeAll();\r\n var length = intervals.length;\r\n for (var i = 0; i < length; i++) {\r\n var interval = intervals.get(i);\r\n if (defined(interval.data) && items.indexOf(interval.data) === -1) {\r\n eventHelper.add(interval.data.definitionChanged, callback);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * A {@link Property} which is defined by a {@link TimeIntervalCollection}, where the\r\n * data property of each {@link TimeInterval} is another Property instance which is\r\n * evaluated at the provided time.\r\n *\r\n * @alias CompositeProperty\r\n * @constructor\r\n *\r\n *\r\n * @example\r\n * var constantProperty = ...;\r\n * var sampledProperty = ...;\r\n *\r\n * //Create a composite property from two previously defined properties\r\n * //where the property is valid on August 1st, 2012 and uses a constant\r\n * //property for the first half of the day and a sampled property for the\r\n * //remaining half.\r\n * var composite = new Cesium.CompositeProperty();\r\n * composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({\r\n * iso8601 : '2012-08-01T00:00:00.00Z/2012-08-01T12:00:00.00Z',\r\n * data : constantProperty\r\n * }));\r\n * composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({\r\n * iso8601 : '2012-08-01T12:00:00.00Z/2012-08-02T00:00:00.00Z',\r\n * isStartIncluded : false,\r\n * isStopIncluded : false,\r\n * data : sampledProperty\r\n * }));\r\n *\r\n * @see CompositeMaterialProperty\r\n * @see CompositePositionProperty\r\n */\r\nfunction CompositeProperty() {\r\n this._eventHelper = new EventHelper();\r\n this._definitionChanged = new Event();\r\n this._intervals = new TimeIntervalCollection();\r\n this._intervals.changedEvent.addEventListener(\r\n CompositeProperty.prototype._intervalsChanged,\r\n this\r\n );\r\n}\r\n\r\nObject.defineProperties(CompositeProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof CompositeProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return this._intervals.isEmpty;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever setValue is called with data different\r\n * than the current value.\r\n * @memberof CompositeProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the interval collection.\r\n * @memberof CompositeProperty.prototype\r\n *\r\n * @type {TimeIntervalCollection}\r\n */\r\n intervals: {\r\n get: function () {\r\n return this._intervals;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nCompositeProperty.prototype.getValue = function (time, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var innerProperty = this._intervals.findDataForIntervalContainingDate(time);\r\n if (defined(innerProperty)) {\r\n return innerProperty.getValue(time, result);\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCompositeProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof CompositeProperty && //\r\n this._intervals.equals(other._intervals, Property.equals))\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCompositeProperty.prototype._intervalsChanged = function () {\r\n subscribeAll(\r\n this,\r\n this._eventHelper,\r\n this._definitionChanged,\r\n this._intervals\r\n );\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\nexport default CompositeProperty;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport CompositeProperty from \"./CompositeProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link CompositeProperty} which is also a {@link MaterialProperty}.\r\n *\r\n * @alias CompositeMaterialProperty\r\n * @constructor\r\n */\r\nfunction CompositeMaterialProperty() {\r\n this._definitionChanged = new Event();\r\n this._composite = new CompositeProperty();\r\n this._composite.definitionChanged.addEventListener(\r\n CompositeMaterialProperty.prototype._raiseDefinitionChanged,\r\n this\r\n );\r\n}\r\n\r\nObject.defineProperties(CompositeMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof CompositeMaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return this._composite.isConstant;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever setValue is called with data different\r\n * than the current value.\r\n * @memberof CompositeMaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the interval collection.\r\n * @memberof CompositeMaterialProperty.prototype\r\n *\r\n * @type {TimeIntervalCollection}\r\n */\r\n intervals: {\r\n get: function () {\r\n return this._composite._intervals;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nCompositeMaterialProperty.prototype.getType = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var innerProperty = this._composite._intervals.findDataForIntervalContainingDate(\r\n time\r\n );\r\n if (defined(innerProperty)) {\r\n return innerProperty.getType(time);\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nCompositeMaterialProperty.prototype.getValue = function (time, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var innerProperty = this._composite._intervals.findDataForIntervalContainingDate(\r\n time\r\n );\r\n if (defined(innerProperty)) {\r\n return innerProperty.getValue(time, result);\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCompositeMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof CompositeMaterialProperty && //\r\n this._composite.equals(other._composite, Property.equals))\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCompositeMaterialProperty.prototype._raiseDefinitionChanged = function () {\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\nexport default CompositeMaterialProperty;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport CompositeProperty from \"./CompositeProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link CompositeProperty} which is also a {@link PositionProperty}.\r\n *\r\n * @alias CompositePositionProperty\r\n * @constructor\r\n *\r\n * @param {ReferenceFrame} [referenceFrame=ReferenceFrame.FIXED] The reference frame in which the position is defined.\r\n */\r\nfunction CompositePositionProperty(referenceFrame) {\r\n this._referenceFrame = defaultValue(referenceFrame, ReferenceFrame.FIXED);\r\n this._definitionChanged = new Event();\r\n this._composite = new CompositeProperty();\r\n this._composite.definitionChanged.addEventListener(\r\n CompositePositionProperty.prototype._raiseDefinitionChanged,\r\n this\r\n );\r\n}\r\n\r\nObject.defineProperties(CompositePositionProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof CompositePositionProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return this._composite.isConstant;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever setValue is called with data different\r\n * than the current value.\r\n * @memberof CompositePositionProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the interval collection.\r\n * @memberof CompositePositionProperty.prototype\r\n *\r\n * @type {TimeIntervalCollection}\r\n */\r\n intervals: {\r\n get: function () {\r\n return this._composite.intervals;\r\n },\r\n },\r\n /**\r\n * Gets or sets the reference frame which this position presents itself as.\r\n * Each PositionProperty making up this object has it's own reference frame,\r\n * so this property merely exposes a \"preferred\" reference frame for clients\r\n * to use.\r\n * @memberof CompositePositionProperty.prototype\r\n *\r\n * @type {ReferenceFrame}\r\n */\r\n referenceFrame: {\r\n get: function () {\r\n return this._referenceFrame;\r\n },\r\n set: function (value) {\r\n this._referenceFrame = value;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time in the fixed frame.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nCompositePositionProperty.prototype.getValue = function (time, result) {\r\n return this.getValueInReferenceFrame(time, ReferenceFrame.FIXED, result);\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time and in the provided reference frame.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {ReferenceFrame} referenceFrame The desired referenceFrame of the result.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nCompositePositionProperty.prototype.getValueInReferenceFrame = function (\r\n time,\r\n referenceFrame,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n if (!defined(referenceFrame)) {\r\n throw new DeveloperError(\"referenceFrame is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var innerProperty = this._composite._intervals.findDataForIntervalContainingDate(\r\n time\r\n );\r\n if (defined(innerProperty)) {\r\n return innerProperty.getValueInReferenceFrame(time, referenceFrame, result);\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nCompositePositionProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof CompositePositionProperty && //\r\n this._referenceFrame === other._referenceFrame && //\r\n this._composite.equals(other._composite, Property.equals))\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nCompositePositionProperty.prototype._raiseDefinitionChanged = function () {\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\nexport default CompositePositionProperty;\r\n","import Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport GeometryOffsetAttribute from \"../Core/GeometryOffsetAttribute.js\";\r\nimport oneTimeWarning from \"../Core/oneTimeWarning.js\";\r\nimport GroundPrimitive from \"../Scene/GroundPrimitive.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport CallbackProperty from \"./CallbackProperty.js\";\r\nimport ConstantProperty from \"./ConstantProperty.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport TerrainOffsetProperty from \"./TerrainOffsetProperty.js\";\r\n\r\nvar defaultZIndex = new ConstantProperty(0);\r\n\r\n/**\r\n * An abstract class for updating ground geometry entities.\r\n * @constructor\r\n * @alias GroundGeometryUpdater\r\n * @param {Object} options An object with the following properties:\r\n * @param {Entity} options.entity The entity containing the geometry to be visualized.\r\n * @param {Scene} options.scene The scene where visualization is taking place.\r\n * @param {Object} options.geometryOptions Options for the geometry\r\n * @param {String} options.geometryPropertyName The geometry property name\r\n * @param {String[]} options.observedPropertyNames The entity properties this geometry cares about\r\n */\r\nfunction GroundGeometryUpdater(options) {\r\n GeometryUpdater.call(this, options);\r\n\r\n this._zIndex = 0;\r\n this._terrainOffsetProperty = undefined;\r\n}\r\n\r\nif (defined(Object.create)) {\r\n GroundGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);\r\n GroundGeometryUpdater.prototype.constructor = GroundGeometryUpdater;\r\n}\r\n\r\nObject.defineProperties(GroundGeometryUpdater.prototype, {\r\n /**\r\n * Gets the zindex\r\n * @type {Number}\r\n * @memberof GroundGeometryUpdater.prototype\r\n * @readonly\r\n */\r\n zIndex: {\r\n get: function () {\r\n return this._zIndex;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the terrain offset property\r\n * @type {TerrainOffsetProperty}\r\n * @memberof GroundGeometryUpdater.prototype\r\n * @readonly\r\n * @private\r\n */\r\n terrainOffsetProperty: {\r\n get: function () {\r\n return this._terrainOffsetProperty;\r\n },\r\n },\r\n});\r\n\r\nGroundGeometryUpdater.prototype._isOnTerrain = function (entity, geometry) {\r\n return (\r\n this._fillEnabled &&\r\n !defined(geometry.height) &&\r\n !defined(geometry.extrudedHeight) &&\r\n GroundPrimitive.isSupported(this._scene)\r\n );\r\n};\r\n\r\nGroundGeometryUpdater.prototype._getIsClosed = function (options) {\r\n var height = options.height;\r\n var extrudedHeight = options.extrudedHeight;\r\n return height === 0 || (defined(extrudedHeight) && extrudedHeight !== height);\r\n};\r\n\r\nGroundGeometryUpdater.prototype._computeCenter =\r\n DeveloperError.throwInstantiationError;\r\n\r\nGroundGeometryUpdater.prototype._onEntityPropertyChanged = function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n) {\r\n GeometryUpdater.prototype._onEntityPropertyChanged.call(\r\n this,\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n );\r\n if (this._observedPropertyNames.indexOf(propertyName) === -1) {\r\n return;\r\n }\r\n\r\n var geometry = this._entity[this._geometryPropertyName];\r\n if (!defined(geometry)) {\r\n return;\r\n }\r\n if (\r\n defined(geometry.zIndex) &&\r\n (defined(geometry.height) || defined(geometry.extrudedHeight))\r\n ) {\r\n oneTimeWarning(oneTimeWarning.geometryZIndex);\r\n }\r\n\r\n this._zIndex = defaultValue(geometry.zIndex, defaultZIndex);\r\n\r\n if (defined(this._terrainOffsetProperty)) {\r\n this._terrainOffsetProperty.destroy();\r\n this._terrainOffsetProperty = undefined;\r\n }\r\n\r\n var heightReferenceProperty = geometry.heightReference;\r\n var extrudedHeightReferenceProperty = geometry.extrudedHeightReference;\r\n\r\n if (\r\n defined(heightReferenceProperty) ||\r\n defined(extrudedHeightReferenceProperty)\r\n ) {\r\n var centerPosition = new CallbackProperty(\r\n this._computeCenter.bind(this),\r\n !this._dynamic\r\n );\r\n this._terrainOffsetProperty = new TerrainOffsetProperty(\r\n this._scene,\r\n centerPosition,\r\n heightReferenceProperty,\r\n extrudedHeightReferenceProperty\r\n );\r\n }\r\n};\r\n\r\n/**\r\n * Destroys and resources used by the object. Once an object is destroyed, it should not be used.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nGroundGeometryUpdater.prototype.destroy = function () {\r\n if (defined(this._terrainOffsetProperty)) {\r\n this._terrainOffsetProperty.destroy();\r\n this._terrainOffsetProperty = undefined;\r\n }\r\n\r\n GeometryUpdater.prototype.destroy.call(this);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nGroundGeometryUpdater.getGeometryHeight = function (height, heightReference) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"heightReference\", heightReference);\r\n //>>includeEnd('debug');\r\n if (!defined(height)) {\r\n if (heightReference !== HeightReference.NONE) {\r\n oneTimeWarning(oneTimeWarning.geometryHeightReference);\r\n }\r\n return;\r\n }\r\n\r\n if (heightReference !== HeightReference.CLAMP_TO_GROUND) {\r\n return height;\r\n }\r\n return 0.0;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nGroundGeometryUpdater.getGeometryExtrudedHeight = function (\r\n extrudedHeight,\r\n extrudedHeightReference\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"extrudedHeightReference\", extrudedHeightReference);\r\n //>>includeEnd('debug');\r\n if (!defined(extrudedHeight)) {\r\n if (extrudedHeightReference !== HeightReference.NONE) {\r\n oneTimeWarning(oneTimeWarning.geometryExtrudedHeightReference);\r\n }\r\n return;\r\n }\r\n if (extrudedHeightReference !== HeightReference.CLAMP_TO_GROUND) {\r\n return extrudedHeight;\r\n }\r\n\r\n return GroundGeometryUpdater.CLAMP_TO_GROUND;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nGroundGeometryUpdater.CLAMP_TO_GROUND = \"clamp\";\r\n\r\n/**\r\n * @private\r\n */\r\nGroundGeometryUpdater.computeGeometryOffsetAttribute = function (\r\n height,\r\n heightReference,\r\n extrudedHeight,\r\n extrudedHeightReference\r\n) {\r\n if (!defined(height) || !defined(heightReference)) {\r\n heightReference = HeightReference.NONE;\r\n }\r\n if (!defined(extrudedHeight) || !defined(extrudedHeightReference)) {\r\n extrudedHeightReference = HeightReference.NONE;\r\n }\r\n var n = 0;\r\n if (heightReference !== HeightReference.NONE) {\r\n n++;\r\n }\r\n if (extrudedHeightReference === HeightReference.RELATIVE_TO_GROUND) {\r\n n++;\r\n }\r\n if (n === 2) {\r\n return GeometryOffsetAttribute.ALL;\r\n }\r\n if (n === 1) {\r\n return GeometryOffsetAttribute.TOP;\r\n }\r\n\r\n return undefined;\r\n};\r\nexport default GroundGeometryUpdater;\r\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport CorridorGeometry from \"../Core/CorridorGeometry.js\";\r\nimport CorridorOutlineGeometry from \"../Core/CorridorOutlineGeometry.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport GroundGeometryUpdater from \"./GroundGeometryUpdater.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar scratchColor = new Color();\r\nvar defaultOffset = Cartesian3.ZERO;\r\nvar offsetScratch = new Cartesian3();\r\nvar scratchRectangle = new Rectangle();\r\n\r\nfunction CorridorGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.positions = undefined;\r\n this.width = undefined;\r\n this.cornerType = undefined;\r\n this.height = undefined;\r\n this.extrudedHeight = undefined;\r\n this.granularity = undefined;\r\n this.offsetAttribute = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for corridors.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias CorridorGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction CorridorGeometryUpdater(entity, scene) {\r\n GroundGeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new CorridorGeometryOptions(entity),\r\n geometryPropertyName: \"corridor\",\r\n observedPropertyNames: [\"availability\", \"corridor\"],\r\n });\r\n\r\n this._onEntityPropertyChanged(entity, \"corridor\", entity.corridor, undefined);\r\n}\r\n\r\nif (defined(Object.create)) {\r\n CorridorGeometryUpdater.prototype = Object.create(\r\n GroundGeometryUpdater.prototype\r\n );\r\n CorridorGeometryUpdater.prototype.constructor = CorridorGeometryUpdater;\r\n}\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nCorridorGeometryUpdater.prototype.createFillGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n ),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n this._distanceDisplayConditionProperty.getValue(time)\r\n ),\r\n offset: undefined,\r\n color: undefined,\r\n };\r\n\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n }\r\n\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new CorridorGeometry(this._options),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nCorridorGeometryUpdater.prototype.createOutlineGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n this._distanceDisplayConditionProperty.getValue(time)\r\n ),\r\n offset: undefined,\r\n };\r\n\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new CorridorOutlineGeometry(this._options),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\nCorridorGeometryUpdater.prototype._computeCenter = function (time, result) {\r\n var positions = Property.getValueOrUndefined(\r\n this._entity.corridor.positions,\r\n time\r\n );\r\n if (!defined(positions) || positions.length === 0) {\r\n return;\r\n }\r\n return Cartesian3.clone(\r\n positions[Math.floor(positions.length / 2.0)],\r\n result\r\n );\r\n};\r\n\r\nCorridorGeometryUpdater.prototype._isHidden = function (entity, corridor) {\r\n return (\r\n !defined(corridor.positions) ||\r\n !defined(corridor.width) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, corridor)\r\n );\r\n};\r\n\r\nCorridorGeometryUpdater.prototype._isDynamic = function (entity, corridor) {\r\n return (\r\n !corridor.positions.isConstant || //\r\n !Property.isConstant(corridor.height) || //\r\n !Property.isConstant(corridor.extrudedHeight) || //\r\n !Property.isConstant(corridor.granularity) || //\r\n !Property.isConstant(corridor.width) || //\r\n !Property.isConstant(corridor.outlineWidth) || //\r\n !Property.isConstant(corridor.cornerType) || //\r\n !Property.isConstant(corridor.zIndex) || //\r\n (this._onTerrain &&\r\n !Property.isConstant(this._materialProperty) &&\r\n !(this._materialProperty instanceof ColorMaterialProperty))\r\n );\r\n};\r\n\r\nCorridorGeometryUpdater.prototype._setStaticOptions = function (\r\n entity,\r\n corridor\r\n) {\r\n var heightValue = Property.getValueOrUndefined(\r\n corridor.height,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n var heightReferenceValue = Property.getValueOrDefault(\r\n corridor.heightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightValue = Property.getValueOrUndefined(\r\n corridor.extrudedHeight,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n var extrudedHeightReferenceValue = Property.getValueOrDefault(\r\n corridor.extrudedHeightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n if (defined(extrudedHeightValue) && !defined(heightValue)) {\r\n heightValue = 0;\r\n }\r\n\r\n var options = this._options;\r\n options.vertexFormat =\r\n this._materialProperty instanceof ColorMaterialProperty\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.positions = corridor.positions.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.positions\r\n );\r\n options.width = corridor.width.getValue(Iso8601.MINIMUM_VALUE);\r\n options.granularity = Property.getValueOrUndefined(\r\n corridor.granularity,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.cornerType = Property.getValueOrUndefined(\r\n corridor.cornerType,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.offsetAttribute = GroundGeometryUpdater.computeGeometryOffsetAttribute(\r\n heightValue,\r\n heightReferenceValue,\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n options.height = GroundGeometryUpdater.getGeometryHeight(\r\n heightValue,\r\n heightReferenceValue\r\n );\r\n\r\n extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {\r\n extrudedHeightValue = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n CorridorGeometry.computeRectangle(options, scratchRectangle)\r\n ).minimumTerrainHeight;\r\n }\r\n\r\n options.extrudedHeight = extrudedHeightValue;\r\n};\r\n\r\nCorridorGeometryUpdater.DynamicGeometryUpdater = DynamicCorridorGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicCorridorGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicCorridorGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicCorridorGeometryUpdater.prototype.constructor = DynamicCorridorGeometryUpdater;\r\n}\r\n\r\nDynamicCorridorGeometryUpdater.prototype._isHidden = function (\r\n entity,\r\n corridor,\r\n time\r\n) {\r\n var options = this._options;\r\n return (\r\n !defined(options.positions) ||\r\n !defined(options.width) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(\r\n this,\r\n entity,\r\n corridor,\r\n time\r\n )\r\n );\r\n};\r\n\r\nDynamicCorridorGeometryUpdater.prototype._setOptions = function (\r\n entity,\r\n corridor,\r\n time\r\n) {\r\n var options = this._options;\r\n var heightValue = Property.getValueOrUndefined(corridor.height, time);\r\n var heightReferenceValue = Property.getValueOrDefault(\r\n corridor.heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightValue = Property.getValueOrUndefined(\r\n corridor.extrudedHeight,\r\n time\r\n );\r\n var extrudedHeightReferenceValue = Property.getValueOrDefault(\r\n corridor.extrudedHeightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n if (defined(extrudedHeightValue) && !defined(heightValue)) {\r\n heightValue = 0;\r\n }\r\n\r\n options.positions = Property.getValueOrUndefined(corridor.positions, time);\r\n options.width = Property.getValueOrUndefined(corridor.width, time);\r\n options.granularity = Property.getValueOrUndefined(\r\n corridor.granularity,\r\n time\r\n );\r\n options.cornerType = Property.getValueOrUndefined(corridor.cornerType, time);\r\n options.offsetAttribute = GroundGeometryUpdater.computeGeometryOffsetAttribute(\r\n heightValue,\r\n heightReferenceValue,\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n options.height = GroundGeometryUpdater.getGeometryHeight(\r\n heightValue,\r\n heightReferenceValue\r\n );\r\n\r\n extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {\r\n extrudedHeightValue = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n CorridorGeometry.computeRectangle(options, scratchRectangle)\r\n ).minimumTerrainHeight;\r\n }\r\n\r\n options.extrudedHeight = extrudedHeightValue;\r\n};\r\nexport default CorridorGeometryUpdater;\r\n","import DeveloperError from \"../Core/DeveloperError.js\";\r\n\r\n/**\r\n * Defines the interface for data sources, which turn arbitrary data into a\r\n * {@link EntityCollection} for generic consumption. This object is an interface\r\n * for documentation purposes and is not intended to be instantiated directly.\r\n * @alias DataSource\r\n * @constructor\r\n *\r\n * @see Entity\r\n * @see DataSourceDisplay\r\n */\r\nfunction DataSource() {\r\n DeveloperError.throwInstantiationError();\r\n}\r\n\r\nObject.defineProperties(DataSource.prototype, {\r\n /**\r\n * Gets a human-readable name for this instance.\r\n * @memberof DataSource.prototype\r\n * @type {String}\r\n */\r\n name: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets the preferred clock settings for this data source.\r\n * @memberof DataSource.prototype\r\n * @type {DataSourceClock}\r\n */\r\n clock: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets the collection of {@link Entity} instances.\r\n * @memberof DataSource.prototype\r\n * @type {EntityCollection}\r\n */\r\n entities: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets a value indicating if the data source is currently loading data.\r\n * @memberof DataSource.prototype\r\n * @type {Boolean}\r\n */\r\n isLoading: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets an event that will be raised when the underlying data changes.\r\n * @memberof DataSource.prototype\r\n * @type {Event}\r\n */\r\n changedEvent: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets an event that will be raised if an error is encountered during processing.\r\n * @memberof DataSource.prototype\r\n * @type {Event}\r\n */\r\n errorEvent: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets an event that will be raised when the value of isLoading changes.\r\n * @memberof DataSource.prototype\r\n * @type {Event}\r\n */\r\n loadingEvent: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n /**\r\n * Gets whether or not this data source should be displayed.\r\n * @memberof DataSource.prototype\r\n * @type {Boolean}\r\n */\r\n show: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n\r\n /**\r\n * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.\r\n *\r\n * @memberof DataSource.prototype\r\n * @type {EntityCluster}\r\n */\r\n clustering: {\r\n get: DeveloperError.throwInstantiationError,\r\n },\r\n});\r\n\r\n/**\r\n * Updates the data source to the provided time. This function is optional and\r\n * is not required to be implemented. It is provided for data sources which\r\n * retrieve data based on the current animation time or scene state.\r\n * If implemented, update will be called by {@link DataSourceDisplay} once a frame.\r\n *\r\n * @param {JulianDate} time The simulation time.\r\n * @returns {Boolean} True if this data source is ready to be displayed at the provided time, false otherwise.\r\n */\r\nDataSource.prototype.update = function (time) {\r\n DeveloperError.throwInstantiationError();\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nDataSource.setLoading = function (dataSource, isLoading) {\r\n if (dataSource._isLoading !== isLoading) {\r\n if (isLoading) {\r\n dataSource._entityCollection.suspendEvents();\r\n } else {\r\n dataSource._entityCollection.resumeEvents();\r\n }\r\n dataSource._isLoading = isLoading;\r\n dataSource._loading.raiseEvent(dataSource, isLoading);\r\n }\r\n};\r\nexport default DataSource;\r\n","import BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartesian4 from \"../Core/Cartesian4.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport NearFarScalar from \"../Core/NearFarScalar.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\nimport SceneTransforms from \"./SceneTransforms.js\";\r\n\r\n/**\r\n * A graphical point positioned in the 3D scene, that is created\r\n * and rendered using a {@link PointPrimitiveCollection}. A point is created and its initial\r\n * properties are set by calling {@link PointPrimitiveCollection#add}.\r\n *\r\n * @alias PointPrimitive\r\n *\r\n * @performance Reading a property, e.g., {@link PointPrimitive#show}, is constant time.\r\n * Assigning to a property is constant time but results in\r\n * CPU to GPU traffic when {@link PointPrimitiveCollection#update} is called. The per-pointPrimitive traffic is\r\n * the same regardless of how many properties were updated. If most pointPrimitives in a collection need to be\r\n * updated, it may be more efficient to clear the collection with {@link PointPrimitiveCollection#removeAll}\r\n * and add new pointPrimitives instead of modifying each one.\r\n *\r\n * @exception {DeveloperError} scaleByDistance.far must be greater than scaleByDistance.near\r\n * @exception {DeveloperError} translucencyByDistance.far must be greater than translucencyByDistance.near\r\n * @exception {DeveloperError} distanceDisplayCondition.far must be greater than distanceDisplayCondition.near\r\n *\r\n * @see PointPrimitiveCollection\r\n * @see PointPrimitiveCollection#add\r\n *\r\n * @internalConstructor\r\n * @class\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Points.html|Cesium Sandcastle Points Demo}\r\n */\r\nfunction PointPrimitive(options, pointPrimitiveCollection) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n defined(options.disableDepthTestDistance) &&\r\n options.disableDepthTestDistance < 0.0\r\n ) {\r\n throw new DeveloperError(\r\n \"disableDepthTestDistance must be greater than or equal to 0.0.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var translucencyByDistance = options.translucencyByDistance;\r\n var scaleByDistance = options.scaleByDistance;\r\n var distanceDisplayCondition = options.distanceDisplayCondition;\r\n if (defined(translucencyByDistance)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (translucencyByDistance.far <= translucencyByDistance.near) {\r\n throw new DeveloperError(\r\n \"translucencyByDistance.far must be greater than translucencyByDistance.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n translucencyByDistance = NearFarScalar.clone(translucencyByDistance);\r\n }\r\n if (defined(scaleByDistance)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (scaleByDistance.far <= scaleByDistance.near) {\r\n throw new DeveloperError(\r\n \"scaleByDistance.far must be greater than scaleByDistance.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n scaleByDistance = NearFarScalar.clone(scaleByDistance);\r\n }\r\n if (defined(distanceDisplayCondition)) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (distanceDisplayCondition.far <= distanceDisplayCondition.near) {\r\n throw new DeveloperError(\r\n \"distanceDisplayCondition.far must be greater than distanceDisplayCondition.near.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n distanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition\r\n );\r\n }\r\n\r\n this._show = defaultValue(options.show, true);\r\n this._position = Cartesian3.clone(\r\n defaultValue(options.position, Cartesian3.ZERO)\r\n );\r\n this._actualPosition = Cartesian3.clone(this._position); // For columbus view and 2D\r\n this._color = Color.clone(defaultValue(options.color, Color.WHITE));\r\n this._outlineColor = Color.clone(\r\n defaultValue(options.outlineColor, Color.TRANSPARENT)\r\n );\r\n this._outlineWidth = defaultValue(options.outlineWidth, 0.0);\r\n this._pixelSize = defaultValue(options.pixelSize, 10.0);\r\n this._scaleByDistance = scaleByDistance;\r\n this._translucencyByDistance = translucencyByDistance;\r\n this._distanceDisplayCondition = distanceDisplayCondition;\r\n this._disableDepthTestDistance = defaultValue(\r\n options.disableDepthTestDistance,\r\n 0.0\r\n );\r\n this._id = options.id;\r\n this._collection = defaultValue(options.collection, pointPrimitiveCollection);\r\n\r\n this._clusterShow = true;\r\n\r\n this._pickId = undefined;\r\n this._pointPrimitiveCollection = pointPrimitiveCollection;\r\n this._dirty = false;\r\n this._index = -1; //Used only by PointPrimitiveCollection\r\n}\r\n\r\nvar SHOW_INDEX = (PointPrimitive.SHOW_INDEX = 0);\r\nvar POSITION_INDEX = (PointPrimitive.POSITION_INDEX = 1);\r\nvar COLOR_INDEX = (PointPrimitive.COLOR_INDEX = 2);\r\nvar OUTLINE_COLOR_INDEX = (PointPrimitive.OUTLINE_COLOR_INDEX = 3);\r\nvar OUTLINE_WIDTH_INDEX = (PointPrimitive.OUTLINE_WIDTH_INDEX = 4);\r\nvar PIXEL_SIZE_INDEX = (PointPrimitive.PIXEL_SIZE_INDEX = 5);\r\nvar SCALE_BY_DISTANCE_INDEX = (PointPrimitive.SCALE_BY_DISTANCE_INDEX = 6);\r\nvar TRANSLUCENCY_BY_DISTANCE_INDEX = (PointPrimitive.TRANSLUCENCY_BY_DISTANCE_INDEX = 7);\r\nvar DISTANCE_DISPLAY_CONDITION_INDEX = (PointPrimitive.DISTANCE_DISPLAY_CONDITION_INDEX = 8);\r\nvar DISABLE_DEPTH_DISTANCE_INDEX = (PointPrimitive.DISABLE_DEPTH_DISTANCE_INDEX = 9);\r\nPointPrimitive.NUMBER_OF_PROPERTIES = 10;\r\n\r\nfunction makeDirty(pointPrimitive, propertyChanged) {\r\n var pointPrimitiveCollection = pointPrimitive._pointPrimitiveCollection;\r\n if (defined(pointPrimitiveCollection)) {\r\n pointPrimitiveCollection._updatePointPrimitive(\r\n pointPrimitive,\r\n propertyChanged\r\n );\r\n pointPrimitive._dirty = true;\r\n }\r\n}\r\n\r\nObject.defineProperties(PointPrimitive.prototype, {\r\n /**\r\n * Determines if this point will be shown. Use this to hide or show a point, instead\r\n * of removing it and re-adding it to the collection.\r\n * @memberof PointPrimitive.prototype\r\n * @type {Boolean}\r\n */\r\n show: {\r\n get: function () {\r\n return this._show;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._show !== value) {\r\n this._show = value;\r\n makeDirty(this, SHOW_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the Cartesian position of this point.\r\n * @memberof PointPrimitive.prototype\r\n * @type {Cartesian3}\r\n */\r\n position: {\r\n get: function () {\r\n return this._position;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug)\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var position = this._position;\r\n if (!Cartesian3.equals(position, value)) {\r\n Cartesian3.clone(value, position);\r\n Cartesian3.clone(value, this._actualPosition);\r\n\r\n makeDirty(this, POSITION_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets near and far scaling properties of a point based on the point's distance from the camera.\r\n * A point's scale will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the point's scale remains clamped to the nearest bound. This scale\r\n * multiplies the pixelSize and outlineWidth to affect the total size of the point. If undefined,\r\n * scaleByDistance will be disabled.\r\n * @memberof PointPrimitive.prototype\r\n * @type {NearFarScalar}\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a pointPrimitive's scaleByDistance to scale to 15 when the\r\n * // camera is 1500 meters from the pointPrimitive and disappear as\r\n * // the camera distance approaches 8.0e6 meters.\r\n * p.scaleByDistance = new Cesium.NearFarScalar(1.5e2, 15, 8.0e6, 0.0);\r\n *\r\n * @example\r\n * // Example 2.\r\n * // disable scaling by distance\r\n * p.scaleByDistance = undefined;\r\n */\r\n scaleByDistance: {\r\n get: function () {\r\n return this._scaleByDistance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var scaleByDistance = this._scaleByDistance;\r\n if (!NearFarScalar.equals(scaleByDistance, value)) {\r\n this._scaleByDistance = NearFarScalar.clone(value, scaleByDistance);\r\n makeDirty(this, SCALE_BY_DISTANCE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets near and far translucency properties of a point based on the point's distance from the camera.\r\n * A point's translucency will interpolate between the {@link NearFarScalar#nearValue} and\r\n * {@link NearFarScalar#farValue} while the camera distance falls within the lower and upper bounds\r\n * of the specified {@link NearFarScalar#near} and {@link NearFarScalar#far}.\r\n * Outside of these ranges the point's translucency remains clamped to the nearest bound. If undefined,\r\n * translucencyByDistance will be disabled.\r\n * @memberof PointPrimitive.prototype\r\n * @type {NearFarScalar}\r\n *\r\n * @example\r\n * // Example 1.\r\n * // Set a point's translucency to 1.0 when the\r\n * // camera is 1500 meters from the point and disappear as\r\n * // the camera distance approaches 8.0e6 meters.\r\n * p.translucencyByDistance = new Cesium.NearFarScalar(1.5e2, 1.0, 8.0e6, 0.0);\r\n *\r\n * @example\r\n * // Example 2.\r\n * // disable translucency by distance\r\n * p.translucencyByDistance = undefined;\r\n */\r\n translucencyByDistance: {\r\n get: function () {\r\n return this._translucencyByDistance;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\r\n \"far distance must be greater than near distance.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var translucencyByDistance = this._translucencyByDistance;\r\n if (!NearFarScalar.equals(translucencyByDistance, value)) {\r\n this._translucencyByDistance = NearFarScalar.clone(\r\n value,\r\n translucencyByDistance\r\n );\r\n makeDirty(this, TRANSLUCENCY_BY_DISTANCE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the inner size of the point in pixels.\r\n * @memberof PointPrimitive.prototype\r\n * @type {Number}\r\n */\r\n pixelSize: {\r\n get: function () {\r\n return this._pixelSize;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._pixelSize !== value) {\r\n this._pixelSize = value;\r\n makeDirty(this, PIXEL_SIZE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the inner color of the point.\r\n * The red, green, blue, and alpha values are indicated by value's red, green,\r\n * blue, and alpha properties as shown in Example 1. These components range from 0.0\r\n * (no intensity) to 1.0 (full intensity).\r\n * @memberof PointPrimitive.prototype\r\n * @type {Color}\r\n *\r\n * @example\r\n * // Example 1. Assign yellow.\r\n * p.color = Cesium.Color.YELLOW;\r\n *\r\n * @example\r\n * // Example 2. Make a pointPrimitive 50% translucent.\r\n * p.color = new Cesium.Color(1.0, 1.0, 1.0, 0.5);\r\n */\r\n color: {\r\n get: function () {\r\n return this._color;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var color = this._color;\r\n if (!Color.equals(color, value)) {\r\n Color.clone(value, color);\r\n makeDirty(this, COLOR_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the outline color of the point.\r\n * @memberof PointPrimitive.prototype\r\n * @type {Color}\r\n */\r\n outlineColor: {\r\n get: function () {\r\n return this._outlineColor;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var outlineColor = this._outlineColor;\r\n if (!Color.equals(outlineColor, value)) {\r\n Color.clone(value, outlineColor);\r\n makeDirty(this, OUTLINE_COLOR_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the outline width in pixels. This width adds to pixelSize,\r\n * increasing the total size of the point.\r\n * @memberof PointPrimitive.prototype\r\n * @type {Number}\r\n */\r\n outlineWidth: {\r\n get: function () {\r\n return this._outlineWidth;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (this._outlineWidth !== value) {\r\n this._outlineWidth = value;\r\n makeDirty(this, OUTLINE_WIDTH_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the condition specifying at what distance from the camera that this point will be displayed.\r\n * @memberof PointPrimitive.prototype\r\n * @type {DistanceDisplayCondition}\r\n * @default undefined\r\n */\r\n distanceDisplayCondition: {\r\n get: function () {\r\n return this._distanceDisplayCondition;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (defined(value) && value.far <= value.near) {\r\n throw new DeveloperError(\"far must be greater than near\");\r\n }\r\n //>>includeEnd('debug');\r\n if (\r\n !DistanceDisplayCondition.equals(this._distanceDisplayCondition, value)\r\n ) {\r\n this._distanceDisplayCondition = DistanceDisplayCondition.clone(\r\n value,\r\n this._distanceDisplayCondition\r\n );\r\n makeDirty(this, DISTANCE_DISPLAY_CONDITION_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the distance from the camera at which to disable the depth test to, for example, prevent clipping against terrain.\r\n * When set to zero, the depth test is always applied. When set to Number.POSITIVE_INFINITY, the depth test is never applied.\r\n * @memberof PointPrimitive.prototype\r\n * @type {Number}\r\n * @default 0.0\r\n */\r\n disableDepthTestDistance: {\r\n get: function () {\r\n return this._disableDepthTestDistance;\r\n },\r\n set: function (value) {\r\n if (this._disableDepthTestDistance !== value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value) || value < 0.0) {\r\n throw new DeveloperError(\r\n \"disableDepthTestDistance must be greater than or equal to 0.0.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n this._disableDepthTestDistance = value;\r\n makeDirty(this, DISABLE_DEPTH_DISTANCE_INDEX);\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the user-defined value returned when the point is picked.\r\n * @memberof PointPrimitive.prototype\r\n * @type {*}\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n set: function (value) {\r\n this._id = value;\r\n if (defined(this._pickId)) {\r\n this._pickId.object.id = value;\r\n }\r\n },\r\n },\r\n\r\n /**\r\n * @private\r\n */\r\n pickId: {\r\n get: function () {\r\n return this._pickId;\r\n },\r\n },\r\n\r\n /**\r\n * Determines whether or not this point will be shown or hidden because it was clustered.\r\n * @memberof PointPrimitive.prototype\r\n * @type {Boolean}\r\n * @private\r\n */\r\n clusterShow: {\r\n get: function () {\r\n return this._clusterShow;\r\n },\r\n set: function (value) {\r\n if (this._clusterShow !== value) {\r\n this._clusterShow = value;\r\n makeDirty(this, SHOW_INDEX);\r\n }\r\n },\r\n },\r\n});\r\n\r\nPointPrimitive.prototype.getPickId = function (context) {\r\n if (!defined(this._pickId)) {\r\n this._pickId = context.createPickId({\r\n primitive: this,\r\n collection: this._collection,\r\n id: this._id,\r\n });\r\n }\r\n\r\n return this._pickId;\r\n};\r\n\r\nPointPrimitive.prototype._getActualPosition = function () {\r\n return this._actualPosition;\r\n};\r\n\r\nPointPrimitive.prototype._setActualPosition = function (value) {\r\n Cartesian3.clone(value, this._actualPosition);\r\n makeDirty(this, POSITION_INDEX);\r\n};\r\n\r\nvar tempCartesian3 = new Cartesian4();\r\nPointPrimitive._computeActualPosition = function (\r\n position,\r\n frameState,\r\n modelMatrix\r\n) {\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n return position;\r\n }\r\n\r\n Matrix4.multiplyByPoint(modelMatrix, position, tempCartesian3);\r\n return SceneTransforms.computeActualWgs84Position(frameState, tempCartesian3);\r\n};\r\n\r\nvar scratchCartesian4 = new Cartesian4();\r\n\r\n// This function is basically a stripped-down JavaScript version of PointPrimitiveCollectionVS.glsl\r\nPointPrimitive._computeScreenSpacePosition = function (\r\n modelMatrix,\r\n position,\r\n scene,\r\n result\r\n) {\r\n // Model to world coordinates\r\n var positionWorld = Matrix4.multiplyByVector(\r\n modelMatrix,\r\n Cartesian4.fromElements(\r\n position.x,\r\n position.y,\r\n position.z,\r\n 1,\r\n scratchCartesian4\r\n ),\r\n scratchCartesian4\r\n );\r\n var positionWC = SceneTransforms.wgs84ToWindowCoordinates(\r\n scene,\r\n positionWorld,\r\n result\r\n );\r\n return positionWC;\r\n};\r\n\r\n/**\r\n * Computes the screen-space position of the point's origin.\r\n * The screen space origin is the top, left corner of the canvas; x increases from\r\n * left to right, and y increases from top to bottom.\r\n *\r\n * @param {Scene} scene The scene.\r\n * @param {Cartesian2} [result] The object onto which to store the result.\r\n * @returns {Cartesian2} The screen-space position of the point.\r\n *\r\n * @exception {DeveloperError} PointPrimitive must be in a collection.\r\n *\r\n * @example\r\n * console.log(p.computeScreenSpacePosition(scene).toString());\r\n */\r\nPointPrimitive.prototype.computeScreenSpacePosition = function (scene, result) {\r\n var pointPrimitiveCollection = this._pointPrimitiveCollection;\r\n if (!defined(result)) {\r\n result = new Cartesian2();\r\n }\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(pointPrimitiveCollection)) {\r\n throw new DeveloperError(\"PointPrimitive must be in a collection.\");\r\n }\r\n if (!defined(scene)) {\r\n throw new DeveloperError(\"scene is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var modelMatrix = pointPrimitiveCollection.modelMatrix;\r\n var windowCoordinates = PointPrimitive._computeScreenSpacePosition(\r\n modelMatrix,\r\n this._actualPosition,\r\n scene,\r\n result\r\n );\r\n if (!defined(windowCoordinates)) {\r\n return undefined;\r\n }\r\n\r\n windowCoordinates.y = scene.canvas.clientHeight - windowCoordinates.y;\r\n return windowCoordinates;\r\n};\r\n\r\n/**\r\n * Gets a point's screen space bounding box centered around screenSpacePosition.\r\n * @param {PointPrimitive} point The point to get the screen space bounding box for.\r\n * @param {Cartesian2} screenSpacePosition The screen space center of the label.\r\n * @param {BoundingRectangle} [result] The object onto which to store the result.\r\n * @returns {BoundingRectangle} The screen space bounding box.\r\n *\r\n * @private\r\n */\r\nPointPrimitive.getScreenSpaceBoundingBox = function (\r\n point,\r\n screenSpacePosition,\r\n result\r\n) {\r\n var size = point.pixelSize;\r\n var halfSize = size * 0.5;\r\n\r\n var x = screenSpacePosition.x - halfSize;\r\n var y = screenSpacePosition.y - halfSize;\r\n var width = size;\r\n var height = size;\r\n\r\n if (!defined(result)) {\r\n result = new BoundingRectangle();\r\n }\r\n\r\n result.x = x;\r\n result.y = y;\r\n result.width = width;\r\n result.height = height;\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * Determines if this point equals another point. Points are equal if all their properties\r\n * are equal. Points in different collections can be equal.\r\n *\r\n * @param {PointPrimitive} other The point to compare for equality.\r\n * @returns {Boolean} true if the points are equal; otherwise, false.\r\n */\r\nPointPrimitive.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (defined(other) &&\r\n this._id === other._id &&\r\n Cartesian3.equals(this._position, other._position) &&\r\n Color.equals(this._color, other._color) &&\r\n this._pixelSize === other._pixelSize &&\r\n this._outlineWidth === other._outlineWidth &&\r\n this._show === other._show &&\r\n Color.equals(this._outlineColor, other._outlineColor) &&\r\n NearFarScalar.equals(this._scaleByDistance, other._scaleByDistance) &&\r\n NearFarScalar.equals(\r\n this._translucencyByDistance,\r\n other._translucencyByDistance\r\n ) &&\r\n DistanceDisplayCondition.equals(\r\n this._distanceDisplayCondition,\r\n other._distanceDisplayCondition\r\n ) &&\r\n this._disableDepthTestDistance === other._disableDepthTestDistance)\r\n );\r\n};\r\n\r\nPointPrimitive.prototype._destroy = function () {\r\n this._pickId = this._pickId && this._pickId.destroy();\r\n this._pointPrimitiveCollection = undefined;\r\n};\r\nexport default PointPrimitive;\r\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"varying vec4 v_color;\\n\\\nvarying vec4 v_outlineColor;\\n\\\nvarying float v_innerPercent;\\n\\\nvarying float v_pixelDistance;\\n\\\nvarying vec4 v_pickColor;\\n\\\nvoid main()\\n\\\n{\\n\\\nfloat distanceToCenter = length(gl_PointCoord - vec2(0.5));\\n\\\nfloat maxDistance = max(0.0, 0.5 - v_pixelDistance);\\n\\\nfloat wholeAlpha = 1.0 - smoothstep(maxDistance, 0.5, distanceToCenter);\\n\\\nfloat innerAlpha = 1.0 - smoothstep(maxDistance * v_innerPercent, 0.5 * v_innerPercent, distanceToCenter);\\n\\\nvec4 color = mix(v_outlineColor, v_color, innerAlpha);\\n\\\ncolor.a *= wholeAlpha;\\n\\\n#if !defined(OPAQUE) && !defined(TRANSLUCENT)\\n\\\nif (color.a < 0.005)\\n\\\n{\\n\\\ndiscard;\\n\\\n}\\n\\\n#else\\n\\\n#ifdef OPAQUE\\n\\\nif (color.a < 0.995)\\n\\\n{\\n\\\ndiscard;\\n\\\n}\\n\\\n#else\\n\\\nif (color.a >= 0.995)\\n\\\n{\\n\\\ndiscard;\\n\\\n}\\n\\\n#endif\\n\\\n#endif\\n\\\ngl_FragColor = czm_gammaCorrect(color);\\n\\\nczm_writeLogDepth();\\n\\\n}\\n\\\n\";\n","//This file is automatically rebuilt by the Cesium build process.\nexport default \"uniform float u_maxTotalPointSize;\\n\\\nattribute vec4 positionHighAndSize;\\n\\\nattribute vec4 positionLowAndOutline;\\n\\\nattribute vec4 compressedAttribute0;\\n\\\nattribute vec4 compressedAttribute1;\\n\\\nattribute vec4 scaleByDistance;\\n\\\nattribute vec3 distanceDisplayConditionAndDisableDepth;\\n\\\nvarying vec4 v_color;\\n\\\nvarying vec4 v_outlineColor;\\n\\\nvarying float v_innerPercent;\\n\\\nvarying float v_pixelDistance;\\n\\\nvarying vec4 v_pickColor;\\n\\\nconst float SHIFT_LEFT8 = 256.0;\\n\\\nconst float SHIFT_RIGHT8 = 1.0 / 256.0;\\n\\\nvoid main()\\n\\\n{\\n\\\nvec3 positionHigh = positionHighAndSize.xyz;\\n\\\nvec3 positionLow = positionLowAndOutline.xyz;\\n\\\nfloat outlineWidthBothSides = 2.0 * positionLowAndOutline.w;\\n\\\nfloat totalSize = positionHighAndSize.w + outlineWidthBothSides;\\n\\\nfloat outlinePercent = outlineWidthBothSides / totalSize;\\n\\\ntotalSize *= czm_pixelRatio;\\n\\\ntotalSize += 3.0;\\n\\\nfloat temp = compressedAttribute1.x * SHIFT_RIGHT8;\\n\\\nfloat show = floor(temp);\\n\\\n#ifdef EYE_DISTANCE_TRANSLUCENCY\\n\\\nvec4 translucencyByDistance;\\n\\\ntranslucencyByDistance.x = compressedAttribute1.z;\\n\\\ntranslucencyByDistance.z = compressedAttribute1.w;\\n\\\ntranslucencyByDistance.y = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;\\n\\\ntemp = compressedAttribute1.y * SHIFT_RIGHT8;\\n\\\ntranslucencyByDistance.w = ((temp - floor(temp)) * SHIFT_LEFT8) / 255.0;\\n\\\n#endif\\n\\\nvec4 color;\\n\\\nvec4 outlineColor;\\n\\\nvec4 pickColor;\\n\\\ntemp = compressedAttribute0.z * SHIFT_RIGHT8;\\n\\\npickColor.b = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\npickColor.g = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\npickColor.r = floor(temp);\\n\\\ntemp = compressedAttribute0.x * SHIFT_RIGHT8;\\n\\\ncolor.b = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\ncolor.g = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ncolor.r = floor(temp);\\n\\\ntemp = compressedAttribute0.y * SHIFT_RIGHT8;\\n\\\noutlineColor.b = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\noutlineColor.g = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\noutlineColor.r = floor(temp);\\n\\\ntemp = compressedAttribute0.w * SHIFT_RIGHT8;\\n\\\npickColor.a = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\npickColor = pickColor / 255.0;\\n\\\ntemp = floor(temp) * SHIFT_RIGHT8;\\n\\\noutlineColor.a = (temp - floor(temp)) * SHIFT_LEFT8;\\n\\\noutlineColor /= 255.0;\\n\\\ncolor.a = floor(temp);\\n\\\ncolor /= 255.0;\\n\\\nvec4 p = czm_translateRelativeToEye(positionHigh, positionLow);\\n\\\nvec4 positionEC = czm_modelViewRelativeToEye * p;\\n\\\n#if defined(EYE_DISTANCE_SCALING) || defined(EYE_DISTANCE_TRANSLUCENCY) || defined(DISTANCE_DISPLAY_CONDITION) || defined(DISABLE_DEPTH_DISTANCE)\\n\\\nfloat lengthSq;\\n\\\nif (czm_sceneMode == czm_sceneMode2D)\\n\\\n{\\n\\\nlengthSq = czm_eyeHeight2D.y;\\n\\\n}\\n\\\nelse\\n\\\n{\\n\\\nlengthSq = dot(positionEC.xyz, positionEC.xyz);\\n\\\n}\\n\\\n#endif\\n\\\n#ifdef EYE_DISTANCE_SCALING\\n\\\ntotalSize *= czm_nearFarScalar(scaleByDistance, lengthSq);\\n\\\n#endif\\n\\\ntotalSize = min(totalSize, u_maxTotalPointSize);\\n\\\nif (totalSize < 1.0)\\n\\\n{\\n\\\npositionEC.xyz = vec3(0.0);\\n\\\ntotalSize = 1.0;\\n\\\n}\\n\\\nfloat translucency = 1.0;\\n\\\n#ifdef EYE_DISTANCE_TRANSLUCENCY\\n\\\ntranslucency = czm_nearFarScalar(translucencyByDistance, lengthSq);\\n\\\nif (translucency < 0.004)\\n\\\n{\\n\\\npositionEC.xyz = vec3(0.0);\\n\\\n}\\n\\\n#endif\\n\\\n#ifdef DISTANCE_DISPLAY_CONDITION\\n\\\nfloat nearSq = distanceDisplayConditionAndDisableDepth.x;\\n\\\nfloat farSq = distanceDisplayConditionAndDisableDepth.y;\\n\\\nif (lengthSq < nearSq || lengthSq > farSq) {\\n\\\npositionEC.xyz = vec3(0.0, 0.0, 1.0);\\n\\\n}\\n\\\n#endif\\n\\\ngl_Position = czm_projection * positionEC;\\n\\\nczm_vertexLogDepth();\\n\\\n#ifdef DISABLE_DEPTH_DISTANCE\\n\\\nfloat disableDepthTestDistance = distanceDisplayConditionAndDisableDepth.z;\\n\\\nif (disableDepthTestDistance == 0.0 && czm_minimumDisableDepthTestDistance != 0.0)\\n\\\n{\\n\\\ndisableDepthTestDistance = czm_minimumDisableDepthTestDistance;\\n\\\n}\\n\\\nif (disableDepthTestDistance != 0.0)\\n\\\n{\\n\\\nfloat zclip = gl_Position.z / gl_Position.w;\\n\\\nbool clipped = (zclip < -1.0 || zclip > 1.0);\\n\\\nif (!clipped && (disableDepthTestDistance < 0.0 || (lengthSq > 0.0 && lengthSq < disableDepthTestDistance)))\\n\\\n{\\n\\\ngl_Position.z = -gl_Position.w;\\n\\\n#ifdef LOG_DEPTH\\n\\\nczm_vertexLogDepth(vec4(czm_currentFrustum.x));\\n\\\n#endif\\n\\\n}\\n\\\n}\\n\\\n#endif\\n\\\nv_color = color;\\n\\\nv_color.a *= translucency * show;\\n\\\nv_outlineColor = outlineColor;\\n\\\nv_outlineColor.a *= translucency * show;\\n\\\nv_innerPercent = 1.0 - outlinePercent;\\n\\\nv_pixelDistance = 2.0 / totalSize;\\n\\\ngl_PointSize = totalSize * show;\\n\\\ngl_Position *= show;\\n\\\nv_pickColor = pickColor;\\n\\\n}\\n\\\n\";\n","import BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ComponentDatatype from \"../Core/ComponentDatatype.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport EncodedCartesian3 from \"../Core/EncodedCartesian3.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport PrimitiveType from \"../Core/PrimitiveType.js\";\r\nimport WebGLConstants from \"../Core/WebGLConstants.js\";\r\nimport BufferUsage from \"../Renderer/BufferUsage.js\";\r\nimport ContextLimits from \"../Renderer/ContextLimits.js\";\r\nimport DrawCommand from \"../Renderer/DrawCommand.js\";\r\nimport Pass from \"../Renderer/Pass.js\";\r\nimport RenderState from \"../Renderer/RenderState.js\";\r\nimport ShaderProgram from \"../Renderer/ShaderProgram.js\";\r\nimport ShaderSource from \"../Renderer/ShaderSource.js\";\r\nimport VertexArrayFacade from \"../Renderer/VertexArrayFacade.js\";\r\nimport PointPrimitiveCollectionFS from \"../Shaders/PointPrimitiveCollectionFS.js\";\r\nimport PointPrimitiveCollectionVS from \"../Shaders/PointPrimitiveCollectionVS.js\";\r\nimport BlendingState from \"./BlendingState.js\";\r\nimport BlendOption from \"./BlendOption.js\";\r\nimport PointPrimitive from \"./PointPrimitive.js\";\r\nimport SceneMode from \"./SceneMode.js\";\r\n\r\nvar SHOW_INDEX = PointPrimitive.SHOW_INDEX;\r\nvar POSITION_INDEX = PointPrimitive.POSITION_INDEX;\r\nvar COLOR_INDEX = PointPrimitive.COLOR_INDEX;\r\nvar OUTLINE_COLOR_INDEX = PointPrimitive.OUTLINE_COLOR_INDEX;\r\nvar OUTLINE_WIDTH_INDEX = PointPrimitive.OUTLINE_WIDTH_INDEX;\r\nvar PIXEL_SIZE_INDEX = PointPrimitive.PIXEL_SIZE_INDEX;\r\nvar SCALE_BY_DISTANCE_INDEX = PointPrimitive.SCALE_BY_DISTANCE_INDEX;\r\nvar TRANSLUCENCY_BY_DISTANCE_INDEX =\r\n PointPrimitive.TRANSLUCENCY_BY_DISTANCE_INDEX;\r\nvar DISTANCE_DISPLAY_CONDITION_INDEX =\r\n PointPrimitive.DISTANCE_DISPLAY_CONDITION_INDEX;\r\nvar DISABLE_DEPTH_DISTANCE_INDEX = PointPrimitive.DISABLE_DEPTH_DISTANCE_INDEX;\r\nvar NUMBER_OF_PROPERTIES = PointPrimitive.NUMBER_OF_PROPERTIES;\r\n\r\nvar attributeLocations = {\r\n positionHighAndSize: 0,\r\n positionLowAndOutline: 1,\r\n compressedAttribute0: 2, // color, outlineColor, pick color\r\n compressedAttribute1: 3, // show, translucency by distance, some free space\r\n scaleByDistance: 4,\r\n distanceDisplayConditionAndDisableDepth: 5,\r\n};\r\n\r\n/**\r\n * A renderable collection of points.\r\n *

\r\n * Points are added and removed from the collection using {@link PointPrimitiveCollection#add}\r\n * and {@link PointPrimitiveCollection#remove}.\r\n *\r\n * @alias PointPrimitiveCollection\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] The 4x4 transformation matrix that transforms each point from model to world coordinates.\r\n * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Determines if this primitive's commands' bounding spheres are shown.\r\n * @param {BlendOption} [options.blendOption=BlendOption.OPAQUE_AND_TRANSLUCENT] The point blending option. The default\r\n * is used for rendering both opaque and translucent points. However, if either all of the points are completely opaque or all are completely translucent,\r\n * setting the technique to BlendOption.OPAQUE or BlendOption.TRANSLUCENT can improve performance by up to 2x.\r\n * @param {Boolean} [options.show=true] Determines if the primitives in the collection will be shown.\r\n *\r\n * @performance For best performance, prefer a few collections, each with many points, to\r\n * many collections with only a few points each. Organize collections so that points\r\n * with the same update frequency are in the same collection, i.e., points that do not\r\n * change should be in one collection; points that change every frame should be in another\r\n * collection; and so on.\r\n *\r\n *\r\n * @example\r\n * // Create a pointPrimitive collection with two points\r\n * var points = scene.primitives.add(new Cesium.PointPrimitiveCollection());\r\n * points.add({\r\n * position : new Cesium.Cartesian3(1.0, 2.0, 3.0),\r\n * color : Cesium.Color.YELLOW\r\n * });\r\n * points.add({\r\n * position : new Cesium.Cartesian3(4.0, 5.0, 6.0),\r\n * color : Cesium.Color.CYAN\r\n * });\r\n *\r\n * @see PointPrimitiveCollection#add\r\n * @see PointPrimitiveCollection#remove\r\n * @see PointPrimitive\r\n */\r\nfunction PointPrimitiveCollection(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._sp = undefined;\r\n this._spTranslucent = undefined;\r\n this._rsOpaque = undefined;\r\n this._rsTranslucent = undefined;\r\n this._vaf = undefined;\r\n\r\n this._pointPrimitives = [];\r\n this._pointPrimitivesToUpdate = [];\r\n this._pointPrimitivesToUpdateIndex = 0;\r\n this._pointPrimitivesRemoved = false;\r\n this._createVertexArray = false;\r\n\r\n this._shaderScaleByDistance = false;\r\n this._compiledShaderScaleByDistance = false;\r\n\r\n this._shaderTranslucencyByDistance = false;\r\n this._compiledShaderTranslucencyByDistance = false;\r\n\r\n this._shaderDistanceDisplayCondition = false;\r\n this._compiledShaderDistanceDisplayCondition = false;\r\n\r\n this._shaderDisableDepthDistance = false;\r\n this._compiledShaderDisableDepthDistance = false;\r\n\r\n this._propertiesChanged = new Uint32Array(NUMBER_OF_PROPERTIES);\r\n\r\n this._maxPixelSize = 1.0;\r\n\r\n this._baseVolume = new BoundingSphere();\r\n this._baseVolumeWC = new BoundingSphere();\r\n this._baseVolume2D = new BoundingSphere();\r\n this._boundingVolume = new BoundingSphere();\r\n this._boundingVolumeDirty = false;\r\n\r\n this._colorCommands = [];\r\n\r\n /**\r\n * Determines if primitives in this collection will be shown.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * The 4x4 transformation matrix that transforms each point in this collection from model to world coordinates.\r\n * When this is the identity matrix, the pointPrimitives are drawn in world coordinates, i.e., Earth's WGS84 coordinates.\r\n * Local reference frames can be used by providing a different transformation matrix, like that returned\r\n * by {@link Transforms.eastNorthUpToFixedFrame}.\r\n *\r\n * @type {Matrix4}\r\n * @default {@link Matrix4.IDENTITY}\r\n *\r\n *\r\n * @example\r\n * var center = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);\r\n * pointPrimitives.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(center);\r\n * pointPrimitives.add({\r\n * color : Cesium.Color.ORANGE,\r\n * position : new Cesium.Cartesian3(0.0, 0.0, 0.0) // center\r\n * });\r\n * pointPrimitives.add({\r\n * color : Cesium.Color.YELLOW,\r\n * position : new Cesium.Cartesian3(1000000.0, 0.0, 0.0) // east\r\n * });\r\n * pointPrimitives.add({\r\n * color : Cesium.Color.GREEN,\r\n * position : new Cesium.Cartesian3(0.0, 1000000.0, 0.0) // north\r\n * });\r\n * pointPrimitives.add({\r\n * color : Cesium.Color.CYAN,\r\n * position : new Cesium.Cartesian3(0.0, 0.0, 1000000.0) // up\r\n * });\r\n *\r\n * @see Transforms.eastNorthUpToFixedFrame\r\n */\r\n this.modelMatrix = Matrix4.clone(\r\n defaultValue(options.modelMatrix, Matrix4.IDENTITY)\r\n );\r\n this._modelMatrix = Matrix4.clone(Matrix4.IDENTITY);\r\n\r\n /**\r\n * This property is for debugging only; it is not for production use nor is it optimized.\r\n *

\r\n * Draws the bounding sphere for each draw command in the primitive.\r\n *

\r\n *\r\n * @type {Boolean}\r\n *\r\n * @default false\r\n */\r\n this.debugShowBoundingVolume = defaultValue(\r\n options.debugShowBoundingVolume,\r\n false\r\n );\r\n\r\n /**\r\n * The point blending option. The default is used for rendering both opaque and translucent points.\r\n * However, if either all of the points are completely opaque or all are completely translucent,\r\n * setting the technique to BlendOption.OPAQUE or BlendOption.TRANSLUCENT can improve\r\n * performance by up to 2x.\r\n * @type {BlendOption}\r\n * @default BlendOption.OPAQUE_AND_TRANSLUCENT\r\n */\r\n this.blendOption = defaultValue(\r\n options.blendOption,\r\n BlendOption.OPAQUE_AND_TRANSLUCENT\r\n );\r\n this._blendOption = undefined;\r\n\r\n this._mode = SceneMode.SCENE3D;\r\n this._maxTotalPointSize = 1;\r\n\r\n // The buffer usage for each attribute is determined based on the usage of the attribute over time.\r\n this._buffersUsage = [\r\n BufferUsage.STATIC_DRAW, // SHOW_INDEX\r\n BufferUsage.STATIC_DRAW, // POSITION_INDEX\r\n BufferUsage.STATIC_DRAW, // COLOR_INDEX\r\n BufferUsage.STATIC_DRAW, // OUTLINE_COLOR_INDEX\r\n BufferUsage.STATIC_DRAW, // OUTLINE_WIDTH_INDEX\r\n BufferUsage.STATIC_DRAW, // PIXEL_SIZE_INDEX\r\n BufferUsage.STATIC_DRAW, // SCALE_BY_DISTANCE_INDEX\r\n BufferUsage.STATIC_DRAW, // TRANSLUCENCY_BY_DISTANCE_INDEX\r\n BufferUsage.STATIC_DRAW, // DISTANCE_DISPLAY_CONDITION_INDEX\r\n ];\r\n\r\n var that = this;\r\n this._uniforms = {\r\n u_maxTotalPointSize: function () {\r\n return that._maxTotalPointSize;\r\n },\r\n };\r\n}\r\n\r\nObject.defineProperties(PointPrimitiveCollection.prototype, {\r\n /**\r\n * Returns the number of points in this collection. This is commonly used with\r\n * {@link PointPrimitiveCollection#get} to iterate over all the points\r\n * in the collection.\r\n * @memberof PointPrimitiveCollection.prototype\r\n * @type {Number}\r\n */\r\n length: {\r\n get: function () {\r\n removePointPrimitives(this);\r\n return this._pointPrimitives.length;\r\n },\r\n },\r\n});\r\n\r\nfunction destroyPointPrimitives(pointPrimitives) {\r\n var length = pointPrimitives.length;\r\n for (var i = 0; i < length; ++i) {\r\n if (pointPrimitives[i]) {\r\n pointPrimitives[i]._destroy();\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Creates and adds a point with the specified initial properties to the collection.\r\n * The added point is returned so it can be modified or removed from the collection later.\r\n *\r\n * @param {Object}[options] A template describing the point's properties as shown in Example 1.\r\n * @returns {PointPrimitive} The point that was added to the collection.\r\n *\r\n * @performance Calling add is expected constant time. However, the collection's vertex buffer\r\n * is rewritten - an O(n) operation that also incurs CPU to GPU overhead. For\r\n * best performance, add as many pointPrimitives as possible before calling update.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * // Example 1: Add a point, specifying all the default values.\r\n * var p = pointPrimitives.add({\r\n * show : true,\r\n * position : Cesium.Cartesian3.ZERO,\r\n * pixelSize : 10.0,\r\n * color : Cesium.Color.WHITE,\r\n * outlineColor : Cesium.Color.TRANSPARENT,\r\n * outlineWidth : 0.0,\r\n * id : undefined\r\n * });\r\n *\r\n * @example\r\n * // Example 2: Specify only the point's cartographic position.\r\n * var p = pointPrimitives.add({\r\n * position : Cesium.Cartesian3.fromDegrees(longitude, latitude, height)\r\n * });\r\n *\r\n * @see PointPrimitiveCollection#remove\r\n * @see PointPrimitiveCollection#removeAll\r\n */\r\nPointPrimitiveCollection.prototype.add = function (options) {\r\n var p = new PointPrimitive(options, this);\r\n p._index = this._pointPrimitives.length;\r\n\r\n this._pointPrimitives.push(p);\r\n this._createVertexArray = true;\r\n\r\n return p;\r\n};\r\n\r\n/**\r\n * Removes a point from the collection.\r\n *\r\n * @param {PointPrimitive} pointPrimitive The point to remove.\r\n * @returns {Boolean} true if the point was removed; false if the point was not found in the collection.\r\n *\r\n * @performance Calling remove is expected constant time. However, the collection's vertex buffer\r\n * is rewritten - an O(n) operation that also incurs CPU to GPU overhead. For\r\n * best performance, remove as many points as possible before calling update.\r\n * If you intend to temporarily hide a point, it is usually more efficient to call\r\n * {@link PointPrimitive#show} instead of removing and re-adding the point.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * var p = pointPrimitives.add(...);\r\n * pointPrimitives.remove(p); // Returns true\r\n *\r\n * @see PointPrimitiveCollection#add\r\n * @see PointPrimitiveCollection#removeAll\r\n * @see PointPrimitive#show\r\n */\r\nPointPrimitiveCollection.prototype.remove = function (pointPrimitive) {\r\n if (this.contains(pointPrimitive)) {\r\n this._pointPrimitives[pointPrimitive._index] = null; // Removed later\r\n this._pointPrimitivesRemoved = true;\r\n this._createVertexArray = true;\r\n pointPrimitive._destroy();\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes all points from the collection.\r\n *\r\n * @performance O(n). It is more efficient to remove all the points\r\n * from a collection and then add new ones than to create a new collection entirely.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * pointPrimitives.add(...);\r\n * pointPrimitives.add(...);\r\n * pointPrimitives.removeAll();\r\n *\r\n * @see PointPrimitiveCollection#add\r\n * @see PointPrimitiveCollection#remove\r\n */\r\nPointPrimitiveCollection.prototype.removeAll = function () {\r\n destroyPointPrimitives(this._pointPrimitives);\r\n this._pointPrimitives = [];\r\n this._pointPrimitivesToUpdate = [];\r\n this._pointPrimitivesToUpdateIndex = 0;\r\n this._pointPrimitivesRemoved = false;\r\n\r\n this._createVertexArray = true;\r\n};\r\n\r\nfunction removePointPrimitives(pointPrimitiveCollection) {\r\n if (pointPrimitiveCollection._pointPrimitivesRemoved) {\r\n pointPrimitiveCollection._pointPrimitivesRemoved = false;\r\n\r\n var newPointPrimitives = [];\r\n var pointPrimitives = pointPrimitiveCollection._pointPrimitives;\r\n var length = pointPrimitives.length;\r\n for (var i = 0, j = 0; i < length; ++i) {\r\n var pointPrimitive = pointPrimitives[i];\r\n if (pointPrimitive) {\r\n pointPrimitive._index = j++;\r\n newPointPrimitives.push(pointPrimitive);\r\n }\r\n }\r\n\r\n pointPrimitiveCollection._pointPrimitives = newPointPrimitives;\r\n }\r\n}\r\n\r\nPointPrimitiveCollection.prototype._updatePointPrimitive = function (\r\n pointPrimitive,\r\n propertyChanged\r\n) {\r\n if (!pointPrimitive._dirty) {\r\n this._pointPrimitivesToUpdate[\r\n this._pointPrimitivesToUpdateIndex++\r\n ] = pointPrimitive;\r\n }\r\n\r\n ++this._propertiesChanged[propertyChanged];\r\n};\r\n\r\n/**\r\n * Check whether this collection contains a given point.\r\n *\r\n * @param {PointPrimitive} [pointPrimitive] The point to check for.\r\n * @returns {Boolean} true if this collection contains the point, false otherwise.\r\n *\r\n * @see PointPrimitiveCollection#get\r\n */\r\nPointPrimitiveCollection.prototype.contains = function (pointPrimitive) {\r\n return (\r\n defined(pointPrimitive) && pointPrimitive._pointPrimitiveCollection === this\r\n );\r\n};\r\n\r\n/**\r\n * Returns the point in the collection at the specified index. Indices are zero-based\r\n * and increase as points are added. Removing a point shifts all points after\r\n * it to the left, changing their indices. This function is commonly used with\r\n * {@link PointPrimitiveCollection#length} to iterate over all the points\r\n * in the collection.\r\n *\r\n * @param {Number} index The zero-based index of the point.\r\n * @returns {PointPrimitive} The point at the specified index.\r\n *\r\n * @performance Expected constant time. If points were removed from the collection and\r\n * {@link PointPrimitiveCollection#update} was not called, an implicit O(n)\r\n * operation is performed.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * // Toggle the show property of every point in the collection\r\n * var len = pointPrimitives.length;\r\n * for (var i = 0; i < len; ++i) {\r\n * var p = pointPrimitives.get(i);\r\n * p.show = !p.show;\r\n * }\r\n *\r\n * @see PointPrimitiveCollection#length\r\n */\r\nPointPrimitiveCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n removePointPrimitives(this);\r\n return this._pointPrimitives[index];\r\n};\r\n\r\nPointPrimitiveCollection.prototype.computeNewBuffersUsage = function () {\r\n var buffersUsage = this._buffersUsage;\r\n var usageChanged = false;\r\n\r\n var properties = this._propertiesChanged;\r\n for (var k = 0; k < NUMBER_OF_PROPERTIES; ++k) {\r\n var newUsage =\r\n properties[k] === 0 ? BufferUsage.STATIC_DRAW : BufferUsage.STREAM_DRAW;\r\n usageChanged = usageChanged || buffersUsage[k] !== newUsage;\r\n buffersUsage[k] = newUsage;\r\n }\r\n\r\n return usageChanged;\r\n};\r\n\r\nfunction createVAF(context, numberOfPointPrimitives, buffersUsage) {\r\n return new VertexArrayFacade(\r\n context,\r\n [\r\n {\r\n index: attributeLocations.positionHighAndSize,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[POSITION_INDEX],\r\n },\r\n {\r\n index: attributeLocations.positionLowAndShow,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[POSITION_INDEX],\r\n },\r\n {\r\n index: attributeLocations.compressedAttribute0,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[COLOR_INDEX],\r\n },\r\n {\r\n index: attributeLocations.compressedAttribute1,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[TRANSLUCENCY_BY_DISTANCE_INDEX],\r\n },\r\n {\r\n index: attributeLocations.scaleByDistance,\r\n componentsPerAttribute: 4,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[SCALE_BY_DISTANCE_INDEX],\r\n },\r\n {\r\n index: attributeLocations.distanceDisplayConditionAndDisableDepth,\r\n componentsPerAttribute: 3,\r\n componentDatatype: ComponentDatatype.FLOAT,\r\n usage: buffersUsage[DISTANCE_DISPLAY_CONDITION_INDEX],\r\n },\r\n ],\r\n numberOfPointPrimitives\r\n ); // 1 vertex per pointPrimitive\r\n}\r\n\r\n///////////////////////////////////////////////////////////////////////////\r\n\r\n// PERFORMANCE_IDEA: Save memory if a property is the same for all pointPrimitives, use a latched attribute state,\r\n// instead of storing it in a vertex buffer.\r\n\r\nvar writePositionScratch = new EncodedCartesian3();\r\n\r\nfunction writePositionSizeAndOutline(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n) {\r\n var i = pointPrimitive._index;\r\n var position = pointPrimitive._getActualPosition();\r\n\r\n if (pointPrimitiveCollection._mode === SceneMode.SCENE3D) {\r\n BoundingSphere.expand(\r\n pointPrimitiveCollection._baseVolume,\r\n position,\r\n pointPrimitiveCollection._baseVolume\r\n );\r\n pointPrimitiveCollection._boundingVolumeDirty = true;\r\n }\r\n\r\n EncodedCartesian3.fromCartesian(position, writePositionScratch);\r\n var pixelSize = pointPrimitive.pixelSize;\r\n var outlineWidth = pointPrimitive.outlineWidth;\r\n\r\n pointPrimitiveCollection._maxPixelSize = Math.max(\r\n pointPrimitiveCollection._maxPixelSize,\r\n pixelSize + outlineWidth\r\n );\r\n\r\n var positionHighWriter = vafWriters[attributeLocations.positionHighAndSize];\r\n var high = writePositionScratch.high;\r\n positionHighWriter(i, high.x, high.y, high.z, pixelSize);\r\n\r\n var positionLowWriter = vafWriters[attributeLocations.positionLowAndOutline];\r\n var low = writePositionScratch.low;\r\n positionLowWriter(i, low.x, low.y, low.z, outlineWidth);\r\n}\r\n\r\nvar LEFT_SHIFT16 = 65536.0; // 2^16\r\nvar LEFT_SHIFT8 = 256.0; // 2^8\r\n\r\nfunction writeCompressedAttrib0(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n) {\r\n var i = pointPrimitive._index;\r\n\r\n var color = pointPrimitive.color;\r\n var pickColor = pointPrimitive.getPickId(context).color;\r\n var outlineColor = pointPrimitive.outlineColor;\r\n\r\n var red = Color.floatToByte(color.red);\r\n var green = Color.floatToByte(color.green);\r\n var blue = Color.floatToByte(color.blue);\r\n var compressed0 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;\r\n\r\n red = Color.floatToByte(outlineColor.red);\r\n green = Color.floatToByte(outlineColor.green);\r\n blue = Color.floatToByte(outlineColor.blue);\r\n var compressed1 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;\r\n\r\n red = Color.floatToByte(pickColor.red);\r\n green = Color.floatToByte(pickColor.green);\r\n blue = Color.floatToByte(pickColor.blue);\r\n var compressed2 = red * LEFT_SHIFT16 + green * LEFT_SHIFT8 + blue;\r\n\r\n var compressed3 =\r\n Color.floatToByte(color.alpha) * LEFT_SHIFT16 +\r\n Color.floatToByte(outlineColor.alpha) * LEFT_SHIFT8 +\r\n Color.floatToByte(pickColor.alpha);\r\n\r\n var writer = vafWriters[attributeLocations.compressedAttribute0];\r\n writer(i, compressed0, compressed1, compressed2, compressed3);\r\n}\r\n\r\nfunction writeCompressedAttrib1(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n) {\r\n var i = pointPrimitive._index;\r\n\r\n var near = 0.0;\r\n var nearValue = 1.0;\r\n var far = 1.0;\r\n var farValue = 1.0;\r\n\r\n var translucency = pointPrimitive.translucencyByDistance;\r\n if (defined(translucency)) {\r\n near = translucency.near;\r\n nearValue = translucency.nearValue;\r\n far = translucency.far;\r\n farValue = translucency.farValue;\r\n\r\n if (nearValue !== 1.0 || farValue !== 1.0) {\r\n // translucency by distance calculation in shader need not be enabled\r\n // until a pointPrimitive with near and far !== 1.0 is found\r\n pointPrimitiveCollection._shaderTranslucencyByDistance = true;\r\n }\r\n }\r\n\r\n var show = pointPrimitive.show && pointPrimitive.clusterShow;\r\n\r\n // If the color alphas are zero, do not show this pointPrimitive. This lets us avoid providing\r\n // color during the pick pass and also eliminates a discard in the fragment shader.\r\n if (\r\n pointPrimitive.color.alpha === 0.0 &&\r\n pointPrimitive.outlineColor.alpha === 0.0\r\n ) {\r\n show = false;\r\n }\r\n\r\n nearValue = CesiumMath.clamp(nearValue, 0.0, 1.0);\r\n nearValue = nearValue === 1.0 ? 255.0 : (nearValue * 255.0) | 0;\r\n var compressed0 = (show ? 1.0 : 0.0) * LEFT_SHIFT8 + nearValue;\r\n\r\n farValue = CesiumMath.clamp(farValue, 0.0, 1.0);\r\n farValue = farValue === 1.0 ? 255.0 : (farValue * 255.0) | 0;\r\n var compressed1 = farValue;\r\n\r\n var writer = vafWriters[attributeLocations.compressedAttribute1];\r\n writer(i, compressed0, compressed1, near, far);\r\n}\r\n\r\nfunction writeScaleByDistance(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n) {\r\n var i = pointPrimitive._index;\r\n var writer = vafWriters[attributeLocations.scaleByDistance];\r\n var near = 0.0;\r\n var nearValue = 1.0;\r\n var far = 1.0;\r\n var farValue = 1.0;\r\n\r\n var scale = pointPrimitive.scaleByDistance;\r\n if (defined(scale)) {\r\n near = scale.near;\r\n nearValue = scale.nearValue;\r\n far = scale.far;\r\n farValue = scale.farValue;\r\n\r\n if (nearValue !== 1.0 || farValue !== 1.0) {\r\n // scale by distance calculation in shader need not be enabled\r\n // until a pointPrimitive with near and far !== 1.0 is found\r\n pointPrimitiveCollection._shaderScaleByDistance = true;\r\n }\r\n }\r\n\r\n writer(i, near, nearValue, far, farValue);\r\n}\r\n\r\nfunction writeDistanceDisplayConditionAndDepthDisable(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n) {\r\n var i = pointPrimitive._index;\r\n var writer =\r\n vafWriters[attributeLocations.distanceDisplayConditionAndDisableDepth];\r\n var near = 0.0;\r\n var far = Number.MAX_VALUE;\r\n\r\n var distanceDisplayCondition = pointPrimitive.distanceDisplayCondition;\r\n if (defined(distanceDisplayCondition)) {\r\n near = distanceDisplayCondition.near;\r\n far = distanceDisplayCondition.far;\r\n\r\n near *= near;\r\n far *= far;\r\n\r\n pointPrimitiveCollection._shaderDistanceDisplayCondition = true;\r\n }\r\n\r\n var disableDepthTestDistance = pointPrimitive.disableDepthTestDistance;\r\n disableDepthTestDistance *= disableDepthTestDistance;\r\n if (disableDepthTestDistance > 0.0) {\r\n pointPrimitiveCollection._shaderDisableDepthDistance = true;\r\n if (disableDepthTestDistance === Number.POSITIVE_INFINITY) {\r\n disableDepthTestDistance = -1.0;\r\n }\r\n }\r\n\r\n writer(i, near, far, disableDepthTestDistance);\r\n}\r\n\r\nfunction writePointPrimitive(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n) {\r\n writePositionSizeAndOutline(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n );\r\n writeCompressedAttrib0(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n );\r\n writeCompressedAttrib1(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n );\r\n writeScaleByDistance(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n );\r\n writeDistanceDisplayConditionAndDepthDisable(\r\n pointPrimitiveCollection,\r\n context,\r\n vafWriters,\r\n pointPrimitive\r\n );\r\n}\r\n\r\nfunction recomputeActualPositions(\r\n pointPrimitiveCollection,\r\n pointPrimitives,\r\n length,\r\n frameState,\r\n modelMatrix,\r\n recomputeBoundingVolume\r\n) {\r\n var boundingVolume;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n boundingVolume = pointPrimitiveCollection._baseVolume;\r\n pointPrimitiveCollection._boundingVolumeDirty = true;\r\n } else {\r\n boundingVolume = pointPrimitiveCollection._baseVolume2D;\r\n }\r\n\r\n var positions = [];\r\n for (var i = 0; i < length; ++i) {\r\n var pointPrimitive = pointPrimitives[i];\r\n var position = pointPrimitive.position;\r\n var actualPosition = PointPrimitive._computeActualPosition(\r\n position,\r\n frameState,\r\n modelMatrix\r\n );\r\n if (defined(actualPosition)) {\r\n pointPrimitive._setActualPosition(actualPosition);\r\n\r\n if (recomputeBoundingVolume) {\r\n positions.push(actualPosition);\r\n } else {\r\n BoundingSphere.expand(boundingVolume, actualPosition, boundingVolume);\r\n }\r\n }\r\n }\r\n\r\n if (recomputeBoundingVolume) {\r\n BoundingSphere.fromPoints(positions, boundingVolume);\r\n }\r\n}\r\n\r\nfunction updateMode(pointPrimitiveCollection, frameState) {\r\n var mode = frameState.mode;\r\n\r\n var pointPrimitives = pointPrimitiveCollection._pointPrimitives;\r\n var pointPrimitivesToUpdate =\r\n pointPrimitiveCollection._pointPrimitivesToUpdate;\r\n var modelMatrix = pointPrimitiveCollection._modelMatrix;\r\n\r\n if (\r\n pointPrimitiveCollection._createVertexArray ||\r\n pointPrimitiveCollection._mode !== mode ||\r\n (mode !== SceneMode.SCENE3D &&\r\n !Matrix4.equals(modelMatrix, pointPrimitiveCollection.modelMatrix))\r\n ) {\r\n pointPrimitiveCollection._mode = mode;\r\n Matrix4.clone(pointPrimitiveCollection.modelMatrix, modelMatrix);\r\n pointPrimitiveCollection._createVertexArray = true;\r\n\r\n if (\r\n mode === SceneMode.SCENE3D ||\r\n mode === SceneMode.SCENE2D ||\r\n mode === SceneMode.COLUMBUS_VIEW\r\n ) {\r\n recomputeActualPositions(\r\n pointPrimitiveCollection,\r\n pointPrimitives,\r\n pointPrimitives.length,\r\n frameState,\r\n modelMatrix,\r\n true\r\n );\r\n }\r\n } else if (mode === SceneMode.MORPHING) {\r\n recomputeActualPositions(\r\n pointPrimitiveCollection,\r\n pointPrimitives,\r\n pointPrimitives.length,\r\n frameState,\r\n modelMatrix,\r\n true\r\n );\r\n } else if (mode === SceneMode.SCENE2D || mode === SceneMode.COLUMBUS_VIEW) {\r\n recomputeActualPositions(\r\n pointPrimitiveCollection,\r\n pointPrimitivesToUpdate,\r\n pointPrimitiveCollection._pointPrimitivesToUpdateIndex,\r\n frameState,\r\n modelMatrix,\r\n false\r\n );\r\n }\r\n}\r\n\r\nfunction updateBoundingVolume(collection, frameState, boundingVolume) {\r\n var pixelSize = frameState.camera.getPixelSize(\r\n boundingVolume,\r\n frameState.context.drawingBufferWidth,\r\n frameState.context.drawingBufferHeight\r\n );\r\n var size = pixelSize * collection._maxPixelSize;\r\n boundingVolume.radius += size;\r\n}\r\n\r\nvar scratchWriterArray = [];\r\n\r\n/**\r\n * @private\r\n */\r\nPointPrimitiveCollection.prototype.update = function (frameState) {\r\n removePointPrimitives(this);\r\n\r\n if (!this.show) {\r\n return;\r\n }\r\n\r\n this._maxTotalPointSize = ContextLimits.maximumAliasedPointSize;\r\n\r\n updateMode(this, frameState);\r\n\r\n var pointPrimitives = this._pointPrimitives;\r\n var pointPrimitivesLength = pointPrimitives.length;\r\n var pointPrimitivesToUpdate = this._pointPrimitivesToUpdate;\r\n var pointPrimitivesToUpdateLength = this._pointPrimitivesToUpdateIndex;\r\n\r\n var properties = this._propertiesChanged;\r\n\r\n var createVertexArray = this._createVertexArray;\r\n\r\n var vafWriters;\r\n var context = frameState.context;\r\n var pass = frameState.passes;\r\n var picking = pass.pick;\r\n\r\n // PERFORMANCE_IDEA: Round robin multiple buffers.\r\n if (createVertexArray || (!picking && this.computeNewBuffersUsage())) {\r\n this._createVertexArray = false;\r\n\r\n for (var k = 0; k < NUMBER_OF_PROPERTIES; ++k) {\r\n properties[k] = 0;\r\n }\r\n\r\n this._vaf = this._vaf && this._vaf.destroy();\r\n\r\n if (pointPrimitivesLength > 0) {\r\n // PERFORMANCE_IDEA: Instead of creating a new one, resize like std::vector.\r\n this._vaf = createVAF(context, pointPrimitivesLength, this._buffersUsage);\r\n vafWriters = this._vaf.writers;\r\n\r\n // Rewrite entire buffer if pointPrimitives were added or removed.\r\n for (var i = 0; i < pointPrimitivesLength; ++i) {\r\n var pointPrimitive = this._pointPrimitives[i];\r\n pointPrimitive._dirty = false; // In case it needed an update.\r\n writePointPrimitive(this, context, vafWriters, pointPrimitive);\r\n }\r\n\r\n this._vaf.commit();\r\n }\r\n\r\n this._pointPrimitivesToUpdateIndex = 0;\r\n } else if (pointPrimitivesToUpdateLength > 0) {\r\n // PointPrimitives were modified, but none were added or removed.\r\n var writers = scratchWriterArray;\r\n writers.length = 0;\r\n\r\n if (\r\n properties[POSITION_INDEX] ||\r\n properties[OUTLINE_WIDTH_INDEX] ||\r\n properties[PIXEL_SIZE_INDEX]\r\n ) {\r\n writers.push(writePositionSizeAndOutline);\r\n }\r\n\r\n if (properties[COLOR_INDEX] || properties[OUTLINE_COLOR_INDEX]) {\r\n writers.push(writeCompressedAttrib0);\r\n }\r\n\r\n if (properties[SHOW_INDEX] || properties[TRANSLUCENCY_BY_DISTANCE_INDEX]) {\r\n writers.push(writeCompressedAttrib1);\r\n }\r\n\r\n if (properties[SCALE_BY_DISTANCE_INDEX]) {\r\n writers.push(writeScaleByDistance);\r\n }\r\n\r\n if (\r\n properties[DISTANCE_DISPLAY_CONDITION_INDEX] ||\r\n properties[DISABLE_DEPTH_DISTANCE_INDEX]\r\n ) {\r\n writers.push(writeDistanceDisplayConditionAndDepthDisable);\r\n }\r\n\r\n var numWriters = writers.length;\r\n\r\n vafWriters = this._vaf.writers;\r\n\r\n if (pointPrimitivesToUpdateLength / pointPrimitivesLength > 0.1) {\r\n // If more than 10% of pointPrimitive change, rewrite the entire buffer.\r\n\r\n // PERFORMANCE_IDEA: I totally made up 10% :).\r\n\r\n for (var m = 0; m < pointPrimitivesToUpdateLength; ++m) {\r\n var b = pointPrimitivesToUpdate[m];\r\n b._dirty = false;\r\n\r\n for (var n = 0; n < numWriters; ++n) {\r\n writers[n](this, context, vafWriters, b);\r\n }\r\n }\r\n this._vaf.commit();\r\n } else {\r\n for (var h = 0; h < pointPrimitivesToUpdateLength; ++h) {\r\n var bb = pointPrimitivesToUpdate[h];\r\n bb._dirty = false;\r\n\r\n for (var o = 0; o < numWriters; ++o) {\r\n writers[o](this, context, vafWriters, bb);\r\n }\r\n this._vaf.subCommit(bb._index, 1);\r\n }\r\n this._vaf.endSubCommits();\r\n }\r\n\r\n this._pointPrimitivesToUpdateIndex = 0;\r\n }\r\n\r\n // If the number of total pointPrimitives ever shrinks considerably\r\n // Truncate pointPrimitivesToUpdate so that we free memory that we're\r\n // not going to be using.\r\n if (pointPrimitivesToUpdateLength > pointPrimitivesLength * 1.5) {\r\n pointPrimitivesToUpdate.length = pointPrimitivesLength;\r\n }\r\n\r\n if (!defined(this._vaf) || !defined(this._vaf.va)) {\r\n return;\r\n }\r\n\r\n if (this._boundingVolumeDirty) {\r\n this._boundingVolumeDirty = false;\r\n BoundingSphere.transform(\r\n this._baseVolume,\r\n this.modelMatrix,\r\n this._baseVolumeWC\r\n );\r\n }\r\n\r\n var boundingVolume;\r\n var modelMatrix = Matrix4.IDENTITY;\r\n if (frameState.mode === SceneMode.SCENE3D) {\r\n modelMatrix = this.modelMatrix;\r\n boundingVolume = BoundingSphere.clone(\r\n this._baseVolumeWC,\r\n this._boundingVolume\r\n );\r\n } else {\r\n boundingVolume = BoundingSphere.clone(\r\n this._baseVolume2D,\r\n this._boundingVolume\r\n );\r\n }\r\n updateBoundingVolume(this, frameState, boundingVolume);\r\n\r\n var blendOptionChanged = this._blendOption !== this.blendOption;\r\n this._blendOption = this.blendOption;\r\n\r\n if (blendOptionChanged) {\r\n if (\r\n this._blendOption === BlendOption.OPAQUE ||\r\n this._blendOption === BlendOption.OPAQUE_AND_TRANSLUCENT\r\n ) {\r\n this._rsOpaque = RenderState.fromCache({\r\n depthTest: {\r\n enabled: true,\r\n func: WebGLConstants.LEQUAL,\r\n },\r\n depthMask: true,\r\n });\r\n } else {\r\n this._rsOpaque = undefined;\r\n }\r\n\r\n if (\r\n this._blendOption === BlendOption.TRANSLUCENT ||\r\n this._blendOption === BlendOption.OPAQUE_AND_TRANSLUCENT\r\n ) {\r\n this._rsTranslucent = RenderState.fromCache({\r\n depthTest: {\r\n enabled: true,\r\n func: WebGLConstants.LEQUAL,\r\n },\r\n depthMask: false,\r\n blending: BlendingState.ALPHA_BLEND,\r\n });\r\n } else {\r\n this._rsTranslucent = undefined;\r\n }\r\n }\r\n\r\n this._shaderDisableDepthDistance =\r\n this._shaderDisableDepthDistance ||\r\n frameState.minimumDisableDepthTestDistance !== 0.0;\r\n var vs;\r\n var fs;\r\n\r\n if (\r\n blendOptionChanged ||\r\n (this._shaderScaleByDistance && !this._compiledShaderScaleByDistance) ||\r\n (this._shaderTranslucencyByDistance &&\r\n !this._compiledShaderTranslucencyByDistance) ||\r\n (this._shaderDistanceDisplayCondition &&\r\n !this._compiledShaderDistanceDisplayCondition) ||\r\n this._shaderDisableDepthDistance !==\r\n this._compiledShaderDisableDepthDistance\r\n ) {\r\n vs = new ShaderSource({\r\n sources: [PointPrimitiveCollectionVS],\r\n });\r\n if (this._shaderScaleByDistance) {\r\n vs.defines.push(\"EYE_DISTANCE_SCALING\");\r\n }\r\n if (this._shaderTranslucencyByDistance) {\r\n vs.defines.push(\"EYE_DISTANCE_TRANSLUCENCY\");\r\n }\r\n if (this._shaderDistanceDisplayCondition) {\r\n vs.defines.push(\"DISTANCE_DISPLAY_CONDITION\");\r\n }\r\n if (this._shaderDisableDepthDistance) {\r\n vs.defines.push(\"DISABLE_DEPTH_DISTANCE\");\r\n }\r\n\r\n if (this._blendOption === BlendOption.OPAQUE_AND_TRANSLUCENT) {\r\n fs = new ShaderSource({\r\n defines: [\"OPAQUE\"],\r\n sources: [PointPrimitiveCollectionFS],\r\n });\r\n this._sp = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: this._sp,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n\r\n fs = new ShaderSource({\r\n defines: [\"TRANSLUCENT\"],\r\n sources: [PointPrimitiveCollectionFS],\r\n });\r\n this._spTranslucent = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: this._spTranslucent,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n }\r\n\r\n if (this._blendOption === BlendOption.OPAQUE) {\r\n fs = new ShaderSource({\r\n sources: [PointPrimitiveCollectionFS],\r\n });\r\n this._sp = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: this._sp,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n }\r\n\r\n if (this._blendOption === BlendOption.TRANSLUCENT) {\r\n fs = new ShaderSource({\r\n sources: [PointPrimitiveCollectionFS],\r\n });\r\n this._spTranslucent = ShaderProgram.replaceCache({\r\n context: context,\r\n shaderProgram: this._spTranslucent,\r\n vertexShaderSource: vs,\r\n fragmentShaderSource: fs,\r\n attributeLocations: attributeLocations,\r\n });\r\n }\r\n\r\n this._compiledShaderScaleByDistance = this._shaderScaleByDistance;\r\n this._compiledShaderTranslucencyByDistance = this._shaderTranslucencyByDistance;\r\n this._compiledShaderDistanceDisplayCondition = this._shaderDistanceDisplayCondition;\r\n this._compiledShaderDisableDepthDistance = this._shaderDisableDepthDistance;\r\n }\r\n\r\n var va;\r\n var vaLength;\r\n var command;\r\n var j;\r\n\r\n var commandList = frameState.commandList;\r\n\r\n if (pass.render || picking) {\r\n var colorList = this._colorCommands;\r\n\r\n var opaque = this._blendOption === BlendOption.OPAQUE;\r\n var opaqueAndTranslucent =\r\n this._blendOption === BlendOption.OPAQUE_AND_TRANSLUCENT;\r\n\r\n va = this._vaf.va;\r\n vaLength = va.length;\r\n\r\n colorList.length = vaLength;\r\n var totalLength = opaqueAndTranslucent ? vaLength * 2 : vaLength;\r\n for (j = 0; j < totalLength; ++j) {\r\n var opaqueCommand = opaque || (opaqueAndTranslucent && j % 2 === 0);\r\n\r\n command = colorList[j];\r\n if (!defined(command)) {\r\n command = colorList[j] = new DrawCommand();\r\n }\r\n\r\n command.primitiveType = PrimitiveType.POINTS;\r\n command.pass =\r\n opaqueCommand || !opaqueAndTranslucent ? Pass.OPAQUE : Pass.TRANSLUCENT;\r\n command.owner = this;\r\n\r\n var index = opaqueAndTranslucent ? Math.floor(j / 2.0) : j;\r\n command.boundingVolume = boundingVolume;\r\n command.modelMatrix = modelMatrix;\r\n command.shaderProgram = opaqueCommand ? this._sp : this._spTranslucent;\r\n command.uniformMap = this._uniforms;\r\n command.vertexArray = va[index].va;\r\n command.renderState = opaqueCommand\r\n ? this._rsOpaque\r\n : this._rsTranslucent;\r\n command.debugShowBoundingVolume = this.debugShowBoundingVolume;\r\n command.pickId = \"v_pickColor\";\r\n\r\n commandList.push(command);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see PointPrimitiveCollection#destroy\r\n */\r\nPointPrimitiveCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * pointPrimitives = pointPrimitives && pointPrimitives.destroy();\r\n *\r\n * @see PointPrimitiveCollection#isDestroyed\r\n */\r\nPointPrimitiveCollection.prototype.destroy = function () {\r\n this._sp = this._sp && this._sp.destroy();\r\n this._spTranslucent = this._spTranslucent && this._spTranslucent.destroy();\r\n this._spPick = this._spPick && this._spPick.destroy();\r\n this._vaf = this._vaf && this._vaf.destroy();\r\n destroyPointPrimitives(this._pointPrimitives);\r\n\r\n return destroyObject(this);\r\n};\r\nexport default PointPrimitiveCollection;\r\n","function kdbush(points, getX, getY, nodeSize, ArrayType) {\r\n return new KDBush(points, getX, getY, nodeSize, ArrayType);\r\n}\r\n\r\nfunction KDBush(points, getX, getY, nodeSize, ArrayType) {\r\n getX = getX || defaultGetX;\r\n getY = getY || defaultGetY;\r\n ArrayType = ArrayType || Array;\r\n\r\n this.nodeSize = nodeSize || 64;\r\n this.points = points;\r\n\r\n this.ids = new ArrayType(points.length);\r\n this.coords = new ArrayType(points.length * 2);\r\n\r\n for (var i = 0; i < points.length; i++) {\r\n this.ids[i] = i;\r\n this.coords[2 * i] = getX(points[i]);\r\n this.coords[2 * i + 1] = getY(points[i]);\r\n }\r\n\r\n sort(this.ids, this.coords, this.nodeSize, 0, this.ids.length - 1, 0);\r\n}\r\n\r\nKDBush.prototype = {\r\n range: function (minX, minY, maxX, maxY) {\r\n return range(this.ids, this.coords, minX, minY, maxX, maxY, this.nodeSize);\r\n },\r\n\r\n within: function (x, y, r) {\r\n return within(this.ids, this.coords, x, y, r, this.nodeSize);\r\n }\r\n};\r\n\r\nfunction defaultGetX(p) { return p[0]; }\r\nfunction defaultGetY(p) { return p[1]; }\r\n\r\nfunction range(ids, coords, minX, minY, maxX, maxY, nodeSize) {\r\n var stack = [0, ids.length - 1, 0];\r\n var result = [];\r\n var x, y;\r\n\r\n while (stack.length) {\r\n var axis = stack.pop();\r\n var right = stack.pop();\r\n var left = stack.pop();\r\n\r\n if (right - left <= nodeSize) {\r\n for (var i = left; i <= right; i++) {\r\n x = coords[2 * i];\r\n y = coords[2 * i + 1];\r\n if (x >= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[i]);\r\n }\r\n continue;\r\n }\r\n\r\n var m = Math.floor((left + right) / 2);\r\n\r\n x = coords[2 * m];\r\n y = coords[2 * m + 1];\r\n\r\n if (x >= minX && x <= maxX && y >= minY && y <= maxY) result.push(ids[m]);\r\n\r\n var nextAxis = (axis + 1) % 2;\r\n\r\n if (axis === 0 ? minX <= x : minY <= y) {\r\n stack.push(left);\r\n stack.push(m - 1);\r\n stack.push(nextAxis);\r\n }\r\n if (axis === 0 ? maxX >= x : maxY >= y) {\r\n stack.push(m + 1);\r\n stack.push(right);\r\n stack.push(nextAxis);\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction sort(ids, coords, nodeSize, left, right, depth) {\r\n if (right - left <= nodeSize) return;\r\n\r\n var m = Math.floor((left + right) / 2);\r\n\r\n select(ids, coords, m, left, right, depth % 2);\r\n\r\n sort(ids, coords, nodeSize, left, m - 1, depth + 1);\r\n sort(ids, coords, nodeSize, m + 1, right, depth + 1);\r\n}\r\n\r\nfunction select(ids, coords, k, left, right, inc) {\r\n\r\n while (right > left) {\r\n if (right - left > 600) {\r\n var n = right - left + 1;\r\n var m = k - left + 1;\r\n var z = Math.log(n);\r\n var s = 0.5 * Math.exp(2 * z / 3);\r\n var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);\r\n var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));\r\n var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));\r\n select(ids, coords, k, newLeft, newRight, inc);\r\n }\r\n\r\n var t = coords[2 * k + inc];\r\n var i = left;\r\n var j = right;\r\n\r\n swapItem(ids, coords, left, k);\r\n if (coords[2 * right + inc] > t) swapItem(ids, coords, left, right);\r\n\r\n while (i < j) {\r\n swapItem(ids, coords, i, j);\r\n i++;\r\n j--;\r\n while (coords[2 * i + inc] < t) i++;\r\n while (coords[2 * j + inc] > t) j--;\r\n }\r\n\r\n if (coords[2 * left + inc] === t) swapItem(ids, coords, left, j);\r\n else {\r\n j++;\r\n swapItem(ids, coords, j, right);\r\n }\r\n\r\n if (j <= k) left = j + 1;\r\n if (k <= j) right = j - 1;\r\n }\r\n}\r\n\r\nfunction swapItem(ids, coords, i, j) {\r\n swap(ids, i, j);\r\n swap(coords, 2 * i, 2 * j);\r\n swap(coords, 2 * i + 1, 2 * j + 1);\r\n}\r\n\r\nfunction swap(arr, i, j) {\r\n var tmp = arr[i];\r\n arr[i] = arr[j];\r\n arr[j] = tmp;\r\n}\r\n\r\nfunction within(ids, coords, qx, qy, r, nodeSize) {\r\n var stack = [0, ids.length - 1, 0];\r\n var result = [];\r\n var r2 = r * r;\r\n\r\n while (stack.length) {\r\n var axis = stack.pop();\r\n var right = stack.pop();\r\n var left = stack.pop();\r\n\r\n if (right - left <= nodeSize) {\r\n for (var i = left; i <= right; i++) {\r\n if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2) result.push(ids[i]);\r\n }\r\n continue;\r\n }\r\n\r\n var m = Math.floor((left + right) / 2);\r\n\r\n var x = coords[2 * m];\r\n var y = coords[2 * m + 1];\r\n\r\n if (sqDist(x, y, qx, qy) <= r2) result.push(ids[m]);\r\n\r\n var nextAxis = (axis + 1) % 2;\r\n\r\n if (axis === 0 ? qx - r <= x : qy - r <= y) {\r\n stack.push(left);\r\n stack.push(m - 1);\r\n stack.push(nextAxis);\r\n }\r\n if (axis === 0 ? qx + r >= x : qy + r >= y) {\r\n stack.push(m + 1);\r\n stack.push(right);\r\n stack.push(nextAxis);\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction sqDist(ax, ay, bx, by) {\r\n var dx = ax - bx;\r\n var dy = ay - by;\r\n return dx * dx + dy * dy;\r\n}\r\n\r\nexport default kdbush;\r\n","import BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport EllipsoidalOccluder from \"../Core/EllipsoidalOccluder.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Billboard from \"../Scene/Billboard.js\";\r\nimport BillboardCollection from \"../Scene/BillboardCollection.js\";\r\nimport Label from \"../Scene/Label.js\";\r\nimport LabelCollection from \"../Scene/LabelCollection.js\";\r\nimport PointPrimitive from \"../Scene/PointPrimitive.js\";\r\nimport PointPrimitiveCollection from \"../Scene/PointPrimitiveCollection.js\";\r\nimport SceneMode from \"../Scene/SceneMode.js\";\r\nimport kdbush from \"../ThirdParty/kdbush.js\";\r\n\r\n/**\r\n * Defines how screen space objects (billboards, points, labels) are clustered.\r\n *\r\n * @param {Object} [options] An object with the following properties:\r\n * @param {Boolean} [options.enabled=false] Whether or not to enable clustering.\r\n * @param {Number} [options.pixelRange=80] The pixel range to extend the screen space bounding box.\r\n * @param {Number} [options.minimumClusterSize=2] The minimum number of screen space objects that can be clustered.\r\n * @param {Boolean} [options.clusterBillboards=true] Whether or not to cluster the billboards of an entity.\r\n * @param {Boolean} [options.clusterLabels=true] Whether or not to cluster the labels of an entity.\r\n * @param {Boolean} [options.clusterPoints=true] Whether or not to cluster the points of an entity.\r\n * @param {Boolean} [options.show=true] Determines if the entities in the cluster will be shown.\r\n *\r\n * @alias EntityCluster\r\n * @constructor\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Clustering.html|Cesium Sandcastle Clustering Demo}\r\n */\r\nfunction EntityCluster(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._enabled = defaultValue(options.enabled, false);\r\n this._pixelRange = defaultValue(options.pixelRange, 80);\r\n this._minimumClusterSize = defaultValue(options.minimumClusterSize, 2);\r\n this._clusterBillboards = defaultValue(options.clusterBillboards, true);\r\n this._clusterLabels = defaultValue(options.clusterLabels, true);\r\n this._clusterPoints = defaultValue(options.clusterPoints, true);\r\n\r\n this._labelCollection = undefined;\r\n this._billboardCollection = undefined;\r\n this._pointCollection = undefined;\r\n\r\n this._clusterBillboardCollection = undefined;\r\n this._clusterLabelCollection = undefined;\r\n this._clusterPointCollection = undefined;\r\n\r\n this._collectionIndicesByEntity = {};\r\n\r\n this._unusedLabelIndices = [];\r\n this._unusedBillboardIndices = [];\r\n this._unusedPointIndices = [];\r\n\r\n this._previousClusters = [];\r\n this._previousHeight = undefined;\r\n\r\n this._enabledDirty = false;\r\n this._clusterDirty = false;\r\n\r\n this._cluster = undefined;\r\n this._removeEventListener = undefined;\r\n\r\n this._clusterEvent = new Event();\r\n\r\n /**\r\n * Determines if entities in this collection will be shown.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n}\r\n\r\nfunction getX(point) {\r\n return point.coord.x;\r\n}\r\n\r\nfunction getY(point) {\r\n return point.coord.y;\r\n}\r\n\r\nfunction expandBoundingBox(bbox, pixelRange) {\r\n bbox.x -= pixelRange;\r\n bbox.y -= pixelRange;\r\n bbox.width += pixelRange * 2.0;\r\n bbox.height += pixelRange * 2.0;\r\n}\r\n\r\nvar labelBoundingBoxScratch = new BoundingRectangle();\r\n\r\nfunction getBoundingBox(item, coord, pixelRange, entityCluster, result) {\r\n if (defined(item._labelCollection) && entityCluster._clusterLabels) {\r\n result = Label.getScreenSpaceBoundingBox(item, coord, result);\r\n } else if (\r\n defined(item._billboardCollection) &&\r\n entityCluster._clusterBillboards\r\n ) {\r\n result = Billboard.getScreenSpaceBoundingBox(item, coord, result);\r\n } else if (\r\n defined(item._pointPrimitiveCollection) &&\r\n entityCluster._clusterPoints\r\n ) {\r\n result = PointPrimitive.getScreenSpaceBoundingBox(item, coord, result);\r\n }\r\n\r\n expandBoundingBox(result, pixelRange);\r\n\r\n if (\r\n entityCluster._clusterLabels &&\r\n !defined(item._labelCollection) &&\r\n defined(item.id) &&\r\n hasLabelIndex(entityCluster, item.id.id) &&\r\n defined(item.id._label)\r\n ) {\r\n var labelIndex =\r\n entityCluster._collectionIndicesByEntity[item.id.id].labelIndex;\r\n var label = entityCluster._labelCollection.get(labelIndex);\r\n var labelBBox = Label.getScreenSpaceBoundingBox(\r\n label,\r\n coord,\r\n labelBoundingBoxScratch\r\n );\r\n expandBoundingBox(labelBBox, pixelRange);\r\n result = BoundingRectangle.union(result, labelBBox, result);\r\n }\r\n\r\n return result;\r\n}\r\n\r\nfunction addNonClusteredItem(item, entityCluster) {\r\n item.clusterShow = true;\r\n\r\n if (\r\n !defined(item._labelCollection) &&\r\n defined(item.id) &&\r\n hasLabelIndex(entityCluster, item.id.id) &&\r\n defined(item.id._label)\r\n ) {\r\n var labelIndex =\r\n entityCluster._collectionIndicesByEntity[item.id.id].labelIndex;\r\n var label = entityCluster._labelCollection.get(labelIndex);\r\n label.clusterShow = true;\r\n }\r\n}\r\n\r\nfunction addCluster(position, numPoints, ids, entityCluster) {\r\n var cluster = {\r\n billboard: entityCluster._clusterBillboardCollection.add(),\r\n label: entityCluster._clusterLabelCollection.add(),\r\n point: entityCluster._clusterPointCollection.add(),\r\n };\r\n\r\n cluster.billboard.show = false;\r\n cluster.point.show = false;\r\n cluster.label.show = true;\r\n cluster.label.text = numPoints.toLocaleString();\r\n cluster.label.id = ids;\r\n cluster.billboard.position = cluster.label.position = cluster.point.position = position;\r\n\r\n entityCluster._clusterEvent.raiseEvent(ids, cluster);\r\n}\r\n\r\nfunction hasLabelIndex(entityCluster, entityId) {\r\n return (\r\n defined(entityCluster) &&\r\n defined(entityCluster._collectionIndicesByEntity[entityId]) &&\r\n defined(entityCluster._collectionIndicesByEntity[entityId].labelIndex)\r\n );\r\n}\r\n\r\nfunction getScreenSpacePositions(\r\n collection,\r\n points,\r\n scene,\r\n occluder,\r\n entityCluster\r\n) {\r\n if (!defined(collection)) {\r\n return;\r\n }\r\n\r\n var length = collection.length;\r\n for (var i = 0; i < length; ++i) {\r\n var item = collection.get(i);\r\n item.clusterShow = false;\r\n\r\n if (\r\n !item.show ||\r\n (entityCluster._scene.mode === SceneMode.SCENE3D &&\r\n !occluder.isPointVisible(item.position))\r\n ) {\r\n continue;\r\n }\r\n\r\n var canClusterLabels =\r\n entityCluster._clusterLabels && defined(item._labelCollection);\r\n var canClusterBillboards =\r\n entityCluster._clusterBillboards && defined(item.id._billboard);\r\n var canClusterPoints =\r\n entityCluster._clusterPoints && defined(item.id._point);\r\n if (canClusterLabels && (canClusterPoints || canClusterBillboards)) {\r\n continue;\r\n }\r\n\r\n var coord = item.computeScreenSpacePosition(scene);\r\n if (!defined(coord)) {\r\n continue;\r\n }\r\n\r\n points.push({\r\n index: i,\r\n collection: collection,\r\n clustered: false,\r\n coord: coord,\r\n });\r\n }\r\n}\r\n\r\nvar pointBoundinRectangleScratch = new BoundingRectangle();\r\nvar totalBoundingRectangleScratch = new BoundingRectangle();\r\nvar neighborBoundingRectangleScratch = new BoundingRectangle();\r\n\r\nfunction createDeclutterCallback(entityCluster) {\r\n return function (amount) {\r\n if ((defined(amount) && amount < 0.05) || !entityCluster.enabled) {\r\n return;\r\n }\r\n\r\n var scene = entityCluster._scene;\r\n\r\n var labelCollection = entityCluster._labelCollection;\r\n var billboardCollection = entityCluster._billboardCollection;\r\n var pointCollection = entityCluster._pointCollection;\r\n\r\n if (\r\n (!defined(labelCollection) &&\r\n !defined(billboardCollection) &&\r\n !defined(pointCollection)) ||\r\n (!entityCluster._clusterBillboards &&\r\n !entityCluster._clusterLabels &&\r\n !entityCluster._clusterPoints)\r\n ) {\r\n return;\r\n }\r\n\r\n var clusteredLabelCollection = entityCluster._clusterLabelCollection;\r\n var clusteredBillboardCollection =\r\n entityCluster._clusterBillboardCollection;\r\n var clusteredPointCollection = entityCluster._clusterPointCollection;\r\n\r\n if (defined(clusteredLabelCollection)) {\r\n clusteredLabelCollection.removeAll();\r\n } else {\r\n clusteredLabelCollection = entityCluster._clusterLabelCollection = new LabelCollection(\r\n {\r\n scene: scene,\r\n }\r\n );\r\n }\r\n\r\n if (defined(clusteredBillboardCollection)) {\r\n clusteredBillboardCollection.removeAll();\r\n } else {\r\n clusteredBillboardCollection = entityCluster._clusterBillboardCollection = new BillboardCollection(\r\n {\r\n scene: scene,\r\n }\r\n );\r\n }\r\n\r\n if (defined(clusteredPointCollection)) {\r\n clusteredPointCollection.removeAll();\r\n } else {\r\n clusteredPointCollection = entityCluster._clusterPointCollection = new PointPrimitiveCollection();\r\n }\r\n\r\n var pixelRange = entityCluster._pixelRange;\r\n var minimumClusterSize = entityCluster._minimumClusterSize;\r\n\r\n var clusters = entityCluster._previousClusters;\r\n var newClusters = [];\r\n\r\n var previousHeight = entityCluster._previousHeight;\r\n var currentHeight = scene.camera.positionCartographic.height;\r\n\r\n var ellipsoid = scene.mapProjection.ellipsoid;\r\n var cameraPosition = scene.camera.positionWC;\r\n var occluder = new EllipsoidalOccluder(ellipsoid, cameraPosition);\r\n\r\n var points = [];\r\n if (entityCluster._clusterLabels) {\r\n getScreenSpacePositions(\r\n labelCollection,\r\n points,\r\n scene,\r\n occluder,\r\n entityCluster\r\n );\r\n }\r\n if (entityCluster._clusterBillboards) {\r\n getScreenSpacePositions(\r\n billboardCollection,\r\n points,\r\n scene,\r\n occluder,\r\n entityCluster\r\n );\r\n }\r\n if (entityCluster._clusterPoints) {\r\n getScreenSpacePositions(\r\n pointCollection,\r\n points,\r\n scene,\r\n occluder,\r\n entityCluster\r\n );\r\n }\r\n\r\n var i;\r\n var j;\r\n var length;\r\n var bbox;\r\n var neighbors;\r\n var neighborLength;\r\n var neighborIndex;\r\n var neighborPoint;\r\n var ids;\r\n var numPoints;\r\n\r\n var collection;\r\n var collectionIndex;\r\n\r\n var index = kdbush(points, getX, getY, 64, Int32Array);\r\n\r\n if (currentHeight < previousHeight) {\r\n length = clusters.length;\r\n for (i = 0; i < length; ++i) {\r\n var cluster = clusters[i];\r\n\r\n if (!occluder.isPointVisible(cluster.position)) {\r\n continue;\r\n }\r\n\r\n var coord = Billboard._computeScreenSpacePosition(\r\n Matrix4.IDENTITY,\r\n cluster.position,\r\n Cartesian3.ZERO,\r\n Cartesian2.ZERO,\r\n scene\r\n );\r\n if (!defined(coord)) {\r\n continue;\r\n }\r\n\r\n var factor = 1.0 - currentHeight / previousHeight;\r\n var width = (cluster.width = cluster.width * factor);\r\n var height = (cluster.height = cluster.height * factor);\r\n\r\n width = Math.max(width, cluster.minimumWidth);\r\n height = Math.max(height, cluster.minimumHeight);\r\n\r\n var minX = coord.x - width * 0.5;\r\n var minY = coord.y - height * 0.5;\r\n var maxX = coord.x + width;\r\n var maxY = coord.y + height;\r\n\r\n neighbors = index.range(minX, minY, maxX, maxY);\r\n neighborLength = neighbors.length;\r\n numPoints = 0;\r\n ids = [];\r\n\r\n for (j = 0; j < neighborLength; ++j) {\r\n neighborIndex = neighbors[j];\r\n neighborPoint = points[neighborIndex];\r\n if (!neighborPoint.clustered) {\r\n ++numPoints;\r\n\r\n collection = neighborPoint.collection;\r\n collectionIndex = neighborPoint.index;\r\n ids.push(collection.get(collectionIndex).id);\r\n }\r\n }\r\n\r\n if (numPoints >= minimumClusterSize) {\r\n addCluster(cluster.position, numPoints, ids, entityCluster);\r\n newClusters.push(cluster);\r\n\r\n for (j = 0; j < neighborLength; ++j) {\r\n points[neighbors[j]].clustered = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n length = points.length;\r\n for (i = 0; i < length; ++i) {\r\n var point = points[i];\r\n if (point.clustered) {\r\n continue;\r\n }\r\n\r\n point.clustered = true;\r\n\r\n collection = point.collection;\r\n collectionIndex = point.index;\r\n\r\n var item = collection.get(collectionIndex);\r\n bbox = getBoundingBox(\r\n item,\r\n point.coord,\r\n pixelRange,\r\n entityCluster,\r\n pointBoundinRectangleScratch\r\n );\r\n var totalBBox = BoundingRectangle.clone(\r\n bbox,\r\n totalBoundingRectangleScratch\r\n );\r\n\r\n neighbors = index.range(\r\n bbox.x,\r\n bbox.y,\r\n bbox.x + bbox.width,\r\n bbox.y + bbox.height\r\n );\r\n neighborLength = neighbors.length;\r\n\r\n var clusterPosition = Cartesian3.clone(item.position);\r\n numPoints = 1;\r\n ids = [item.id];\r\n\r\n for (j = 0; j < neighborLength; ++j) {\r\n neighborIndex = neighbors[j];\r\n neighborPoint = points[neighborIndex];\r\n if (!neighborPoint.clustered) {\r\n var neighborItem = neighborPoint.collection.get(neighborPoint.index);\r\n var neighborBBox = getBoundingBox(\r\n neighborItem,\r\n neighborPoint.coord,\r\n pixelRange,\r\n entityCluster,\r\n neighborBoundingRectangleScratch\r\n );\r\n\r\n Cartesian3.add(\r\n neighborItem.position,\r\n clusterPosition,\r\n clusterPosition\r\n );\r\n\r\n BoundingRectangle.union(totalBBox, neighborBBox, totalBBox);\r\n ++numPoints;\r\n\r\n ids.push(neighborItem.id);\r\n }\r\n }\r\n\r\n if (numPoints >= minimumClusterSize) {\r\n var position = Cartesian3.multiplyByScalar(\r\n clusterPosition,\r\n 1.0 / numPoints,\r\n clusterPosition\r\n );\r\n addCluster(position, numPoints, ids, entityCluster);\r\n newClusters.push({\r\n position: position,\r\n width: totalBBox.width,\r\n height: totalBBox.height,\r\n minimumWidth: bbox.width,\r\n minimumHeight: bbox.height,\r\n });\r\n\r\n for (j = 0; j < neighborLength; ++j) {\r\n points[neighbors[j]].clustered = true;\r\n }\r\n } else {\r\n addNonClusteredItem(item, entityCluster);\r\n }\r\n }\r\n\r\n if (clusteredLabelCollection.length === 0) {\r\n clusteredLabelCollection.destroy();\r\n entityCluster._clusterLabelCollection = undefined;\r\n }\r\n\r\n if (clusteredBillboardCollection.length === 0) {\r\n clusteredBillboardCollection.destroy();\r\n entityCluster._clusterBillboardCollection = undefined;\r\n }\r\n\r\n if (clusteredPointCollection.length === 0) {\r\n clusteredPointCollection.destroy();\r\n entityCluster._clusterPointCollection = undefined;\r\n }\r\n\r\n entityCluster._previousClusters = newClusters;\r\n entityCluster._previousHeight = currentHeight;\r\n };\r\n}\r\n\r\nEntityCluster.prototype._initialize = function (scene) {\r\n this._scene = scene;\r\n\r\n var cluster = createDeclutterCallback(this);\r\n this._cluster = cluster;\r\n this._removeEventListener = scene.camera.changed.addEventListener(cluster);\r\n};\r\n\r\nObject.defineProperties(EntityCluster.prototype, {\r\n /**\r\n * Gets or sets whether clustering is enabled.\r\n * @memberof EntityCluster.prototype\r\n * @type {Boolean}\r\n */\r\n enabled: {\r\n get: function () {\r\n return this._enabled;\r\n },\r\n set: function (value) {\r\n this._enabledDirty = value !== this._enabled;\r\n this._enabled = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets the pixel range to extend the screen space bounding box.\r\n * @memberof EntityCluster.prototype\r\n * @type {Number}\r\n */\r\n pixelRange: {\r\n get: function () {\r\n return this._pixelRange;\r\n },\r\n set: function (value) {\r\n this._clusterDirty = this._clusterDirty || value !== this._pixelRange;\r\n this._pixelRange = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets the minimum number of screen space objects that can be clustered.\r\n * @memberof EntityCluster.prototype\r\n * @type {Number}\r\n */\r\n minimumClusterSize: {\r\n get: function () {\r\n return this._minimumClusterSize;\r\n },\r\n set: function (value) {\r\n this._clusterDirty =\r\n this._clusterDirty || value !== this._minimumClusterSize;\r\n this._minimumClusterSize = value;\r\n },\r\n },\r\n /**\r\n * Gets the event that will be raised when a new cluster will be displayed. The signature of the event listener is {@link EntityCluster.newClusterCallback}.\r\n * @memberof EntityCluster.prototype\r\n * @type {Event}\r\n */\r\n clusterEvent: {\r\n get: function () {\r\n return this._clusterEvent;\r\n },\r\n },\r\n /**\r\n * Gets or sets whether clustering billboard entities is enabled.\r\n * @memberof EntityCluster.prototype\r\n * @type {Boolean}\r\n */\r\n clusterBillboards: {\r\n get: function () {\r\n return this._clusterBillboards;\r\n },\r\n set: function (value) {\r\n this._clusterDirty =\r\n this._clusterDirty || value !== this._clusterBillboards;\r\n this._clusterBillboards = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets whether clustering labels entities is enabled.\r\n * @memberof EntityCluster.prototype\r\n * @type {Boolean}\r\n */\r\n clusterLabels: {\r\n get: function () {\r\n return this._clusterLabels;\r\n },\r\n set: function (value) {\r\n this._clusterDirty = this._clusterDirty || value !== this._clusterLabels;\r\n this._clusterLabels = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets whether clustering point entities is enabled.\r\n * @memberof EntityCluster.prototype\r\n * @type {Boolean}\r\n */\r\n clusterPoints: {\r\n get: function () {\r\n return this._clusterPoints;\r\n },\r\n set: function (value) {\r\n this._clusterDirty = this._clusterDirty || value !== this._clusterPoints;\r\n this._clusterPoints = value;\r\n },\r\n },\r\n});\r\n\r\nfunction createGetEntity(\r\n collectionProperty,\r\n CollectionConstructor,\r\n unusedIndicesProperty,\r\n entityIndexProperty\r\n) {\r\n return function (entity) {\r\n var collection = this[collectionProperty];\r\n\r\n if (!defined(this._collectionIndicesByEntity)) {\r\n this._collectionIndicesByEntity = {};\r\n }\r\n\r\n var entityIndices = this._collectionIndicesByEntity[entity.id];\r\n\r\n if (!defined(entityIndices)) {\r\n entityIndices = this._collectionIndicesByEntity[entity.id] = {\r\n billboardIndex: undefined,\r\n labelIndex: undefined,\r\n pointIndex: undefined,\r\n };\r\n }\r\n\r\n if (defined(collection) && defined(entityIndices[entityIndexProperty])) {\r\n return collection.get(entityIndices[entityIndexProperty]);\r\n }\r\n\r\n if (!defined(collection)) {\r\n collection = this[collectionProperty] = new CollectionConstructor({\r\n scene: this._scene,\r\n });\r\n }\r\n\r\n var index;\r\n var entityItem;\r\n\r\n var unusedIndices = this[unusedIndicesProperty];\r\n if (unusedIndices.length > 0) {\r\n index = unusedIndices.pop();\r\n entityItem = collection.get(index);\r\n } else {\r\n entityItem = collection.add();\r\n index = collection.length - 1;\r\n }\r\n\r\n entityIndices[entityIndexProperty] = index;\r\n\r\n this._clusterDirty = true;\r\n\r\n return entityItem;\r\n };\r\n}\r\n\r\nfunction removeEntityIndicesIfUnused(entityCluster, entityId) {\r\n var indices = entityCluster._collectionIndicesByEntity[entityId];\r\n\r\n if (\r\n !defined(indices.billboardIndex) &&\r\n !defined(indices.labelIndex) &&\r\n !defined(indices.pointIndex)\r\n ) {\r\n delete entityCluster._collectionIndicesByEntity[entityId];\r\n }\r\n}\r\n\r\n/**\r\n * Returns a new {@link Label}.\r\n * @param {Entity} entity The entity that will use the returned {@link Label} for visualization.\r\n * @returns {Label} The label that will be used to visualize an entity.\r\n *\r\n * @private\r\n */\r\nEntityCluster.prototype.getLabel = createGetEntity(\r\n \"_labelCollection\",\r\n LabelCollection,\r\n \"_unusedLabelIndices\",\r\n \"labelIndex\"\r\n);\r\n\r\n/**\r\n * Removes the {@link Label} associated with an entity so it can be reused by another entity.\r\n * @param {Entity} entity The entity that will uses the returned {@link Label} for visualization.\r\n *\r\n * @private\r\n */\r\nEntityCluster.prototype.removeLabel = function (entity) {\r\n var entityIndices =\r\n this._collectionIndicesByEntity &&\r\n this._collectionIndicesByEntity[entity.id];\r\n if (\r\n !defined(this._labelCollection) ||\r\n !defined(entityIndices) ||\r\n !defined(entityIndices.labelIndex)\r\n ) {\r\n return;\r\n }\r\n\r\n var index = entityIndices.labelIndex;\r\n entityIndices.labelIndex = undefined;\r\n removeEntityIndicesIfUnused(this, entity.id);\r\n\r\n var label = this._labelCollection.get(index);\r\n label.show = false;\r\n label.text = \"\";\r\n label.id = undefined;\r\n\r\n this._unusedLabelIndices.push(index);\r\n\r\n this._clusterDirty = true;\r\n};\r\n\r\n/**\r\n * Returns a new {@link Billboard}.\r\n * @param {Entity} entity The entity that will use the returned {@link Billboard} for visualization.\r\n * @returns {Billboard} The label that will be used to visualize an entity.\r\n *\r\n * @private\r\n */\r\nEntityCluster.prototype.getBillboard = createGetEntity(\r\n \"_billboardCollection\",\r\n BillboardCollection,\r\n \"_unusedBillboardIndices\",\r\n \"billboardIndex\"\r\n);\r\n\r\n/**\r\n * Removes the {@link Billboard} associated with an entity so it can be reused by another entity.\r\n * @param {Entity} entity The entity that will uses the returned {@link Billboard} for visualization.\r\n *\r\n * @private\r\n */\r\nEntityCluster.prototype.removeBillboard = function (entity) {\r\n var entityIndices =\r\n this._collectionIndicesByEntity &&\r\n this._collectionIndicesByEntity[entity.id];\r\n if (\r\n !defined(this._billboardCollection) ||\r\n !defined(entityIndices) ||\r\n !defined(entityIndices.billboardIndex)\r\n ) {\r\n return;\r\n }\r\n\r\n var index = entityIndices.billboardIndex;\r\n entityIndices.billboardIndex = undefined;\r\n removeEntityIndicesIfUnused(this, entity.id);\r\n\r\n var billboard = this._billboardCollection.get(index);\r\n billboard.id = undefined;\r\n billboard.show = false;\r\n billboard.image = undefined;\r\n\r\n this._unusedBillboardIndices.push(index);\r\n\r\n this._clusterDirty = true;\r\n};\r\n\r\n/**\r\n * Returns a new {@link Point}.\r\n * @param {Entity} entity The entity that will use the returned {@link Point} for visualization.\r\n * @returns {Point} The label that will be used to visualize an entity.\r\n *\r\n * @private\r\n */\r\nEntityCluster.prototype.getPoint = createGetEntity(\r\n \"_pointCollection\",\r\n PointPrimitiveCollection,\r\n \"_unusedPointIndices\",\r\n \"pointIndex\"\r\n);\r\n\r\n/**\r\n * Removes the {@link Point} associated with an entity so it can be reused by another entity.\r\n * @param {Entity} entity The entity that will uses the returned {@link Point} for visualization.\r\n *\r\n * @private\r\n */\r\nEntityCluster.prototype.removePoint = function (entity) {\r\n var entityIndices =\r\n this._collectionIndicesByEntity &&\r\n this._collectionIndicesByEntity[entity.id];\r\n if (\r\n !defined(this._pointCollection) ||\r\n !defined(entityIndices) ||\r\n !defined(entityIndices.pointIndex)\r\n ) {\r\n return;\r\n }\r\n\r\n var index = entityIndices.pointIndex;\r\n entityIndices.pointIndex = undefined;\r\n removeEntityIndicesIfUnused(this, entity.id);\r\n\r\n var point = this._pointCollection.get(index);\r\n point.show = false;\r\n point.id = undefined;\r\n\r\n this._unusedPointIndices.push(index);\r\n\r\n this._clusterDirty = true;\r\n};\r\n\r\nfunction disableCollectionClustering(collection) {\r\n if (!defined(collection)) {\r\n return;\r\n }\r\n\r\n var length = collection.length;\r\n for (var i = 0; i < length; ++i) {\r\n collection.get(i).clusterShow = true;\r\n }\r\n}\r\n\r\nfunction updateEnable(entityCluster) {\r\n if (entityCluster.enabled) {\r\n return;\r\n }\r\n\r\n if (defined(entityCluster._clusterLabelCollection)) {\r\n entityCluster._clusterLabelCollection.destroy();\r\n }\r\n if (defined(entityCluster._clusterBillboardCollection)) {\r\n entityCluster._clusterBillboardCollection.destroy();\r\n }\r\n if (defined(entityCluster._clusterPointCollection)) {\r\n entityCluster._clusterPointCollection.destroy();\r\n }\r\n\r\n entityCluster._clusterLabelCollection = undefined;\r\n entityCluster._clusterBillboardCollection = undefined;\r\n entityCluster._clusterPointCollection = undefined;\r\n\r\n disableCollectionClustering(entityCluster._labelCollection);\r\n disableCollectionClustering(entityCluster._billboardCollection);\r\n disableCollectionClustering(entityCluster._pointCollection);\r\n}\r\n\r\n/**\r\n * Gets the draw commands for the clustered billboards/points/labels if enabled, otherwise,\r\n * queues the draw commands for billboards/points/labels created for entities.\r\n * @private\r\n */\r\nEntityCluster.prototype.update = function (frameState) {\r\n if (!this.show) {\r\n return;\r\n }\r\n\r\n // If clustering is enabled before the label collection is updated,\r\n // the glyphs haven't been created so the screen space bounding boxes\r\n // are incorrect.\r\n var commandList;\r\n if (\r\n defined(this._labelCollection) &&\r\n this._labelCollection.length > 0 &&\r\n this._labelCollection.get(0)._glyphs.length === 0\r\n ) {\r\n commandList = frameState.commandList;\r\n frameState.commandList = [];\r\n this._labelCollection.update(frameState);\r\n frameState.commandList = commandList;\r\n }\r\n\r\n // If clustering is enabled before the billboard collection is updated,\r\n // the images haven't been added to the image atlas so the screen space bounding boxes\r\n // are incorrect.\r\n if (\r\n defined(this._billboardCollection) &&\r\n this._billboardCollection.length > 0 &&\r\n !defined(this._billboardCollection.get(0).width)\r\n ) {\r\n commandList = frameState.commandList;\r\n frameState.commandList = [];\r\n this._billboardCollection.update(frameState);\r\n frameState.commandList = commandList;\r\n }\r\n\r\n if (this._enabledDirty) {\r\n this._enabledDirty = false;\r\n updateEnable(this);\r\n this._clusterDirty = true;\r\n }\r\n\r\n if (this._clusterDirty) {\r\n this._clusterDirty = false;\r\n this._cluster();\r\n }\r\n\r\n if (defined(this._clusterLabelCollection)) {\r\n this._clusterLabelCollection.update(frameState);\r\n }\r\n if (defined(this._clusterBillboardCollection)) {\r\n this._clusterBillboardCollection.update(frameState);\r\n }\r\n if (defined(this._clusterPointCollection)) {\r\n this._clusterPointCollection.update(frameState);\r\n }\r\n\r\n if (defined(this._labelCollection)) {\r\n this._labelCollection.update(frameState);\r\n }\r\n if (defined(this._billboardCollection)) {\r\n this._billboardCollection.update(frameState);\r\n }\r\n if (defined(this._pointCollection)) {\r\n this._pointCollection.update(frameState);\r\n }\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Unlike other objects that use WebGL resources, this object can be reused. For example, if a data source is removed\r\n * from a data source collection and added to another.\r\n *

\r\n */\r\nEntityCluster.prototype.destroy = function () {\r\n this._labelCollection =\r\n this._labelCollection && this._labelCollection.destroy();\r\n this._billboardCollection =\r\n this._billboardCollection && this._billboardCollection.destroy();\r\n this._pointCollection =\r\n this._pointCollection && this._pointCollection.destroy();\r\n\r\n this._clusterLabelCollection =\r\n this._clusterLabelCollection && this._clusterLabelCollection.destroy();\r\n this._clusterBillboardCollection =\r\n this._clusterBillboardCollection &&\r\n this._clusterBillboardCollection.destroy();\r\n this._clusterPointCollection =\r\n this._clusterPointCollection && this._clusterPointCollection.destroy();\r\n\r\n if (defined(this._removeEventListener)) {\r\n this._removeEventListener();\r\n this._removeEventListener = undefined;\r\n }\r\n\r\n this._labelCollection = undefined;\r\n this._billboardCollection = undefined;\r\n this._pointCollection = undefined;\r\n\r\n this._clusterBillboardCollection = undefined;\r\n this._clusterLabelCollection = undefined;\r\n this._clusterPointCollection = undefined;\r\n\r\n this._collectionIndicesByEntity = undefined;\r\n\r\n this._unusedLabelIndices = [];\r\n this._unusedBillboardIndices = [];\r\n this._unusedPointIndices = [];\r\n\r\n this._previousClusters = [];\r\n this._previousHeight = undefined;\r\n\r\n this._enabledDirty = false;\r\n this._pixelRangeDirty = false;\r\n this._minimumClusterSizeDirty = false;\r\n\r\n return undefined;\r\n};\r\n\r\n/**\r\n * A event listener function used to style clusters.\r\n * @callback EntityCluster.newClusterCallback\r\n *\r\n * @param {Entity[]} clusteredEntities An array of the entities contained in the cluster.\r\n * @param {Object} cluster An object containing billboard, label, and point properties. The values are the same as\r\n * billboard, label and point entities, but must be the values of the ConstantProperty.\r\n *\r\n * @example\r\n * // The default cluster values.\r\n * dataSource.clustering.clusterEvent.addEventListener(function(entities, cluster) {\r\n * cluster.label.show = true;\r\n * cluster.label.text = entities.length.toLocaleString();\r\n * });\r\n */\r\nexport default EntityCluster;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport DataSource from \"./DataSource.js\";\r\nimport EntityCluster from \"./EntityCluster.js\";\r\nimport EntityCollection from \"./EntityCollection.js\";\r\n\r\n/**\r\n * A {@link DataSource} implementation which can be used to manually manage a group of entities.\r\n *\r\n * @alias CustomDataSource\r\n * @constructor\r\n *\r\n * @param {String} [name] A human-readable name for this instance.\r\n *\r\n * @example\r\n * var dataSource = new Cesium.CustomDataSource('myData');\r\n *\r\n * var entity = dataSource.entities.add({\r\n * position : Cesium.Cartesian3.fromDegrees(1, 2, 0),\r\n * billboard : {\r\n * image : 'image.png'\r\n * }\r\n * });\r\n *\r\n * viewer.dataSources.add(dataSource);\r\n */\r\nfunction CustomDataSource(name) {\r\n this._name = name;\r\n this._clock = undefined;\r\n this._changed = new Event();\r\n this._error = new Event();\r\n this._isLoading = false;\r\n this._loading = new Event();\r\n this._entityCollection = new EntityCollection(this);\r\n this._entityCluster = new EntityCluster();\r\n}\r\n\r\nObject.defineProperties(CustomDataSource.prototype, {\r\n /**\r\n * Gets or sets a human-readable name for this instance.\r\n * @memberof CustomDataSource.prototype\r\n * @type {String}\r\n */\r\n name: {\r\n get: function () {\r\n return this._name;\r\n },\r\n set: function (value) {\r\n if (this._name !== value) {\r\n this._name = value;\r\n this._changed.raiseEvent(this);\r\n }\r\n },\r\n },\r\n /**\r\n * Gets or sets the clock for this instance.\r\n * @memberof CustomDataSource.prototype\r\n * @type {DataSourceClock}\r\n */\r\n clock: {\r\n get: function () {\r\n return this._clock;\r\n },\r\n set: function (value) {\r\n if (this._clock !== value) {\r\n this._clock = value;\r\n this._changed.raiseEvent(this);\r\n }\r\n },\r\n },\r\n /**\r\n * Gets the collection of {@link Entity} instances.\r\n * @memberof CustomDataSource.prototype\r\n * @type {EntityCollection}\r\n */\r\n entities: {\r\n get: function () {\r\n return this._entityCollection;\r\n },\r\n },\r\n /**\r\n * Gets or sets whether the data source is currently loading data.\r\n * @memberof CustomDataSource.prototype\r\n * @type {Boolean}\r\n */\r\n isLoading: {\r\n get: function () {\r\n return this._isLoading;\r\n },\r\n set: function (value) {\r\n DataSource.setLoading(this, value);\r\n },\r\n },\r\n /**\r\n * Gets an event that will be raised when the underlying data changes.\r\n * @memberof CustomDataSource.prototype\r\n * @type {Event}\r\n */\r\n changedEvent: {\r\n get: function () {\r\n return this._changed;\r\n },\r\n },\r\n /**\r\n * Gets an event that will be raised if an error is encountered during processing.\r\n * @memberof CustomDataSource.prototype\r\n * @type {Event}\r\n */\r\n errorEvent: {\r\n get: function () {\r\n return this._error;\r\n },\r\n },\r\n /**\r\n * Gets an event that will be raised when the data source either starts or stops loading.\r\n * @memberof CustomDataSource.prototype\r\n * @type {Event}\r\n */\r\n loadingEvent: {\r\n get: function () {\r\n return this._loading;\r\n },\r\n },\r\n /**\r\n * Gets whether or not this data source should be displayed.\r\n * @memberof CustomDataSource.prototype\r\n * @type {Boolean}\r\n */\r\n show: {\r\n get: function () {\r\n return this._entityCollection.show;\r\n },\r\n set: function (value) {\r\n this._entityCollection.show = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.\r\n *\r\n * @memberof CustomDataSource.prototype\r\n * @type {EntityCluster}\r\n */\r\n clustering: {\r\n get: function () {\r\n return this._entityCluster;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value must be defined.\");\r\n }\r\n //>>includeEnd('debug');\r\n this._entityCluster = value;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Updates the data source to the provided time. This function is optional and\r\n * is not required to be implemented. It is provided for data sources which\r\n * retrieve data based on the current animation time or scene state.\r\n * If implemented, update will be called by {@link DataSourceDisplay} once a frame.\r\n *\r\n * @param {JulianDate} time The simulation time.\r\n * @returns {Boolean} True if this data source is ready to be displayed at the provided time, false otherwise.\r\n */\r\nCustomDataSource.prototype.update = function (time) {\r\n return true;\r\n};\r\n\r\nexport default CustomDataSource;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport CylinderGeometry from \"../Core/CylinderGeometry.js\";\r\nimport CylinderOutlineGeometry from \"../Core/CylinderOutlineGeometry.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport GeometryOffsetAttribute from \"../Core/GeometryOffsetAttribute.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport heightReferenceOnEntityPropertyChanged from \"./heightReferenceOnEntityPropertyChanged.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultOffset = Cartesian3.ZERO;\r\n\r\nvar offsetScratch = new Cartesian3();\r\nvar positionScratch = new Cartesian3();\r\nvar scratchColor = new Color();\r\n\r\nfunction CylinderGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.length = undefined;\r\n this.topRadius = undefined;\r\n this.bottomRadius = undefined;\r\n this.slices = undefined;\r\n this.numberOfVerticalLines = undefined;\r\n this.offsetAttribute = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for cylinders.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias CylinderGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction CylinderGeometryUpdater(entity, scene) {\r\n GeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new CylinderGeometryOptions(entity),\r\n geometryPropertyName: \"cylinder\",\r\n observedPropertyNames: [\r\n \"availability\",\r\n \"position\",\r\n \"orientation\",\r\n \"cylinder\",\r\n ],\r\n });\r\n\r\n this._onEntityPropertyChanged(entity, \"cylinder\", entity.cylinder, undefined);\r\n}\r\n\r\nif (defined(Object.create)) {\r\n CylinderGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);\r\n CylinderGeometryUpdater.prototype.constructor = CylinderGeometryUpdater;\r\n}\r\n\r\nObject.defineProperties(CylinderGeometryUpdater.prototype, {\r\n /**\r\n * Gets the terrain offset property\r\n * @type {TerrainOffsetProperty}\r\n * @memberof CylinderGeometryUpdater.prototype\r\n * @readonly\r\n * @private\r\n */\r\n terrainOffsetProperty: {\r\n get: function () {\r\n return this._terrainOffsetProperty;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nCylinderGeometryUpdater.prototype.createFillGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var show = new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n );\r\n\r\n var attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n color: undefined,\r\n offset: undefined,\r\n };\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n }\r\n\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new CylinderGeometry(this._options),\r\n modelMatrix: entity.computeModelMatrixForHeightReference(\r\n time,\r\n entity.cylinder.heightReference,\r\n this._options.length * 0.5,\r\n this._scene.mapProjection.ellipsoid\r\n ),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nCylinderGeometryUpdater.prototype.createOutlineGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n offset: undefined,\r\n };\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new CylinderOutlineGeometry(this._options),\r\n modelMatrix: entity.computeModelMatrixForHeightReference(\r\n time,\r\n entity.cylinder.heightReference,\r\n this._options.length * 0.5,\r\n this._scene.mapProjection.ellipsoid\r\n ),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\nCylinderGeometryUpdater.prototype._computeCenter = function (time, result) {\r\n return Property.getValueOrUndefined(this._entity.position, time, result);\r\n};\r\n\r\nCylinderGeometryUpdater.prototype._isHidden = function (entity, cylinder) {\r\n return (\r\n !defined(entity.position) ||\r\n !defined(cylinder.length) ||\r\n !defined(cylinder.topRadius) ||\r\n !defined(cylinder.bottomRadius) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, cylinder)\r\n );\r\n};\r\n\r\nCylinderGeometryUpdater.prototype._isDynamic = function (entity, cylinder) {\r\n return (\r\n !entity.position.isConstant || //\r\n !Property.isConstant(entity.orientation) || //\r\n !cylinder.length.isConstant || //\r\n !cylinder.topRadius.isConstant || //\r\n !cylinder.bottomRadius.isConstant || //\r\n !Property.isConstant(cylinder.slices) || //\r\n !Property.isConstant(cylinder.outlineWidth) || //\r\n !Property.isConstant(cylinder.numberOfVerticalLines)\r\n );\r\n};\r\n\r\nCylinderGeometryUpdater.prototype._setStaticOptions = function (\r\n entity,\r\n cylinder\r\n) {\r\n var heightReference = Property.getValueOrDefault(\r\n cylinder.heightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n var options = this._options;\r\n options.vertexFormat =\r\n this._materialProperty instanceof ColorMaterialProperty\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.length = cylinder.length.getValue(Iso8601.MINIMUM_VALUE);\r\n options.topRadius = cylinder.topRadius.getValue(Iso8601.MINIMUM_VALUE);\r\n options.bottomRadius = cylinder.bottomRadius.getValue(Iso8601.MINIMUM_VALUE);\r\n options.slices = Property.getValueOrUndefined(\r\n cylinder.slices,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.numberOfVerticalLines = Property.getValueOrUndefined(\r\n cylinder.numberOfVerticalLines,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.offsetAttribute =\r\n heightReference !== HeightReference.NONE\r\n ? GeometryOffsetAttribute.ALL\r\n : undefined;\r\n};\r\n\r\nCylinderGeometryUpdater.prototype._onEntityPropertyChanged = heightReferenceOnEntityPropertyChanged;\r\n\r\nCylinderGeometryUpdater.DynamicGeometryUpdater = DynamicCylinderGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicCylinderGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicCylinderGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicCylinderGeometryUpdater.prototype.constructor = DynamicCylinderGeometryUpdater;\r\n}\r\n\r\nDynamicCylinderGeometryUpdater.prototype._isHidden = function (\r\n entity,\r\n cylinder,\r\n time\r\n) {\r\n var options = this._options;\r\n var position = Property.getValueOrUndefined(\r\n entity.position,\r\n time,\r\n positionScratch\r\n );\r\n return (\r\n !defined(position) ||\r\n !defined(options.length) ||\r\n !defined(options.topRadius) || //\r\n !defined(options.bottomRadius) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(\r\n this,\r\n entity,\r\n cylinder,\r\n time\r\n )\r\n );\r\n};\r\n\r\nDynamicCylinderGeometryUpdater.prototype._setOptions = function (\r\n entity,\r\n cylinder,\r\n time\r\n) {\r\n var heightReference = Property.getValueOrDefault(\r\n cylinder.heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var options = this._options;\r\n options.length = Property.getValueOrUndefined(cylinder.length, time);\r\n options.topRadius = Property.getValueOrUndefined(cylinder.topRadius, time);\r\n options.bottomRadius = Property.getValueOrUndefined(\r\n cylinder.bottomRadius,\r\n time\r\n );\r\n options.slices = Property.getValueOrUndefined(cylinder.slices, time);\r\n options.numberOfVerticalLines = Property.getValueOrUndefined(\r\n cylinder.numberOfVerticalLines,\r\n time\r\n );\r\n options.offsetAttribute =\r\n heightReference !== HeightReference.NONE\r\n ? GeometryOffsetAttribute.ALL\r\n : undefined;\r\n};\r\nexport default CylinderGeometryUpdater;\r\n","import Clock from \"../Core/Clock.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport createRawPropertyDescriptor from \"./createRawPropertyDescriptor.js\";\r\n\r\n/**\r\n * Represents desired clock settings for a particular {@link DataSource}. These settings may be applied\r\n * to the {@link Clock} when the DataSource is loaded.\r\n *\r\n * @alias DataSourceClock\r\n * @constructor\r\n */\r\nfunction DataSourceClock() {\r\n this._definitionChanged = new Event();\r\n this._startTime = undefined;\r\n this._stopTime = undefined;\r\n this._currentTime = undefined;\r\n this._clockRange = undefined;\r\n this._clockStep = undefined;\r\n this._multiplier = undefined;\r\n}\r\n\r\nObject.defineProperties(DataSourceClock.prototype, {\r\n /**\r\n * Gets the event that is raised whenever a new property is assigned.\r\n * @memberof DataSourceClock.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the desired start time of the clock.\r\n * See {@link Clock#startTime}.\r\n * @memberof DataSourceClock.prototype\r\n * @type {JulianDate}\r\n */\r\n startTime: createRawPropertyDescriptor(\"startTime\"),\r\n\r\n /**\r\n * Gets or sets the desired stop time of the clock.\r\n * See {@link Clock#stopTime}.\r\n * @memberof DataSourceClock.prototype\r\n * @type {JulianDate}\r\n */\r\n stopTime: createRawPropertyDescriptor(\"stopTime\"),\r\n\r\n /**\r\n * Gets or sets the desired current time when this data source is loaded.\r\n * See {@link Clock#currentTime}.\r\n * @memberof DataSourceClock.prototype\r\n * @type {JulianDate}\r\n */\r\n currentTime: createRawPropertyDescriptor(\"currentTime\"),\r\n\r\n /**\r\n * Gets or sets the desired clock range setting.\r\n * See {@link Clock#clockRange}.\r\n * @memberof DataSourceClock.prototype\r\n * @type {ClockRange}\r\n */\r\n clockRange: createRawPropertyDescriptor(\"clockRange\"),\r\n\r\n /**\r\n * Gets or sets the desired clock step setting.\r\n * See {@link Clock#clockStep}.\r\n * @memberof DataSourceClock.prototype\r\n * @type {ClockStep}\r\n */\r\n clockStep: createRawPropertyDescriptor(\"clockStep\"),\r\n\r\n /**\r\n * Gets or sets the desired clock multiplier.\r\n * See {@link Clock#multiplier}.\r\n * @memberof DataSourceClock.prototype\r\n * @type {Number}\r\n */\r\n multiplier: createRawPropertyDescriptor(\"multiplier\"),\r\n});\r\n\r\n/**\r\n * Duplicates a DataSourceClock instance.\r\n *\r\n * @param {DataSourceClock} [result] The object onto which to store the result.\r\n * @returns {DataSourceClock} The modified result parameter or a new instance if one was not provided.\r\n */\r\nDataSourceClock.prototype.clone = function (result) {\r\n if (!defined(result)) {\r\n result = new DataSourceClock();\r\n }\r\n result.startTime = this.startTime;\r\n result.stopTime = this.stopTime;\r\n result.currentTime = this.currentTime;\r\n result.clockRange = this.clockRange;\r\n result.clockStep = this.clockStep;\r\n result.multiplier = this.multiplier;\r\n return result;\r\n};\r\n\r\n/**\r\n * Returns true if this DataSourceClock is equivalent to the other\r\n *\r\n * @param {DataSourceClock} other The other DataSourceClock to compare to.\r\n * @returns {Boolean} true if the DataSourceClocks are equal; otherwise, false.\r\n */\r\nDataSourceClock.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (defined(other) &&\r\n JulianDate.equals(this.startTime, other.startTime) &&\r\n JulianDate.equals(this.stopTime, other.stopTime) &&\r\n JulianDate.equals(this.currentTime, other.currentTime) &&\r\n this.clockRange === other.clockRange &&\r\n this.clockStep === other.clockStep &&\r\n this.multiplier === other.multiplier)\r\n );\r\n};\r\n\r\n/**\r\n * Assigns each unassigned property on this object to the value\r\n * of the same property on the provided source object.\r\n *\r\n * @param {DataSourceClock} source The object to be merged into this object.\r\n */\r\nDataSourceClock.prototype.merge = function (source) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(source)) {\r\n throw new DeveloperError(\"source is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this.startTime = defaultValue(this.startTime, source.startTime);\r\n this.stopTime = defaultValue(this.stopTime, source.stopTime);\r\n this.currentTime = defaultValue(this.currentTime, source.currentTime);\r\n this.clockRange = defaultValue(this.clockRange, source.clockRange);\r\n this.clockStep = defaultValue(this.clockStep, source.clockStep);\r\n this.multiplier = defaultValue(this.multiplier, source.multiplier);\r\n};\r\n\r\n/**\r\n * Gets the value of this clock instance as a {@link Clock} object.\r\n *\r\n * @returns {Clock} The modified result parameter or a new instance if one was not provided.\r\n */\r\nDataSourceClock.prototype.getValue = function (result) {\r\n if (!defined(result)) {\r\n result = new Clock();\r\n }\r\n result.startTime = defaultValue(this.startTime, result.startTime);\r\n result.stopTime = defaultValue(this.stopTime, result.stopTime);\r\n result.currentTime = defaultValue(this.currentTime, result.currentTime);\r\n result.clockRange = defaultValue(this.clockRange, result.clockRange);\r\n result.multiplier = defaultValue(this.multiplier, result.multiplier);\r\n result.clockStep = defaultValue(this.clockStep, result.clockStep);\r\n return result;\r\n};\r\nexport default DataSourceClock;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultColor = Color.WHITE;\r\nvar defaultCellAlpha = 0.1;\r\nvar defaultLineCount = new Cartesian2(8, 8);\r\nvar defaultLineOffset = new Cartesian2(0, 0);\r\nvar defaultLineThickness = new Cartesian2(1, 1);\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to grid {@link Material} uniforms.\r\n * @alias GridMaterialProperty\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Property|Color} [options.color=Color.WHITE] A Property specifying the grid {@link Color}.\r\n * @param {Property|Number} [options.cellAlpha=0.1] A numeric Property specifying cell alpha values.\r\n * @param {Property|Cartesian2} [options.lineCount=new Cartesian2(8, 8)] A {@link Cartesian2} Property specifying the number of grid lines along each axis.\r\n * @param {Property|Cartesian2} [options.lineThickness=new Cartesian2(1.0, 1.0)] A {@link Cartesian2} Property specifying the thickness of grid lines along each axis.\r\n * @param {Property|Cartesian2} [options.lineOffset=new Cartesian2(0.0, 0.0)] A {@link Cartesian2} Property specifying starting offset of grid lines along each axis.\r\n *\r\n * @constructor\r\n */\r\nfunction GridMaterialProperty(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._definitionChanged = new Event();\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n this._cellAlpha = undefined;\r\n this._cellAlphaSubscription = undefined;\r\n this._lineCount = undefined;\r\n this._lineCountSubscription = undefined;\r\n this._lineThickness = undefined;\r\n this._lineThicknessSubscription = undefined;\r\n this._lineOffset = undefined;\r\n this._lineOffsetSubscription = undefined;\r\n\r\n this.color = options.color;\r\n this.cellAlpha = options.cellAlpha;\r\n this.lineCount = options.lineCount;\r\n this.lineThickness = options.lineThickness;\r\n this.lineOffset = options.lineOffset;\r\n}\r\n\r\nObject.defineProperties(GridMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof GridMaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n Property.isConstant(this._color) &&\r\n Property.isConstant(this._cellAlpha) &&\r\n Property.isConstant(this._lineCount) &&\r\n Property.isConstant(this._lineThickness) &&\r\n Property.isConstant(this._lineOffset)\r\n );\r\n },\r\n },\r\n\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof GridMaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the Property specifying the grid {@link Color}.\r\n * @memberof GridMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying cell alpha values.\r\n * @memberof GridMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default 0.1\r\n */\r\n cellAlpha: createPropertyDescriptor(\"cellAlpha\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying the number of grid lines along each axis.\r\n * @memberof GridMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default new Cartesian2(8.0, 8.0)\r\n */\r\n lineCount: createPropertyDescriptor(\"lineCount\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying the thickness of grid lines along each axis.\r\n * @memberof GridMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default new Cartesian2(1.0, 1.0)\r\n */\r\n lineThickness: createPropertyDescriptor(\"lineThickness\"),\r\n\r\n /**\r\n * Gets or sets the {@link Cartesian2} Property specifying the starting offset of grid lines along each axis.\r\n * @memberof GridMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default new Cartesian2(0.0, 0.0)\r\n */\r\n lineOffset: createPropertyDescriptor(\"lineOffset\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nGridMaterialProperty.prototype.getType = function (time) {\r\n return \"Grid\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nGridMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n result.color = Property.getValueOrClonedDefault(\r\n this._color,\r\n time,\r\n defaultColor,\r\n result.color\r\n );\r\n result.cellAlpha = Property.getValueOrDefault(\r\n this._cellAlpha,\r\n time,\r\n defaultCellAlpha\r\n );\r\n result.lineCount = Property.getValueOrClonedDefault(\r\n this._lineCount,\r\n time,\r\n defaultLineCount,\r\n result.lineCount\r\n );\r\n result.lineThickness = Property.getValueOrClonedDefault(\r\n this._lineThickness,\r\n time,\r\n defaultLineThickness,\r\n result.lineThickness\r\n );\r\n result.lineOffset = Property.getValueOrClonedDefault(\r\n this._lineOffset,\r\n time,\r\n defaultLineOffset,\r\n result.lineOffset\r\n );\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nGridMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof GridMaterialProperty && //\r\n Property.equals(this._color, other._color) && //\r\n Property.equals(this._cellAlpha, other._cellAlpha) && //\r\n Property.equals(this._lineCount, other._lineCount) && //\r\n Property.equals(this._lineThickness, other._lineThickness) && //\r\n Property.equals(this._lineOffset, other._lineOffset))\r\n );\r\n};\r\nexport default GridMaterialProperty;\r\n","import Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to PolylineArrow {@link Material} uniforms.\r\n *\r\n * @param {Property|Color} [color=Color.WHITE] The {@link Color} Property to be used.\r\n *\r\n * @alias PolylineArrowMaterialProperty\r\n * @constructor\r\n */\r\nfunction PolylineArrowMaterialProperty(color) {\r\n this._definitionChanged = new Event();\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n\r\n this.color = color;\r\n}\r\n\r\nObject.defineProperties(PolylineArrowMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof PolylineArrowMaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return Property.isConstant(this._color);\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof PolylineArrowMaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets or sets the {@link Color} {@link Property}.\r\n * @memberof PolylineArrowMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nPolylineArrowMaterialProperty.prototype.getType = function (time) {\r\n return \"PolylineArrow\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPolylineArrowMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n result.color = Property.getValueOrClonedDefault(\r\n this._color,\r\n time,\r\n Color.WHITE,\r\n result.color\r\n );\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPolylineArrowMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof PolylineArrowMaterialProperty && //\r\n Property.equals(this._color, other._color))\r\n );\r\n};\r\nexport default PolylineArrowMaterialProperty;\r\n","import Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultColor = Color.WHITE;\r\nvar defaultGapColor = Color.TRANSPARENT;\r\nvar defaultDashLength = 16.0;\r\nvar defaultDashPattern = 255.0;\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to polyline dash {@link Material} uniforms.\r\n * @alias PolylineDashMaterialProperty\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Property|Color} [options.color=Color.WHITE] A Property specifying the {@link Color} of the line.\r\n * @param {Property|Color} [options.gapColor=Color.TRANSPARENT] A Property specifying the {@link Color} of the gaps in the line.\r\n * @param {Property|Number} [options.dashLength=16.0] A numeric Property specifying the length of the dash pattern in pixels.\r\n * @param {Property|Number} [options.dashPattern=255.0] A numeric Property specifying a 16 bit pattern for the dash\r\n */\r\nfunction PolylineDashMaterialProperty(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._definitionChanged = new Event();\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n this._gapColor = undefined;\r\n this._gapColorSubscription = undefined;\r\n this._dashLength = undefined;\r\n this._dashLengthSubscription = undefined;\r\n this._dashPattern = undefined;\r\n this._dashPatternSubscription = undefined;\r\n\r\n this.color = options.color;\r\n this.gapColor = options.gapColor;\r\n this.dashLength = options.dashLength;\r\n this.dashPattern = options.dashPattern;\r\n}\r\n\r\nObject.defineProperties(PolylineDashMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof PolylineDashMaterialProperty.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n Property.isConstant(this._color) &&\r\n Property.isConstant(this._gapColor) &&\r\n Property.isConstant(this._dashLength) &&\r\n Property.isConstant(this._dashPattern)\r\n );\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof PolylineDashMaterialProperty.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the line.\r\n * @memberof PolylineDashMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the gaps in the line.\r\n * @memberof PolylineDashMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n */\r\n gapColor: createPropertyDescriptor(\"gapColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the length of a dash cycle\r\n * @memberof PolylineDashMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n */\r\n dashLength: createPropertyDescriptor(\"dashLength\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying a dash pattern\r\n * @memberof PolylineDashMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n */\r\n dashPattern: createPropertyDescriptor(\"dashPattern\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nPolylineDashMaterialProperty.prototype.getType = function (time) {\r\n return \"PolylineDash\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPolylineDashMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n result.color = Property.getValueOrClonedDefault(\r\n this._color,\r\n time,\r\n defaultColor,\r\n result.color\r\n );\r\n result.gapColor = Property.getValueOrClonedDefault(\r\n this._gapColor,\r\n time,\r\n defaultGapColor,\r\n result.gapColor\r\n );\r\n result.dashLength = Property.getValueOrDefault(\r\n this._dashLength,\r\n time,\r\n defaultDashLength,\r\n result.dashLength\r\n );\r\n result.dashPattern = Property.getValueOrDefault(\r\n this._dashPattern,\r\n time,\r\n defaultDashPattern,\r\n result.dashPattern\r\n );\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPolylineDashMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof PolylineDashMaterialProperty &&\r\n Property.equals(this._color, other._color) &&\r\n Property.equals(this._gapColor, other._gapColor) &&\r\n Property.equals(this._dashLength, other._dashLength) &&\r\n Property.equals(this._dashPattern, other._dashPattern))\r\n );\r\n};\r\nexport default PolylineDashMaterialProperty;\r\n","import Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultColor = Color.WHITE;\r\nvar defaultGlowPower = 0.25;\r\nvar defaultTaperPower = 1.0;\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to polyline glow {@link Material} uniforms.\r\n * @alias PolylineGlowMaterialProperty\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Property|Color} [options.color=Color.WHITE] A Property specifying the {@link Color} of the line.\r\n * @param {Property|Number} [options.glowPower=0.25] A numeric Property specifying the strength of the glow, as a percentage of the total line width.\r\n * @param {Property|Number} [options.taperPower=1.0] A numeric Property specifying the strength of the tapering effect, as a percentage of the total line length. If 1.0 or higher, no taper effect is used.\r\n */\r\nfunction PolylineGlowMaterialProperty(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._definitionChanged = new Event();\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n this._glowPower = undefined;\r\n this._glowPowerSubscription = undefined;\r\n this._taperPower = undefined;\r\n this._taperPowerSubscription = undefined;\r\n\r\n this.color = options.color;\r\n this.glowPower = options.glowPower;\r\n this.taperPower = options.taperPower;\r\n}\r\n\r\nObject.defineProperties(PolylineGlowMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof PolylineGlowMaterialProperty.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n Property.isConstant(this._color) && Property.isConstant(this._glow)\r\n );\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof PolylineGlowMaterialProperty.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the line.\r\n * @memberof PolylineGlowMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the strength of the glow, as a percentage of the total line width (less than 1.0).\r\n * @memberof PolylineGlowMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n */\r\n glowPower: createPropertyDescriptor(\"glowPower\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the strength of the tapering effect, as a percentage of the total line length. If 1.0 or higher, no taper effect is used.\r\n * @memberof PolylineGlowMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n */\r\n taperPower: createPropertyDescriptor(\"taperPower\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nPolylineGlowMaterialProperty.prototype.getType = function (time) {\r\n return \"PolylineGlow\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPolylineGlowMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n result.color = Property.getValueOrClonedDefault(\r\n this._color,\r\n time,\r\n defaultColor,\r\n result.color\r\n );\r\n result.glowPower = Property.getValueOrDefault(\r\n this._glowPower,\r\n time,\r\n defaultGlowPower,\r\n result.glowPower\r\n );\r\n result.taperPower = Property.getValueOrDefault(\r\n this._taperPower,\r\n time,\r\n defaultTaperPower,\r\n result.taperPower\r\n );\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPolylineGlowMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (other instanceof PolylineGlowMaterialProperty &&\r\n Property.equals(this._color, other._color) &&\r\n Property.equals(this._glowPower, other._glowPower) &&\r\n Property.equals(this._taperPower, other._taperPower))\r\n );\r\n};\r\nexport default PolylineGlowMaterialProperty;\r\n","import Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultColor = Color.WHITE;\r\nvar defaultOutlineColor = Color.BLACK;\r\nvar defaultOutlineWidth = 1.0;\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to polyline outline {@link Material} uniforms.\r\n * @alias PolylineOutlineMaterialProperty\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Property|Color} [options.color=Color.WHITE] A Property specifying the {@link Color} of the line.\r\n * @param {Property|Color} [options.outlineColor=Color.BLACK] A Property specifying the {@link Color} of the outline.\r\n * @param {Property|Number} [options.outlineWidth=1.0] A numeric Property specifying the width of the outline, in pixels.\r\n */\r\nfunction PolylineOutlineMaterialProperty(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._definitionChanged = new Event();\r\n this._color = undefined;\r\n this._colorSubscription = undefined;\r\n this._outlineColor = undefined;\r\n this._outlineColorSubscription = undefined;\r\n this._outlineWidth = undefined;\r\n this._outlineWidthSubscription = undefined;\r\n\r\n this.color = options.color;\r\n this.outlineColor = options.outlineColor;\r\n this.outlineWidth = options.outlineWidth;\r\n}\r\n\r\nObject.defineProperties(PolylineOutlineMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof PolylineOutlineMaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n Property.isConstant(this._color) &&\r\n Property.isConstant(this._outlineColor) &&\r\n Property.isConstant(this._outlineWidth)\r\n );\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof PolylineOutlineMaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the line.\r\n * @memberof PolylineOutlineMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n color: createPropertyDescriptor(\"color\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link Color} of the outline.\r\n * @memberof PolylineOutlineMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n outlineColor: createPropertyDescriptor(\"outlineColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the width of the outline.\r\n * @memberof PolylineOutlineMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n outlineWidth: createPropertyDescriptor(\"outlineWidth\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nPolylineOutlineMaterialProperty.prototype.getType = function (time) {\r\n return \"PolylineOutline\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPolylineOutlineMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n result.color = Property.getValueOrClonedDefault(\r\n this._color,\r\n time,\r\n defaultColor,\r\n result.color\r\n );\r\n result.outlineColor = Property.getValueOrClonedDefault(\r\n this._outlineColor,\r\n time,\r\n defaultOutlineColor,\r\n result.outlineColor\r\n );\r\n result.outlineWidth = Property.getValueOrDefault(\r\n this._outlineWidth,\r\n time,\r\n defaultOutlineWidth\r\n );\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPolylineOutlineMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof PolylineOutlineMaterialProperty && //\r\n Property.equals(this._color, other._color) && //\r\n Property.equals(this._outlineColor, other._outlineColor) && //\r\n Property.equals(this._outlineWidth, other._outlineWidth))\r\n );\r\n};\r\nexport default PolylineOutlineMaterialProperty;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport EventHelper from \"../Core/EventHelper.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link Property} whose value is an array whose items are the computed value\r\n * of other PositionProperty instances.\r\n *\r\n * @alias PositionPropertyArray\r\n * @constructor\r\n *\r\n * @param {Property[]} [value] An array of Property instances.\r\n * @param {ReferenceFrame} [referenceFrame=ReferenceFrame.FIXED] The reference frame in which the position is defined.\r\n */\r\nfunction PositionPropertyArray(value, referenceFrame) {\r\n this._value = undefined;\r\n this._definitionChanged = new Event();\r\n this._eventHelper = new EventHelper();\r\n this._referenceFrame = defaultValue(referenceFrame, ReferenceFrame.FIXED);\r\n this.setValue(value);\r\n}\r\n\r\nObject.defineProperties(PositionPropertyArray.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. This property\r\n * is considered constant if all property items in the array are constant.\r\n * @memberof PositionPropertyArray.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n var value = this._value;\r\n if (!defined(value)) {\r\n return true;\r\n }\r\n\r\n var length = value.length;\r\n for (var i = 0; i < length; i++) {\r\n if (!Property.isConstant(value[i])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever setValue is called with data different\r\n * than the current value or one of the properties in the array also changes.\r\n * @memberof PositionPropertyArray.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the reference frame in which the position is defined.\r\n * @memberof PositionPropertyArray.prototype\r\n * @type {ReferenceFrame}\r\n * @default ReferenceFrame.FIXED;\r\n */\r\n referenceFrame: {\r\n get: function () {\r\n return this._referenceFrame;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Cartesian3[]} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3[]} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPositionPropertyArray.prototype.getValue = function (time, result) {\r\n return this.getValueInReferenceFrame(time, ReferenceFrame.FIXED, result);\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time and in the provided reference frame.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {ReferenceFrame} referenceFrame The desired referenceFrame of the result.\r\n * @param {Cartesian3[]} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3[]} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nPositionPropertyArray.prototype.getValueInReferenceFrame = function (\r\n time,\r\n referenceFrame,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n if (!defined(referenceFrame)) {\r\n throw new DeveloperError(\"referenceFrame is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var value = this._value;\r\n if (!defined(value)) {\r\n return undefined;\r\n }\r\n\r\n var length = value.length;\r\n if (!defined(result)) {\r\n result = new Array(length);\r\n }\r\n var i = 0;\r\n var x = 0;\r\n while (i < length) {\r\n var property = value[i];\r\n var itemValue = property.getValueInReferenceFrame(\r\n time,\r\n referenceFrame,\r\n result[i]\r\n );\r\n if (defined(itemValue)) {\r\n result[x] = itemValue;\r\n x++;\r\n }\r\n i++;\r\n }\r\n result.length = x;\r\n return result;\r\n};\r\n\r\n/**\r\n * Sets the value of the property.\r\n *\r\n * @param {Property[]} value An array of Property instances.\r\n */\r\nPositionPropertyArray.prototype.setValue = function (value) {\r\n var eventHelper = this._eventHelper;\r\n eventHelper.removeAll();\r\n\r\n if (defined(value)) {\r\n this._value = value.slice();\r\n var length = value.length;\r\n for (var i = 0; i < length; i++) {\r\n var property = value[i];\r\n if (defined(property)) {\r\n eventHelper.add(\r\n property.definitionChanged,\r\n PositionPropertyArray.prototype._raiseDefinitionChanged,\r\n this\r\n );\r\n }\r\n }\r\n } else {\r\n this._value = undefined;\r\n }\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPositionPropertyArray.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof PositionPropertyArray && //\r\n this._referenceFrame === other._referenceFrame && //\r\n Property.arrayEquals(this._value, other._value))\r\n );\r\n};\r\n\r\nPositionPropertyArray.prototype._raiseDefinitionChanged = function () {\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\nexport default PositionPropertyArray;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport EventHelper from \"../Core/EventHelper.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link Property} whose value is an array whose items are the computed value\r\n * of other property instances.\r\n *\r\n * @alias PropertyArray\r\n * @constructor\r\n *\r\n * @param {Property[]} [value] An array of Property instances.\r\n */\r\nfunction PropertyArray(value) {\r\n this._value = undefined;\r\n this._definitionChanged = new Event();\r\n this._eventHelper = new EventHelper();\r\n this.setValue(value);\r\n}\r\n\r\nObject.defineProperties(PropertyArray.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. This property\r\n * is considered constant if all property items in the array are constant.\r\n * @memberof PropertyArray.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n var value = this._value;\r\n if (!defined(value)) {\r\n return true;\r\n }\r\n var length = value.length;\r\n for (var i = 0; i < length; i++) {\r\n if (!Property.isConstant(value[i])) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever setValue is called with data different\r\n * than the current value or one of the properties in the array also changes.\r\n * @memberof PropertyArray.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object[]} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object[]} The modified result parameter, which is an array of values produced by evaluating each of the contained properties at the given time or a new instance if the result parameter was not supplied.\r\n */\r\nPropertyArray.prototype.getValue = function (time, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var value = this._value;\r\n if (!defined(value)) {\r\n return undefined;\r\n }\r\n\r\n var length = value.length;\r\n if (!defined(result)) {\r\n result = new Array(length);\r\n }\r\n var i = 0;\r\n var x = 0;\r\n while (i < length) {\r\n var property = this._value[i];\r\n var itemValue = property.getValue(time, result[i]);\r\n if (defined(itemValue)) {\r\n result[x] = itemValue;\r\n x++;\r\n }\r\n i++;\r\n }\r\n result.length = x;\r\n return result;\r\n};\r\n\r\n/**\r\n * Sets the value of the property.\r\n *\r\n * @param {Property[]} value An array of Property instances.\r\n */\r\nPropertyArray.prototype.setValue = function (value) {\r\n var eventHelper = this._eventHelper;\r\n eventHelper.removeAll();\r\n\r\n if (defined(value)) {\r\n this._value = value.slice();\r\n var length = value.length;\r\n for (var i = 0; i < length; i++) {\r\n var property = value[i];\r\n if (defined(property)) {\r\n eventHelper.add(\r\n property.definitionChanged,\r\n PropertyArray.prototype._raiseDefinitionChanged,\r\n this\r\n );\r\n }\r\n }\r\n } else {\r\n this._value = undefined;\r\n }\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nPropertyArray.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof PropertyArray && //\r\n Property.arrayEquals(this._value, other._value))\r\n );\r\n};\r\n\r\nPropertyArray.prototype._raiseDefinitionChanged = function () {\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\nexport default PropertyArray;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nfunction resolve(that) {\r\n var targetProperty = that._targetProperty;\r\n\r\n if (!defined(targetProperty)) {\r\n var targetEntity = that._targetEntity;\r\n\r\n if (!defined(targetEntity)) {\r\n targetEntity = that._targetCollection.getById(that._targetId);\r\n\r\n if (!defined(targetEntity)) {\r\n // target entity not found\r\n that._targetEntity = that._targetProperty = undefined;\r\n return;\r\n }\r\n\r\n // target entity was found. listen for changes to entity definition\r\n targetEntity.definitionChanged.addEventListener(\r\n ReferenceProperty.prototype._onTargetEntityDefinitionChanged,\r\n that\r\n );\r\n that._targetEntity = targetEntity;\r\n }\r\n\r\n // walk the list of property names and resolve properties\r\n var targetPropertyNames = that._targetPropertyNames;\r\n targetProperty = that._targetEntity;\r\n for (\r\n var i = 0, len = targetPropertyNames.length;\r\n i < len && defined(targetProperty);\r\n ++i\r\n ) {\r\n targetProperty = targetProperty[targetPropertyNames[i]];\r\n }\r\n\r\n // target property may or may not be defined, depending on if it was found\r\n that._targetProperty = targetProperty;\r\n }\r\n\r\n return targetProperty;\r\n}\r\n\r\n/**\r\n * A {@link Property} which transparently links to another property on a provided object.\r\n *\r\n * @alias ReferenceProperty\r\n * @constructor\r\n *\r\n * @param {EntityCollection} targetCollection The entity collection which will be used to resolve the reference.\r\n * @param {String} targetId The id of the entity which is being referenced.\r\n * @param {String[]} targetPropertyNames The names of the property on the target entity which we will use.\r\n *\r\n * @example\r\n * var collection = new Cesium.EntityCollection();\r\n *\r\n * //Create a new entity and assign a billboard scale.\r\n * var object1 = new Cesium.Entity({id:'object1'});\r\n * object1.billboard = new Cesium.BillboardGraphics();\r\n * object1.billboard.scale = new Cesium.ConstantProperty(2.0);\r\n * collection.add(object1);\r\n *\r\n * //Create a second entity and reference the scale from the first one.\r\n * var object2 = new Cesium.Entity({id:'object2'});\r\n * object2.model = new Cesium.ModelGraphics();\r\n * object2.model.scale = new Cesium.ReferenceProperty(collection, 'object1', ['billboard', 'scale']);\r\n * collection.add(object2);\r\n *\r\n * //Create a third object, but use the fromString helper function.\r\n * var object3 = new Cesium.Entity({id:'object3'});\r\n * object3.billboard = new Cesium.BillboardGraphics();\r\n * object3.billboard.scale = Cesium.ReferenceProperty.fromString(collection, 'object1#billboard.scale');\r\n * collection.add(object3);\r\n *\r\n * //You can refer to an entity with a # or . in id and property names by escaping them.\r\n * var object4 = new Cesium.Entity({id:'#object.4'});\r\n * object4.billboard = new Cesium.BillboardGraphics();\r\n * object4.billboard.scale = new Cesium.ConstantProperty(2.0);\r\n * collection.add(object4);\r\n *\r\n * var object5 = new Cesium.Entity({id:'object5'});\r\n * object5.billboard = new Cesium.BillboardGraphics();\r\n * object5.billboard.scale = Cesium.ReferenceProperty.fromString(collection, '\\\\#object\\\\.4#billboard.scale');\r\n * collection.add(object5);\r\n */\r\nfunction ReferenceProperty(targetCollection, targetId, targetPropertyNames) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(targetCollection)) {\r\n throw new DeveloperError(\"targetCollection is required.\");\r\n }\r\n if (!defined(targetId) || targetId === \"\") {\r\n throw new DeveloperError(\"targetId is required.\");\r\n }\r\n if (!defined(targetPropertyNames) || targetPropertyNames.length === 0) {\r\n throw new DeveloperError(\"targetPropertyNames is required.\");\r\n }\r\n for (var i = 0; i < targetPropertyNames.length; i++) {\r\n var item = targetPropertyNames[i];\r\n if (!defined(item) || item === \"\") {\r\n throw new DeveloperError(\"reference contains invalid properties.\");\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._targetCollection = targetCollection;\r\n this._targetId = targetId;\r\n this._targetPropertyNames = targetPropertyNames;\r\n this._targetProperty = undefined;\r\n this._targetEntity = undefined;\r\n this._definitionChanged = new Event();\r\n\r\n targetCollection.collectionChanged.addEventListener(\r\n ReferenceProperty.prototype._onCollectionChanged,\r\n this\r\n );\r\n}\r\n\r\nObject.defineProperties(ReferenceProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant.\r\n * @memberof ReferenceProperty.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return Property.isConstant(resolve(this));\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever the referenced property's definition is changed.\r\n * @memberof ReferenceProperty.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the reference frame that the position is defined in.\r\n * This property is only valid if the referenced property is a {@link PositionProperty}.\r\n * @memberof ReferenceProperty.prototype\r\n * @type {ReferenceFrame}\r\n * @readonly\r\n */\r\n referenceFrame: {\r\n get: function () {\r\n var target = resolve(this);\r\n return defined(target) ? target.referenceFrame : undefined;\r\n },\r\n },\r\n /**\r\n * Gets the id of the entity being referenced.\r\n * @memberof ReferenceProperty.prototype\r\n * @type {String}\r\n * @readonly\r\n */\r\n targetId: {\r\n get: function () {\r\n return this._targetId;\r\n },\r\n },\r\n /**\r\n * Gets the collection containing the entity being referenced.\r\n * @memberof ReferenceProperty.prototype\r\n * @type {EntityCollection}\r\n * @readonly\r\n */\r\n targetCollection: {\r\n get: function () {\r\n return this._targetCollection;\r\n },\r\n },\r\n /**\r\n * Gets the array of property names used to retrieve the referenced property.\r\n * @memberof ReferenceProperty.prototype\r\n * @type {String[]}\r\n * @readonly\r\n */\r\n targetPropertyNames: {\r\n get: function () {\r\n return this._targetPropertyNames;\r\n },\r\n },\r\n /**\r\n * Gets the resolved instance of the underlying referenced property.\r\n * @memberof ReferenceProperty.prototype\r\n * @type {Property|undefined}\r\n * @readonly\r\n */\r\n resolvedProperty: {\r\n get: function () {\r\n return resolve(this);\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates a new instance given the entity collection that will\r\n * be used to resolve it and a string indicating the target entity id and property.\r\n * The format of the string is \"objectId#foo.bar\", where # separates the id from\r\n * property path and . separates sub-properties. If the reference identifier or\r\n * or any sub-properties contains a # . or \\ they must be escaped.\r\n *\r\n * @param {EntityCollection} targetCollection\r\n * @param {String} referenceString\r\n * @returns {ReferenceProperty} A new instance of ReferenceProperty.\r\n *\r\n * @exception {DeveloperError} invalid referenceString.\r\n */\r\nReferenceProperty.fromString = function (targetCollection, referenceString) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(targetCollection)) {\r\n throw new DeveloperError(\"targetCollection is required.\");\r\n }\r\n if (!defined(referenceString)) {\r\n throw new DeveloperError(\"referenceString is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var identifier;\r\n var values = [];\r\n\r\n var inIdentifier = true;\r\n var isEscaped = false;\r\n var token = \"\";\r\n for (var i = 0; i < referenceString.length; ++i) {\r\n var c = referenceString.charAt(i);\r\n\r\n if (isEscaped) {\r\n token += c;\r\n isEscaped = false;\r\n } else if (c === \"\\\\\") {\r\n isEscaped = true;\r\n } else if (inIdentifier && c === \"#\") {\r\n identifier = token;\r\n inIdentifier = false;\r\n token = \"\";\r\n } else if (!inIdentifier && c === \".\") {\r\n values.push(token);\r\n token = \"\";\r\n } else {\r\n token += c;\r\n }\r\n }\r\n values.push(token);\r\n\r\n return new ReferenceProperty(targetCollection, identifier, values);\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nReferenceProperty.prototype.getValue = function (time, result) {\r\n var target = resolve(this);\r\n return defined(target) ? target.getValue(time, result) : undefined;\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time and in the provided reference frame.\r\n * This method is only valid if the property being referenced is a {@link PositionProperty}.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {ReferenceFrame} referenceFrame The desired referenceFrame of the result.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nReferenceProperty.prototype.getValueInReferenceFrame = function (\r\n time,\r\n referenceFrame,\r\n result\r\n) {\r\n var target = resolve(this);\r\n return defined(target)\r\n ? target.getValueInReferenceFrame(time, referenceFrame, result)\r\n : undefined;\r\n};\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n * This method is only valid if the property being referenced is a {@link MaterialProperty}.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nReferenceProperty.prototype.getType = function (time) {\r\n var target = resolve(this);\r\n return defined(target) ? target.getType(time) : undefined;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nReferenceProperty.prototype.equals = function (other) {\r\n if (this === other) {\r\n return true;\r\n }\r\n\r\n var names = this._targetPropertyNames;\r\n var otherNames = other._targetPropertyNames;\r\n\r\n if (\r\n this._targetCollection !== other._targetCollection || //\r\n this._targetId !== other._targetId || //\r\n names.length !== otherNames.length\r\n ) {\r\n return false;\r\n }\r\n\r\n var length = this._targetPropertyNames.length;\r\n for (var i = 0; i < length; i++) {\r\n if (names[i] !== otherNames[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\nReferenceProperty.prototype._onTargetEntityDefinitionChanged = function (\r\n targetEntity,\r\n name,\r\n value,\r\n oldValue\r\n) {\r\n if (defined(this._targetProperty) && this._targetPropertyNames[0] === name) {\r\n this._targetProperty = undefined;\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n};\r\n\r\nReferenceProperty.prototype._onCollectionChanged = function (\r\n collection,\r\n added,\r\n removed\r\n) {\r\n var targetEntity = this._targetEntity;\r\n if (defined(targetEntity) && removed.indexOf(targetEntity) !== -1) {\r\n targetEntity.definitionChanged.removeEventListener(\r\n ReferenceProperty.prototype._onTargetEntityDefinitionChanged,\r\n this\r\n );\r\n this._targetEntity = this._targetProperty = undefined;\r\n } else if (!defined(targetEntity)) {\r\n targetEntity = resolve(this);\r\n if (defined(targetEntity)) {\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n }\r\n};\r\nexport default ReferenceProperty;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\n\r\n/**\r\n * Represents a {@link Packable} number that always interpolates values\r\n * towards the shortest angle of rotation. This object is never used directly\r\n * but is instead passed to the constructor of {@link SampledProperty}\r\n * in order to represent a two-dimensional angle of rotation.\r\n *\r\n * @interface Rotation\r\n *\r\n *\r\n * @example\r\n * var time1 = Cesium.JulianDate.fromIso8601('2010-05-07T00:00:00');\r\n * var time2 = Cesium.JulianDate.fromIso8601('2010-05-07T00:01:00');\r\n * var time3 = Cesium.JulianDate.fromIso8601('2010-05-07T00:02:00');\r\n *\r\n * var property = new Cesium.SampledProperty(Cesium.Rotation);\r\n * property.addSample(time1, 0);\r\n * property.addSample(time3, Cesium.Math.toRadians(350));\r\n *\r\n * //Getting the value at time2 will equal 355 degrees instead\r\n * //of 175 degrees (which is what you get if you construct\r\n * //a SampledProperty(Number) instead. Note, the actual\r\n * //return value is in radians, not degrees.\r\n * property.getValue(time2);\r\n *\r\n * @see PackableForInterpolation\r\n */\r\nvar Rotation = {\r\n /**\r\n * The number of elements used to pack the object into an array.\r\n * @type {Number}\r\n */\r\n packedLength: 1,\r\n\r\n /**\r\n * Stores the provided instance into the provided array.\r\n *\r\n * @param {Rotation} value The value to pack.\r\n * @param {Number[]} array The array to pack into.\r\n * @param {Number} [startingIndex=0] The index into the array at which to start packing the elements.\r\n *\r\n * @returns {Number[]} The array that was packed into\r\n */\r\n pack: function (value, array, startingIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value is required\");\r\n }\r\n\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n array[startingIndex] = value;\r\n\r\n return array;\r\n },\r\n\r\n /**\r\n * Retrieves an instance from a packed array.\r\n *\r\n * @param {Number[]} array The packed array.\r\n * @param {Number} [startingIndex=0] The starting index of the element to be unpacked.\r\n * @param {Rotation} [result] The object into which to store the result.\r\n * @returns {Rotation} The modified result parameter or a new Rotation instance if one was not provided.\r\n */\r\n unpack: function (array, startingIndex, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n return array[startingIndex];\r\n },\r\n\r\n /**\r\n * Converts a packed array into a form suitable for interpolation.\r\n *\r\n * @param {Number[]} packedArray The packed array.\r\n * @param {Number} [startingIndex=0] The index of the first element to be converted.\r\n * @param {Number} [lastIndex=packedArray.length] The index of the last element to be converted.\r\n * @param {Number[]} [result] The object into which to store the result.\r\n */\r\n convertPackedArrayForInterpolation: function (\r\n packedArray,\r\n startingIndex,\r\n lastIndex,\r\n result\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(packedArray)) {\r\n throw new DeveloperError(\"packedArray is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(result)) {\r\n result = [];\r\n }\r\n\r\n startingIndex = defaultValue(startingIndex, 0);\r\n lastIndex = defaultValue(lastIndex, packedArray.length);\r\n\r\n var previousValue;\r\n for (var i = 0, len = lastIndex - startingIndex + 1; i < len; i++) {\r\n var value = packedArray[startingIndex + i];\r\n if (i === 0 || Math.abs(previousValue - value) < Math.PI) {\r\n result[i] = value;\r\n } else {\r\n result[i] = value - CesiumMath.TWO_PI;\r\n }\r\n previousValue = value;\r\n }\r\n },\r\n\r\n /**\r\n * Retrieves an instance from a packed array converted with {@link Rotation.convertPackedArrayForInterpolation}.\r\n *\r\n * @param {Number[]} array The array previously packed for interpolation.\r\n * @param {Number[]} sourceArray The original packed array.\r\n * @param {Number} [firstIndex=0] The firstIndex used to convert the array.\r\n * @param {Number} [lastIndex=packedArray.length] The lastIndex used to convert the array.\r\n * @param {Rotation} [result] The object into which to store the result.\r\n * @returns {Rotation} The modified result parameter or a new Rotation instance if one was not provided.\r\n */\r\n unpackInterpolationResult: function (\r\n array,\r\n sourceArray,\r\n firstIndex,\r\n lastIndex,\r\n result\r\n ) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(array)) {\r\n throw new DeveloperError(\"array is required\");\r\n }\r\n if (!defined(sourceArray)) {\r\n throw new DeveloperError(\"sourceArray is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n result = array[0];\r\n if (result < 0) {\r\n return result + CesiumMath.TWO_PI;\r\n }\r\n return result;\r\n },\r\n};\r\nexport default Rotation;\r\n","import binarySearch from \"../Core/binarySearch.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport ExtrapolationType from \"../Core/ExtrapolationType.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport LinearApproximation from \"../Core/LinearApproximation.js\";\r\n\r\nvar PackableNumber = {\r\n packedLength: 1,\r\n pack: function (value, array, startingIndex) {\r\n startingIndex = defaultValue(startingIndex, 0);\r\n array[startingIndex] = value;\r\n },\r\n unpack: function (array, startingIndex, result) {\r\n startingIndex = defaultValue(startingIndex, 0);\r\n return array[startingIndex];\r\n },\r\n};\r\n\r\n//We can't use splice for inserting new elements because function apply can't handle\r\n//a huge number of arguments. See https://code.google.com/p/chromium/issues/detail?id=56588\r\nfunction arrayInsert(array, startIndex, items) {\r\n var i;\r\n var arrayLength = array.length;\r\n var itemsLength = items.length;\r\n var newLength = arrayLength + itemsLength;\r\n\r\n array.length = newLength;\r\n if (arrayLength !== startIndex) {\r\n var q = arrayLength - 1;\r\n for (i = newLength - 1; i >= startIndex; i--) {\r\n array[i] = array[q--];\r\n }\r\n }\r\n\r\n for (i = 0; i < itemsLength; i++) {\r\n array[startIndex++] = items[i];\r\n }\r\n}\r\n\r\nfunction convertDate(date, epoch) {\r\n if (date instanceof JulianDate) {\r\n return date;\r\n }\r\n if (typeof date === \"string\") {\r\n return JulianDate.fromIso8601(date);\r\n }\r\n return JulianDate.addSeconds(epoch, date, new JulianDate());\r\n}\r\n\r\nvar timesSpliceArgs = [];\r\nvar valuesSpliceArgs = [];\r\n\r\nfunction mergeNewSamples(epoch, times, values, newData, packedLength) {\r\n var newDataIndex = 0;\r\n var i;\r\n var prevItem;\r\n var timesInsertionPoint;\r\n var valuesInsertionPoint;\r\n var currentTime;\r\n var nextTime;\r\n\r\n while (newDataIndex < newData.length) {\r\n currentTime = convertDate(newData[newDataIndex], epoch);\r\n timesInsertionPoint = binarySearch(times, currentTime, JulianDate.compare);\r\n var timesSpliceArgsCount = 0;\r\n var valuesSpliceArgsCount = 0;\r\n\r\n if (timesInsertionPoint < 0) {\r\n //Doesn't exist, insert as many additional values as we can.\r\n timesInsertionPoint = ~timesInsertionPoint;\r\n\r\n valuesInsertionPoint = timesInsertionPoint * packedLength;\r\n prevItem = undefined;\r\n nextTime = times[timesInsertionPoint];\r\n while (newDataIndex < newData.length) {\r\n currentTime = convertDate(newData[newDataIndex], epoch);\r\n if (\r\n (defined(prevItem) &&\r\n JulianDate.compare(prevItem, currentTime) >= 0) ||\r\n (defined(nextTime) && JulianDate.compare(currentTime, nextTime) >= 0)\r\n ) {\r\n break;\r\n }\r\n timesSpliceArgs[timesSpliceArgsCount++] = currentTime;\r\n newDataIndex = newDataIndex + 1;\r\n for (i = 0; i < packedLength; i++) {\r\n valuesSpliceArgs[valuesSpliceArgsCount++] = newData[newDataIndex];\r\n newDataIndex = newDataIndex + 1;\r\n }\r\n prevItem = currentTime;\r\n }\r\n\r\n if (timesSpliceArgsCount > 0) {\r\n valuesSpliceArgs.length = valuesSpliceArgsCount;\r\n arrayInsert(values, valuesInsertionPoint, valuesSpliceArgs);\r\n\r\n timesSpliceArgs.length = timesSpliceArgsCount;\r\n arrayInsert(times, timesInsertionPoint, timesSpliceArgs);\r\n }\r\n } else {\r\n //Found an exact match\r\n for (i = 0; i < packedLength; i++) {\r\n newDataIndex++;\r\n values[timesInsertionPoint * packedLength + i] = newData[newDataIndex];\r\n }\r\n newDataIndex++;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * A {@link Property} whose value is interpolated for a given time from the\r\n * provided set of samples and specified interpolation algorithm and degree.\r\n * @alias SampledProperty\r\n * @constructor\r\n *\r\n * @param {Number|Packable} type The type of property.\r\n * @param {Packable[]} [derivativeTypes] When supplied, indicates that samples will contain derivative information of the specified types.\r\n *\r\n *\r\n * @example\r\n * //Create a linearly interpolated Cartesian2\r\n * var property = new Cesium.SampledProperty(Cesium.Cartesian2);\r\n *\r\n * //Populate it with data\r\n * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:00:00.00Z'), new Cesium.Cartesian2(0, 0));\r\n * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-02T00:00:00.00Z'), new Cesium.Cartesian2(4, 7));\r\n *\r\n * //Retrieve an interpolated value\r\n * var result = property.getValue(Cesium.JulianDate.fromIso8601('2012-08-01T12:00:00.00Z'));\r\n *\r\n * @example\r\n * //Create a simple numeric SampledProperty that uses third degree Hermite Polynomial Approximation\r\n * var property = new Cesium.SampledProperty(Number);\r\n * property.setInterpolationOptions({\r\n * interpolationDegree : 3,\r\n * interpolationAlgorithm : Cesium.HermitePolynomialApproximation\r\n * });\r\n *\r\n * //Populate it with data\r\n * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:00:00.00Z'), 1.0);\r\n * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:01:00.00Z'), 6.0);\r\n * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:02:00.00Z'), 12.0);\r\n * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:03:30.00Z'), 5.0);\r\n * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:06:30.00Z'), 2.0);\r\n *\r\n * //Samples can be added in any order.\r\n * property.addSample(Cesium.JulianDate.fromIso8601('2012-08-01T00:00:30.00Z'), 6.2);\r\n *\r\n * //Retrieve an interpolated value\r\n * var result = property.getValue(Cesium.JulianDate.fromIso8601('2012-08-01T00:02:34.00Z'));\r\n *\r\n * @see SampledPositionProperty\r\n */\r\nfunction SampledProperty(type, derivativeTypes) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"type\", type);\r\n //>>includeEnd('debug');\r\n\r\n var innerType = type;\r\n if (innerType === Number) {\r\n innerType = PackableNumber;\r\n }\r\n var packedLength = innerType.packedLength;\r\n var packedInterpolationLength = defaultValue(\r\n innerType.packedInterpolationLength,\r\n packedLength\r\n );\r\n\r\n var inputOrder = 0;\r\n var innerDerivativeTypes;\r\n if (defined(derivativeTypes)) {\r\n var length = derivativeTypes.length;\r\n innerDerivativeTypes = new Array(length);\r\n for (var i = 0; i < length; i++) {\r\n var derivativeType = derivativeTypes[i];\r\n if (derivativeType === Number) {\r\n derivativeType = PackableNumber;\r\n }\r\n var derivativePackedLength = derivativeType.packedLength;\r\n packedLength += derivativePackedLength;\r\n packedInterpolationLength += defaultValue(\r\n derivativeType.packedInterpolationLength,\r\n derivativePackedLength\r\n );\r\n innerDerivativeTypes[i] = derivativeType;\r\n }\r\n inputOrder = length;\r\n }\r\n\r\n this._type = type;\r\n this._innerType = innerType;\r\n this._interpolationDegree = 1;\r\n this._interpolationAlgorithm = LinearApproximation;\r\n this._numberOfPoints = 0;\r\n this._times = [];\r\n this._values = [];\r\n this._xTable = [];\r\n this._yTable = [];\r\n this._packedLength = packedLength;\r\n this._packedInterpolationLength = packedInterpolationLength;\r\n this._updateTableLength = true;\r\n this._interpolationResult = new Array(packedInterpolationLength);\r\n this._definitionChanged = new Event();\r\n this._derivativeTypes = derivativeTypes;\r\n this._innerDerivativeTypes = innerDerivativeTypes;\r\n this._inputOrder = inputOrder;\r\n this._forwardExtrapolationType = ExtrapolationType.NONE;\r\n this._forwardExtrapolationDuration = 0;\r\n this._backwardExtrapolationType = ExtrapolationType.NONE;\r\n this._backwardExtrapolationDuration = 0;\r\n}\r\n\r\nObject.defineProperties(SampledProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof SampledProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return this._values.length === 0;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof SampledProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the type of property.\r\n * @memberof SampledProperty.prototype\r\n * @type {*}\r\n */\r\n type: {\r\n get: function () {\r\n return this._type;\r\n },\r\n },\r\n /**\r\n * Gets the derivative types used by this property.\r\n * @memberof SampledProperty.prototype\r\n * @type {Packable[]}\r\n */\r\n derivativeTypes: {\r\n get: function () {\r\n return this._derivativeTypes;\r\n },\r\n },\r\n /**\r\n * Gets the degree of interpolation to perform when retrieving a value.\r\n * @memberof SampledProperty.prototype\r\n * @type {Number}\r\n * @default 1\r\n */\r\n interpolationDegree: {\r\n get: function () {\r\n return this._interpolationDegree;\r\n },\r\n },\r\n /**\r\n * Gets the interpolation algorithm to use when retrieving a value.\r\n * @memberof SampledProperty.prototype\r\n * @type {InterpolationAlgorithm}\r\n * @default LinearApproximation\r\n */\r\n interpolationAlgorithm: {\r\n get: function () {\r\n return this._interpolationAlgorithm;\r\n },\r\n },\r\n /**\r\n * Gets or sets the type of extrapolation to perform when a value\r\n * is requested at a time after any available samples.\r\n * @memberof SampledProperty.prototype\r\n * @type {ExtrapolationType}\r\n * @default ExtrapolationType.NONE\r\n */\r\n forwardExtrapolationType: {\r\n get: function () {\r\n return this._forwardExtrapolationType;\r\n },\r\n set: function (value) {\r\n if (this._forwardExtrapolationType !== value) {\r\n this._forwardExtrapolationType = value;\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n },\r\n },\r\n /**\r\n * Gets or sets the amount of time to extrapolate forward before\r\n * the property becomes undefined. A value of 0 will extrapolate forever.\r\n * @memberof SampledProperty.prototype\r\n * @type {Number}\r\n * @default 0\r\n */\r\n forwardExtrapolationDuration: {\r\n get: function () {\r\n return this._forwardExtrapolationDuration;\r\n },\r\n set: function (value) {\r\n if (this._forwardExtrapolationDuration !== value) {\r\n this._forwardExtrapolationDuration = value;\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n },\r\n },\r\n /**\r\n * Gets or sets the type of extrapolation to perform when a value\r\n * is requested at a time before any available samples.\r\n * @memberof SampledProperty.prototype\r\n * @type {ExtrapolationType}\r\n * @default ExtrapolationType.NONE\r\n */\r\n backwardExtrapolationType: {\r\n get: function () {\r\n return this._backwardExtrapolationType;\r\n },\r\n set: function (value) {\r\n if (this._backwardExtrapolationType !== value) {\r\n this._backwardExtrapolationType = value;\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n },\r\n },\r\n /**\r\n * Gets or sets the amount of time to extrapolate backward\r\n * before the property becomes undefined. A value of 0 will extrapolate forever.\r\n * @memberof SampledProperty.prototype\r\n * @type {Number}\r\n * @default 0\r\n */\r\n backwardExtrapolationDuration: {\r\n get: function () {\r\n return this._backwardExtrapolationDuration;\r\n },\r\n set: function (value) {\r\n if (this._backwardExtrapolationDuration !== value) {\r\n this._backwardExtrapolationDuration = value;\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nSampledProperty.prototype.getValue = function (time, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var times = this._times;\r\n var timesLength = times.length;\r\n if (timesLength === 0) {\r\n return undefined;\r\n }\r\n\r\n var timeout;\r\n var innerType = this._innerType;\r\n var values = this._values;\r\n var index = binarySearch(times, time, JulianDate.compare);\r\n\r\n if (index < 0) {\r\n index = ~index;\r\n\r\n if (index === 0) {\r\n var startTime = times[index];\r\n timeout = this._backwardExtrapolationDuration;\r\n if (\r\n this._backwardExtrapolationType === ExtrapolationType.NONE ||\r\n (timeout !== 0 &&\r\n JulianDate.secondsDifference(startTime, time) > timeout)\r\n ) {\r\n return undefined;\r\n }\r\n if (this._backwardExtrapolationType === ExtrapolationType.HOLD) {\r\n return innerType.unpack(values, 0, result);\r\n }\r\n }\r\n\r\n if (index >= timesLength) {\r\n index = timesLength - 1;\r\n var endTime = times[index];\r\n timeout = this._forwardExtrapolationDuration;\r\n if (\r\n this._forwardExtrapolationType === ExtrapolationType.NONE ||\r\n (timeout !== 0 && JulianDate.secondsDifference(time, endTime) > timeout)\r\n ) {\r\n return undefined;\r\n }\r\n if (this._forwardExtrapolationType === ExtrapolationType.HOLD) {\r\n index = timesLength - 1;\r\n return innerType.unpack(values, index * innerType.packedLength, result);\r\n }\r\n }\r\n\r\n var xTable = this._xTable;\r\n var yTable = this._yTable;\r\n var interpolationAlgorithm = this._interpolationAlgorithm;\r\n var packedInterpolationLength = this._packedInterpolationLength;\r\n var inputOrder = this._inputOrder;\r\n\r\n if (this._updateTableLength) {\r\n this._updateTableLength = false;\r\n var numberOfPoints = Math.min(\r\n interpolationAlgorithm.getRequiredDataPoints(\r\n this._interpolationDegree,\r\n inputOrder\r\n ),\r\n timesLength\r\n );\r\n if (numberOfPoints !== this._numberOfPoints) {\r\n this._numberOfPoints = numberOfPoints;\r\n xTable.length = numberOfPoints;\r\n yTable.length = numberOfPoints * packedInterpolationLength;\r\n }\r\n }\r\n\r\n var degree = this._numberOfPoints - 1;\r\n if (degree < 1) {\r\n return undefined;\r\n }\r\n\r\n var firstIndex = 0;\r\n var lastIndex = timesLength - 1;\r\n var pointsInCollection = lastIndex - firstIndex + 1;\r\n\r\n if (pointsInCollection >= degree + 1) {\r\n var computedFirstIndex = index - ((degree / 2) | 0) - 1;\r\n if (computedFirstIndex < firstIndex) {\r\n computedFirstIndex = firstIndex;\r\n }\r\n var computedLastIndex = computedFirstIndex + degree;\r\n if (computedLastIndex > lastIndex) {\r\n computedLastIndex = lastIndex;\r\n computedFirstIndex = computedLastIndex - degree;\r\n if (computedFirstIndex < firstIndex) {\r\n computedFirstIndex = firstIndex;\r\n }\r\n }\r\n\r\n firstIndex = computedFirstIndex;\r\n lastIndex = computedLastIndex;\r\n }\r\n var length = lastIndex - firstIndex + 1;\r\n\r\n // Build the tables\r\n for (var i = 0; i < length; ++i) {\r\n xTable[i] = JulianDate.secondsDifference(\r\n times[firstIndex + i],\r\n times[lastIndex]\r\n );\r\n }\r\n\r\n if (!defined(innerType.convertPackedArrayForInterpolation)) {\r\n var destinationIndex = 0;\r\n var packedLength = this._packedLength;\r\n var sourceIndex = firstIndex * packedLength;\r\n var stop = (lastIndex + 1) * packedLength;\r\n\r\n while (sourceIndex < stop) {\r\n yTable[destinationIndex] = values[sourceIndex];\r\n sourceIndex++;\r\n destinationIndex++;\r\n }\r\n } else {\r\n innerType.convertPackedArrayForInterpolation(\r\n values,\r\n firstIndex,\r\n lastIndex,\r\n yTable\r\n );\r\n }\r\n\r\n // Interpolate!\r\n var x = JulianDate.secondsDifference(time, times[lastIndex]);\r\n var interpolationResult;\r\n if (inputOrder === 0 || !defined(interpolationAlgorithm.interpolate)) {\r\n interpolationResult = interpolationAlgorithm.interpolateOrderZero(\r\n x,\r\n xTable,\r\n yTable,\r\n packedInterpolationLength,\r\n this._interpolationResult\r\n );\r\n } else {\r\n var yStride = Math.floor(packedInterpolationLength / (inputOrder + 1));\r\n interpolationResult = interpolationAlgorithm.interpolate(\r\n x,\r\n xTable,\r\n yTable,\r\n yStride,\r\n inputOrder,\r\n inputOrder,\r\n this._interpolationResult\r\n );\r\n }\r\n\r\n if (!defined(innerType.unpackInterpolationResult)) {\r\n return innerType.unpack(interpolationResult, 0, result);\r\n }\r\n return innerType.unpackInterpolationResult(\r\n interpolationResult,\r\n values,\r\n firstIndex,\r\n lastIndex,\r\n result\r\n );\r\n }\r\n return innerType.unpack(values, index * this._packedLength, result);\r\n};\r\n\r\n/**\r\n * Sets the algorithm and degree to use when interpolating a value.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {InterpolationAlgorithm} [options.interpolationAlgorithm] The new interpolation algorithm. If undefined, the existing property will be unchanged.\r\n * @param {Number} [options.interpolationDegree] The new interpolation degree. If undefined, the existing property will be unchanged.\r\n */\r\nSampledProperty.prototype.setInterpolationOptions = function (options) {\r\n if (!defined(options)) {\r\n return;\r\n }\r\n\r\n var valuesChanged = false;\r\n\r\n var interpolationAlgorithm = options.interpolationAlgorithm;\r\n var interpolationDegree = options.interpolationDegree;\r\n\r\n if (\r\n defined(interpolationAlgorithm) &&\r\n this._interpolationAlgorithm !== interpolationAlgorithm\r\n ) {\r\n this._interpolationAlgorithm = interpolationAlgorithm;\r\n valuesChanged = true;\r\n }\r\n\r\n if (\r\n defined(interpolationDegree) &&\r\n this._interpolationDegree !== interpolationDegree\r\n ) {\r\n this._interpolationDegree = interpolationDegree;\r\n valuesChanged = true;\r\n }\r\n\r\n if (valuesChanged) {\r\n this._updateTableLength = true;\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n};\r\n\r\n/**\r\n * Adds a new sample.\r\n *\r\n * @param {JulianDate} time The sample time.\r\n * @param {Packable} value The value at the provided time.\r\n * @param {Packable[]} [derivatives] The array of derivatives at the provided time.\r\n */\r\nSampledProperty.prototype.addSample = function (time, value, derivatives) {\r\n var innerDerivativeTypes = this._innerDerivativeTypes;\r\n var hasDerivatives = defined(innerDerivativeTypes);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n Check.defined(\"value\", value);\r\n if (hasDerivatives) {\r\n Check.defined(\"derivatives\", derivatives);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var innerType = this._innerType;\r\n var data = [];\r\n data.push(time);\r\n innerType.pack(value, data, data.length);\r\n\r\n if (hasDerivatives) {\r\n var derivativesLength = innerDerivativeTypes.length;\r\n for (var x = 0; x < derivativesLength; x++) {\r\n innerDerivativeTypes[x].pack(derivatives[x], data, data.length);\r\n }\r\n }\r\n mergeNewSamples(\r\n undefined,\r\n this._times,\r\n this._values,\r\n data,\r\n this._packedLength\r\n );\r\n this._updateTableLength = true;\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\n\r\n/**\r\n * Adds an array of samples.\r\n *\r\n * @param {JulianDate[]} times An array of JulianDate instances where each index is a sample time.\r\n * @param {Packable[]} values The array of values, where each value corresponds to the provided times index.\r\n * @param {Array[]} [derivativeValues] An array where each item is the array of derivatives at the equivalent time index.\r\n *\r\n * @exception {DeveloperError} times and values must be the same length.\r\n * @exception {DeveloperError} times and derivativeValues must be the same length.\r\n */\r\nSampledProperty.prototype.addSamples = function (\r\n times,\r\n values,\r\n derivativeValues\r\n) {\r\n var innerDerivativeTypes = this._innerDerivativeTypes;\r\n var hasDerivatives = defined(innerDerivativeTypes);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"times\", times);\r\n Check.defined(\"values\", values);\r\n if (times.length !== values.length) {\r\n throw new DeveloperError(\"times and values must be the same length.\");\r\n }\r\n if (\r\n hasDerivatives &&\r\n (!defined(derivativeValues) || derivativeValues.length !== times.length)\r\n ) {\r\n throw new DeveloperError(\r\n \"times and derivativeValues must be the same length.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var innerType = this._innerType;\r\n var length = times.length;\r\n var data = [];\r\n for (var i = 0; i < length; i++) {\r\n data.push(times[i]);\r\n innerType.pack(values[i], data, data.length);\r\n\r\n if (hasDerivatives) {\r\n var derivatives = derivativeValues[i];\r\n var derivativesLength = innerDerivativeTypes.length;\r\n for (var x = 0; x < derivativesLength; x++) {\r\n innerDerivativeTypes[x].pack(derivatives[x], data, data.length);\r\n }\r\n }\r\n }\r\n mergeNewSamples(\r\n undefined,\r\n this._times,\r\n this._values,\r\n data,\r\n this._packedLength\r\n );\r\n this._updateTableLength = true;\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\n\r\n/**\r\n * Adds samples as a single packed array where each new sample is represented as a date,\r\n * followed by the packed representation of the corresponding value and derivatives.\r\n *\r\n * @param {Number[]} packedSamples The array of packed samples.\r\n * @param {JulianDate} [epoch] If any of the dates in packedSamples are numbers, they are considered an offset from this epoch, in seconds.\r\n */\r\nSampledProperty.prototype.addSamplesPackedArray = function (\r\n packedSamples,\r\n epoch\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"packedSamples\", packedSamples);\r\n //>>includeEnd('debug');\r\n\r\n mergeNewSamples(\r\n epoch,\r\n this._times,\r\n this._values,\r\n packedSamples,\r\n this._packedLength\r\n );\r\n this._updateTableLength = true;\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\n\r\n/**\r\n * Removes a sample at the given time, if present.\r\n *\r\n * @param {JulianDate} time The sample time.\r\n * @returns {Boolean} true if a sample at time was removed, false otherwise.\r\n */\r\nSampledProperty.prototype.removeSample = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var index = binarySearch(this._times, time, JulianDate.compare);\r\n if (index < 0) {\r\n return false;\r\n }\r\n removeSamples(this, index, 1);\r\n return true;\r\n};\r\n\r\nfunction removeSamples(property, startIndex, numberToRemove) {\r\n var packedLength = property._packedLength;\r\n property._times.splice(startIndex, numberToRemove);\r\n property._values.splice(\r\n startIndex * packedLength,\r\n numberToRemove * packedLength\r\n );\r\n property._updateTableLength = true;\r\n property._definitionChanged.raiseEvent(property);\r\n}\r\n\r\n/**\r\n * Removes all samples for the given time interval.\r\n *\r\n * @param {TimeInterval} time The time interval for which to remove all samples.\r\n */\r\nSampledProperty.prototype.removeSamples = function (timeInterval) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"timeInterval\", timeInterval);\r\n //>>includeEnd('debug');\r\n\r\n var times = this._times;\r\n var startIndex = binarySearch(times, timeInterval.start, JulianDate.compare);\r\n if (startIndex < 0) {\r\n startIndex = ~startIndex;\r\n } else if (!timeInterval.isStartIncluded) {\r\n ++startIndex;\r\n }\r\n var stopIndex = binarySearch(times, timeInterval.stop, JulianDate.compare);\r\n if (stopIndex < 0) {\r\n stopIndex = ~stopIndex;\r\n } else if (timeInterval.isStopIncluded) {\r\n ++stopIndex;\r\n }\r\n\r\n removeSamples(this, startIndex, stopIndex - startIndex);\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nSampledProperty.prototype.equals = function (other) {\r\n if (this === other) {\r\n return true;\r\n }\r\n if (!defined(other)) {\r\n return false;\r\n }\r\n\r\n if (\r\n this._type !== other._type || //\r\n this._interpolationDegree !== other._interpolationDegree || //\r\n this._interpolationAlgorithm !== other._interpolationAlgorithm\r\n ) {\r\n return false;\r\n }\r\n\r\n var derivativeTypes = this._derivativeTypes;\r\n var hasDerivatives = defined(derivativeTypes);\r\n var otherDerivativeTypes = other._derivativeTypes;\r\n var otherHasDerivatives = defined(otherDerivativeTypes);\r\n if (hasDerivatives !== otherHasDerivatives) {\r\n return false;\r\n }\r\n\r\n var i;\r\n var length;\r\n if (hasDerivatives) {\r\n length = derivativeTypes.length;\r\n if (length !== otherDerivativeTypes.length) {\r\n return false;\r\n }\r\n\r\n for (i = 0; i < length; i++) {\r\n if (derivativeTypes[i] !== otherDerivativeTypes[i]) {\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n var times = this._times;\r\n var otherTimes = other._times;\r\n length = times.length;\r\n\r\n if (length !== otherTimes.length) {\r\n return false;\r\n }\r\n\r\n for (i = 0; i < length; i++) {\r\n if (!JulianDate.equals(times[i], otherTimes[i])) {\r\n return false;\r\n }\r\n }\r\n\r\n var values = this._values;\r\n var otherValues = other._values;\r\n length = values.length;\r\n\r\n //Since time lengths are equal, values length and other length are guaranteed to be equal.\r\n for (i = 0; i < length; i++) {\r\n if (values[i] !== otherValues[i]) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\n//Exposed for testing.\r\nSampledProperty._mergeNewSamples = mergeNewSamples;\r\nexport default SampledProperty;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport PositionProperty from \"./PositionProperty.js\";\r\nimport Property from \"./Property.js\";\r\nimport SampledProperty from \"./SampledProperty.js\";\r\n\r\n/**\r\n * A {@link SampledProperty} which is also a {@link PositionProperty}.\r\n *\r\n * @alias SampledPositionProperty\r\n * @constructor\r\n *\r\n * @param {ReferenceFrame} [referenceFrame=ReferenceFrame.FIXED] The reference frame in which the position is defined.\r\n * @param {Number} [numberOfDerivatives=0] The number of derivatives that accompany each position; i.e. velocity, acceleration, etc...\r\n */\r\nfunction SampledPositionProperty(referenceFrame, numberOfDerivatives) {\r\n numberOfDerivatives = defaultValue(numberOfDerivatives, 0);\r\n\r\n var derivativeTypes;\r\n if (numberOfDerivatives > 0) {\r\n derivativeTypes = new Array(numberOfDerivatives);\r\n for (var i = 0; i < numberOfDerivatives; i++) {\r\n derivativeTypes[i] = Cartesian3;\r\n }\r\n }\r\n\r\n this._numberOfDerivatives = numberOfDerivatives;\r\n this._property = new SampledProperty(Cartesian3, derivativeTypes);\r\n this._definitionChanged = new Event();\r\n this._referenceFrame = defaultValue(referenceFrame, ReferenceFrame.FIXED);\r\n\r\n this._property._definitionChanged.addEventListener(function () {\r\n this._definitionChanged.raiseEvent(this);\r\n }, this);\r\n}\r\n\r\nObject.defineProperties(SampledPositionProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof SampledPositionProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return this._property.isConstant;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof SampledPositionProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the reference frame in which the position is defined.\r\n * @memberof SampledPositionProperty.prototype\r\n * @type {ReferenceFrame}\r\n * @default ReferenceFrame.FIXED;\r\n */\r\n referenceFrame: {\r\n get: function () {\r\n return this._referenceFrame;\r\n },\r\n },\r\n /**\r\n * Gets the degree of interpolation to perform when retrieving a value. Call setInterpolationOptions to set this.\r\n * @memberof SampledPositionProperty.prototype\r\n *\r\n * @type {Number}\r\n * @default 1\r\n * @readonly\r\n */\r\n interpolationDegree: {\r\n get: function () {\r\n return this._property.interpolationDegree;\r\n },\r\n },\r\n /**\r\n * Gets the interpolation algorithm to use when retrieving a value. Call setInterpolationOptions to set this.\r\n * @memberof SampledPositionProperty.prototype\r\n *\r\n * @type {InterpolationAlgorithm}\r\n * @default LinearApproximation\r\n * @readonly\r\n */\r\n interpolationAlgorithm: {\r\n get: function () {\r\n return this._property.interpolationAlgorithm;\r\n },\r\n },\r\n /**\r\n * The number of derivatives contained by this property; i.e. 0 for just position, 1 for velocity, etc.\r\n * @memberof SampledPositionProperty.prototype\r\n *\r\n * @type {Number}\r\n * @default 0\r\n */\r\n numberOfDerivatives: {\r\n get: function () {\r\n return this._numberOfDerivatives;\r\n },\r\n },\r\n /**\r\n * Gets or sets the type of extrapolation to perform when a value\r\n * is requested at a time after any available samples.\r\n * @memberof SampledPositionProperty.prototype\r\n * @type {ExtrapolationType}\r\n * @default ExtrapolationType.NONE\r\n */\r\n forwardExtrapolationType: {\r\n get: function () {\r\n return this._property.forwardExtrapolationType;\r\n },\r\n set: function (value) {\r\n this._property.forwardExtrapolationType = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets the amount of time to extrapolate forward before\r\n * the property becomes undefined. A value of 0 will extrapolate forever.\r\n * @memberof SampledPositionProperty.prototype\r\n * @type {Number}\r\n * @default 0\r\n */\r\n forwardExtrapolationDuration: {\r\n get: function () {\r\n return this._property.forwardExtrapolationDuration;\r\n },\r\n set: function (value) {\r\n this._property.forwardExtrapolationDuration = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets the type of extrapolation to perform when a value\r\n * is requested at a time before any available samples.\r\n * @memberof SampledPositionProperty.prototype\r\n * @type {ExtrapolationType}\r\n * @default ExtrapolationType.NONE\r\n */\r\n backwardExtrapolationType: {\r\n get: function () {\r\n return this._property.backwardExtrapolationType;\r\n },\r\n set: function (value) {\r\n this._property.backwardExtrapolationType = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets the amount of time to extrapolate backward\r\n * before the property becomes undefined. A value of 0 will extrapolate forever.\r\n * @memberof SampledPositionProperty.prototype\r\n * @type {Number}\r\n * @default 0\r\n */\r\n backwardExtrapolationDuration: {\r\n get: function () {\r\n return this._property.backwardExtrapolationDuration;\r\n },\r\n set: function (value) {\r\n this._property.backwardExtrapolationDuration = value;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the position at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nSampledPositionProperty.prototype.getValue = function (time, result) {\r\n return this.getValueInReferenceFrame(time, ReferenceFrame.FIXED, result);\r\n};\r\n\r\n/**\r\n * Gets the position at the provided time and in the provided reference frame.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {ReferenceFrame} referenceFrame The desired referenceFrame of the result.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nSampledPositionProperty.prototype.getValueInReferenceFrame = function (\r\n time,\r\n referenceFrame,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n Check.defined(\"referenceFrame\", referenceFrame);\r\n //>>includeEnd('debug');\r\n\r\n result = this._property.getValue(time, result);\r\n if (defined(result)) {\r\n return PositionProperty.convertToReferenceFrame(\r\n time,\r\n result,\r\n this._referenceFrame,\r\n referenceFrame,\r\n result\r\n );\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Sets the algorithm and degree to use when interpolating a position.\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {InterpolationAlgorithm} [options.interpolationAlgorithm] The new interpolation algorithm. If undefined, the existing property will be unchanged.\r\n * @param {Number} [options.interpolationDegree] The new interpolation degree. If undefined, the existing property will be unchanged.\r\n */\r\nSampledPositionProperty.prototype.setInterpolationOptions = function (options) {\r\n this._property.setInterpolationOptions(options);\r\n};\r\n\r\n/**\r\n * Adds a new sample.\r\n *\r\n * @param {JulianDate} time The sample time.\r\n * @param {Cartesian3} position The position at the provided time.\r\n * @param {Cartesian3[]} [derivatives] The array of derivative values at the provided time.\r\n */\r\nSampledPositionProperty.prototype.addSample = function (\r\n time,\r\n position,\r\n derivatives\r\n) {\r\n var numberOfDerivatives = this._numberOfDerivatives;\r\n //>>includeStart('debug', pragmas.debug);\r\n if (\r\n numberOfDerivatives > 0 &&\r\n (!defined(derivatives) || derivatives.length !== numberOfDerivatives)\r\n ) {\r\n throw new DeveloperError(\r\n \"derivatives length must be equal to the number of derivatives.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n this._property.addSample(time, position, derivatives);\r\n};\r\n\r\n/**\r\n * Adds multiple samples via parallel arrays.\r\n *\r\n * @param {JulianDate[]} times An array of JulianDate instances where each index is a sample time.\r\n * @param {Cartesian3[]} positions An array of Cartesian3 position instances, where each value corresponds to the provided time index.\r\n * @param {Array[]} [derivatives] An array where each value is another array containing derivatives for the corresponding time index.\r\n *\r\n * @exception {DeveloperError} All arrays must be the same length.\r\n */\r\nSampledPositionProperty.prototype.addSamples = function (\r\n times,\r\n positions,\r\n derivatives\r\n) {\r\n this._property.addSamples(times, positions, derivatives);\r\n};\r\n\r\n/**\r\n * Adds samples as a single packed array where each new sample is represented as a date,\r\n * followed by the packed representation of the corresponding value and derivatives.\r\n *\r\n * @param {Number[]} packedSamples The array of packed samples.\r\n * @param {JulianDate} [epoch] If any of the dates in packedSamples are numbers, they are considered an offset from this epoch, in seconds.\r\n */\r\nSampledPositionProperty.prototype.addSamplesPackedArray = function (\r\n packedSamples,\r\n epoch\r\n) {\r\n this._property.addSamplesPackedArray(packedSamples, epoch);\r\n};\r\n\r\n/**\r\n * Removes a sample at the given time, if present.\r\n *\r\n * @param {JulianDate} time The sample time.\r\n * @returns {Boolean} true if a sample at time was removed, false otherwise.\r\n */\r\nSampledPositionProperty.prototype.removeSample = function (time) {\r\n return this._property.removeSample(time);\r\n};\r\n\r\n/**\r\n * Removes all samples for the given time interval.\r\n *\r\n * @param {TimeInterval} time The time interval for which to remove all samples.\r\n */\r\nSampledPositionProperty.prototype.removeSamples = function (timeInterval) {\r\n this._property.removeSamples(timeInterval);\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nSampledPositionProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof SampledPositionProperty &&\r\n Property.equals(this._property, other._property) && //\r\n this._referenceFrame === other._referenceFrame)\r\n );\r\n};\r\nexport default SampledPositionProperty;\r\n","/**\r\n * Defined the orientation of stripes in {@link StripeMaterialProperty}.\r\n *\r\n * @enum {Number}\r\n */\r\nvar StripeOrientation = {\r\n /**\r\n * Horizontal orientation.\r\n * @type {Number}\r\n */\r\n HORIZONTAL: 0,\r\n\r\n /**\r\n * Vertical orientation.\r\n * @type {Number}\r\n */\r\n VERTICAL: 1,\r\n};\r\nexport default Object.freeze(StripeOrientation);\r\n","import Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport createPropertyDescriptor from \"./createPropertyDescriptor.js\";\r\nimport Property from \"./Property.js\";\r\nimport StripeOrientation from \"./StripeOrientation.js\";\r\n\r\nvar defaultOrientation = StripeOrientation.HORIZONTAL;\r\nvar defaultEvenColor = Color.WHITE;\r\nvar defaultOddColor = Color.BLACK;\r\nvar defaultOffset = 0;\r\nvar defaultRepeat = 1;\r\n\r\n/**\r\n * A {@link MaterialProperty} that maps to stripe {@link Material} uniforms.\r\n * @alias StripeMaterialProperty\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Property|StripeOrientation} [options.orientation=StripeOrientation.HORIZONTAL] A Property specifying the {@link StripeOrientation}.\r\n * @param {Property|Color} [options.evenColor=Color.WHITE] A Property specifying the first {@link Color}.\r\n * @param {Property|Color} [options.oddColor=Color.BLACK] A Property specifying the second {@link Color}.\r\n * @param {Property|Number} [options.offset=0] A numeric Property specifying how far into the pattern to start the material.\r\n * @param {Property|Number} [options.repeat=1] A numeric Property specifying how many times the stripes repeat.\r\n */\r\nfunction StripeMaterialProperty(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._definitionChanged = new Event();\r\n this._orientation = undefined;\r\n this._orientationSubscription = undefined;\r\n this._evenColor = undefined;\r\n this._evenColorSubscription = undefined;\r\n this._oddColor = undefined;\r\n this._oddColorSubscription = undefined;\r\n this._offset = undefined;\r\n this._offsetSubscription = undefined;\r\n this._repeat = undefined;\r\n this._repeatSubscription = undefined;\r\n\r\n this.orientation = options.orientation;\r\n this.evenColor = options.evenColor;\r\n this.oddColor = options.oddColor;\r\n this.offset = options.offset;\r\n this.repeat = options.repeat;\r\n}\r\n\r\nObject.defineProperties(StripeMaterialProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof StripeMaterialProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return (\r\n Property.isConstant(this._orientation) && //\r\n Property.isConstant(this._evenColor) && //\r\n Property.isConstant(this._oddColor) && //\r\n Property.isConstant(this._offset) && //\r\n Property.isConstant(this._repeat)\r\n );\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof StripeMaterialProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the Property specifying the {@link StripeOrientation}/\r\n * @memberof StripeMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default StripeOrientation.HORIZONTAL\r\n */\r\n orientation: createPropertyDescriptor(\"orientation\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the first {@link Color}.\r\n * @memberof StripeMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.WHITE\r\n */\r\n evenColor: createPropertyDescriptor(\"evenColor\"),\r\n\r\n /**\r\n * Gets or sets the Property specifying the second {@link Color}.\r\n * @memberof StripeMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default Color.BLACK\r\n */\r\n oddColor: createPropertyDescriptor(\"oddColor\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying the point into the pattern\r\n * to begin drawing; with 0.0 being the beginning of the even color, 1.0 the beginning\r\n * of the odd color, 2.0 being the even color again, and any multiple or fractional values\r\n * being in between.\r\n * @memberof StripeMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default 0.0\r\n */\r\n offset: createPropertyDescriptor(\"offset\"),\r\n\r\n /**\r\n * Gets or sets the numeric Property specifying how many times the stripes repeat.\r\n * @memberof StripeMaterialProperty.prototype\r\n * @type {Property|undefined}\r\n * @default 1.0\r\n */\r\n repeat: createPropertyDescriptor(\"repeat\"),\r\n});\r\n\r\n/**\r\n * Gets the {@link Material} type at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the type.\r\n * @returns {String} The type of material.\r\n */\r\nStripeMaterialProperty.prototype.getType = function (time) {\r\n return \"Stripe\";\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nStripeMaterialProperty.prototype.getValue = function (time, result) {\r\n if (!defined(result)) {\r\n result = {};\r\n }\r\n result.horizontal =\r\n Property.getValueOrDefault(this._orientation, time, defaultOrientation) ===\r\n StripeOrientation.HORIZONTAL;\r\n result.evenColor = Property.getValueOrClonedDefault(\r\n this._evenColor,\r\n time,\r\n defaultEvenColor,\r\n result.evenColor\r\n );\r\n result.oddColor = Property.getValueOrClonedDefault(\r\n this._oddColor,\r\n time,\r\n defaultOddColor,\r\n result.oddColor\r\n );\r\n result.offset = Property.getValueOrDefault(this._offset, time, defaultOffset);\r\n result.repeat = Property.getValueOrDefault(this._repeat, time, defaultRepeat);\r\n return result;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nStripeMaterialProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof StripeMaterialProperty && //\r\n Property.equals(this._orientation, other._orientation) && //\r\n Property.equals(this._evenColor, other._evenColor) && //\r\n Property.equals(this._oddColor, other._oddColor) && //\r\n Property.equals(this._offset, other._offset) && //\r\n Property.equals(this._repeat, other._repeat))\r\n );\r\n};\r\nexport default StripeMaterialProperty;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport TimeIntervalCollection from \"../Core/TimeIntervalCollection.js\";\r\nimport PositionProperty from \"./PositionProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link TimeIntervalCollectionProperty} which is also a {@link PositionProperty}.\r\n *\r\n * @alias TimeIntervalCollectionPositionProperty\r\n * @constructor\r\n *\r\n * @param {ReferenceFrame} [referenceFrame=ReferenceFrame.FIXED] The reference frame in which the position is defined.\r\n */\r\nfunction TimeIntervalCollectionPositionProperty(referenceFrame) {\r\n this._definitionChanged = new Event();\r\n this._intervals = new TimeIntervalCollection();\r\n this._intervals.changedEvent.addEventListener(\r\n TimeIntervalCollectionPositionProperty.prototype._intervalsChanged,\r\n this\r\n );\r\n this._referenceFrame = defaultValue(referenceFrame, ReferenceFrame.FIXED);\r\n}\r\n\r\nObject.defineProperties(TimeIntervalCollectionPositionProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof TimeIntervalCollectionPositionProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return this._intervals.isEmpty;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is considered to have changed if a call to getValue would return\r\n * a different result for the same time.\r\n * @memberof TimeIntervalCollectionPositionProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the interval collection.\r\n * @memberof TimeIntervalCollectionPositionProperty.prototype\r\n * @type {TimeIntervalCollection}\r\n */\r\n intervals: {\r\n get: function () {\r\n return this._intervals;\r\n },\r\n },\r\n /**\r\n * Gets the reference frame in which the position is defined.\r\n * @memberof TimeIntervalCollectionPositionProperty.prototype\r\n * @type {ReferenceFrame}\r\n * @default ReferenceFrame.FIXED;\r\n */\r\n referenceFrame: {\r\n get: function () {\r\n return this._referenceFrame;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time in the fixed frame.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nTimeIntervalCollectionPositionProperty.prototype.getValue = function (\r\n time,\r\n result\r\n) {\r\n return this.getValueInReferenceFrame(time, ReferenceFrame.FIXED, result);\r\n};\r\n\r\n/**\r\n * Gets the value of the property at the provided time and in the provided reference frame.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {ReferenceFrame} referenceFrame The desired referenceFrame of the result.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nTimeIntervalCollectionPositionProperty.prototype.getValueInReferenceFrame = function (\r\n time,\r\n referenceFrame,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n if (!defined(referenceFrame)) {\r\n throw new DeveloperError(\"referenceFrame is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var position = this._intervals.findDataForIntervalContainingDate(time);\r\n if (defined(position)) {\r\n return PositionProperty.convertToReferenceFrame(\r\n time,\r\n position,\r\n this._referenceFrame,\r\n referenceFrame,\r\n result\r\n );\r\n }\r\n return undefined;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nTimeIntervalCollectionPositionProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof TimeIntervalCollectionPositionProperty && //\r\n this._intervals.equals(other._intervals, Property.equals) && //\r\n this._referenceFrame === other._referenceFrame)\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nTimeIntervalCollectionPositionProperty.prototype._intervalsChanged = function () {\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\nexport default TimeIntervalCollectionPositionProperty;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport TimeIntervalCollection from \"../Core/TimeIntervalCollection.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link Property} which is defined by a {@link TimeIntervalCollection}, where the\r\n * data property of each {@link TimeInterval} represents the value at time.\r\n *\r\n * @alias TimeIntervalCollectionProperty\r\n * @constructor\r\n *\r\n * @example\r\n * //Create a Cartesian2 interval property which contains data on August 1st, 2012\r\n * //and uses a different value every 6 hours.\r\n * var composite = new Cesium.TimeIntervalCollectionProperty();\r\n * composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({\r\n * iso8601 : '2012-08-01T00:00:00.00Z/2012-08-01T06:00:00.00Z',\r\n * isStartIncluded : true,\r\n * isStopIncluded : false,\r\n * data : new Cesium.Cartesian2(2.0, 3.4)\r\n * }));\r\n * composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({\r\n * iso8601 : '2012-08-01T06:00:00.00Z/2012-08-01T12:00:00.00Z',\r\n * isStartIncluded : true,\r\n * isStopIncluded : false,\r\n * data : new Cesium.Cartesian2(12.0, 2.7)\r\n * }));\r\n * composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({\r\n * iso8601 : '2012-08-01T12:00:00.00Z/2012-08-01T18:00:00.00Z',\r\n * isStartIncluded : true,\r\n * isStopIncluded : false,\r\n * data : new Cesium.Cartesian2(5.0, 12.4)\r\n * }));\r\n * composite.intervals.addInterval(Cesium.TimeInterval.fromIso8601({\r\n * iso8601 : '2012-08-01T18:00:00.00Z/2012-08-02T00:00:00.00Z',\r\n * isStartIncluded : true,\r\n * isStopIncluded : true,\r\n * data : new Cesium.Cartesian2(85.0, 4.1)\r\n * }));\r\n */\r\nfunction TimeIntervalCollectionProperty() {\r\n this._definitionChanged = new Event();\r\n this._intervals = new TimeIntervalCollection();\r\n this._intervals.changedEvent.addEventListener(\r\n TimeIntervalCollectionProperty.prototype._intervalsChanged,\r\n this\r\n );\r\n}\r\n\r\nObject.defineProperties(TimeIntervalCollectionProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant. A property is considered\r\n * constant if getValue always returns the same result for the current definition.\r\n * @memberof TimeIntervalCollectionProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return this._intervals.isEmpty;\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * The definition is changed whenever setValue is called with data different\r\n * than the current value.\r\n * @memberof TimeIntervalCollectionProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets the interval collection.\r\n * @memberof TimeIntervalCollectionProperty.prototype\r\n *\r\n * @type {TimeIntervalCollection}\r\n */\r\n intervals: {\r\n get: function () {\r\n return this._intervals;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve the value.\r\n * @param {Object} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Object} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nTimeIntervalCollectionProperty.prototype.getValue = function (time, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var value = this._intervals.findDataForIntervalContainingDate(time);\r\n if (defined(value) && typeof value.clone === \"function\") {\r\n return value.clone(result);\r\n }\r\n return value;\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nTimeIntervalCollectionProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof TimeIntervalCollectionProperty && //\r\n this._intervals.equals(other._intervals, Property.equals))\r\n );\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nTimeIntervalCollectionProperty.prototype._intervalsChanged = function () {\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\nexport default TimeIntervalCollectionProperty;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * A {@link Property} which evaluates to a {@link Cartesian3} vector\r\n * based on the velocity of the provided {@link PositionProperty}.\r\n *\r\n * @alias VelocityVectorProperty\r\n * @constructor\r\n *\r\n * @param {PositionProperty} [position] The position property used to compute the velocity.\r\n * @param {Boolean} [normalize=true] Whether to normalize the computed velocity vector.\r\n *\r\n * @example\r\n * //Create an entity with a billboard rotated to match its velocity.\r\n * var position = new Cesium.SampledProperty();\r\n * position.addSamples(...);\r\n * var entity = viewer.entities.add({\r\n * position : position,\r\n * billboard : {\r\n * image : 'image.png',\r\n * alignedAxis : new Cesium.VelocityVectorProperty(position, true) // alignedAxis must be a unit vector\r\n * }\r\n * }));\r\n */\r\nfunction VelocityVectorProperty(position, normalize) {\r\n this._position = undefined;\r\n this._subscription = undefined;\r\n this._definitionChanged = new Event();\r\n this._normalize = defaultValue(normalize, true);\r\n\r\n this.position = position;\r\n}\r\n\r\nObject.defineProperties(VelocityVectorProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant.\r\n * @memberof VelocityVectorProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return Property.isConstant(this._position);\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * @memberof VelocityVectorProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets or sets the position property used to compute the velocity vector.\r\n * @memberof VelocityVectorProperty.prototype\r\n *\r\n * @type {Property|undefined}\r\n */\r\n position: {\r\n get: function () {\r\n return this._position;\r\n },\r\n set: function (value) {\r\n var oldValue = this._position;\r\n if (oldValue !== value) {\r\n if (defined(oldValue)) {\r\n this._subscription();\r\n }\r\n\r\n this._position = value;\r\n\r\n if (defined(value)) {\r\n this._subscription = value._definitionChanged.addEventListener(\r\n function () {\r\n this._definitionChanged.raiseEvent(this);\r\n },\r\n this\r\n );\r\n }\r\n\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n },\r\n },\r\n /**\r\n * Gets or sets whether the vector produced by this property\r\n * will be normalized or not.\r\n * @memberof VelocityVectorProperty.prototype\r\n *\r\n * @type {Boolean}\r\n */\r\n normalize: {\r\n get: function () {\r\n return this._normalize;\r\n },\r\n set: function (value) {\r\n if (this._normalize === value) {\r\n return;\r\n }\r\n\r\n this._normalize = value;\r\n this._definitionChanged.raiseEvent(this);\r\n },\r\n },\r\n});\r\n\r\nvar position1Scratch = new Cartesian3();\r\nvar position2Scratch = new Cartesian3();\r\nvar timeScratch = new JulianDate();\r\nvar step = 1.0 / 60.0;\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} [time] The time for which to retrieve the value.\r\n * @param {Cartesian3} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Cartesian3} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nVelocityVectorProperty.prototype.getValue = function (time, result) {\r\n return this._getValue(time, result);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nVelocityVectorProperty.prototype._getValue = function (\r\n time,\r\n velocityResult,\r\n positionResult\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(velocityResult)) {\r\n velocityResult = new Cartesian3();\r\n }\r\n\r\n var property = this._position;\r\n if (Property.isConstant(property)) {\r\n return this._normalize\r\n ? undefined\r\n : Cartesian3.clone(Cartesian3.ZERO, velocityResult);\r\n }\r\n\r\n var position1 = property.getValue(time, position1Scratch);\r\n var position2 = property.getValue(\r\n JulianDate.addSeconds(time, step, timeScratch),\r\n position2Scratch\r\n );\r\n\r\n //If we don't have a position for now, return undefined.\r\n if (!defined(position1)) {\r\n return undefined;\r\n }\r\n\r\n //If we don't have a position for now + step, see if we have a position for now - step.\r\n if (!defined(position2)) {\r\n position2 = position1;\r\n position1 = property.getValue(\r\n JulianDate.addSeconds(time, -step, timeScratch),\r\n position2Scratch\r\n );\r\n\r\n if (!defined(position1)) {\r\n return undefined;\r\n }\r\n }\r\n\r\n if (Cartesian3.equals(position1, position2)) {\r\n return this._normalize\r\n ? undefined\r\n : Cartesian3.clone(Cartesian3.ZERO, velocityResult);\r\n }\r\n\r\n if (defined(positionResult)) {\r\n position1.clone(positionResult);\r\n }\r\n\r\n var velocity = Cartesian3.subtract(position2, position1, velocityResult);\r\n if (this._normalize) {\r\n return Cartesian3.normalize(velocity, velocityResult);\r\n }\r\n\r\n return Cartesian3.divideByScalar(velocity, step, velocityResult);\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nVelocityVectorProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof VelocityVectorProperty &&\r\n Property.equals(this._position, other._position))\r\n );\r\n};\r\nexport default VelocityVectorProperty;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Quaternion from \"../Core/Quaternion.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport Property from \"./Property.js\";\r\nimport VelocityVectorProperty from \"./VelocityVectorProperty.js\";\r\n\r\n/**\r\n * A {@link Property} which evaluates to a {@link Quaternion} rotation\r\n * based on the velocity of the provided {@link PositionProperty}.\r\n *\r\n * @alias VelocityOrientationProperty\r\n * @constructor\r\n *\r\n * @param {PositionProperty} [position] The position property used to compute the orientation.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid used to determine which way is up.\r\n *\r\n * @example\r\n * //Create an entity with position and orientation.\r\n * var position = new Cesium.SampledProperty();\r\n * position.addSamples(...);\r\n * var entity = viewer.entities.add({\r\n * position : position,\r\n * orientation : new Cesium.VelocityOrientationProperty(position)\r\n * }));\r\n */\r\nfunction VelocityOrientationProperty(position, ellipsoid) {\r\n this._velocityVectorProperty = new VelocityVectorProperty(position, true);\r\n this._subscription = undefined;\r\n this._ellipsoid = undefined;\r\n this._definitionChanged = new Event();\r\n\r\n this.ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n\r\n var that = this;\r\n this._velocityVectorProperty.definitionChanged.addEventListener(function () {\r\n that._definitionChanged.raiseEvent(that);\r\n });\r\n}\r\n\r\nObject.defineProperties(VelocityOrientationProperty.prototype, {\r\n /**\r\n * Gets a value indicating if this property is constant.\r\n * @memberof VelocityOrientationProperty.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isConstant: {\r\n get: function () {\r\n return Property.isConstant(this._velocityVectorProperty);\r\n },\r\n },\r\n /**\r\n * Gets the event that is raised whenever the definition of this property changes.\r\n * @memberof VelocityOrientationProperty.prototype\r\n *\r\n * @type {Event}\r\n * @readonly\r\n */\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n /**\r\n * Gets or sets the position property used to compute orientation.\r\n * @memberof VelocityOrientationProperty.prototype\r\n *\r\n * @type {Property|undefined}\r\n */\r\n position: {\r\n get: function () {\r\n return this._velocityVectorProperty.position;\r\n },\r\n set: function (value) {\r\n this._velocityVectorProperty.position = value;\r\n },\r\n },\r\n /**\r\n * Gets or sets the ellipsoid used to determine which way is up.\r\n * @memberof VelocityOrientationProperty.prototype\r\n *\r\n * @type {Property|undefined}\r\n */\r\n ellipsoid: {\r\n get: function () {\r\n return this._ellipsoid;\r\n },\r\n set: function (value) {\r\n var oldValue = this._ellipsoid;\r\n if (oldValue !== value) {\r\n this._ellipsoid = value;\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n },\r\n },\r\n});\r\n\r\nvar positionScratch = new Cartesian3();\r\nvar velocityScratch = new Cartesian3();\r\nvar rotationScratch = new Matrix3();\r\n\r\n/**\r\n * Gets the value of the property at the provided time.\r\n *\r\n * @param {JulianDate} [time] The time for which to retrieve the value.\r\n * @param {Quaternion} [result] The object to store the value into, if omitted, a new instance is created and returned.\r\n * @returns {Quaternion} The modified result parameter or a new instance if the result parameter was not supplied.\r\n */\r\nVelocityOrientationProperty.prototype.getValue = function (time, result) {\r\n var velocity = this._velocityVectorProperty._getValue(\r\n time,\r\n velocityScratch,\r\n positionScratch\r\n );\r\n\r\n if (!defined(velocity)) {\r\n return undefined;\r\n }\r\n\r\n Transforms.rotationMatrixFromPositionVelocity(\r\n positionScratch,\r\n velocity,\r\n this._ellipsoid,\r\n rotationScratch\r\n );\r\n return Quaternion.fromRotationMatrix(rotationScratch, result);\r\n};\r\n\r\n/**\r\n * Compares this property to the provided property and returns\r\n * true if they are equal, false otherwise.\r\n *\r\n * @param {Property} [other] The other property.\r\n * @returns {Boolean} true if left and right are equal, false otherwise.\r\n */\r\nVelocityOrientationProperty.prototype.equals = function (other) {\r\n return (\r\n this === other || //\r\n (other instanceof VelocityOrientationProperty &&\r\n Property.equals(\r\n this._velocityVectorProperty,\r\n other._velocityVectorProperty\r\n ) &&\r\n (this._ellipsoid === other._ellipsoid ||\r\n this._ellipsoid.equals(other._ellipsoid)))\r\n );\r\n};\r\nexport default VelocityOrientationProperty;\r\n","import ArcType from \"../Core/ArcType.js\";\r\nimport BoundingRectangle from \"../Core/BoundingRectangle.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport ClockRange from \"../Core/ClockRange.js\";\r\nimport ClockStep from \"../Core/ClockStep.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport CornerType from \"../Core/CornerType.js\";\r\nimport Credit from \"../Core/Credit.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport ExtrapolationType from \"../Core/ExtrapolationType.js\";\r\nimport getFilenameFromUri from \"../Core/getFilenameFromUri.js\";\r\nimport HermitePolynomialApproximation from \"../Core/HermitePolynomialApproximation.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport LagrangePolynomialApproximation from \"../Core/LagrangePolynomialApproximation.js\";\r\nimport LinearApproximation from \"../Core/LinearApproximation.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport NearFarScalar from \"../Core/NearFarScalar.js\";\r\nimport PolygonHierarchy from \"../Core/PolygonHierarchy.js\";\r\nimport Quaternion from \"../Core/Quaternion.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport Spherical from \"../Core/Spherical.js\";\r\nimport TimeInterval from \"../Core/TimeInterval.js\";\r\nimport TimeIntervalCollection from \"../Core/TimeIntervalCollection.js\";\r\nimport ClassificationType from \"../Scene/ClassificationType.js\";\r\nimport ColorBlendMode from \"../Scene/ColorBlendMode.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport HorizontalOrigin from \"../Scene/HorizontalOrigin.js\";\r\nimport LabelStyle from \"../Scene/LabelStyle.js\";\r\nimport ShadowMode from \"../Scene/ShadowMode.js\";\r\nimport VerticalOrigin from \"../Scene/VerticalOrigin.js\";\r\nimport Uri from \"../ThirdParty/Uri.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport BillboardGraphics from \"./BillboardGraphics.js\";\r\nimport BoxGraphics from \"./BoxGraphics.js\";\r\nimport CallbackProperty from \"./CallbackProperty.js\";\r\nimport CheckerboardMaterialProperty from \"./CheckerboardMaterialProperty.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport CompositeMaterialProperty from \"./CompositeMaterialProperty.js\";\r\nimport CompositePositionProperty from \"./CompositePositionProperty.js\";\r\nimport CompositeProperty from \"./CompositeProperty.js\";\r\nimport ConstantPositionProperty from \"./ConstantPositionProperty.js\";\r\nimport ConstantProperty from \"./ConstantProperty.js\";\r\nimport CorridorGraphics from \"./CorridorGraphics.js\";\r\nimport CylinderGraphics from \"./CylinderGraphics.js\";\r\nimport DataSource from \"./DataSource.js\";\r\nimport DataSourceClock from \"./DataSourceClock.js\";\r\nimport EllipseGraphics from \"./EllipseGraphics.js\";\r\nimport EllipsoidGraphics from \"./EllipsoidGraphics.js\";\r\nimport EntityCluster from \"./EntityCluster.js\";\r\nimport EntityCollection from \"./EntityCollection.js\";\r\nimport GridMaterialProperty from \"./GridMaterialProperty.js\";\r\nimport ImageMaterialProperty from \"./ImageMaterialProperty.js\";\r\nimport LabelGraphics from \"./LabelGraphics.js\";\r\nimport ModelGraphics from \"./ModelGraphics.js\";\r\nimport NodeTransformationProperty from \"./NodeTransformationProperty.js\";\r\nimport PathGraphics from \"./PathGraphics.js\";\r\nimport PointGraphics from \"./PointGraphics.js\";\r\nimport PolygonGraphics from \"./PolygonGraphics.js\";\r\nimport PolylineArrowMaterialProperty from \"./PolylineArrowMaterialProperty.js\";\r\nimport PolylineDashMaterialProperty from \"./PolylineDashMaterialProperty.js\";\r\nimport PolylineGlowMaterialProperty from \"./PolylineGlowMaterialProperty.js\";\r\nimport PolylineGraphics from \"./PolylineGraphics.js\";\r\nimport PolylineOutlineMaterialProperty from \"./PolylineOutlineMaterialProperty.js\";\r\nimport PolylineVolumeGraphics from \"./PolylineVolumeGraphics.js\";\r\nimport PositionPropertyArray from \"./PositionPropertyArray.js\";\r\nimport Property from \"./Property.js\";\r\nimport PropertyArray from \"./PropertyArray.js\";\r\nimport PropertyBag from \"./PropertyBag.js\";\r\nimport RectangleGraphics from \"./RectangleGraphics.js\";\r\nimport ReferenceProperty from \"./ReferenceProperty.js\";\r\nimport Rotation from \"./Rotation.js\";\r\nimport SampledPositionProperty from \"./SampledPositionProperty.js\";\r\nimport SampledProperty from \"./SampledProperty.js\";\r\nimport StripeMaterialProperty from \"./StripeMaterialProperty.js\";\r\nimport StripeOrientation from \"./StripeOrientation.js\";\r\nimport TimeIntervalCollectionPositionProperty from \"./TimeIntervalCollectionPositionProperty.js\";\r\nimport TimeIntervalCollectionProperty from \"./TimeIntervalCollectionProperty.js\";\r\nimport VelocityOrientationProperty from \"./VelocityOrientationProperty.js\";\r\nimport VelocityVectorProperty from \"./VelocityVectorProperty.js\";\r\nimport WallGraphics from \"./WallGraphics.js\";\r\nimport Cesium3DTilesetGraphics from \"./Cesium3DTilesetGraphics.js\";\r\n\r\n// A marker type to distinguish CZML properties where we need to end up with a unit vector.\r\n// The data is still loaded into Cartesian3 objects but they are normalized.\r\nfunction UnitCartesian3() {}\r\nUnitCartesian3.packedLength = Cartesian3.packedLength;\r\nUnitCartesian3.unpack = Cartesian3.unpack;\r\nUnitCartesian3.pack = Cartesian3.pack;\r\n\r\n// As a side note, for the purposes of CZML, Quaternion always indicates a unit quaternion.\r\n\r\nvar currentId;\r\n\r\nfunction createReferenceProperty(entityCollection, referenceString) {\r\n if (referenceString[0] === \"#\") {\r\n referenceString = currentId + referenceString;\r\n }\r\n return ReferenceProperty.fromString(entityCollection, referenceString);\r\n}\r\n\r\nfunction createSpecializedProperty(type, entityCollection, packetData) {\r\n if (defined(packetData.reference)) {\r\n return createReferenceProperty(entityCollection, packetData.reference);\r\n }\r\n\r\n if (defined(packetData.velocityReference)) {\r\n var referenceProperty = createReferenceProperty(\r\n entityCollection,\r\n packetData.velocityReference\r\n );\r\n switch (type) {\r\n case Cartesian3:\r\n case UnitCartesian3:\r\n return new VelocityVectorProperty(\r\n referenceProperty,\r\n type === UnitCartesian3\r\n );\r\n case Quaternion:\r\n return new VelocityOrientationProperty(referenceProperty);\r\n }\r\n }\r\n\r\n throw new RuntimeError(JSON.stringify(packetData) + \" is not valid CZML.\");\r\n}\r\n\r\nfunction createAdapterProperty(property, adapterFunction) {\r\n return new CallbackProperty(function (time, result) {\r\n return adapterFunction(property.getValue(time, result));\r\n }, property.isConstant);\r\n}\r\n\r\nvar scratchCartesian = new Cartesian3();\r\nvar scratchSpherical = new Spherical();\r\nvar scratchCartographic = new Cartographic();\r\nvar scratchTimeInterval = new TimeInterval();\r\nvar scratchQuaternion = new Quaternion();\r\n\r\nfunction unwrapColorInterval(czmlInterval) {\r\n var rgbaf = czmlInterval.rgbaf;\r\n if (defined(rgbaf)) {\r\n return rgbaf;\r\n }\r\n\r\n var rgba = czmlInterval.rgba;\r\n if (!defined(rgba)) {\r\n return undefined;\r\n }\r\n\r\n var length = rgba.length;\r\n if (length === Color.packedLength) {\r\n return [\r\n Color.byteToFloat(rgba[0]),\r\n Color.byteToFloat(rgba[1]),\r\n Color.byteToFloat(rgba[2]),\r\n Color.byteToFloat(rgba[3]),\r\n ];\r\n }\r\n\r\n rgbaf = new Array(length);\r\n for (var i = 0; i < length; i += 5) {\r\n rgbaf[i] = rgba[i];\r\n rgbaf[i + 1] = Color.byteToFloat(rgba[i + 1]);\r\n rgbaf[i + 2] = Color.byteToFloat(rgba[i + 2]);\r\n rgbaf[i + 3] = Color.byteToFloat(rgba[i + 3]);\r\n rgbaf[i + 4] = Color.byteToFloat(rgba[i + 4]);\r\n }\r\n return rgbaf;\r\n}\r\n\r\nfunction unwrapUriInterval(czmlInterval, sourceUri) {\r\n var uri = defaultValue(czmlInterval.uri, czmlInterval);\r\n if (defined(sourceUri)) {\r\n return sourceUri.getDerivedResource({\r\n url: uri,\r\n });\r\n }\r\n\r\n return Resource.createIfNeeded(uri);\r\n}\r\n\r\nfunction unwrapRectangleInterval(czmlInterval) {\r\n var wsen = czmlInterval.wsen;\r\n if (defined(wsen)) {\r\n return wsen;\r\n }\r\n\r\n var wsenDegrees = czmlInterval.wsenDegrees;\r\n if (!defined(wsenDegrees)) {\r\n return undefined;\r\n }\r\n\r\n var length = wsenDegrees.length;\r\n if (length === Rectangle.packedLength) {\r\n return [\r\n CesiumMath.toRadians(wsenDegrees[0]),\r\n CesiumMath.toRadians(wsenDegrees[1]),\r\n CesiumMath.toRadians(wsenDegrees[2]),\r\n CesiumMath.toRadians(wsenDegrees[3]),\r\n ];\r\n }\r\n\r\n wsen = new Array(length);\r\n for (var i = 0; i < length; i += 5) {\r\n wsen[i] = wsenDegrees[i];\r\n wsen[i + 1] = CesiumMath.toRadians(wsenDegrees[i + 1]);\r\n wsen[i + 2] = CesiumMath.toRadians(wsenDegrees[i + 2]);\r\n wsen[i + 3] = CesiumMath.toRadians(wsenDegrees[i + 3]);\r\n wsen[i + 4] = CesiumMath.toRadians(wsenDegrees[i + 4]);\r\n }\r\n return wsen;\r\n}\r\n\r\nfunction convertUnitSphericalToCartesian(unitSpherical) {\r\n var length = unitSpherical.length;\r\n scratchSpherical.magnitude = 1.0;\r\n if (length === 2) {\r\n scratchSpherical.clock = unitSpherical[0];\r\n scratchSpherical.cone = unitSpherical[1];\r\n Cartesian3.fromSpherical(scratchSpherical, scratchCartesian);\r\n return [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z];\r\n }\r\n\r\n var result = new Array((length / 3) * 4);\r\n for (var i = 0, j = 0; i < length; i += 3, j += 4) {\r\n result[j] = unitSpherical[i];\r\n\r\n scratchSpherical.clock = unitSpherical[i + 1];\r\n scratchSpherical.cone = unitSpherical[i + 2];\r\n Cartesian3.fromSpherical(scratchSpherical, scratchCartesian);\r\n\r\n result[j + 1] = scratchCartesian.x;\r\n result[j + 2] = scratchCartesian.y;\r\n result[j + 3] = scratchCartesian.z;\r\n }\r\n return result;\r\n}\r\n\r\nfunction convertSphericalToCartesian(spherical) {\r\n var length = spherical.length;\r\n if (length === 3) {\r\n scratchSpherical.clock = spherical[0];\r\n scratchSpherical.cone = spherical[1];\r\n scratchSpherical.magnitude = spherical[2];\r\n Cartesian3.fromSpherical(scratchSpherical, scratchCartesian);\r\n return [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z];\r\n }\r\n\r\n var result = new Array(length);\r\n for (var i = 0; i < length; i += 4) {\r\n result[i] = spherical[i];\r\n\r\n scratchSpherical.clock = spherical[i + 1];\r\n scratchSpherical.cone = spherical[i + 2];\r\n scratchSpherical.magnitude = spherical[i + 3];\r\n Cartesian3.fromSpherical(scratchSpherical, scratchCartesian);\r\n\r\n result[i + 1] = scratchCartesian.x;\r\n result[i + 2] = scratchCartesian.y;\r\n result[i + 3] = scratchCartesian.z;\r\n }\r\n return result;\r\n}\r\n\r\nfunction convertCartographicRadiansToCartesian(cartographicRadians) {\r\n var length = cartographicRadians.length;\r\n if (length === 3) {\r\n scratchCartographic.longitude = cartographicRadians[0];\r\n scratchCartographic.latitude = cartographicRadians[1];\r\n scratchCartographic.height = cartographicRadians[2];\r\n Ellipsoid.WGS84.cartographicToCartesian(\r\n scratchCartographic,\r\n scratchCartesian\r\n );\r\n return [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z];\r\n }\r\n\r\n var result = new Array(length);\r\n for (var i = 0; i < length; i += 4) {\r\n result[i] = cartographicRadians[i];\r\n\r\n scratchCartographic.longitude = cartographicRadians[i + 1];\r\n scratchCartographic.latitude = cartographicRadians[i + 2];\r\n scratchCartographic.height = cartographicRadians[i + 3];\r\n Ellipsoid.WGS84.cartographicToCartesian(\r\n scratchCartographic,\r\n scratchCartesian\r\n );\r\n\r\n result[i + 1] = scratchCartesian.x;\r\n result[i + 2] = scratchCartesian.y;\r\n result[i + 3] = scratchCartesian.z;\r\n }\r\n return result;\r\n}\r\n\r\nfunction convertCartographicDegreesToCartesian(cartographicDegrees) {\r\n var length = cartographicDegrees.length;\r\n if (length === 3) {\r\n scratchCartographic.longitude = CesiumMath.toRadians(\r\n cartographicDegrees[0]\r\n );\r\n scratchCartographic.latitude = CesiumMath.toRadians(cartographicDegrees[1]);\r\n scratchCartographic.height = cartographicDegrees[2];\r\n Ellipsoid.WGS84.cartographicToCartesian(\r\n scratchCartographic,\r\n scratchCartesian\r\n );\r\n return [scratchCartesian.x, scratchCartesian.y, scratchCartesian.z];\r\n }\r\n\r\n var result = new Array(length);\r\n for (var i = 0; i < length; i += 4) {\r\n result[i] = cartographicDegrees[i];\r\n\r\n scratchCartographic.longitude = CesiumMath.toRadians(\r\n cartographicDegrees[i + 1]\r\n );\r\n scratchCartographic.latitude = CesiumMath.toRadians(\r\n cartographicDegrees[i + 2]\r\n );\r\n scratchCartographic.height = cartographicDegrees[i + 3];\r\n Ellipsoid.WGS84.cartographicToCartesian(\r\n scratchCartographic,\r\n scratchCartesian\r\n );\r\n\r\n result[i + 1] = scratchCartesian.x;\r\n result[i + 2] = scratchCartesian.y;\r\n result[i + 3] = scratchCartesian.z;\r\n }\r\n return result;\r\n}\r\n\r\nfunction unwrapCartesianInterval(czmlInterval) {\r\n var cartesian = czmlInterval.cartesian;\r\n if (defined(cartesian)) {\r\n return cartesian;\r\n }\r\n\r\n var cartesianVelocity = czmlInterval.cartesianVelocity;\r\n if (defined(cartesianVelocity)) {\r\n return cartesianVelocity;\r\n }\r\n\r\n var unitCartesian = czmlInterval.unitCartesian;\r\n if (defined(unitCartesian)) {\r\n return unitCartesian;\r\n }\r\n\r\n var unitSpherical = czmlInterval.unitSpherical;\r\n if (defined(unitSpherical)) {\r\n return convertUnitSphericalToCartesian(unitSpherical);\r\n }\r\n\r\n var spherical = czmlInterval.spherical;\r\n if (defined(spherical)) {\r\n return convertSphericalToCartesian(spherical);\r\n }\r\n\r\n var cartographicRadians = czmlInterval.cartographicRadians;\r\n if (defined(cartographicRadians)) {\r\n return convertCartographicRadiansToCartesian(cartographicRadians);\r\n }\r\n\r\n var cartographicDegrees = czmlInterval.cartographicDegrees;\r\n if (defined(cartographicDegrees)) {\r\n return convertCartographicDegreesToCartesian(cartographicDegrees);\r\n }\r\n\r\n throw new RuntimeError(\r\n JSON.stringify(czmlInterval) + \" is not a valid CZML interval.\"\r\n );\r\n}\r\n\r\nfunction normalizePackedCartesianArray(array, startingIndex) {\r\n Cartesian3.unpack(array, startingIndex, scratchCartesian);\r\n Cartesian3.normalize(scratchCartesian, scratchCartesian);\r\n Cartesian3.pack(scratchCartesian, array, startingIndex);\r\n}\r\n\r\nfunction unwrapUnitCartesianInterval(czmlInterval) {\r\n var cartesian = unwrapCartesianInterval(czmlInterval);\r\n if (cartesian.length === 3) {\r\n normalizePackedCartesianArray(cartesian, 0);\r\n return cartesian;\r\n }\r\n\r\n for (var i = 1; i < cartesian.length; i += 4) {\r\n normalizePackedCartesianArray(cartesian, i);\r\n }\r\n\r\n return cartesian;\r\n}\r\n\r\nfunction normalizePackedQuaternionArray(array, startingIndex) {\r\n Quaternion.unpack(array, startingIndex, scratchQuaternion);\r\n Quaternion.normalize(scratchQuaternion, scratchQuaternion);\r\n Quaternion.pack(scratchQuaternion, array, startingIndex);\r\n}\r\n\r\nfunction unwrapQuaternionInterval(czmlInterval) {\r\n var unitQuaternion = czmlInterval.unitQuaternion;\r\n if (defined(unitQuaternion)) {\r\n if (unitQuaternion.length === 4) {\r\n normalizePackedQuaternionArray(unitQuaternion, 0);\r\n return unitQuaternion;\r\n }\r\n\r\n for (var i = 1; i < unitQuaternion.length; i += 5) {\r\n normalizePackedQuaternionArray(unitQuaternion, i);\r\n }\r\n }\r\n return unitQuaternion;\r\n}\r\n\r\nfunction getPropertyType(czmlInterval) {\r\n // The associations in this function need to be kept in sync with the\r\n // associations in unwrapInterval.\r\n\r\n // Intentionally omitted due to conficts in CZML property names:\r\n // * Image (conflicts with Uri)\r\n // * Rotation (conflicts with Number)\r\n //\r\n // cartesianVelocity is also omitted due to incomplete support for\r\n // derivative information in CZML properties.\r\n // (Currently cartesianVelocity is hacked directly into the position processing code)\r\n if (typeof czmlInterval === \"boolean\") {\r\n return Boolean;\r\n } else if (typeof czmlInterval === \"number\") {\r\n return Number;\r\n } else if (typeof czmlInterval === \"string\") {\r\n return String;\r\n } else if (czmlInterval.hasOwnProperty(\"array\")) {\r\n return Array;\r\n } else if (czmlInterval.hasOwnProperty(\"boolean\")) {\r\n return Boolean;\r\n } else if (czmlInterval.hasOwnProperty(\"boundingRectangle\")) {\r\n return BoundingRectangle;\r\n } else if (czmlInterval.hasOwnProperty(\"cartesian2\")) {\r\n return Cartesian2;\r\n } else if (\r\n czmlInterval.hasOwnProperty(\"cartesian\") ||\r\n czmlInterval.hasOwnProperty(\"spherical\") ||\r\n czmlInterval.hasOwnProperty(\"cartographicRadians\") ||\r\n czmlInterval.hasOwnProperty(\"cartographicDegrees\")\r\n ) {\r\n return Cartesian3;\r\n } else if (\r\n czmlInterval.hasOwnProperty(\"unitCartesian\") ||\r\n czmlInterval.hasOwnProperty(\"unitSpherical\")\r\n ) {\r\n return UnitCartesian3;\r\n } else if (\r\n czmlInterval.hasOwnProperty(\"rgba\") ||\r\n czmlInterval.hasOwnProperty(\"rgbaf\")\r\n ) {\r\n return Color;\r\n } else if (czmlInterval.hasOwnProperty(\"arcType\")) {\r\n return ArcType;\r\n } else if (czmlInterval.hasOwnProperty(\"classificationType\")) {\r\n return ClassificationType;\r\n } else if (czmlInterval.hasOwnProperty(\"colorBlendMode\")) {\r\n return ColorBlendMode;\r\n } else if (czmlInterval.hasOwnProperty(\"cornerType\")) {\r\n return CornerType;\r\n } else if (czmlInterval.hasOwnProperty(\"heightReference\")) {\r\n return HeightReference;\r\n } else if (czmlInterval.hasOwnProperty(\"horizontalOrigin\")) {\r\n return HorizontalOrigin;\r\n } else if (czmlInterval.hasOwnProperty(\"date\")) {\r\n return JulianDate;\r\n } else if (czmlInterval.hasOwnProperty(\"labelStyle\")) {\r\n return LabelStyle;\r\n } else if (czmlInterval.hasOwnProperty(\"number\")) {\r\n return Number;\r\n } else if (czmlInterval.hasOwnProperty(\"nearFarScalar\")) {\r\n return NearFarScalar;\r\n } else if (czmlInterval.hasOwnProperty(\"distanceDisplayCondition\")) {\r\n return DistanceDisplayCondition;\r\n } else if (\r\n czmlInterval.hasOwnProperty(\"object\") ||\r\n czmlInterval.hasOwnProperty(\"value\")\r\n ) {\r\n return Object;\r\n } else if (czmlInterval.hasOwnProperty(\"unitQuaternion\")) {\r\n return Quaternion;\r\n } else if (czmlInterval.hasOwnProperty(\"shadowMode\")) {\r\n return ShadowMode;\r\n } else if (czmlInterval.hasOwnProperty(\"string\")) {\r\n return String;\r\n } else if (czmlInterval.hasOwnProperty(\"stripeOrientation\")) {\r\n return StripeOrientation;\r\n } else if (\r\n czmlInterval.hasOwnProperty(\"wsen\") ||\r\n czmlInterval.hasOwnProperty(\"wsenDegrees\")\r\n ) {\r\n return Rectangle;\r\n } else if (czmlInterval.hasOwnProperty(\"uri\")) {\r\n return Uri;\r\n } else if (czmlInterval.hasOwnProperty(\"verticalOrigin\")) {\r\n return VerticalOrigin;\r\n }\r\n // fallback case\r\n return Object;\r\n}\r\n\r\nfunction unwrapInterval(type, czmlInterval, sourceUri) {\r\n // The associations in this function need to be kept in sync with the\r\n // associations in getPropertyType\r\n switch (type) {\r\n case ArcType:\r\n return ArcType[defaultValue(czmlInterval.arcType, czmlInterval)];\r\n case Array:\r\n return czmlInterval.array;\r\n case Boolean:\r\n return defaultValue(czmlInterval[\"boolean\"], czmlInterval);\r\n case BoundingRectangle:\r\n return czmlInterval.boundingRectangle;\r\n case Cartesian2:\r\n return czmlInterval.cartesian2;\r\n case Cartesian3:\r\n return unwrapCartesianInterval(czmlInterval);\r\n case UnitCartesian3:\r\n return unwrapUnitCartesianInterval(czmlInterval);\r\n case Color:\r\n return unwrapColorInterval(czmlInterval);\r\n case ClassificationType:\r\n return ClassificationType[\r\n defaultValue(czmlInterval.classificationType, czmlInterval)\r\n ];\r\n case ColorBlendMode:\r\n return ColorBlendMode[\r\n defaultValue(czmlInterval.colorBlendMode, czmlInterval)\r\n ];\r\n case CornerType:\r\n return CornerType[defaultValue(czmlInterval.cornerType, czmlInterval)];\r\n case HeightReference:\r\n return HeightReference[\r\n defaultValue(czmlInterval.heightReference, czmlInterval)\r\n ];\r\n case HorizontalOrigin:\r\n return HorizontalOrigin[\r\n defaultValue(czmlInterval.horizontalOrigin, czmlInterval)\r\n ];\r\n case Image:\r\n return unwrapUriInterval(czmlInterval, sourceUri);\r\n case JulianDate:\r\n return JulianDate.fromIso8601(\r\n defaultValue(czmlInterval.date, czmlInterval)\r\n );\r\n case LabelStyle:\r\n return LabelStyle[defaultValue(czmlInterval.labelStyle, czmlInterval)];\r\n case Number:\r\n return defaultValue(czmlInterval.number, czmlInterval);\r\n case NearFarScalar:\r\n return czmlInterval.nearFarScalar;\r\n case DistanceDisplayCondition:\r\n return czmlInterval.distanceDisplayCondition;\r\n case Object:\r\n return defaultValue(\r\n defaultValue(czmlInterval.object, czmlInterval.value),\r\n czmlInterval\r\n );\r\n case Quaternion:\r\n return unwrapQuaternionInterval(czmlInterval);\r\n case Rotation:\r\n return defaultValue(czmlInterval.number, czmlInterval);\r\n case ShadowMode:\r\n return ShadowMode[\r\n defaultValue(\r\n defaultValue(czmlInterval.shadowMode, czmlInterval.shadows),\r\n czmlInterval\r\n )\r\n ];\r\n case String:\r\n return defaultValue(czmlInterval.string, czmlInterval);\r\n case StripeOrientation:\r\n return StripeOrientation[\r\n defaultValue(czmlInterval.stripeOrientation, czmlInterval)\r\n ];\r\n case Rectangle:\r\n return unwrapRectangleInterval(czmlInterval);\r\n case Uri:\r\n return unwrapUriInterval(czmlInterval, sourceUri);\r\n case VerticalOrigin:\r\n return VerticalOrigin[\r\n defaultValue(czmlInterval.verticalOrigin, czmlInterval)\r\n ];\r\n default:\r\n throw new RuntimeError(type);\r\n }\r\n}\r\n\r\nvar interpolators = {\r\n HERMITE: HermitePolynomialApproximation,\r\n LAGRANGE: LagrangePolynomialApproximation,\r\n LINEAR: LinearApproximation,\r\n};\r\n\r\nfunction updateInterpolationSettings(packetData, property) {\r\n var interpolationAlgorithm = packetData.interpolationAlgorithm;\r\n var interpolationDegree = packetData.interpolationDegree;\r\n if (defined(interpolationAlgorithm) || defined(interpolationDegree)) {\r\n property.setInterpolationOptions({\r\n interpolationAlgorithm: interpolators[interpolationAlgorithm],\r\n interpolationDegree: interpolationDegree,\r\n });\r\n }\r\n\r\n var forwardExtrapolationType = packetData.forwardExtrapolationType;\r\n if (defined(forwardExtrapolationType)) {\r\n property.forwardExtrapolationType =\r\n ExtrapolationType[forwardExtrapolationType];\r\n }\r\n\r\n var forwardExtrapolationDuration = packetData.forwardExtrapolationDuration;\r\n if (defined(forwardExtrapolationDuration)) {\r\n property.forwardExtrapolationDuration = forwardExtrapolationDuration;\r\n }\r\n\r\n var backwardExtrapolationType = packetData.backwardExtrapolationType;\r\n if (defined(backwardExtrapolationType)) {\r\n property.backwardExtrapolationType =\r\n ExtrapolationType[backwardExtrapolationType];\r\n }\r\n\r\n var backwardExtrapolationDuration = packetData.backwardExtrapolationDuration;\r\n if (defined(backwardExtrapolationDuration)) {\r\n property.backwardExtrapolationDuration = backwardExtrapolationDuration;\r\n }\r\n}\r\n\r\nvar iso8601Scratch = {\r\n iso8601: undefined,\r\n};\r\n\r\nfunction intervalFromString(intervalString) {\r\n if (!defined(intervalString)) {\r\n return undefined;\r\n }\r\n iso8601Scratch.iso8601 = intervalString;\r\n return TimeInterval.fromIso8601(iso8601Scratch);\r\n}\r\n\r\nfunction wrapPropertyInInfiniteInterval(property) {\r\n var interval = Iso8601.MAXIMUM_INTERVAL.clone();\r\n interval.data = property;\r\n return interval;\r\n}\r\n\r\nfunction convertPropertyToComposite(property) {\r\n // Create the composite and add the old property, wrapped in an infinite interval.\r\n var composite = new CompositeProperty();\r\n composite.intervals.addInterval(wrapPropertyInInfiniteInterval(property));\r\n return composite;\r\n}\r\n\r\nfunction convertPositionPropertyToComposite(property) {\r\n // Create the composite and add the old property, wrapped in an infinite interval.\r\n var composite = new CompositePositionProperty(property.referenceFrame);\r\n composite.intervals.addInterval(wrapPropertyInInfiniteInterval(property));\r\n return composite;\r\n}\r\n\r\nfunction processProperty(\r\n type,\r\n object,\r\n propertyName,\r\n packetData,\r\n constrainedInterval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n var combinedInterval = intervalFromString(packetData.interval);\r\n if (defined(constrainedInterval)) {\r\n if (defined(combinedInterval)) {\r\n combinedInterval = TimeInterval.intersect(\r\n combinedInterval,\r\n constrainedInterval,\r\n scratchTimeInterval\r\n );\r\n } else {\r\n combinedInterval = constrainedInterval;\r\n }\r\n }\r\n\r\n var packedLength;\r\n var unwrappedInterval;\r\n var unwrappedIntervalLength;\r\n\r\n // CZML properties can be defined in many ways. Most ways represent a structure for\r\n // encoding a single value (number, string, cartesian, etc.) Regardless of the value type,\r\n // if it encodes a single value it will get loaded into a ConstantProperty eventually.\r\n // Alternatively, there are ways of defining a property that require specialized\r\n // client-side representation. Currently, these are ReferenceProperty,\r\n // and client-side velocity computation properties such as VelocityVectorProperty.\r\n var isValue =\r\n !defined(packetData.reference) && !defined(packetData.velocityReference);\r\n var hasInterval =\r\n defined(combinedInterval) &&\r\n !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL);\r\n\r\n if (packetData.delete === true) {\r\n // If deleting this property for all time, we can simply set to undefined and return.\r\n if (!hasInterval) {\r\n object[propertyName] = undefined;\r\n return;\r\n }\r\n\r\n // Deleting depends on the type of property we have.\r\n return removePropertyData(object[propertyName], combinedInterval);\r\n }\r\n\r\n var isSampled = false;\r\n\r\n if (isValue) {\r\n unwrappedInterval = unwrapInterval(type, packetData, sourceUri);\r\n if (!defined(unwrappedInterval)) {\r\n // not a known value type, bail\r\n return;\r\n }\r\n packedLength = defaultValue(type.packedLength, 1);\r\n unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1);\r\n isSampled =\r\n !defined(packetData.array) &&\r\n typeof unwrappedInterval !== \"string\" &&\r\n unwrappedIntervalLength > packedLength &&\r\n type !== Object;\r\n }\r\n\r\n // Rotation is a special case because it represents a native type (Number)\r\n // and therefore does not need to be unpacked when loaded as a constant value.\r\n var needsUnpacking = typeof type.unpack === \"function\" && type !== Rotation;\r\n\r\n // Any time a constant value is assigned, it completely blows away anything else.\r\n if (!isSampled && !hasInterval) {\r\n if (isValue) {\r\n object[propertyName] = new ConstantProperty(\r\n needsUnpacking ? type.unpack(unwrappedInterval, 0) : unwrappedInterval\r\n );\r\n } else {\r\n object[propertyName] = createSpecializedProperty(\r\n type,\r\n entityCollection,\r\n packetData\r\n );\r\n }\r\n return;\r\n }\r\n\r\n var property = object[propertyName];\r\n\r\n var epoch;\r\n var packetEpoch = packetData.epoch;\r\n if (defined(packetEpoch)) {\r\n epoch = JulianDate.fromIso8601(packetEpoch);\r\n }\r\n\r\n // Without an interval, any sampled value is infinite, meaning it completely\r\n // replaces any non-sampled property that may exist.\r\n if (isSampled && !hasInterval) {\r\n if (!(property instanceof SampledProperty)) {\r\n object[propertyName] = property = new SampledProperty(type);\r\n }\r\n property.addSamplesPackedArray(unwrappedInterval, epoch);\r\n updateInterpolationSettings(packetData, property);\r\n return;\r\n }\r\n\r\n var interval;\r\n\r\n // A constant value with an interval is normally part of a TimeIntervalCollection,\r\n // However, if the current property is not a time-interval collection, we need\r\n // to turn it into a Composite, preserving the old data with the new interval.\r\n if (!isSampled && hasInterval) {\r\n // Create a new interval for the constant value.\r\n combinedInterval = combinedInterval.clone();\r\n if (isValue) {\r\n combinedInterval.data = needsUnpacking\r\n ? type.unpack(unwrappedInterval, 0)\r\n : unwrappedInterval;\r\n } else {\r\n combinedInterval.data = createSpecializedProperty(\r\n type,\r\n entityCollection,\r\n packetData\r\n );\r\n }\r\n\r\n // If no property exists, simply use a new interval collection\r\n if (!defined(property)) {\r\n object[propertyName] = property = isValue\r\n ? new TimeIntervalCollectionProperty()\r\n : new CompositeProperty();\r\n }\r\n\r\n if (isValue && property instanceof TimeIntervalCollectionProperty) {\r\n // If we created a collection, or it already was one, use it.\r\n property.intervals.addInterval(combinedInterval);\r\n } else if (property instanceof CompositeProperty) {\r\n // If the collection was already a CompositeProperty, use it.\r\n if (isValue) {\r\n combinedInterval.data = new ConstantProperty(combinedInterval.data);\r\n }\r\n property.intervals.addInterval(combinedInterval);\r\n } else {\r\n // Otherwise, create a CompositeProperty but preserve the existing data.\r\n object[propertyName] = property = convertPropertyToComposite(property);\r\n\r\n // Change the new data to a ConstantProperty and add it.\r\n if (isValue) {\r\n combinedInterval.data = new ConstantProperty(combinedInterval.data);\r\n }\r\n property.intervals.addInterval(combinedInterval);\r\n }\r\n\r\n return;\r\n }\r\n\r\n // isSampled && hasInterval\r\n if (!defined(property)) {\r\n object[propertyName] = property = new CompositeProperty();\r\n }\r\n\r\n // Create a CompositeProperty but preserve the existing data.\r\n if (!(property instanceof CompositeProperty)) {\r\n object[propertyName] = property = convertPropertyToComposite(property);\r\n }\r\n\r\n // Check if the interval already exists in the composite.\r\n var intervals = property.intervals;\r\n interval = intervals.findInterval(combinedInterval);\r\n if (!defined(interval) || !(interval.data instanceof SampledProperty)) {\r\n // If not, create a SampledProperty for it.\r\n interval = combinedInterval.clone();\r\n interval.data = new SampledProperty(type);\r\n intervals.addInterval(interval);\r\n }\r\n interval.data.addSamplesPackedArray(unwrappedInterval, epoch);\r\n updateInterpolationSettings(packetData, interval.data);\r\n}\r\n\r\nfunction removePropertyData(property, interval) {\r\n if (property instanceof SampledProperty) {\r\n property.removeSamples(interval);\r\n return;\r\n } else if (property instanceof TimeIntervalCollectionProperty) {\r\n property.intervals.removeInterval(interval);\r\n return;\r\n } else if (property instanceof CompositeProperty) {\r\n var intervals = property.intervals;\r\n for (var i = 0; i < intervals.length; ++i) {\r\n var intersection = TimeInterval.intersect(\r\n intervals.get(i),\r\n interval,\r\n scratchTimeInterval\r\n );\r\n if (!intersection.isEmpty) {\r\n // remove data from the contained properties\r\n removePropertyData(intersection.data, interval);\r\n }\r\n }\r\n // remove the intervals from the composite\r\n intervals.removeInterval(interval);\r\n return;\r\n }\r\n}\r\n\r\nfunction processPacketData(\r\n type,\r\n object,\r\n propertyName,\r\n packetData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n if (Array.isArray(packetData)) {\r\n for (var i = 0, len = packetData.length; i < len; ++i) {\r\n processProperty(\r\n type,\r\n object,\r\n propertyName,\r\n packetData[i],\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processProperty(\r\n type,\r\n object,\r\n propertyName,\r\n packetData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processPositionProperty(\r\n object,\r\n propertyName,\r\n packetData,\r\n constrainedInterval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n var combinedInterval = intervalFromString(packetData.interval);\r\n if (defined(constrainedInterval)) {\r\n if (defined(combinedInterval)) {\r\n combinedInterval = TimeInterval.intersect(\r\n combinedInterval,\r\n constrainedInterval,\r\n scratchTimeInterval\r\n );\r\n } else {\r\n combinedInterval = constrainedInterval;\r\n }\r\n }\r\n\r\n var numberOfDerivatives = defined(packetData.cartesianVelocity) ? 1 : 0;\r\n var packedLength = Cartesian3.packedLength * (numberOfDerivatives + 1);\r\n var unwrappedInterval;\r\n var unwrappedIntervalLength;\r\n var isValue = !defined(packetData.reference);\r\n var hasInterval =\r\n defined(combinedInterval) &&\r\n !combinedInterval.equals(Iso8601.MAXIMUM_INTERVAL);\r\n\r\n if (packetData.delete === true) {\r\n // If deleting this property for all time, we can simply set to undefined and return.\r\n if (!hasInterval) {\r\n object[propertyName] = undefined;\r\n return;\r\n }\r\n\r\n // Deleting depends on the type of property we have.\r\n return removePositionPropertyData(object[propertyName], combinedInterval);\r\n }\r\n\r\n var referenceFrame;\r\n var isSampled = false;\r\n\r\n if (isValue) {\r\n if (defined(packetData.referenceFrame)) {\r\n referenceFrame = ReferenceFrame[packetData.referenceFrame];\r\n }\r\n referenceFrame = defaultValue(referenceFrame, ReferenceFrame.FIXED);\r\n unwrappedInterval = unwrapCartesianInterval(packetData);\r\n unwrappedIntervalLength = defaultValue(unwrappedInterval.length, 1);\r\n isSampled = unwrappedIntervalLength > packedLength;\r\n }\r\n\r\n // Any time a constant value is assigned, it completely blows away anything else.\r\n if (!isSampled && !hasInterval) {\r\n if (isValue) {\r\n object[propertyName] = new ConstantPositionProperty(\r\n Cartesian3.unpack(unwrappedInterval),\r\n referenceFrame\r\n );\r\n } else {\r\n object[propertyName] = createReferenceProperty(\r\n entityCollection,\r\n packetData.reference\r\n );\r\n }\r\n return;\r\n }\r\n\r\n var property = object[propertyName];\r\n\r\n var epoch;\r\n var packetEpoch = packetData.epoch;\r\n if (defined(packetEpoch)) {\r\n epoch = JulianDate.fromIso8601(packetEpoch);\r\n }\r\n\r\n // Without an interval, any sampled value is infinite, meaning it completely\r\n // replaces any non-sampled property that may exist.\r\n if (isSampled && !hasInterval) {\r\n if (\r\n !(property instanceof SampledPositionProperty) ||\r\n (defined(referenceFrame) && property.referenceFrame !== referenceFrame)\r\n ) {\r\n object[propertyName] = property = new SampledPositionProperty(\r\n referenceFrame,\r\n numberOfDerivatives\r\n );\r\n }\r\n property.addSamplesPackedArray(unwrappedInterval, epoch);\r\n updateInterpolationSettings(packetData, property);\r\n return;\r\n }\r\n\r\n var interval;\r\n\r\n // A constant value with an interval is normally part of a TimeIntervalCollection,\r\n // However, if the current property is not a time-interval collection, we need\r\n // to turn it into a Composite, preserving the old data with the new interval.\r\n if (!isSampled && hasInterval) {\r\n // Create a new interval for the constant value.\r\n combinedInterval = combinedInterval.clone();\r\n if (isValue) {\r\n combinedInterval.data = Cartesian3.unpack(unwrappedInterval);\r\n } else {\r\n combinedInterval.data = createReferenceProperty(\r\n entityCollection,\r\n packetData.reference\r\n );\r\n }\r\n\r\n // If no property exists, simply use a new interval collection\r\n if (!defined(property)) {\r\n if (isValue) {\r\n property = new TimeIntervalCollectionPositionProperty(referenceFrame);\r\n } else {\r\n property = new CompositePositionProperty(referenceFrame);\r\n }\r\n object[propertyName] = property;\r\n }\r\n\r\n if (\r\n isValue &&\r\n property instanceof TimeIntervalCollectionPositionProperty &&\r\n defined(referenceFrame) &&\r\n property.referenceFrame === referenceFrame\r\n ) {\r\n // If we create a collection, or it already existed, use it.\r\n property.intervals.addInterval(combinedInterval);\r\n } else if (property instanceof CompositePositionProperty) {\r\n // If the collection was already a CompositePositionProperty, use it.\r\n if (isValue) {\r\n combinedInterval.data = new ConstantPositionProperty(\r\n combinedInterval.data,\r\n referenceFrame\r\n );\r\n }\r\n property.intervals.addInterval(combinedInterval);\r\n } else {\r\n // Otherwise, create a CompositePositionProperty but preserve the existing data.\r\n object[propertyName] = property = convertPositionPropertyToComposite(\r\n property\r\n );\r\n\r\n // Change the new data to a ConstantPositionProperty and add it.\r\n if (isValue) {\r\n combinedInterval.data = new ConstantPositionProperty(\r\n combinedInterval.data,\r\n referenceFrame\r\n );\r\n }\r\n property.intervals.addInterval(combinedInterval);\r\n }\r\n\r\n return;\r\n }\r\n\r\n // isSampled && hasInterval\r\n if (!defined(property)) {\r\n object[propertyName] = property = new CompositePositionProperty(\r\n referenceFrame\r\n );\r\n } else if (!(property instanceof CompositePositionProperty)) {\r\n // Create a CompositeProperty but preserve the existing data.\r\n object[propertyName] = property = convertPositionPropertyToComposite(\r\n property\r\n );\r\n }\r\n\r\n // Check if the interval already exists in the composite.\r\n var intervals = property.intervals;\r\n interval = intervals.findInterval(combinedInterval);\r\n if (\r\n !defined(interval) ||\r\n !(interval.data instanceof SampledPositionProperty) ||\r\n (defined(referenceFrame) && interval.data.referenceFrame !== referenceFrame)\r\n ) {\r\n // If not, create a SampledPositionProperty for it.\r\n interval = combinedInterval.clone();\r\n interval.data = new SampledPositionProperty(\r\n referenceFrame,\r\n numberOfDerivatives\r\n );\r\n intervals.addInterval(interval);\r\n }\r\n interval.data.addSamplesPackedArray(unwrappedInterval, epoch);\r\n updateInterpolationSettings(packetData, interval.data);\r\n}\r\n\r\nfunction removePositionPropertyData(property, interval) {\r\n if (property instanceof SampledPositionProperty) {\r\n property.removeSamples(interval);\r\n return;\r\n } else if (property instanceof TimeIntervalCollectionPositionProperty) {\r\n property.intervals.removeInterval(interval);\r\n return;\r\n } else if (property instanceof CompositePositionProperty) {\r\n var intervals = property.intervals;\r\n for (var i = 0; i < intervals.length; ++i) {\r\n var intersection = TimeInterval.intersect(\r\n intervals.get(i),\r\n interval,\r\n scratchTimeInterval\r\n );\r\n if (!intersection.isEmpty) {\r\n // remove data from the contained properties\r\n removePositionPropertyData(intersection.data, interval);\r\n }\r\n }\r\n // remove the intervals from the composite\r\n intervals.removeInterval(interval);\r\n return;\r\n }\r\n}\r\n\r\nfunction processPositionPacketData(\r\n object,\r\n propertyName,\r\n packetData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n if (Array.isArray(packetData)) {\r\n for (var i = 0, len = packetData.length; i < len; ++i) {\r\n processPositionProperty(\r\n object,\r\n propertyName,\r\n packetData[i],\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processPositionProperty(\r\n object,\r\n propertyName,\r\n packetData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processShapePacketData(\r\n object,\r\n propertyName,\r\n packetData,\r\n entityCollection\r\n) {\r\n if (defined(packetData.references)) {\r\n processReferencesArrayPacketData(\r\n object,\r\n propertyName,\r\n packetData.references,\r\n packetData.interval,\r\n entityCollection,\r\n PropertyArray,\r\n CompositeProperty\r\n );\r\n } else {\r\n if (defined(packetData.cartesian2)) {\r\n packetData.array = Cartesian2.unpackArray(packetData.cartesian2);\r\n } else if (defined(packetData.cartesian)) {\r\n // for backwards compatibility, also accept `cartesian`\r\n packetData.array = Cartesian2.unpackArray(packetData.cartesian);\r\n }\r\n\r\n if (defined(packetData.array)) {\r\n processPacketData(\r\n Array,\r\n object,\r\n propertyName,\r\n packetData,\r\n undefined,\r\n undefined,\r\n entityCollection\r\n );\r\n }\r\n }\r\n}\r\n\r\nfunction processMaterialProperty(\r\n object,\r\n propertyName,\r\n packetData,\r\n constrainedInterval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n var combinedInterval = intervalFromString(packetData.interval);\r\n if (defined(constrainedInterval)) {\r\n if (defined(combinedInterval)) {\r\n combinedInterval = TimeInterval.intersect(\r\n combinedInterval,\r\n constrainedInterval,\r\n scratchTimeInterval\r\n );\r\n } else {\r\n combinedInterval = constrainedInterval;\r\n }\r\n }\r\n\r\n var property = object[propertyName];\r\n var existingMaterial;\r\n var existingInterval;\r\n\r\n if (defined(combinedInterval)) {\r\n if (!(property instanceof CompositeMaterialProperty)) {\r\n property = new CompositeMaterialProperty();\r\n object[propertyName] = property;\r\n }\r\n //See if we already have data at that interval.\r\n var thisIntervals = property.intervals;\r\n existingInterval = thisIntervals.findInterval({\r\n start: combinedInterval.start,\r\n stop: combinedInterval.stop,\r\n });\r\n if (defined(existingInterval)) {\r\n //We have an interval, but we need to make sure the\r\n //new data is the same type of material as the old data.\r\n existingMaterial = existingInterval.data;\r\n } else {\r\n //If not, create it.\r\n existingInterval = combinedInterval.clone();\r\n thisIntervals.addInterval(existingInterval);\r\n }\r\n } else {\r\n existingMaterial = property;\r\n }\r\n\r\n var materialData;\r\n if (defined(packetData.solidColor)) {\r\n if (!(existingMaterial instanceof ColorMaterialProperty)) {\r\n existingMaterial = new ColorMaterialProperty();\r\n }\r\n materialData = packetData.solidColor;\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"color\",\r\n materialData.color,\r\n undefined,\r\n undefined,\r\n entityCollection\r\n );\r\n } else if (defined(packetData.grid)) {\r\n if (!(existingMaterial instanceof GridMaterialProperty)) {\r\n existingMaterial = new GridMaterialProperty();\r\n }\r\n materialData = packetData.grid;\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"color\",\r\n materialData.color,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n existingMaterial,\r\n \"cellAlpha\",\r\n materialData.cellAlpha,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian2,\r\n existingMaterial,\r\n \"lineCount\",\r\n materialData.lineCount,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian2,\r\n existingMaterial,\r\n \"lineThickness\",\r\n materialData.lineThickness,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian2,\r\n existingMaterial,\r\n \"lineOffset\",\r\n materialData.lineOffset,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n } else if (defined(packetData.image)) {\r\n if (!(existingMaterial instanceof ImageMaterialProperty)) {\r\n existingMaterial = new ImageMaterialProperty();\r\n }\r\n materialData = packetData.image;\r\n processPacketData(\r\n Image,\r\n existingMaterial,\r\n \"image\",\r\n materialData.image,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian2,\r\n existingMaterial,\r\n \"repeat\",\r\n materialData.repeat,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"color\",\r\n materialData.color,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n existingMaterial,\r\n \"transparent\",\r\n materialData.transparent,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n } else if (defined(packetData.stripe)) {\r\n if (!(existingMaterial instanceof StripeMaterialProperty)) {\r\n existingMaterial = new StripeMaterialProperty();\r\n }\r\n materialData = packetData.stripe;\r\n processPacketData(\r\n StripeOrientation,\r\n existingMaterial,\r\n \"orientation\",\r\n materialData.orientation,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"evenColor\",\r\n materialData.evenColor,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"oddColor\",\r\n materialData.oddColor,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n existingMaterial,\r\n \"offset\",\r\n materialData.offset,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n existingMaterial,\r\n \"repeat\",\r\n materialData.repeat,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n } else if (defined(packetData.polylineOutline)) {\r\n if (!(existingMaterial instanceof PolylineOutlineMaterialProperty)) {\r\n existingMaterial = new PolylineOutlineMaterialProperty();\r\n }\r\n materialData = packetData.polylineOutline;\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"color\",\r\n materialData.color,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"outlineColor\",\r\n materialData.outlineColor,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n existingMaterial,\r\n \"outlineWidth\",\r\n materialData.outlineWidth,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n } else if (defined(packetData.polylineGlow)) {\r\n if (!(existingMaterial instanceof PolylineGlowMaterialProperty)) {\r\n existingMaterial = new PolylineGlowMaterialProperty();\r\n }\r\n materialData = packetData.polylineGlow;\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"color\",\r\n materialData.color,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n existingMaterial,\r\n \"glowPower\",\r\n materialData.glowPower,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n existingMaterial,\r\n \"taperPower\",\r\n materialData.taperPower,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n } else if (defined(packetData.polylineArrow)) {\r\n if (!(existingMaterial instanceof PolylineArrowMaterialProperty)) {\r\n existingMaterial = new PolylineArrowMaterialProperty();\r\n }\r\n materialData = packetData.polylineArrow;\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"color\",\r\n materialData.color,\r\n undefined,\r\n undefined,\r\n entityCollection\r\n );\r\n } else if (defined(packetData.polylineDash)) {\r\n if (!(existingMaterial instanceof PolylineDashMaterialProperty)) {\r\n existingMaterial = new PolylineDashMaterialProperty();\r\n }\r\n materialData = packetData.polylineDash;\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"color\",\r\n materialData.color,\r\n undefined,\r\n undefined,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"gapColor\",\r\n materialData.gapColor,\r\n undefined,\r\n undefined,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n existingMaterial,\r\n \"dashLength\",\r\n materialData.dashLength,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n existingMaterial,\r\n \"dashPattern\",\r\n materialData.dashPattern,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n } else if (defined(packetData.checkerboard)) {\r\n if (!(existingMaterial instanceof CheckerboardMaterialProperty)) {\r\n existingMaterial = new CheckerboardMaterialProperty();\r\n }\r\n materialData = packetData.checkerboard;\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"evenColor\",\r\n materialData.evenColor,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n existingMaterial,\r\n \"oddColor\",\r\n materialData.oddColor,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian2,\r\n existingMaterial,\r\n \"repeat\",\r\n materialData.repeat,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n\r\n if (defined(existingInterval)) {\r\n existingInterval.data = existingMaterial;\r\n } else {\r\n object[propertyName] = existingMaterial;\r\n }\r\n}\r\n\r\nfunction processMaterialPacketData(\r\n object,\r\n propertyName,\r\n packetData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n if (Array.isArray(packetData)) {\r\n for (var i = 0, len = packetData.length; i < len; ++i) {\r\n processMaterialProperty(\r\n object,\r\n propertyName,\r\n packetData[i],\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processMaterialProperty(\r\n object,\r\n propertyName,\r\n packetData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processName(entity, packet, entityCollection, sourceUri) {\r\n var nameData = packet.name;\r\n if (defined(nameData)) {\r\n entity.name = packet.name;\r\n }\r\n}\r\n\r\nfunction processDescription(entity, packet, entityCollection, sourceUri) {\r\n var descriptionData = packet.description;\r\n if (defined(descriptionData)) {\r\n processPacketData(\r\n String,\r\n entity,\r\n \"description\",\r\n descriptionData,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processPosition(entity, packet, entityCollection, sourceUri) {\r\n var positionData = packet.position;\r\n if (defined(positionData)) {\r\n processPositionPacketData(\r\n entity,\r\n \"position\",\r\n positionData,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processViewFrom(entity, packet, entityCollection, sourceUri) {\r\n var viewFromData = packet.viewFrom;\r\n if (defined(viewFromData)) {\r\n processPacketData(\r\n Cartesian3,\r\n entity,\r\n \"viewFrom\",\r\n viewFromData,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processOrientation(entity, packet, entityCollection, sourceUri) {\r\n var orientationData = packet.orientation;\r\n if (defined(orientationData)) {\r\n processPacketData(\r\n Quaternion,\r\n entity,\r\n \"orientation\",\r\n orientationData,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processProperties(entity, packet, entityCollection, sourceUri) {\r\n var propertiesData = packet.properties;\r\n if (defined(propertiesData)) {\r\n if (!defined(entity.properties)) {\r\n entity.properties = new PropertyBag();\r\n }\r\n\r\n // We cannot simply call processPacketData(entity, 'properties', propertyData, undefined, sourceUri, entityCollection)\r\n // because each property of \"properties\" may vary separately.\r\n // The properties will be accessible as entity.properties.myprop.getValue(time).\r\n\r\n for (var key in propertiesData) {\r\n if (propertiesData.hasOwnProperty(key)) {\r\n if (!entity.properties.hasProperty(key)) {\r\n entity.properties.addProperty(key);\r\n }\r\n\r\n var propertyData = propertiesData[key];\r\n if (Array.isArray(propertyData)) {\r\n for (var i = 0, len = propertyData.length; i < len; ++i) {\r\n processProperty(\r\n getPropertyType(propertyData[i]),\r\n entity.properties,\r\n key,\r\n propertyData[i],\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processProperty(\r\n getPropertyType(propertyData),\r\n entity.properties,\r\n key,\r\n propertyData,\r\n undefined,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nfunction processReferencesArrayPacketData(\r\n object,\r\n propertyName,\r\n references,\r\n interval,\r\n entityCollection,\r\n PropertyArrayType,\r\n CompositePropertyArrayType\r\n) {\r\n var properties = references.map(function (reference) {\r\n return createReferenceProperty(entityCollection, reference);\r\n });\r\n\r\n if (defined(interval)) {\r\n interval = intervalFromString(interval);\r\n var property = object[propertyName];\r\n if (!(property instanceof CompositePropertyArrayType)) {\r\n // If the property was not already a CompositeProperty,\r\n // create a CompositeProperty but preserve the existing data.\r\n\r\n // Create the composite and add the old property, wrapped in an infinite interval.\r\n var composite = new CompositePropertyArrayType();\r\n composite.intervals.addInterval(wrapPropertyInInfiniteInterval(property));\r\n\r\n object[propertyName] = property = composite;\r\n }\r\n\r\n interval.data = new PropertyArrayType(properties);\r\n property.intervals.addInterval(interval);\r\n } else {\r\n object[propertyName] = new PropertyArrayType(properties);\r\n }\r\n}\r\n\r\nfunction processArrayPacketData(\r\n object,\r\n propertyName,\r\n packetData,\r\n entityCollection\r\n) {\r\n var references = packetData.references;\r\n if (defined(references)) {\r\n processReferencesArrayPacketData(\r\n object,\r\n propertyName,\r\n references,\r\n packetData.interval,\r\n entityCollection,\r\n PropertyArray,\r\n CompositeProperty\r\n );\r\n } else {\r\n processPacketData(\r\n Array,\r\n object,\r\n propertyName,\r\n packetData,\r\n undefined,\r\n undefined,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processArray(object, propertyName, packetData, entityCollection) {\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n if (Array.isArray(packetData)) {\r\n for (var i = 0, length = packetData.length; i < length; ++i) {\r\n processArrayPacketData(\r\n object,\r\n propertyName,\r\n packetData[i],\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processArrayPacketData(object, propertyName, packetData, entityCollection);\r\n }\r\n}\r\n\r\nfunction processPositionArrayPacketData(\r\n object,\r\n propertyName,\r\n packetData,\r\n entityCollection\r\n) {\r\n var references = packetData.references;\r\n if (defined(references)) {\r\n processReferencesArrayPacketData(\r\n object,\r\n propertyName,\r\n references,\r\n packetData.interval,\r\n entityCollection,\r\n PositionPropertyArray,\r\n CompositePositionProperty\r\n );\r\n } else {\r\n if (defined(packetData.cartesian)) {\r\n packetData.array = Cartesian3.unpackArray(packetData.cartesian);\r\n } else if (defined(packetData.cartographicRadians)) {\r\n packetData.array = Cartesian3.fromRadiansArrayHeights(\r\n packetData.cartographicRadians\r\n );\r\n } else if (defined(packetData.cartographicDegrees)) {\r\n packetData.array = Cartesian3.fromDegreesArrayHeights(\r\n packetData.cartographicDegrees\r\n );\r\n }\r\n\r\n if (defined(packetData.array)) {\r\n processPacketData(\r\n Array,\r\n object,\r\n propertyName,\r\n packetData,\r\n undefined,\r\n undefined,\r\n entityCollection\r\n );\r\n }\r\n }\r\n}\r\n\r\nfunction processPositionArray(\r\n object,\r\n propertyName,\r\n packetData,\r\n entityCollection\r\n) {\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n if (Array.isArray(packetData)) {\r\n for (var i = 0, length = packetData.length; i < length; ++i) {\r\n processPositionArrayPacketData(\r\n object,\r\n propertyName,\r\n packetData[i],\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processPositionArrayPacketData(\r\n object,\r\n propertyName,\r\n packetData,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction unpackCartesianArray(array) {\r\n return Cartesian3.unpackArray(array);\r\n}\r\n\r\nfunction unpackCartographicRadiansArray(array) {\r\n return Cartesian3.fromRadiansArrayHeights(array);\r\n}\r\n\r\nfunction unpackCartographicDegreesArray(array) {\r\n return Cartesian3.fromDegreesArrayHeights(array);\r\n}\r\n\r\nfunction processPositionArrayOfArraysPacketData(\r\n object,\r\n propertyName,\r\n packetData,\r\n entityCollection\r\n) {\r\n var references = packetData.references;\r\n if (defined(references)) {\r\n var properties = references.map(function (referenceArray) {\r\n var tempObj = {};\r\n processReferencesArrayPacketData(\r\n tempObj,\r\n \"positions\",\r\n referenceArray,\r\n packetData.interval,\r\n entityCollection,\r\n PositionPropertyArray,\r\n CompositePositionProperty\r\n );\r\n return tempObj.positions;\r\n });\r\n object[propertyName] = new PositionPropertyArray(properties);\r\n } else {\r\n if (defined(packetData.cartesian)) {\r\n packetData.array = packetData.cartesian.map(unpackCartesianArray);\r\n } else if (defined(packetData.cartographicRadians)) {\r\n packetData.array = packetData.cartographicRadians.map(\r\n unpackCartographicRadiansArray\r\n );\r\n } else if (defined(packetData.cartographicDegrees)) {\r\n packetData.array = packetData.cartographicDegrees.map(\r\n unpackCartographicDegreesArray\r\n );\r\n }\r\n\r\n if (defined(packetData.array)) {\r\n processPacketData(\r\n Array,\r\n object,\r\n propertyName,\r\n packetData,\r\n undefined,\r\n undefined,\r\n entityCollection\r\n );\r\n }\r\n }\r\n}\r\n\r\nfunction processPositionArrayOfArrays(\r\n object,\r\n propertyName,\r\n packetData,\r\n entityCollection\r\n) {\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n if (Array.isArray(packetData)) {\r\n for (var i = 0, length = packetData.length; i < length; ++i) {\r\n processPositionArrayOfArraysPacketData(\r\n object,\r\n propertyName,\r\n packetData[i],\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processPositionArrayOfArraysPacketData(\r\n object,\r\n propertyName,\r\n packetData,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processShape(object, propertyName, packetData, entityCollection) {\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n if (Array.isArray(packetData)) {\r\n for (var i = 0, length = packetData.length; i < length; i++) {\r\n processShapePacketData(\r\n object,\r\n propertyName,\r\n packetData[i],\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processShapePacketData(object, propertyName, packetData, entityCollection);\r\n }\r\n}\r\n\r\nfunction processAvailability(entity, packet, entityCollection, sourceUri) {\r\n var packetData = packet.availability;\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n var intervals;\r\n if (Array.isArray(packetData)) {\r\n for (var i = 0, len = packetData.length; i < len; ++i) {\r\n if (!defined(intervals)) {\r\n intervals = new TimeIntervalCollection();\r\n }\r\n intervals.addInterval(intervalFromString(packetData[i]));\r\n }\r\n } else {\r\n intervals = new TimeIntervalCollection();\r\n intervals.addInterval(intervalFromString(packetData));\r\n }\r\n entity.availability = intervals;\r\n}\r\n\r\nfunction processAlignedAxis(\r\n billboard,\r\n packetData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n if (!defined(packetData)) {\r\n return;\r\n }\r\n\r\n processPacketData(\r\n UnitCartesian3,\r\n billboard,\r\n \"alignedAxis\",\r\n packetData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processBillboard(entity, packet, entityCollection, sourceUri) {\r\n var billboardData = packet.billboard;\r\n if (!defined(billboardData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(billboardData.interval);\r\n var billboard = entity.billboard;\r\n if (!defined(billboard)) {\r\n entity.billboard = billboard = new BillboardGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n billboard,\r\n \"show\",\r\n billboardData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Image,\r\n billboard,\r\n \"image\",\r\n billboardData.image,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n billboard,\r\n \"scale\",\r\n billboardData.scale,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian2,\r\n billboard,\r\n \"pixelOffset\",\r\n billboardData.pixelOffset,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian3,\r\n billboard,\r\n \"eyeOffset\",\r\n billboardData.eyeOffset,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HorizontalOrigin,\r\n billboard,\r\n \"horizontalOrigin\",\r\n billboardData.horizontalOrigin,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n VerticalOrigin,\r\n billboard,\r\n \"verticalOrigin\",\r\n billboardData.verticalOrigin,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n billboard,\r\n \"heightReference\",\r\n billboardData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n billboard,\r\n \"color\",\r\n billboardData.color,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Rotation,\r\n billboard,\r\n \"rotation\",\r\n billboardData.rotation,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processAlignedAxis(\r\n billboard,\r\n billboardData.alignedAxis,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n billboard,\r\n \"sizeInMeters\",\r\n billboardData.sizeInMeters,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n billboard,\r\n \"width\",\r\n billboardData.width,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n billboard,\r\n \"height\",\r\n billboardData.height,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n NearFarScalar,\r\n billboard,\r\n \"scaleByDistance\",\r\n billboardData.scaleByDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n NearFarScalar,\r\n billboard,\r\n \"translucencyByDistance\",\r\n billboardData.translucencyByDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n NearFarScalar,\r\n billboard,\r\n \"pixelOffsetScaleByDistance\",\r\n billboardData.pixelOffsetScaleByDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n BoundingRectangle,\r\n billboard,\r\n \"imageSubRegion\",\r\n billboardData.imageSubRegion,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n billboard,\r\n \"distanceDisplayCondition\",\r\n billboardData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n billboard,\r\n \"disableDepthTestDistance\",\r\n billboardData.disableDepthTestDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processBox(entity, packet, entityCollection, sourceUri) {\r\n var boxData = packet.box;\r\n if (!defined(boxData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(boxData.interval);\r\n var box = entity.box;\r\n if (!defined(box)) {\r\n entity.box = box = new BoxGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n box,\r\n \"show\",\r\n boxData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian3,\r\n box,\r\n \"dimensions\",\r\n boxData.dimensions,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n box,\r\n \"heightReference\",\r\n boxData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n box,\r\n \"fill\",\r\n boxData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n box,\r\n \"material\",\r\n boxData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n box,\r\n \"outline\",\r\n boxData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n box,\r\n \"outlineColor\",\r\n boxData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n box,\r\n \"outlineWidth\",\r\n boxData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n box,\r\n \"shadows\",\r\n boxData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n box,\r\n \"distanceDisplayCondition\",\r\n boxData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processCorridor(entity, packet, entityCollection, sourceUri) {\r\n var corridorData = packet.corridor;\r\n if (!defined(corridorData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(corridorData.interval);\r\n var corridor = entity.corridor;\r\n if (!defined(corridor)) {\r\n entity.corridor = corridor = new CorridorGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n corridor,\r\n \"show\",\r\n corridorData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPositionArray(\r\n corridor,\r\n \"positions\",\r\n corridorData.positions,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n corridor,\r\n \"width\",\r\n corridorData.width,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n corridor,\r\n \"height\",\r\n corridorData.height,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n corridor,\r\n \"heightReference\",\r\n corridorData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n corridor,\r\n \"extrudedHeight\",\r\n corridorData.extrudedHeight,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n corridor,\r\n \"extrudedHeightReference\",\r\n corridorData.extrudedHeightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n CornerType,\r\n corridor,\r\n \"cornerType\",\r\n corridorData.cornerType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n corridor,\r\n \"granularity\",\r\n corridorData.granularity,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n corridor,\r\n \"fill\",\r\n corridorData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n corridor,\r\n \"material\",\r\n corridorData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n corridor,\r\n \"outline\",\r\n corridorData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n corridor,\r\n \"outlineColor\",\r\n corridorData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n corridor,\r\n \"outlineWidth\",\r\n corridorData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n corridor,\r\n \"shadows\",\r\n corridorData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n corridor,\r\n \"distanceDisplayCondition\",\r\n corridorData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ClassificationType,\r\n corridor,\r\n \"classificationType\",\r\n corridorData.classificationType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n corridor,\r\n \"zIndex\",\r\n corridorData.zIndex,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processCylinder(entity, packet, entityCollection, sourceUri) {\r\n var cylinderData = packet.cylinder;\r\n if (!defined(cylinderData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(cylinderData.interval);\r\n var cylinder = entity.cylinder;\r\n if (!defined(cylinder)) {\r\n entity.cylinder = cylinder = new CylinderGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n cylinder,\r\n \"show\",\r\n cylinderData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n cylinder,\r\n \"length\",\r\n cylinderData.length,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n cylinder,\r\n \"topRadius\",\r\n cylinderData.topRadius,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n cylinder,\r\n \"bottomRadius\",\r\n cylinderData.bottomRadius,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n cylinder,\r\n \"heightReference\",\r\n cylinderData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n cylinder,\r\n \"fill\",\r\n cylinderData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n cylinder,\r\n \"material\",\r\n cylinderData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n cylinder,\r\n \"outline\",\r\n cylinderData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n cylinder,\r\n \"outlineColor\",\r\n cylinderData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n cylinder,\r\n \"outlineWidth\",\r\n cylinderData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n cylinder,\r\n \"numberOfVerticalLines\",\r\n cylinderData.numberOfVerticalLines,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n cylinder,\r\n \"slices\",\r\n cylinderData.slices,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n cylinder,\r\n \"shadows\",\r\n cylinderData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n cylinder,\r\n \"distanceDisplayCondition\",\r\n cylinderData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processDocument(packet, dataSource) {\r\n var version = packet.version;\r\n if (defined(version)) {\r\n if (typeof version === \"string\") {\r\n var tokens = version.split(\".\");\r\n if (tokens.length === 2) {\r\n if (tokens[0] !== \"1\") {\r\n throw new RuntimeError(\"Cesium only supports CZML version 1.\");\r\n }\r\n dataSource._version = version;\r\n }\r\n }\r\n }\r\n\r\n if (!defined(dataSource._version)) {\r\n throw new RuntimeError(\r\n \"CZML version information invalid. It is expected to be a property on the document object in the . version format.\"\r\n );\r\n }\r\n\r\n var documentPacket = dataSource._documentPacket;\r\n\r\n if (defined(packet.name)) {\r\n documentPacket.name = packet.name;\r\n }\r\n\r\n var clockPacket = packet.clock;\r\n if (defined(clockPacket)) {\r\n var clock = documentPacket.clock;\r\n if (!defined(clock)) {\r\n documentPacket.clock = {\r\n interval: clockPacket.interval,\r\n currentTime: clockPacket.currentTime,\r\n range: clockPacket.range,\r\n step: clockPacket.step,\r\n multiplier: clockPacket.multiplier,\r\n };\r\n } else {\r\n clock.interval = defaultValue(clockPacket.interval, clock.interval);\r\n clock.currentTime = defaultValue(\r\n clockPacket.currentTime,\r\n clock.currentTime\r\n );\r\n clock.range = defaultValue(clockPacket.range, clock.range);\r\n clock.step = defaultValue(clockPacket.step, clock.step);\r\n clock.multiplier = defaultValue(clockPacket.multiplier, clock.multiplier);\r\n }\r\n }\r\n}\r\n\r\nfunction processEllipse(entity, packet, entityCollection, sourceUri) {\r\n var ellipseData = packet.ellipse;\r\n if (!defined(ellipseData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(ellipseData.interval);\r\n var ellipse = entity.ellipse;\r\n if (!defined(ellipse)) {\r\n entity.ellipse = ellipse = new EllipseGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n ellipse,\r\n \"show\",\r\n ellipseData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipse,\r\n \"semiMajorAxis\",\r\n ellipseData.semiMajorAxis,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipse,\r\n \"semiMinorAxis\",\r\n ellipseData.semiMinorAxis,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipse,\r\n \"height\",\r\n ellipseData.height,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n ellipse,\r\n \"heightReference\",\r\n ellipseData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipse,\r\n \"extrudedHeight\",\r\n ellipseData.extrudedHeight,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n ellipse,\r\n \"extrudedHeightReference\",\r\n ellipseData.extrudedHeightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Rotation,\r\n ellipse,\r\n \"rotation\",\r\n ellipseData.rotation,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Rotation,\r\n ellipse,\r\n \"stRotation\",\r\n ellipseData.stRotation,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipse,\r\n \"granularity\",\r\n ellipseData.granularity,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n ellipse,\r\n \"fill\",\r\n ellipseData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n ellipse,\r\n \"material\",\r\n ellipseData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n ellipse,\r\n \"outline\",\r\n ellipseData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n ellipse,\r\n \"outlineColor\",\r\n ellipseData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipse,\r\n \"outlineWidth\",\r\n ellipseData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipse,\r\n \"numberOfVerticalLines\",\r\n ellipseData.numberOfVerticalLines,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n ellipse,\r\n \"shadows\",\r\n ellipseData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n ellipse,\r\n \"distanceDisplayCondition\",\r\n ellipseData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ClassificationType,\r\n ellipse,\r\n \"classificationType\",\r\n ellipseData.classificationType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipse,\r\n \"zIndex\",\r\n ellipseData.zIndex,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processEllipsoid(entity, packet, entityCollection, sourceUri) {\r\n var ellipsoidData = packet.ellipsoid;\r\n if (!defined(ellipsoidData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(ellipsoidData.interval);\r\n var ellipsoid = entity.ellipsoid;\r\n if (!defined(ellipsoid)) {\r\n entity.ellipsoid = ellipsoid = new EllipsoidGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n ellipsoid,\r\n \"show\",\r\n ellipsoidData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian3,\r\n ellipsoid,\r\n \"radii\",\r\n ellipsoidData.radii,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian3,\r\n ellipsoid,\r\n \"innerRadii\",\r\n ellipsoidData.innerRadii,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipsoid,\r\n \"minimumClock\",\r\n ellipsoidData.minimumClock,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipsoid,\r\n \"maximumClock\",\r\n ellipsoidData.maximumClock,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipsoid,\r\n \"minimumCone\",\r\n ellipsoidData.minimumCone,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipsoid,\r\n \"maximumCone\",\r\n ellipsoidData.maximumCone,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n ellipsoid,\r\n \"heightReference\",\r\n ellipsoidData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n ellipsoid,\r\n \"fill\",\r\n ellipsoidData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n ellipsoid,\r\n \"material\",\r\n ellipsoidData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n ellipsoid,\r\n \"outline\",\r\n ellipsoidData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n ellipsoid,\r\n \"outlineColor\",\r\n ellipsoidData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipsoid,\r\n \"outlineWidth\",\r\n ellipsoidData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipsoid,\r\n \"stackPartitions\",\r\n ellipsoidData.stackPartitions,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipsoid,\r\n \"slicePartitions\",\r\n ellipsoidData.slicePartitions,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n ellipsoid,\r\n \"subdivisions\",\r\n ellipsoidData.subdivisions,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n ellipsoid,\r\n \"shadows\",\r\n ellipsoidData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n ellipsoid,\r\n \"distanceDisplayCondition\",\r\n ellipsoidData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processLabel(entity, packet, entityCollection, sourceUri) {\r\n var labelData = packet.label;\r\n if (!defined(labelData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(labelData.interval);\r\n var label = entity.label;\r\n if (!defined(label)) {\r\n entity.label = label = new LabelGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n label,\r\n \"show\",\r\n labelData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n String,\r\n label,\r\n \"text\",\r\n labelData.text,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n String,\r\n label,\r\n \"font\",\r\n labelData.font,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n LabelStyle,\r\n label,\r\n \"style\",\r\n labelData.style,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n label,\r\n \"scale\",\r\n labelData.scale,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n label,\r\n \"showBackground\",\r\n labelData.showBackground,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n label,\r\n \"backgroundColor\",\r\n labelData.backgroundColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian2,\r\n label,\r\n \"backgroundPadding\",\r\n labelData.backgroundPadding,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian2,\r\n label,\r\n \"pixelOffset\",\r\n labelData.pixelOffset,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian3,\r\n label,\r\n \"eyeOffset\",\r\n labelData.eyeOffset,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HorizontalOrigin,\r\n label,\r\n \"horizontalOrigin\",\r\n labelData.horizontalOrigin,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n VerticalOrigin,\r\n label,\r\n \"verticalOrigin\",\r\n labelData.verticalOrigin,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n label,\r\n \"heightReference\",\r\n labelData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n label,\r\n \"fillColor\",\r\n labelData.fillColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n label,\r\n \"outlineColor\",\r\n labelData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n label,\r\n \"outlineWidth\",\r\n labelData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n NearFarScalar,\r\n label,\r\n \"translucencyByDistance\",\r\n labelData.translucencyByDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n NearFarScalar,\r\n label,\r\n \"pixelOffsetScaleByDistance\",\r\n labelData.pixelOffsetScaleByDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n NearFarScalar,\r\n label,\r\n \"scaleByDistance\",\r\n labelData.scaleByDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n label,\r\n \"distanceDisplayCondition\",\r\n labelData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n label,\r\n \"disableDepthTestDistance\",\r\n labelData.disableDepthTestDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processModel(entity, packet, entityCollection, sourceUri) {\r\n var modelData = packet.model;\r\n if (!defined(modelData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(modelData.interval);\r\n var model = entity.model;\r\n if (!defined(model)) {\r\n entity.model = model = new ModelGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n model,\r\n \"show\",\r\n modelData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Uri,\r\n model,\r\n \"uri\",\r\n modelData.gltf,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n model,\r\n \"scale\",\r\n modelData.scale,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n model,\r\n \"minimumPixelSize\",\r\n modelData.minimumPixelSize,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n model,\r\n \"maximumScale\",\r\n modelData.maximumScale,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n model,\r\n \"incrementallyLoadTextures\",\r\n modelData.incrementallyLoadTextures,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n model,\r\n \"runAnimations\",\r\n modelData.runAnimations,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n model,\r\n \"clampAnimations\",\r\n modelData.clampAnimations,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n model,\r\n \"shadows\",\r\n modelData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n model,\r\n \"heightReference\",\r\n modelData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n model,\r\n \"silhouetteColor\",\r\n modelData.silhouetteColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n model,\r\n \"silhouetteSize\",\r\n modelData.silhouetteSize,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n model,\r\n \"color\",\r\n modelData.color,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ColorBlendMode,\r\n model,\r\n \"colorBlendMode\",\r\n modelData.colorBlendMode,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n model,\r\n \"colorBlendAmount\",\r\n modelData.colorBlendAmount,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n model,\r\n \"distanceDisplayCondition\",\r\n modelData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n\r\n var i, len;\r\n var nodeTransformationsData = modelData.nodeTransformations;\r\n if (defined(nodeTransformationsData)) {\r\n if (Array.isArray(nodeTransformationsData)) {\r\n for (i = 0, len = nodeTransformationsData.length; i < len; ++i) {\r\n processNodeTransformations(\r\n model,\r\n nodeTransformationsData[i],\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processNodeTransformations(\r\n model,\r\n nodeTransformationsData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n }\r\n\r\n var articulationsData = modelData.articulations;\r\n if (defined(articulationsData)) {\r\n if (Array.isArray(articulationsData)) {\r\n for (i = 0, len = articulationsData.length; i < len; ++i) {\r\n processArticulations(\r\n model,\r\n articulationsData[i],\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n } else {\r\n processArticulations(\r\n model,\r\n articulationsData,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n }\r\n}\r\n\r\nfunction processNodeTransformations(\r\n model,\r\n nodeTransformationsData,\r\n constrainedInterval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n var combinedInterval = intervalFromString(nodeTransformationsData.interval);\r\n if (defined(constrainedInterval)) {\r\n if (defined(combinedInterval)) {\r\n combinedInterval = TimeInterval.intersect(\r\n combinedInterval,\r\n constrainedInterval,\r\n scratchTimeInterval\r\n );\r\n } else {\r\n combinedInterval = constrainedInterval;\r\n }\r\n }\r\n\r\n var nodeTransformations = model.nodeTransformations;\r\n var nodeNames = Object.keys(nodeTransformationsData);\r\n for (var i = 0, len = nodeNames.length; i < len; ++i) {\r\n var nodeName = nodeNames[i];\r\n if (nodeName === \"interval\") {\r\n continue;\r\n }\r\n\r\n var nodeTransformationData = nodeTransformationsData[nodeName];\r\n if (!defined(nodeTransformationData)) {\r\n continue;\r\n }\r\n\r\n if (!defined(nodeTransformations)) {\r\n model.nodeTransformations = nodeTransformations = new PropertyBag();\r\n }\r\n\r\n if (!nodeTransformations.hasProperty(nodeName)) {\r\n nodeTransformations.addProperty(nodeName);\r\n }\r\n\r\n var nodeTransformation = nodeTransformations[nodeName];\r\n if (!defined(nodeTransformation)) {\r\n nodeTransformations[\r\n nodeName\r\n ] = nodeTransformation = new NodeTransformationProperty();\r\n }\r\n\r\n processPacketData(\r\n Cartesian3,\r\n nodeTransformation,\r\n \"translation\",\r\n nodeTransformationData.translation,\r\n combinedInterval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Quaternion,\r\n nodeTransformation,\r\n \"rotation\",\r\n nodeTransformationData.rotation,\r\n combinedInterval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Cartesian3,\r\n nodeTransformation,\r\n \"scale\",\r\n nodeTransformationData.scale,\r\n combinedInterval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processArticulations(\r\n model,\r\n articulationsData,\r\n constrainedInterval,\r\n sourceUri,\r\n entityCollection\r\n) {\r\n var combinedInterval = intervalFromString(articulationsData.interval);\r\n if (defined(constrainedInterval)) {\r\n if (defined(combinedInterval)) {\r\n combinedInterval = TimeInterval.intersect(\r\n combinedInterval,\r\n constrainedInterval,\r\n scratchTimeInterval\r\n );\r\n } else {\r\n combinedInterval = constrainedInterval;\r\n }\r\n }\r\n\r\n var articulations = model.articulations;\r\n var keys = Object.keys(articulationsData);\r\n for (var i = 0, len = keys.length; i < len; ++i) {\r\n var key = keys[i];\r\n if (key === \"interval\") {\r\n continue;\r\n }\r\n\r\n var articulationStageData = articulationsData[key];\r\n if (!defined(articulationStageData)) {\r\n continue;\r\n }\r\n\r\n if (!defined(articulations)) {\r\n model.articulations = articulations = new PropertyBag();\r\n }\r\n\r\n if (!articulations.hasProperty(key)) {\r\n articulations.addProperty(key);\r\n }\r\n\r\n processPacketData(\r\n Number,\r\n articulations,\r\n key,\r\n articulationStageData,\r\n combinedInterval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n }\r\n}\r\n\r\nfunction processPath(entity, packet, entityCollection, sourceUri) {\r\n var pathData = packet.path;\r\n if (!defined(pathData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(pathData.interval);\r\n var path = entity.path;\r\n if (!defined(path)) {\r\n entity.path = path = new PathGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n path,\r\n \"show\",\r\n pathData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n path,\r\n \"leadTime\",\r\n pathData.leadTime,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n path,\r\n \"trailTime\",\r\n pathData.trailTime,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n path,\r\n \"width\",\r\n pathData.width,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n path,\r\n \"resolution\",\r\n pathData.resolution,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n path,\r\n \"material\",\r\n pathData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n path,\r\n \"distanceDisplayCondition\",\r\n pathData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processPoint(entity, packet, entityCollection, sourceUri) {\r\n var pointData = packet.point;\r\n if (!defined(pointData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(pointData.interval);\r\n var point = entity.point;\r\n if (!defined(point)) {\r\n entity.point = point = new PointGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n point,\r\n \"show\",\r\n pointData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n point,\r\n \"pixelSize\",\r\n pointData.pixelSize,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n point,\r\n \"heightReference\",\r\n pointData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n point,\r\n \"color\",\r\n pointData.color,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n point,\r\n \"outlineColor\",\r\n pointData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n point,\r\n \"outlineWidth\",\r\n pointData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n NearFarScalar,\r\n point,\r\n \"scaleByDistance\",\r\n pointData.scaleByDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n NearFarScalar,\r\n point,\r\n \"translucencyByDistance\",\r\n pointData.translucencyByDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n point,\r\n \"distanceDisplayCondition\",\r\n pointData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n point,\r\n \"disableDepthTestDistance\",\r\n pointData.disableDepthTestDistance,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction PolygonHierarchyProperty(polygon) {\r\n this.polygon = polygon;\r\n this._definitionChanged = new Event();\r\n}\r\n\r\nObject.defineProperties(PolygonHierarchyProperty.prototype, {\r\n isConstant: {\r\n get: function () {\r\n var positions = this.polygon._positions;\r\n var holes = this.polygon._holes;\r\n return (\r\n (!defined(positions) || positions.isConstant) &&\r\n (!defined(holes) || holes.isConstant)\r\n );\r\n },\r\n },\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n});\r\n\r\nPolygonHierarchyProperty.prototype.getValue = function (time, result) {\r\n var positions;\r\n if (defined(this.polygon._positions)) {\r\n positions = this.polygon._positions.getValue(time);\r\n }\r\n\r\n var holes;\r\n if (defined(this.polygon._holes)) {\r\n holes = this.polygon._holes.getValue(time);\r\n if (defined(holes)) {\r\n holes = holes.map(function (holePositions) {\r\n return new PolygonHierarchy(holePositions);\r\n });\r\n }\r\n }\r\n\r\n if (!defined(result)) {\r\n return new PolygonHierarchy(positions, holes);\r\n }\r\n\r\n result.positions = positions;\r\n result.holes = holes;\r\n return result;\r\n};\r\n\r\nPolygonHierarchyProperty.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (other instanceof PolygonHierarchyProperty &&\r\n Property.equals(this.polygon._positions, other.polygon._positions) &&\r\n Property.equals(this.polygon._holes, other.polygon._holes))\r\n );\r\n};\r\n\r\nfunction processPolygon(entity, packet, entityCollection, sourceUri) {\r\n var polygonData = packet.polygon;\r\n if (!defined(polygonData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(polygonData.interval);\r\n var polygon = entity.polygon;\r\n if (!defined(polygon)) {\r\n entity.polygon = polygon = new PolygonGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n polygon,\r\n \"show\",\r\n polygonData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n\r\n // adapt 'position' property producing Cartesian[]\r\n // and 'holes' property producing Cartesian[][]\r\n // to a single property producing PolygonHierarchy\r\n processPositionArray(\r\n polygon,\r\n \"_positions\",\r\n polygonData.positions,\r\n entityCollection\r\n );\r\n processPositionArrayOfArrays(\r\n polygon,\r\n \"_holes\",\r\n polygonData.holes,\r\n entityCollection\r\n );\r\n if (defined(polygon._positions) || defined(polygon._holes)) {\r\n polygon.hierarchy = new PolygonHierarchyProperty(polygon);\r\n }\r\n\r\n processPacketData(\r\n Number,\r\n polygon,\r\n \"height\",\r\n polygonData.height,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n polygon,\r\n \"heightReference\",\r\n polygonData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polygon,\r\n \"extrudedHeight\",\r\n polygonData.extrudedHeight,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n polygon,\r\n \"extrudedHeightReference\",\r\n polygonData.extrudedHeightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Rotation,\r\n polygon,\r\n \"stRotation\",\r\n polygonData.stRotation,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polygon,\r\n \"granularity\",\r\n polygonData.granularity,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polygon,\r\n \"fill\",\r\n polygonData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n polygon,\r\n \"material\",\r\n polygonData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polygon,\r\n \"outline\",\r\n polygonData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n polygon,\r\n \"outlineColor\",\r\n polygonData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polygon,\r\n \"outlineWidth\",\r\n polygonData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polygon,\r\n \"perPositionHeight\",\r\n polygonData.perPositionHeight,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polygon,\r\n \"closeTop\",\r\n polygonData.closeTop,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polygon,\r\n \"closeBottom\",\r\n polygonData.closeBottom,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ArcType,\r\n polygon,\r\n \"arcType\",\r\n polygonData.arcType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n polygon,\r\n \"shadows\",\r\n polygonData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n polygon,\r\n \"distanceDisplayCondition\",\r\n polygonData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ClassificationType,\r\n polygon,\r\n \"classificationType\",\r\n polygonData.classificationType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polygon,\r\n \"zIndex\",\r\n polygonData.zIndex,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction adaptFollowSurfaceToArcType(followSurface) {\r\n return followSurface ? ArcType.GEODESIC : ArcType.NONE;\r\n}\r\n\r\nfunction processPolyline(entity, packet, entityCollection, sourceUri) {\r\n var polylineData = packet.polyline;\r\n if (!defined(polylineData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(polylineData.interval);\r\n var polyline = entity.polyline;\r\n if (!defined(polyline)) {\r\n entity.polyline = polyline = new PolylineGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n polyline,\r\n \"show\",\r\n polylineData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPositionArray(\r\n polyline,\r\n \"positions\",\r\n polylineData.positions,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polyline,\r\n \"width\",\r\n polylineData.width,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polyline,\r\n \"granularity\",\r\n polylineData.granularity,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n polyline,\r\n \"material\",\r\n polylineData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n polyline,\r\n \"depthFailMaterial\",\r\n polylineData.depthFailMaterial,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ArcType,\r\n polyline,\r\n \"arcType\",\r\n polylineData.arcType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polyline,\r\n \"clampToGround\",\r\n polylineData.clampToGround,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n polyline,\r\n \"shadows\",\r\n polylineData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n polyline,\r\n \"distanceDisplayCondition\",\r\n polylineData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ClassificationType,\r\n polyline,\r\n \"classificationType\",\r\n polylineData.classificationType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polyline,\r\n \"zIndex\",\r\n polylineData.zIndex,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n\r\n // for backwards compatibility, adapt CZML followSurface to arcType.\r\n if (defined(polylineData.followSurface) && !defined(polylineData.arcType)) {\r\n var tempObj = {};\r\n processPacketData(\r\n Boolean,\r\n tempObj,\r\n \"followSurface\",\r\n polylineData.followSurface,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n polyline.arcType = createAdapterProperty(\r\n tempObj.followSurface,\r\n adaptFollowSurfaceToArcType\r\n );\r\n }\r\n}\r\n\r\nfunction processPolylineVolume(entity, packet, entityCollection, sourceUri) {\r\n var polylineVolumeData = packet.polylineVolume;\r\n if (!defined(polylineVolumeData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(polylineVolumeData.interval);\r\n var polylineVolume = entity.polylineVolume;\r\n if (!defined(polylineVolume)) {\r\n entity.polylineVolume = polylineVolume = new PolylineVolumeGraphics();\r\n }\r\n\r\n processPositionArray(\r\n polylineVolume,\r\n \"positions\",\r\n polylineVolumeData.positions,\r\n entityCollection\r\n );\r\n processShape(\r\n polylineVolume,\r\n \"shape\",\r\n polylineVolumeData.shape,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polylineVolume,\r\n \"show\",\r\n polylineVolumeData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n CornerType,\r\n polylineVolume,\r\n \"cornerType\",\r\n polylineVolumeData.cornerType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polylineVolume,\r\n \"fill\",\r\n polylineVolumeData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n polylineVolume,\r\n \"material\",\r\n polylineVolumeData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n polylineVolume,\r\n \"outline\",\r\n polylineVolumeData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n polylineVolume,\r\n \"outlineColor\",\r\n polylineVolumeData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polylineVolume,\r\n \"outlineWidth\",\r\n polylineVolumeData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n polylineVolume,\r\n \"granularity\",\r\n polylineVolumeData.granularity,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n polylineVolume,\r\n \"shadows\",\r\n polylineVolumeData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n polylineVolume,\r\n \"distanceDisplayCondition\",\r\n polylineVolumeData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processRectangle(entity, packet, entityCollection, sourceUri) {\r\n var rectangleData = packet.rectangle;\r\n if (!defined(rectangleData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(rectangleData.interval);\r\n var rectangle = entity.rectangle;\r\n if (!defined(rectangle)) {\r\n entity.rectangle = rectangle = new RectangleGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n rectangle,\r\n \"show\",\r\n rectangleData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Rectangle,\r\n rectangle,\r\n \"coordinates\",\r\n rectangleData.coordinates,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n rectangle,\r\n \"height\",\r\n rectangleData.height,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n rectangle,\r\n \"heightReference\",\r\n rectangleData.heightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n rectangle,\r\n \"extrudedHeight\",\r\n rectangleData.extrudedHeight,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n HeightReference,\r\n rectangle,\r\n \"extrudedHeightReference\",\r\n rectangleData.extrudedHeightReference,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Rotation,\r\n rectangle,\r\n \"rotation\",\r\n rectangleData.rotation,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Rotation,\r\n rectangle,\r\n \"stRotation\",\r\n rectangleData.stRotation,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n rectangle,\r\n \"granularity\",\r\n rectangleData.granularity,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n rectangle,\r\n \"fill\",\r\n rectangleData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n rectangle,\r\n \"material\",\r\n rectangleData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n rectangle,\r\n \"outline\",\r\n rectangleData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n rectangle,\r\n \"outlineColor\",\r\n rectangleData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n rectangle,\r\n \"outlineWidth\",\r\n rectangleData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n rectangle,\r\n \"shadows\",\r\n rectangleData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n rectangle,\r\n \"distanceDisplayCondition\",\r\n rectangleData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ClassificationType,\r\n rectangle,\r\n \"classificationType\",\r\n rectangleData.classificationType,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n rectangle,\r\n \"zIndex\",\r\n rectangleData.zIndex,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processTileset(entity, packet, entityCollection, sourceUri) {\r\n var tilesetData = packet.tileset;\r\n if (!defined(tilesetData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(tilesetData.interval);\r\n var tileset = entity.tileset;\r\n if (!defined(tileset)) {\r\n entity.tileset = tileset = new Cesium3DTilesetGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n tileset,\r\n \"show\",\r\n tilesetData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Uri,\r\n tileset,\r\n \"uri\",\r\n tilesetData.uri,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n tileset,\r\n \"maximumScreenSpaceError\",\r\n tilesetData.maximumScreenSpaceError,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processWall(entity, packet, entityCollection, sourceUri) {\r\n var wallData = packet.wall;\r\n if (!defined(wallData)) {\r\n return;\r\n }\r\n\r\n var interval = intervalFromString(wallData.interval);\r\n var wall = entity.wall;\r\n if (!defined(wall)) {\r\n entity.wall = wall = new WallGraphics();\r\n }\r\n\r\n processPacketData(\r\n Boolean,\r\n wall,\r\n \"show\",\r\n wallData.show,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPositionArray(wall, \"positions\", wallData.positions, entityCollection);\r\n processArray(\r\n wall,\r\n \"minimumHeights\",\r\n wallData.minimumHeights,\r\n entityCollection\r\n );\r\n processArray(\r\n wall,\r\n \"maximumHeights\",\r\n wallData.maximumHeights,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n wall,\r\n \"granularity\",\r\n wallData.granularity,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n wall,\r\n \"fill\",\r\n wallData.fill,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processMaterialPacketData(\r\n wall,\r\n \"material\",\r\n wallData.material,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Boolean,\r\n wall,\r\n \"outline\",\r\n wallData.outline,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Color,\r\n wall,\r\n \"outlineColor\",\r\n wallData.outlineColor,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n Number,\r\n wall,\r\n \"outlineWidth\",\r\n wallData.outlineWidth,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n ShadowMode,\r\n wall,\r\n \"shadows\",\r\n wallData.shadows,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n processPacketData(\r\n DistanceDisplayCondition,\r\n wall,\r\n \"distanceDisplayCondition\",\r\n wallData.distanceDisplayCondition,\r\n interval,\r\n sourceUri,\r\n entityCollection\r\n );\r\n}\r\n\r\nfunction processCzmlPacket(\r\n packet,\r\n entityCollection,\r\n updaterFunctions,\r\n sourceUri,\r\n dataSource\r\n) {\r\n var objectId = packet.id;\r\n if (!defined(objectId)) {\r\n objectId = createGuid();\r\n }\r\n\r\n currentId = objectId;\r\n\r\n if (!defined(dataSource._version) && objectId !== \"document\") {\r\n throw new RuntimeError(\r\n \"The first CZML packet is required to be the document object.\"\r\n );\r\n }\r\n\r\n if (packet[\"delete\"] === true) {\r\n entityCollection.removeById(objectId);\r\n } else if (objectId === \"document\") {\r\n processDocument(packet, dataSource);\r\n } else {\r\n var entity = entityCollection.getOrCreateEntity(objectId);\r\n\r\n var parentId = packet.parent;\r\n if (defined(parentId)) {\r\n entity.parent = entityCollection.getOrCreateEntity(parentId);\r\n }\r\n\r\n for (var i = updaterFunctions.length - 1; i > -1; i--) {\r\n updaterFunctions[i](entity, packet, entityCollection, sourceUri);\r\n }\r\n }\r\n\r\n currentId = undefined;\r\n}\r\n\r\nfunction updateClock(dataSource) {\r\n var clock;\r\n var clockPacket = dataSource._documentPacket.clock;\r\n if (!defined(clockPacket)) {\r\n if (!defined(dataSource._clock)) {\r\n var availability = dataSource._entityCollection.computeAvailability();\r\n if (!availability.start.equals(Iso8601.MINIMUM_VALUE)) {\r\n var startTime = availability.start;\r\n var stopTime = availability.stop;\r\n var totalSeconds = JulianDate.secondsDifference(stopTime, startTime);\r\n var multiplier = Math.round(totalSeconds / 120.0);\r\n\r\n clock = new DataSourceClock();\r\n clock.startTime = JulianDate.clone(startTime);\r\n clock.stopTime = JulianDate.clone(stopTime);\r\n clock.clockRange = ClockRange.LOOP_STOP;\r\n clock.multiplier = multiplier;\r\n clock.currentTime = JulianDate.clone(startTime);\r\n clock.clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER;\r\n dataSource._clock = clock;\r\n return true;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n if (defined(dataSource._clock)) {\r\n clock = dataSource._clock.clone();\r\n } else {\r\n clock = new DataSourceClock();\r\n clock.startTime = Iso8601.MINIMUM_VALUE.clone();\r\n clock.stopTime = Iso8601.MAXIMUM_VALUE.clone();\r\n clock.currentTime = Iso8601.MINIMUM_VALUE.clone();\r\n clock.clockRange = ClockRange.LOOP_STOP;\r\n clock.clockStep = ClockStep.SYSTEM_CLOCK_MULTIPLIER;\r\n clock.multiplier = 1.0;\r\n }\r\n\r\n var interval = intervalFromString(clockPacket.interval);\r\n if (defined(interval)) {\r\n clock.startTime = interval.start;\r\n clock.stopTime = interval.stop;\r\n }\r\n\r\n if (defined(clockPacket.currentTime)) {\r\n clock.currentTime = JulianDate.fromIso8601(clockPacket.currentTime);\r\n }\r\n if (defined(clockPacket.range)) {\r\n clock.clockRange = defaultValue(\r\n ClockRange[clockPacket.range],\r\n ClockRange.LOOP_STOP\r\n );\r\n }\r\n if (defined(clockPacket.step)) {\r\n clock.clockStep = defaultValue(\r\n ClockStep[clockPacket.step],\r\n ClockStep.SYSTEM_CLOCK_MULTIPLIER\r\n );\r\n }\r\n if (defined(clockPacket.multiplier)) {\r\n clock.multiplier = clockPacket.multiplier;\r\n }\r\n\r\n if (!clock.equals(dataSource._clock)) {\r\n dataSource._clock = clock.clone(dataSource._clock);\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n\r\nfunction load(dataSource, czml, options, clear) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(czml)) {\r\n throw new DeveloperError(\"czml is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n var promise = czml;\r\n var sourceUri = options.sourceUri;\r\n\r\n // User specified credit\r\n var credit = options.credit;\r\n if (typeof credit === \"string\") {\r\n credit = new Credit(credit);\r\n }\r\n dataSource._credit = credit;\r\n\r\n // If the czml is a URL\r\n if (typeof czml === \"string\" || czml instanceof Resource) {\r\n czml = Resource.createIfNeeded(czml);\r\n promise = czml.fetchJson();\r\n sourceUri = defaultValue(sourceUri, czml.clone());\r\n\r\n // Add resource credits to our list of credits to display\r\n var resourceCredits = dataSource._resourceCredits;\r\n var credits = czml.credits;\r\n if (defined(credits)) {\r\n var length = credits.length;\r\n for (var i = 0; i < length; i++) {\r\n resourceCredits.push(credits[i]);\r\n }\r\n }\r\n }\r\n\r\n sourceUri = Resource.createIfNeeded(sourceUri);\r\n\r\n DataSource.setLoading(dataSource, true);\r\n\r\n return when(promise, function (czml) {\r\n return loadCzml(dataSource, czml, sourceUri, clear);\r\n }).otherwise(function (error) {\r\n DataSource.setLoading(dataSource, false);\r\n dataSource._error.raiseEvent(dataSource, error);\r\n console.log(error);\r\n return when.reject(error);\r\n });\r\n}\r\n\r\nfunction loadCzml(dataSource, czml, sourceUri, clear) {\r\n DataSource.setLoading(dataSource, true);\r\n var entityCollection = dataSource._entityCollection;\r\n\r\n if (clear) {\r\n dataSource._version = undefined;\r\n dataSource._documentPacket = new DocumentPacket();\r\n entityCollection.removeAll();\r\n }\r\n\r\n CzmlDataSource._processCzml(\r\n czml,\r\n entityCollection,\r\n sourceUri,\r\n undefined,\r\n dataSource\r\n );\r\n\r\n var raiseChangedEvent = updateClock(dataSource);\r\n\r\n var documentPacket = dataSource._documentPacket;\r\n if (\r\n defined(documentPacket.name) &&\r\n dataSource._name !== documentPacket.name\r\n ) {\r\n dataSource._name = documentPacket.name;\r\n raiseChangedEvent = true;\r\n } else if (!defined(dataSource._name) && defined(sourceUri)) {\r\n dataSource._name = getFilenameFromUri(sourceUri.getUrlComponent());\r\n raiseChangedEvent = true;\r\n }\r\n\r\n DataSource.setLoading(dataSource, false);\r\n if (raiseChangedEvent) {\r\n dataSource._changed.raiseEvent(dataSource);\r\n }\r\n\r\n return dataSource;\r\n}\r\n\r\nfunction DocumentPacket() {\r\n this.name = undefined;\r\n this.clock = undefined;\r\n}\r\n\r\n/**\r\n * @typedef {Object} CzmlDataSource.LoadOptions\r\n *\r\n * Initialization options for the `load` method.\r\n *\r\n * @property {Resource|string} [sourceUri] Overrides the url to use for resolving relative links.\r\n * @property {Credit|string} [credit] A credit for the data source, which is displayed on the canvas.\r\n */\r\n\r\n/**\r\n * A {@link DataSource} which processes {@link https://github.com/AnalyticalGraphicsInc/czml-writer/wiki/CZML-Guide|CZML}.\r\n * @alias CzmlDataSource\r\n * @constructor\r\n *\r\n * @param {String} [name] An optional name for the data source. This value will be overwritten if a loaded document contains a name.\r\n *\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=CZML.html|Cesium Sandcastle CZML Demo}\r\n */\r\nfunction CzmlDataSource(name) {\r\n this._name = name;\r\n this._changed = new Event();\r\n this._error = new Event();\r\n this._isLoading = false;\r\n this._loading = new Event();\r\n this._clock = undefined;\r\n this._documentPacket = new DocumentPacket();\r\n this._version = undefined;\r\n this._entityCollection = new EntityCollection(this);\r\n this._entityCluster = new EntityCluster();\r\n this._credit = undefined;\r\n this._resourceCredits = [];\r\n}\r\n\r\n/**\r\n * Creates a Promise to a new instance loaded with the provided CZML data.\r\n *\r\n * @param {Resource|String|Object} czml A url or CZML object to be processed.\r\n * @param {CzmlDataSource.LoadOptions} [options] An object specifying configuration options\r\n *\r\n * @returns {Promise.} A promise that resolves to the new instance once the data is processed.\r\n */\r\nCzmlDataSource.load = function (czml, options) {\r\n return new CzmlDataSource().load(czml, options);\r\n};\r\n\r\nObject.defineProperties(CzmlDataSource.prototype, {\r\n /**\r\n * Gets a human-readable name for this instance.\r\n * @memberof CzmlDataSource.prototype\r\n * @type {String}\r\n */\r\n name: {\r\n get: function () {\r\n return this._name;\r\n },\r\n },\r\n /**\r\n * Gets the clock settings defined by the loaded CZML. If no clock is explicitly\r\n * defined in the CZML, the combined availability of all objects is returned. If\r\n * only static data exists, this value is undefined.\r\n * @memberof CzmlDataSource.prototype\r\n * @type {DataSourceClock}\r\n */\r\n clock: {\r\n get: function () {\r\n return this._clock;\r\n },\r\n },\r\n /**\r\n * Gets the collection of {@link Entity} instances.\r\n * @memberof CzmlDataSource.prototype\r\n * @type {EntityCollection}\r\n */\r\n entities: {\r\n get: function () {\r\n return this._entityCollection;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the data source is currently loading data.\r\n * @memberof CzmlDataSource.prototype\r\n * @type {Boolean}\r\n */\r\n isLoading: {\r\n get: function () {\r\n return this._isLoading;\r\n },\r\n },\r\n /**\r\n * Gets an event that will be raised when the underlying data changes.\r\n * @memberof CzmlDataSource.prototype\r\n * @type {Event}\r\n */\r\n changedEvent: {\r\n get: function () {\r\n return this._changed;\r\n },\r\n },\r\n /**\r\n * Gets an event that will be raised if an error is encountered during processing.\r\n * @memberof CzmlDataSource.prototype\r\n * @type {Event}\r\n */\r\n errorEvent: {\r\n get: function () {\r\n return this._error;\r\n },\r\n },\r\n /**\r\n * Gets an event that will be raised when the data source either starts or stops loading.\r\n * @memberof CzmlDataSource.prototype\r\n * @type {Event}\r\n */\r\n loadingEvent: {\r\n get: function () {\r\n return this._loading;\r\n },\r\n },\r\n /**\r\n * Gets whether or not this data source should be displayed.\r\n * @memberof CzmlDataSource.prototype\r\n * @type {Boolean}\r\n */\r\n show: {\r\n get: function () {\r\n return this._entityCollection.show;\r\n },\r\n set: function (value) {\r\n this._entityCollection.show = value;\r\n },\r\n },\r\n\r\n /**\r\n * Gets or sets the clustering options for this data source. This object can be shared between multiple data sources.\r\n *\r\n * @memberof CzmlDataSource.prototype\r\n * @type {EntityCluster}\r\n */\r\n clustering: {\r\n get: function () {\r\n return this._entityCluster;\r\n },\r\n set: function (value) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(value)) {\r\n throw new DeveloperError(\"value must be defined.\");\r\n }\r\n //>>includeEnd('debug');\r\n this._entityCluster = value;\r\n },\r\n },\r\n /**\r\n * Gets the credit that will be displayed for the data source\r\n * @memberof CzmlDataSource.prototype\r\n * @type {Credit}\r\n */\r\n credit: {\r\n get: function () {\r\n return this._credit;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Gets the array of CZML processing functions.\r\n * @memberof CzmlDataSource\r\n * @type Array\r\n */\r\nCzmlDataSource.updaters = [\r\n processBillboard, //\r\n processBox, //\r\n processCorridor, //\r\n processCylinder, //\r\n processEllipse, //\r\n processEllipsoid, //\r\n processLabel, //\r\n processModel, //\r\n processName, //\r\n processDescription, //\r\n processPath, //\r\n processPoint, //\r\n processPolygon, //\r\n processPolyline, //\r\n processPolylineVolume, //\r\n processProperties, //\r\n processRectangle, //\r\n processPosition, //\r\n processTileset, //\r\n processViewFrom, //\r\n processWall, //\r\n processOrientation, //\r\n processAvailability,\r\n];\r\n\r\n/**\r\n * Processes the provided url or CZML object without clearing any existing data.\r\n *\r\n * @param {Resource|String|Object} czml A url or CZML object to be processed.\r\n * @param {Object} [options] An object with the following properties:\r\n * @param {String} [options.sourceUri] Overrides the url to use for resolving relative links.\r\n * @returns {Promise.} A promise that resolves to this instances once the data is processed.\r\n */\r\nCzmlDataSource.prototype.process = function (czml, options) {\r\n return load(this, czml, options, false);\r\n};\r\n\r\n/**\r\n * Loads the provided url or CZML object, replacing any existing data.\r\n *\r\n * @param {Resource|String|Object} czml A url or CZML object to be processed.\r\n * @param {CzmlDataSource.LoadOptions} [options] An object specifying configuration options\r\n\r\n * @returns {Promise.} A promise that resolves to this instances once the data is processed.\r\n */\r\nCzmlDataSource.prototype.load = function (czml, options) {\r\n return load(this, czml, options, true);\r\n};\r\n\r\n/**\r\n * Updates the data source to the provided time. This function is optional and\r\n * is not required to be implemented. It is provided for data sources which\r\n * retrieve data based on the current animation time or scene state.\r\n * If implemented, update will be called by {@link DataSourceDisplay} once a frame.\r\n *\r\n * @param {JulianDate} time The simulation time.\r\n * @returns {Boolean} True if this data source is ready to be displayed at the provided time, false otherwise.\r\n */\r\nCzmlDataSource.prototype.update = function (time) {\r\n return true;\r\n};\r\n\r\n/**\r\n * A helper function used by custom CZML updater functions\r\n * which creates or updates a {@link Property} from a CZML packet.\r\n * @function\r\n *\r\n * @param {Function} type The constructor function for the property being processed.\r\n * @param {Object} object The object on which the property will be added or updated.\r\n * @param {String} propertyName The name of the property on the object.\r\n * @param {Object} packetData The CZML packet being processed.\r\n * @param {TimeInterval} interval A constraining interval for which the data is valid.\r\n * @param {String} sourceUri The originating uri of the data being processed.\r\n * @param {EntityCollection} entityCollection The collection being processsed.\r\n */\r\nCzmlDataSource.processPacketData = processPacketData;\r\n\r\n/**\r\n * A helper function used by custom CZML updater functions\r\n * which creates or updates a {@link PositionProperty} from a CZML packet.\r\n * @function\r\n *\r\n * @param {Object} object The object on which the property will be added or updated.\r\n * @param {String} propertyName The name of the property on the object.\r\n * @param {Object} packetData The CZML packet being processed.\r\n * @param {TimeInterval} interval A constraining interval for which the data is valid.\r\n * @param {String} sourceUri The originating uri of the data being processed.\r\n * @param {EntityCollection} entityCollection The collection being processsed.\r\n */\r\nCzmlDataSource.processPositionPacketData = processPositionPacketData;\r\n\r\n/**\r\n * A helper function used by custom CZML updater functions\r\n * which creates or updates a {@link MaterialProperty} from a CZML packet.\r\n * @function\r\n *\r\n * @param {Object} object The object on which the property will be added or updated.\r\n * @param {String} propertyName The name of the property on the object.\r\n * @param {Object} packetData The CZML packet being processed.\r\n * @param {TimeInterval} interval A constraining interval for which the data is valid.\r\n * @param {String} sourceUri The originating uri of the data being processed.\r\n * @param {EntityCollection} entityCollection The collection being processsed.\r\n */\r\nCzmlDataSource.processMaterialPacketData = processMaterialPacketData;\r\n\r\nCzmlDataSource._processCzml = function (\r\n czml,\r\n entityCollection,\r\n sourceUri,\r\n updaterFunctions,\r\n dataSource\r\n) {\r\n updaterFunctions = defaultValue(updaterFunctions, CzmlDataSource.updaters);\r\n\r\n if (Array.isArray(czml)) {\r\n for (var i = 0, len = czml.length; i < len; ++i) {\r\n processCzmlPacket(\r\n czml[i],\r\n entityCollection,\r\n updaterFunctions,\r\n sourceUri,\r\n dataSource\r\n );\r\n }\r\n } else {\r\n processCzmlPacket(\r\n czml,\r\n entityCollection,\r\n updaterFunctions,\r\n sourceUri,\r\n dataSource\r\n );\r\n }\r\n};\r\nexport default CzmlDataSource;\r\n","import defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\n\r\n/**\r\n * A collection of {@link DataSource} instances.\r\n * @alias DataSourceCollection\r\n * @constructor\r\n */\r\nfunction DataSourceCollection() {\r\n this._dataSources = [];\r\n this._dataSourceAdded = new Event();\r\n this._dataSourceRemoved = new Event();\r\n this._dataSourceMoved = new Event();\r\n}\r\n\r\nObject.defineProperties(DataSourceCollection.prototype, {\r\n /**\r\n * Gets the number of data sources in this collection.\r\n * @memberof DataSourceCollection.prototype\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._dataSources.length;\r\n },\r\n },\r\n\r\n /**\r\n * An event that is raised when a data source is added to the collection.\r\n * Event handlers are passed the data source that was added.\r\n * @memberof DataSourceCollection.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n dataSourceAdded: {\r\n get: function () {\r\n return this._dataSourceAdded;\r\n },\r\n },\r\n\r\n /**\r\n * An event that is raised when a data source is removed from the collection.\r\n * Event handlers are passed the data source that was removed.\r\n * @memberof DataSourceCollection.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n dataSourceRemoved: {\r\n get: function () {\r\n return this._dataSourceRemoved;\r\n },\r\n },\r\n\r\n /**\r\n * An event that is raised when a data source changes position in the collection. Event handlers are passed the data source\r\n * that was moved, its new index after the move, and its old index prior to the move.\r\n * @memberof DataSourceCollection.prototype\r\n * @type {Event}\r\n * @readonly\r\n */\r\n dataSourceMoved: {\r\n get: function () {\r\n return this._dataSourceMoved;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Adds a data source to the collection.\r\n *\r\n * @param {DataSource|Promise.} dataSource A data source or a promise to a data source to add to the collection.\r\n * When passing a promise, the data source will not actually be added\r\n * to the collection until the promise resolves successfully.\r\n * @returns {Promise.} A Promise that resolves once the data source has been added to the collection.\r\n */\r\nDataSourceCollection.prototype.add = function (dataSource) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(dataSource)) {\r\n throw new DeveloperError(\"dataSource is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var that = this;\r\n var dataSources = this._dataSources;\r\n return when(dataSource, function (value) {\r\n //Only add the data source if removeAll has not been called\r\n //Since it was added.\r\n if (dataSources === that._dataSources) {\r\n that._dataSources.push(value);\r\n that._dataSourceAdded.raiseEvent(that, value);\r\n }\r\n return value;\r\n });\r\n};\r\n\r\n/**\r\n * Removes a data source from this collection, if present.\r\n *\r\n * @param {DataSource} dataSource The data source to remove.\r\n * @param {Boolean} [destroy=false] Whether to destroy the data source in addition to removing it.\r\n * @returns {Boolean} true if the data source was in the collection and was removed,\r\n * false if the data source was not in the collection.\r\n */\r\nDataSourceCollection.prototype.remove = function (dataSource, destroy) {\r\n destroy = defaultValue(destroy, false);\r\n\r\n var index = this._dataSources.indexOf(dataSource);\r\n if (index !== -1) {\r\n this._dataSources.splice(index, 1);\r\n this._dataSourceRemoved.raiseEvent(this, dataSource);\r\n\r\n if (destroy && typeof dataSource.destroy === \"function\") {\r\n dataSource.destroy();\r\n }\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes all data sources from this collection.\r\n *\r\n * @param {Boolean} [destroy=false] whether to destroy the data sources in addition to removing them.\r\n */\r\nDataSourceCollection.prototype.removeAll = function (destroy) {\r\n destroy = defaultValue(destroy, false);\r\n\r\n var dataSources = this._dataSources;\r\n for (var i = 0, len = dataSources.length; i < len; ++i) {\r\n var dataSource = dataSources[i];\r\n this._dataSourceRemoved.raiseEvent(this, dataSource);\r\n\r\n if (destroy && typeof dataSource.destroy === \"function\") {\r\n dataSource.destroy();\r\n }\r\n }\r\n this._dataSources = [];\r\n};\r\n\r\n/**\r\n * Checks to see if the collection contains a given data source.\r\n *\r\n * @param {DataSource} dataSource The data source to check for.\r\n * @returns {Boolean} true if the collection contains the data source, false otherwise.\r\n */\r\nDataSourceCollection.prototype.contains = function (dataSource) {\r\n return this.indexOf(dataSource) !== -1;\r\n};\r\n\r\n/**\r\n * Determines the index of a given data source in the collection.\r\n *\r\n * @param {DataSource} dataSource The data source to find the index of.\r\n * @returns {Number} The index of the data source in the collection, or -1 if the data source does not exist in the collection.\r\n */\r\nDataSourceCollection.prototype.indexOf = function (dataSource) {\r\n return this._dataSources.indexOf(dataSource);\r\n};\r\n\r\n/**\r\n * Gets a data source by index from the collection.\r\n *\r\n * @param {Number} index the index to retrieve.\r\n * @returns {DataSource} The data source at the specified index.\r\n */\r\nDataSourceCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._dataSources[index];\r\n};\r\n\r\n/**\r\n * Gets a data source by name from the collection.\r\n *\r\n * @param {String} name The name to retrieve.\r\n * @returns {DataSource[]} A list of all data sources matching the provided name.\r\n */\r\nDataSourceCollection.prototype.getByName = function (name) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(name)) {\r\n throw new DeveloperError(\"name is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._dataSources.filter(function (dataSource) {\r\n return dataSource.name === name;\r\n });\r\n};\r\n\r\nfunction getIndex(dataSources, dataSource) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(dataSource)) {\r\n throw new DeveloperError(\"dataSource is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var index = dataSources.indexOf(dataSource);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (index === -1) {\r\n throw new DeveloperError(\"dataSource is not in this collection.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return index;\r\n}\r\n\r\nfunction swapDataSources(collection, i, j) {\r\n var arr = collection._dataSources;\r\n var length = arr.length - 1;\r\n i = CesiumMath.clamp(i, 0, length);\r\n j = CesiumMath.clamp(j, 0, length);\r\n\r\n if (i === j) {\r\n return;\r\n }\r\n\r\n var temp = arr[i];\r\n arr[i] = arr[j];\r\n arr[j] = temp;\r\n\r\n collection.dataSourceMoved.raiseEvent(temp, j, i);\r\n}\r\n\r\n/**\r\n * Raises a data source up one position in the collection.\r\n *\r\n * @param {DataSource} dataSource The data source to move.\r\n *\r\n * @exception {DeveloperError} dataSource is not in this collection.\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nDataSourceCollection.prototype.raise = function (dataSource) {\r\n var index = getIndex(this._dataSources, dataSource);\r\n swapDataSources(this, index, index + 1);\r\n};\r\n\r\n/**\r\n * Lowers a data source down one position in the collection.\r\n *\r\n * @param {DataSource} dataSource The data source to move.\r\n *\r\n * @exception {DeveloperError} dataSource is not in this collection.\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nDataSourceCollection.prototype.lower = function (dataSource) {\r\n var index = getIndex(this._dataSources, dataSource);\r\n swapDataSources(this, index, index - 1);\r\n};\r\n\r\n/**\r\n * Raises a data source to the top of the collection.\r\n *\r\n * @param {DataSource} dataSource The data source to move.\r\n *\r\n * @exception {DeveloperError} dataSource is not in this collection.\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nDataSourceCollection.prototype.raiseToTop = function (dataSource) {\r\n var index = getIndex(this._dataSources, dataSource);\r\n if (index === this._dataSources.length - 1) {\r\n return;\r\n }\r\n this._dataSources.splice(index, 1);\r\n this._dataSources.push(dataSource);\r\n\r\n this.dataSourceMoved.raiseEvent(\r\n dataSource,\r\n this._dataSources.length - 1,\r\n index\r\n );\r\n};\r\n\r\n/**\r\n * Lowers a data source to the bottom of the collection.\r\n *\r\n * @param {DataSource} dataSource The data source to move.\r\n *\r\n * @exception {DeveloperError} dataSource is not in this collection.\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nDataSourceCollection.prototype.lowerToBottom = function (dataSource) {\r\n var index = getIndex(this._dataSources, dataSource);\r\n if (index === 0) {\r\n return;\r\n }\r\n this._dataSources.splice(index, 1);\r\n this._dataSources.splice(0, 0, dataSource);\r\n\r\n this.dataSourceMoved.raiseEvent(dataSource, 0, index);\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} true if this object was destroyed; otherwise, false.\r\n *\r\n * @see DataSourceCollection#destroy\r\n */\r\nDataSourceCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the resources held by all data sources in this collection. Explicitly destroying this\r\n * object allows for deterministic release of WebGL resources, instead of relying on the garbage\r\n * collector. Once this object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * dataSourceCollection = dataSourceCollection && dataSourceCollection.destroy();\r\n *\r\n * @see DataSourceCollection#isDestroyed\r\n */\r\nDataSourceCollection.prototype.destroy = function () {\r\n this.removeAll(true);\r\n return destroyObject(this);\r\n};\r\nexport default DataSourceCollection;\r\n","import createGuid from \"../Core/createGuid.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\n\r\n/**\r\n * A collection of primitives. This is most often used with {@link Scene#primitives},\r\n * but PrimitiveCollection is also a primitive itself so collections can\r\n * be added to collections forming a hierarchy.\r\n *\r\n * @alias PrimitiveCollection\r\n * @constructor\r\n *\r\n * @param {Object} [options] Object with the following properties:\r\n * @param {Boolean} [options.show=true] Determines if the primitives in the collection will be shown.\r\n * @param {Boolean} [options.destroyPrimitives=true] Determines if primitives in the collection are destroyed when they are removed.\r\n *\r\n * @example\r\n * var billboards = new Cesium.BillboardCollection();\r\n * var labels = new Cesium.LabelCollection();\r\n *\r\n * var collection = new Cesium.PrimitiveCollection();\r\n * collection.add(billboards);\r\n *\r\n * scene.primitives.add(collection); // Add collection\r\n * scene.primitives.add(labels); // Add regular primitive\r\n */\r\nfunction PrimitiveCollection(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n\r\n this._primitives = [];\r\n this._guid = createGuid();\r\n\r\n // Used by the OrderedGroundPrimitiveCollection\r\n this._zIndex = undefined;\r\n\r\n /**\r\n * Determines if primitives in this collection will be shown.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n */\r\n this.show = defaultValue(options.show, true);\r\n\r\n /**\r\n * Determines if primitives in the collection are destroyed when they are removed by\r\n * {@link PrimitiveCollection#destroy} or {@link PrimitiveCollection#remove} or implicitly\r\n * by {@link PrimitiveCollection#removeAll}.\r\n *\r\n * @type {Boolean}\r\n * @default true\r\n *\r\n * @example\r\n * // Example 1. Primitives are destroyed by default.\r\n * var primitives = new Cesium.PrimitiveCollection();\r\n * var labels = primitives.add(new Cesium.LabelCollection());\r\n * primitives = primitives.destroy();\r\n * var b = labels.isDestroyed(); // true\r\n *\r\n * @example\r\n * // Example 2. Do not destroy primitives in a collection.\r\n * var primitives = new Cesium.PrimitiveCollection();\r\n * primitives.destroyPrimitives = false;\r\n * var labels = primitives.add(new Cesium.LabelCollection());\r\n * primitives = primitives.destroy();\r\n * var b = labels.isDestroyed(); // false\r\n * labels = labels.destroy(); // explicitly destroy\r\n */\r\n this.destroyPrimitives = defaultValue(options.destroyPrimitives, true);\r\n}\r\n\r\nObject.defineProperties(PrimitiveCollection.prototype, {\r\n /**\r\n * Gets the number of primitives in the collection.\r\n *\r\n * @memberof PrimitiveCollection.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._primitives.length;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Adds a primitive to the collection.\r\n *\r\n * @param {Object} primitive The primitive to add.\r\n * @param {Number} [index] The index to add the layer at. If omitted, the primitive will be added at the bottom of all existing primitives.\r\n * @returns {Object} The primitive added to the collection.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @example\r\n * var billboards = scene.primitives.add(new Cesium.BillboardCollection());\r\n */\r\nPrimitiveCollection.prototype.add = function (primitive, index) {\r\n var hasIndex = defined(index);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(primitive)) {\r\n throw new DeveloperError(\"primitive is required.\");\r\n }\r\n if (hasIndex) {\r\n if (index < 0) {\r\n throw new DeveloperError(\"index must be greater than or equal to zero.\");\r\n } else if (index > this._primitives.length) {\r\n throw new DeveloperError(\r\n \"index must be less than or equal to the number of primitives.\"\r\n );\r\n }\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var external = (primitive._external = primitive._external || {});\r\n var composites = (external._composites = external._composites || {});\r\n composites[this._guid] = {\r\n collection: this,\r\n };\r\n\r\n if (!hasIndex) {\r\n this._primitives.push(primitive);\r\n } else {\r\n this._primitives.splice(index, 0, primitive);\r\n }\r\n\r\n return primitive;\r\n};\r\n\r\n/**\r\n * Removes a primitive from the collection.\r\n *\r\n * @param {Object} [primitive] The primitive to remove.\r\n * @returns {Boolean} true if the primitive was removed; false if the primitive is undefined or was not found in the collection.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * var billboards = scene.primitives.add(new Cesium.BillboardCollection());\r\n * scene.primitives.remove(billboards); // Returns true\r\n *\r\n * @see PrimitiveCollection#destroyPrimitives\r\n */\r\nPrimitiveCollection.prototype.remove = function (primitive) {\r\n // PERFORMANCE_IDEA: We can obviously make this a lot faster.\r\n if (this.contains(primitive)) {\r\n var index = this._primitives.indexOf(primitive);\r\n if (index !== -1) {\r\n this._primitives.splice(index, 1);\r\n\r\n delete primitive._external._composites[this._guid];\r\n\r\n if (this.destroyPrimitives) {\r\n primitive.destroy();\r\n }\r\n\r\n return true;\r\n }\r\n // else ... this is not possible, I swear.\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys a primitive, regardless of destroyPrimitives setting.\r\n * @private\r\n */\r\nPrimitiveCollection.prototype.removeAndDestroy = function (primitive) {\r\n var removed = this.remove(primitive);\r\n if (removed && !this.destroyPrimitives) {\r\n primitive.destroy();\r\n }\r\n return removed;\r\n};\r\n\r\n/**\r\n * Removes all primitives in the collection.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see PrimitiveCollection#destroyPrimitives\r\n */\r\nPrimitiveCollection.prototype.removeAll = function () {\r\n var primitives = this._primitives;\r\n var length = primitives.length;\r\n for (var i = 0; i < length; ++i) {\r\n delete primitives[i]._external._composites[this._guid];\r\n if (this.destroyPrimitives) {\r\n primitives[i].destroy();\r\n }\r\n }\r\n this._primitives = [];\r\n};\r\n\r\n/**\r\n * Determines if this collection contains a primitive.\r\n *\r\n * @param {Object} [primitive] The primitive to check for.\r\n * @returns {Boolean} true if the primitive is in the collection; false if the primitive is undefined or was not found in the collection.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see PrimitiveCollection#get\r\n */\r\nPrimitiveCollection.prototype.contains = function (primitive) {\r\n return !!(\r\n defined(primitive) &&\r\n primitive._external &&\r\n primitive._external._composites &&\r\n primitive._external._composites[this._guid]\r\n );\r\n};\r\n\r\nfunction getPrimitiveIndex(compositePrimitive, primitive) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!compositePrimitive.contains(primitive)) {\r\n throw new DeveloperError(\"primitive is not in this collection.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return compositePrimitive._primitives.indexOf(primitive);\r\n}\r\n\r\n/**\r\n * Raises a primitive \"up one\" in the collection. If all primitives in the collection are drawn\r\n * on the globe surface, this visually moves the primitive up one.\r\n *\r\n * @param {Object} [primitive] The primitive to raise.\r\n *\r\n * @exception {DeveloperError} primitive is not in this collection.\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see PrimitiveCollection#raiseToTop\r\n * @see PrimitiveCollection#lower\r\n * @see PrimitiveCollection#lowerToBottom\r\n */\r\nPrimitiveCollection.prototype.raise = function (primitive) {\r\n if (defined(primitive)) {\r\n var index = getPrimitiveIndex(this, primitive);\r\n var primitives = this._primitives;\r\n\r\n if (index !== primitives.length - 1) {\r\n var p = primitives[index];\r\n primitives[index] = primitives[index + 1];\r\n primitives[index + 1] = p;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Raises a primitive to the \"top\" of the collection. If all primitives in the collection are drawn\r\n * on the globe surface, this visually moves the primitive to the top.\r\n *\r\n * @param {Object} [primitive] The primitive to raise the top.\r\n *\r\n * @exception {DeveloperError} primitive is not in this collection.\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see PrimitiveCollection#raise\r\n * @see PrimitiveCollection#lower\r\n * @see PrimitiveCollection#lowerToBottom\r\n */\r\nPrimitiveCollection.prototype.raiseToTop = function (primitive) {\r\n if (defined(primitive)) {\r\n var index = getPrimitiveIndex(this, primitive);\r\n var primitives = this._primitives;\r\n\r\n if (index !== primitives.length - 1) {\r\n // PERFORMANCE_IDEA: Could be faster\r\n primitives.splice(index, 1);\r\n primitives.push(primitive);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Lowers a primitive \"down one\" in the collection. If all primitives in the collection are drawn\r\n * on the globe surface, this visually moves the primitive down one.\r\n *\r\n * @param {Object} [primitive] The primitive to lower.\r\n *\r\n * @exception {DeveloperError} primitive is not in this collection.\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see PrimitiveCollection#lowerToBottom\r\n * @see PrimitiveCollection#raise\r\n * @see PrimitiveCollection#raiseToTop\r\n */\r\nPrimitiveCollection.prototype.lower = function (primitive) {\r\n if (defined(primitive)) {\r\n var index = getPrimitiveIndex(this, primitive);\r\n var primitives = this._primitives;\r\n\r\n if (index !== 0) {\r\n var p = primitives[index];\r\n primitives[index] = primitives[index - 1];\r\n primitives[index - 1] = p;\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Lowers a primitive to the \"bottom\" of the collection. If all primitives in the collection are drawn\r\n * on the globe surface, this visually moves the primitive to the bottom.\r\n *\r\n * @param {Object} [primitive] The primitive to lower to the bottom.\r\n *\r\n * @exception {DeveloperError} primitive is not in this collection.\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see PrimitiveCollection#lower\r\n * @see PrimitiveCollection#raise\r\n * @see PrimitiveCollection#raiseToTop\r\n */\r\nPrimitiveCollection.prototype.lowerToBottom = function (primitive) {\r\n if (defined(primitive)) {\r\n var index = getPrimitiveIndex(this, primitive);\r\n var primitives = this._primitives;\r\n\r\n if (index !== 0) {\r\n // PERFORMANCE_IDEA: Could be faster\r\n primitives.splice(index, 1);\r\n primitives.unshift(primitive);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Returns the primitive in the collection at the specified index.\r\n *\r\n * @param {Number} index The zero-based index of the primitive to return.\r\n * @returns {Object} The primitive at the index.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * // Toggle the show property of every primitive in the collection.\r\n * var primitives = scene.primitives;\r\n * var length = primitives.length;\r\n * for (var i = 0; i < length; ++i) {\r\n * var p = primitives.get(i);\r\n * p.show = !p.show;\r\n * }\r\n *\r\n * @see PrimitiveCollection#length\r\n */\r\nPrimitiveCollection.prototype.get = function (index) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(index)) {\r\n throw new DeveloperError(\"index is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return this._primitives[index];\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitiveCollection.prototype.update = function (frameState) {\r\n if (!this.show) {\r\n return;\r\n }\r\n\r\n var primitives = this._primitives;\r\n // Using primitives.length in the loop is a temporary workaround\r\n // to allow quadtree updates to add and remove primitives in\r\n // update(). This will be changed to manage added and removed lists.\r\n for (var i = 0; i < primitives.length; ++i) {\r\n primitives[i].update(frameState);\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitiveCollection.prototype.prePassesUpdate = function (frameState) {\r\n var primitives = this._primitives;\r\n // Using primitives.length in the loop is a temporary workaround\r\n // to allow quadtree updates to add and remove primitives in\r\n // update(). This will be changed to manage added and removed lists.\r\n for (var i = 0; i < primitives.length; ++i) {\r\n var primitive = primitives[i];\r\n if (defined(primitive.prePassesUpdate)) {\r\n primitive.prePassesUpdate(frameState);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitiveCollection.prototype.updateForPass = function (frameState, passState) {\r\n var primitives = this._primitives;\r\n // Using primitives.length in the loop is a temporary workaround\r\n // to allow quadtree updates to add and remove primitives in\r\n // update(). This will be changed to manage added and removed lists.\r\n for (var i = 0; i < primitives.length; ++i) {\r\n var primitive = primitives[i];\r\n if (defined(primitive.updateForPass)) {\r\n primitive.updateForPass(frameState, passState);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPrimitiveCollection.prototype.postPassesUpdate = function (frameState) {\r\n var primitives = this._primitives;\r\n // Using primitives.length in the loop is a temporary workaround\r\n // to allow quadtree updates to add and remove primitives in\r\n // update(). This will be changed to manage added and removed lists.\r\n for (var i = 0; i < primitives.length; ++i) {\r\n var primitive = primitives[i];\r\n if (defined(primitive.postPassesUpdate)) {\r\n primitive.postPassesUpdate(frameState);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n *\r\n * @see PrimitiveCollection#destroy\r\n */\r\nPrimitiveCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by each primitive in this collection. Explicitly destroying this\r\n * collection allows for deterministic release of WebGL resources, instead of relying on the garbage\r\n * collector to destroy this collection.\r\n *

\r\n * Since destroying a collection destroys all the contained primitives, only destroy a collection\r\n * when you are sure no other code is still using any of the contained primitives.\r\n *

\r\n * Once this collection is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * primitives = primitives && primitives.destroy();\r\n *\r\n * @see PrimitiveCollection#isDestroyed\r\n */\r\nPrimitiveCollection.prototype.destroy = function () {\r\n this.removeAll();\r\n return destroyObject(this);\r\n};\r\nexport default PrimitiveCollection;\r\n","import Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport PrimitiveCollection from \"./PrimitiveCollection.js\";\r\n\r\n/**\r\n * A primitive collection for helping maintain the order or ground primitives based on a z-index\r\n *\r\n * @private\r\n */\r\nfunction OrderedGroundPrimitiveCollection() {\r\n this._length = 0;\r\n this._collections = {};\r\n this._collectionsArray = [];\r\n\r\n this.show = true;\r\n}\r\n\r\nObject.defineProperties(OrderedGroundPrimitiveCollection.prototype, {\r\n /**\r\n * Gets the number of primitives in the collection.\r\n *\r\n * @memberof OrderedGroundPrimitiveCollection.prototype\r\n *\r\n * @type {Number}\r\n * @readonly\r\n */\r\n length: {\r\n get: function () {\r\n return this._length;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Adds a primitive to the collection.\r\n *\r\n * @param {GroundPrimitive} primitive The primitive to add.\r\n * @param {Number} [zIndex = 0] The index of the primitive\r\n * @returns {GroundPrimitive} The primitive added to the collection.\r\n */\r\nOrderedGroundPrimitiveCollection.prototype.add = function (primitive, zIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"primitive\", primitive);\r\n if (defined(zIndex)) {\r\n Check.typeOf.number(\"zIndex\", zIndex);\r\n }\r\n //>>includeEnd('debug');\r\n\r\n zIndex = defaultValue(zIndex, 0);\r\n var collection = this._collections[zIndex];\r\n if (!defined(collection)) {\r\n collection = new PrimitiveCollection({ destroyPrimitives: false });\r\n collection._zIndex = zIndex;\r\n this._collections[zIndex] = collection;\r\n var array = this._collectionsArray;\r\n var i = 0;\r\n while (i < array.length && array[i]._zIndex < zIndex) {\r\n i++;\r\n }\r\n array.splice(i, 0, collection);\r\n }\r\n\r\n collection.add(primitive);\r\n this._length++;\r\n primitive._zIndex = zIndex;\r\n\r\n return primitive;\r\n};\r\n\r\n/**\r\n * Adjusts the z-index\r\n * @param {GroundPrimitive} primitive\r\n * @param {Number} zIndex\r\n */\r\nOrderedGroundPrimitiveCollection.prototype.set = function (primitive, zIndex) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"primitive\", primitive);\r\n Check.typeOf.number(\"zIndex\", zIndex);\r\n //>>includeEnd('debug');\r\n\r\n if (zIndex === primitive._zIndex) {\r\n return primitive;\r\n }\r\n\r\n this.remove(primitive, true);\r\n this.add(primitive, zIndex);\r\n\r\n return primitive;\r\n};\r\n\r\n/**\r\n * Removes a primitive from the collection.\r\n *\r\n * @param {Object} primitive The primitive to remove.\r\n * @param {Boolean} [doNotDestroy = false]\r\n * @returns {Boolean} true if the primitive was removed; false if the primitive is undefined or was not found in the collection.\r\n */\r\nOrderedGroundPrimitiveCollection.prototype.remove = function (\r\n primitive,\r\n doNotDestroy\r\n) {\r\n if (this.contains(primitive)) {\r\n var index = primitive._zIndex;\r\n var collection = this._collections[index];\r\n var result;\r\n if (doNotDestroy) {\r\n result = collection.remove(primitive);\r\n } else {\r\n result = collection.removeAndDestroy(primitive);\r\n }\r\n\r\n if (result) {\r\n this._length--;\r\n }\r\n\r\n if (collection.length === 0) {\r\n this._collectionsArray.splice(\r\n this._collectionsArray.indexOf(collection),\r\n 1\r\n );\r\n this._collections[index] = undefined;\r\n collection.destroy();\r\n }\r\n\r\n return result;\r\n }\r\n\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes all primitives in the collection.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n * @see OrderedGroundPrimitiveCollection#destroyPrimitives\r\n */\r\nOrderedGroundPrimitiveCollection.prototype.removeAll = function () {\r\n var collections = this._collectionsArray;\r\n for (var i = 0; i < collections.length; i++) {\r\n var collection = collections[i];\r\n collection.destroyPrimitives = true;\r\n collection.destroy();\r\n }\r\n\r\n this._collections = {};\r\n this._collectionsArray = [];\r\n this._length = 0;\r\n};\r\n\r\n/**\r\n * Determines if this collection contains a primitive.\r\n *\r\n * @param {Object} primitive The primitive to check for.\r\n * @returns {Boolean} true if the primitive is in the collection; false if the primitive is undefined or was not found in the collection.\r\n */\r\nOrderedGroundPrimitiveCollection.prototype.contains = function (primitive) {\r\n if (!defined(primitive)) {\r\n return false;\r\n }\r\n var collection = this._collections[primitive._zIndex];\r\n return defined(collection) && collection.contains(primitive);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nOrderedGroundPrimitiveCollection.prototype.update = function (frameState) {\r\n if (!this.show) {\r\n return;\r\n }\r\n\r\n var collections = this._collectionsArray;\r\n for (var i = 0; i < collections.length; i++) {\r\n collections[i].update(frameState);\r\n }\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n *\r\n * @see OrderedGroundPrimitiveCollection#destroy\r\n */\r\nOrderedGroundPrimitiveCollection.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by each primitive in this collection. Explicitly destroying this\r\n * collection allows for deterministic release of WebGL resources, instead of relying on the garbage\r\n * collector to destroy this collection.\r\n *

\r\n * Since destroying a collection destroys all the contained primitives, only destroy a collection\r\n * when you are sure no other code is still using any of the contained primitives.\r\n *

\r\n * Once this collection is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * primitives = primitives && primitives.destroy();\r\n *\r\n * @see OrderedGroundPrimitiveCollection#isDestroyed\r\n */\r\nOrderedGroundPrimitiveCollection.prototype.destroy = function () {\r\n this.removeAll();\r\n return destroyObject(this);\r\n};\r\nexport default OrderedGroundPrimitiveCollection;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicGeometryBatch(primitives, orderedGroundPrimitives) {\r\n this._primitives = primitives;\r\n this._orderedGroundPrimitives = orderedGroundPrimitives;\r\n this._dynamicUpdaters = new AssociativeArray();\r\n}\r\n\r\nDynamicGeometryBatch.prototype.add = function (time, updater) {\r\n this._dynamicUpdaters.set(\r\n updater.id,\r\n updater.createDynamicUpdater(\r\n this._primitives,\r\n this._orderedGroundPrimitives\r\n )\r\n );\r\n};\r\n\r\nDynamicGeometryBatch.prototype.remove = function (updater) {\r\n var id = updater.id;\r\n var dynamicUpdater = this._dynamicUpdaters.get(id);\r\n if (defined(dynamicUpdater)) {\r\n this._dynamicUpdaters.remove(id);\r\n dynamicUpdater.destroy();\r\n }\r\n};\r\n\r\nDynamicGeometryBatch.prototype.update = function (time) {\r\n var geometries = this._dynamicUpdaters.values;\r\n for (var i = 0, len = geometries.length; i < len; i++) {\r\n geometries[i].update(time);\r\n }\r\n return true;\r\n};\r\n\r\nDynamicGeometryBatch.prototype.removeAllPrimitives = function () {\r\n var geometries = this._dynamicUpdaters.values;\r\n for (var i = 0, len = geometries.length; i < len; i++) {\r\n geometries[i].destroy();\r\n }\r\n this._dynamicUpdaters.removeAll();\r\n};\r\n\r\nDynamicGeometryBatch.prototype.getBoundingSphere = function (updater, result) {\r\n updater = this._dynamicUpdaters.get(updater.id);\r\n if (defined(updater) && defined(updater.getBoundingSphere)) {\r\n return updater.getBoundingSphere(result);\r\n }\r\n return BoundingSphereState.FAILED;\r\n};\r\nexport default DynamicGeometryBatch;\r\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport EllipseGeometry from \"../Core/EllipseGeometry.js\";\r\nimport EllipseOutlineGeometry from \"../Core/EllipseOutlineGeometry.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport GroundGeometryUpdater from \"./GroundGeometryUpdater.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar scratchColor = new Color();\r\nvar defaultOffset = Cartesian3.ZERO;\r\nvar offsetScratch = new Cartesian3();\r\nvar scratchRectangle = new Rectangle();\r\n\r\nfunction EllipseGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.center = undefined;\r\n this.semiMajorAxis = undefined;\r\n this.semiMinorAxis = undefined;\r\n this.rotation = undefined;\r\n this.height = undefined;\r\n this.extrudedHeight = undefined;\r\n this.granularity = undefined;\r\n this.stRotation = undefined;\r\n this.numberOfVerticalLines = undefined;\r\n this.offsetAttribute = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for ellipses.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias EllipseGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction EllipseGeometryUpdater(entity, scene) {\r\n GroundGeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new EllipseGeometryOptions(entity),\r\n geometryPropertyName: \"ellipse\",\r\n observedPropertyNames: [\"availability\", \"position\", \"ellipse\"],\r\n });\r\n\r\n this._onEntityPropertyChanged(entity, \"ellipse\", entity.ellipse, undefined);\r\n}\r\n\r\nif (defined(Object.create)) {\r\n EllipseGeometryUpdater.prototype = Object.create(\r\n GroundGeometryUpdater.prototype\r\n );\r\n EllipseGeometryUpdater.prototype.constructor = EllipseGeometryUpdater;\r\n}\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nEllipseGeometryUpdater.prototype.createFillGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n ),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n this._distanceDisplayConditionProperty.getValue(time)\r\n ),\r\n offset: undefined,\r\n color: undefined,\r\n };\r\n\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n }\r\n\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new EllipseGeometry(this._options),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nEllipseGeometryUpdater.prototype.createOutlineGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n offset: undefined,\r\n };\r\n\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new EllipseOutlineGeometry(this._options),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\nEllipseGeometryUpdater.prototype._computeCenter = function (time, result) {\r\n return Property.getValueOrUndefined(this._entity.position, time, result);\r\n};\r\n\r\nEllipseGeometryUpdater.prototype._isHidden = function (entity, ellipse) {\r\n var position = entity.position;\r\n\r\n return (\r\n !defined(position) ||\r\n !defined(ellipse.semiMajorAxis) ||\r\n !defined(ellipse.semiMinorAxis) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, ellipse)\r\n );\r\n};\r\n\r\nEllipseGeometryUpdater.prototype._isDynamic = function (entity, ellipse) {\r\n return (\r\n !entity.position.isConstant || //\r\n !ellipse.semiMajorAxis.isConstant || //\r\n !ellipse.semiMinorAxis.isConstant || //\r\n !Property.isConstant(ellipse.rotation) || //\r\n !Property.isConstant(ellipse.height) || //\r\n !Property.isConstant(ellipse.extrudedHeight) || //\r\n !Property.isConstant(ellipse.granularity) || //\r\n !Property.isConstant(ellipse.stRotation) || //\r\n !Property.isConstant(ellipse.outlineWidth) || //\r\n !Property.isConstant(ellipse.numberOfVerticalLines) || //\r\n !Property.isConstant(ellipse.zIndex) || //\r\n (this._onTerrain &&\r\n !Property.isConstant(this._materialProperty) &&\r\n !(this._materialProperty instanceof ColorMaterialProperty))\r\n );\r\n};\r\n\r\nEllipseGeometryUpdater.prototype._setStaticOptions = function (\r\n entity,\r\n ellipse\r\n) {\r\n var heightValue = Property.getValueOrUndefined(\r\n ellipse.height,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n var heightReferenceValue = Property.getValueOrDefault(\r\n ellipse.heightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightValue = Property.getValueOrUndefined(\r\n ellipse.extrudedHeight,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n var extrudedHeightReferenceValue = Property.getValueOrDefault(\r\n ellipse.extrudedHeightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n if (defined(extrudedHeightValue) && !defined(heightValue)) {\r\n heightValue = 0;\r\n }\r\n\r\n var options = this._options;\r\n options.vertexFormat =\r\n this._materialProperty instanceof ColorMaterialProperty\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.center = entity.position.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.center\r\n );\r\n options.semiMajorAxis = ellipse.semiMajorAxis.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.semiMajorAxis\r\n );\r\n options.semiMinorAxis = ellipse.semiMinorAxis.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.semiMinorAxis\r\n );\r\n options.rotation = Property.getValueOrUndefined(\r\n ellipse.rotation,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.granularity = Property.getValueOrUndefined(\r\n ellipse.granularity,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.stRotation = Property.getValueOrUndefined(\r\n ellipse.stRotation,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.numberOfVerticalLines = Property.getValueOrUndefined(\r\n ellipse.numberOfVerticalLines,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.offsetAttribute = GroundGeometryUpdater.computeGeometryOffsetAttribute(\r\n heightValue,\r\n heightReferenceValue,\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n options.height = GroundGeometryUpdater.getGeometryHeight(\r\n heightValue,\r\n heightReferenceValue\r\n );\r\n\r\n extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {\r\n extrudedHeightValue = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n EllipseGeometry.computeRectangle(options, scratchRectangle)\r\n ).minimumTerrainHeight;\r\n }\r\n\r\n options.extrudedHeight = extrudedHeightValue;\r\n};\r\n\r\nEllipseGeometryUpdater.DynamicGeometryUpdater = DynamicEllipseGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicEllipseGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicEllipseGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicEllipseGeometryUpdater.prototype.constructor = DynamicEllipseGeometryUpdater;\r\n}\r\n\r\nDynamicEllipseGeometryUpdater.prototype._isHidden = function (\r\n entity,\r\n ellipse,\r\n time\r\n) {\r\n var options = this._options;\r\n return (\r\n !defined(options.center) ||\r\n !defined(options.semiMajorAxis) ||\r\n !defined(options.semiMinorAxis) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(this, entity, ellipse, time)\r\n );\r\n};\r\n\r\nDynamicEllipseGeometryUpdater.prototype._setOptions = function (\r\n entity,\r\n ellipse,\r\n time\r\n) {\r\n var options = this._options;\r\n var heightValue = Property.getValueOrUndefined(ellipse.height, time);\r\n var heightReferenceValue = Property.getValueOrDefault(\r\n ellipse.heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightValue = Property.getValueOrUndefined(\r\n ellipse.extrudedHeight,\r\n time\r\n );\r\n var extrudedHeightReferenceValue = Property.getValueOrDefault(\r\n ellipse.extrudedHeightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n if (defined(extrudedHeightValue) && !defined(heightValue)) {\r\n heightValue = 0;\r\n }\r\n\r\n options.center = Property.getValueOrUndefined(\r\n entity.position,\r\n time,\r\n options.center\r\n );\r\n options.semiMajorAxis = Property.getValueOrUndefined(\r\n ellipse.semiMajorAxis,\r\n time\r\n );\r\n options.semiMinorAxis = Property.getValueOrUndefined(\r\n ellipse.semiMinorAxis,\r\n time\r\n );\r\n options.rotation = Property.getValueOrUndefined(ellipse.rotation, time);\r\n options.granularity = Property.getValueOrUndefined(ellipse.granularity, time);\r\n options.stRotation = Property.getValueOrUndefined(ellipse.stRotation, time);\r\n options.numberOfVerticalLines = Property.getValueOrUndefined(\r\n ellipse.numberOfVerticalLines,\r\n time\r\n );\r\n options.offsetAttribute = GroundGeometryUpdater.computeGeometryOffsetAttribute(\r\n heightValue,\r\n heightReferenceValue,\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n options.height = GroundGeometryUpdater.getGeometryHeight(\r\n heightValue,\r\n heightReferenceValue\r\n );\r\n\r\n extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {\r\n extrudedHeightValue = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n EllipseGeometry.computeRectangle(options, scratchRectangle)\r\n ).minimumTerrainHeight;\r\n }\r\n\r\n options.extrudedHeight = extrudedHeightValue;\r\n};\r\nexport default EllipseGeometryUpdater;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport EllipsoidGeometry from \"../Core/EllipsoidGeometry.js\";\r\nimport EllipsoidOutlineGeometry from \"../Core/EllipsoidOutlineGeometry.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport GeometryOffsetAttribute from \"../Core/GeometryOffsetAttribute.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport Primitive from \"../Scene/Primitive.js\";\r\nimport SceneMode from \"../Scene/SceneMode.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport heightReferenceOnEntityPropertyChanged from \"./heightReferenceOnEntityPropertyChanged.js\";\r\nimport MaterialProperty from \"./MaterialProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultMaterial = new ColorMaterialProperty(Color.WHITE);\r\nvar defaultOffset = Cartesian3.ZERO;\r\n\r\nvar offsetScratch = new Cartesian3();\r\nvar radiiScratch = new Cartesian3();\r\nvar innerRadiiScratch = new Cartesian3();\r\nvar scratchColor = new Color();\r\nvar unitSphere = new Cartesian3(1, 1, 1);\r\n\r\nfunction EllipsoidGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.radii = undefined;\r\n this.innerRadii = undefined;\r\n this.minimumClock = undefined;\r\n this.maximumClock = undefined;\r\n this.minimumCone = undefined;\r\n this.maximumCone = undefined;\r\n this.stackPartitions = undefined;\r\n this.slicePartitions = undefined;\r\n this.subdivisions = undefined;\r\n this.offsetAttribute = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for ellipsoids.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias EllipsoidGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction EllipsoidGeometryUpdater(entity, scene) {\r\n GeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new EllipsoidGeometryOptions(entity),\r\n geometryPropertyName: \"ellipsoid\",\r\n observedPropertyNames: [\r\n \"availability\",\r\n \"position\",\r\n \"orientation\",\r\n \"ellipsoid\",\r\n ],\r\n });\r\n\r\n this._onEntityPropertyChanged(\r\n entity,\r\n \"ellipsoid\",\r\n entity.ellipsoid,\r\n undefined\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n EllipsoidGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);\r\n EllipsoidGeometryUpdater.prototype.constructor = EllipsoidGeometryUpdater;\r\n}\r\n\r\nObject.defineProperties(EllipsoidGeometryUpdater.prototype, {\r\n /**\r\n * Gets the terrain offset property\r\n * @type {TerrainOffsetProperty}\r\n * @memberof EllipsoidGeometryUpdater.prototype\r\n * @readonly\r\n * @private\r\n */\r\n terrainOffsetProperty: {\r\n get: function () {\r\n return this._terrainOffsetProperty;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @param {Boolean} [skipModelMatrix=false] Whether to compute a model matrix for the geometry instance\r\n * @param {Matrix4} [modelMatrixResult] Used to store the result of the model matrix calculation\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nEllipsoidGeometryUpdater.prototype.createFillGeometryInstance = function (\r\n time,\r\n skipModelMatrix,\r\n modelMatrixResult\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var color;\r\n var show = new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n );\r\n\r\n var attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n color: undefined,\r\n offset: undefined,\r\n };\r\n\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n attributes.color = color;\r\n }\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new EllipsoidGeometry(this._options),\r\n modelMatrix: skipModelMatrix\r\n ? undefined\r\n : entity.computeModelMatrixForHeightReference(\r\n time,\r\n entity.ellipsoid.heightReference,\r\n this._options.radii.z * 0.5,\r\n this._scene.mapProjection.ellipsoid,\r\n modelMatrixResult\r\n ),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @param {Boolean} [skipModelMatrix=false] Whether to compute a model matrix for the geometry instance\r\n * @param {Matrix4} [modelMatrixResult] Used to store the result of the model matrix calculation\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nEllipsoidGeometryUpdater.prototype.createOutlineGeometryInstance = function (\r\n time,\r\n skipModelMatrix,\r\n modelMatrixResult\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n offset: undefined,\r\n };\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new EllipsoidOutlineGeometry(this._options),\r\n modelMatrix: skipModelMatrix\r\n ? undefined\r\n : entity.computeModelMatrixForHeightReference(\r\n time,\r\n entity.ellipsoid.heightReference,\r\n this._options.radii.z * 0.5,\r\n this._scene.mapProjection.ellipsoid,\r\n modelMatrixResult\r\n ),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\nEllipsoidGeometryUpdater.prototype._computeCenter = function (time, result) {\r\n return Property.getValueOrUndefined(this._entity.position, time, result);\r\n};\r\n\r\nEllipsoidGeometryUpdater.prototype._isHidden = function (entity, ellipsoid) {\r\n return (\r\n !defined(entity.position) ||\r\n !defined(ellipsoid.radii) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, ellipsoid)\r\n );\r\n};\r\n\r\nEllipsoidGeometryUpdater.prototype._isDynamic = function (entity, ellipsoid) {\r\n return (\r\n !entity.position.isConstant || //\r\n !Property.isConstant(entity.orientation) || //\r\n !ellipsoid.radii.isConstant || //\r\n !Property.isConstant(ellipsoid.innerRadii) || //\r\n !Property.isConstant(ellipsoid.stackPartitions) || //\r\n !Property.isConstant(ellipsoid.slicePartitions) || //\r\n !Property.isConstant(ellipsoid.outlineWidth) || //\r\n !Property.isConstant(ellipsoid.minimumClock) || //\r\n !Property.isConstant(ellipsoid.maximumClock) || //\r\n !Property.isConstant(ellipsoid.minimumCone) || //\r\n !Property.isConstant(ellipsoid.maximumCone) || //\r\n !Property.isConstant(ellipsoid.subdivisions)\r\n );\r\n};\r\n\r\nEllipsoidGeometryUpdater.prototype._setStaticOptions = function (\r\n entity,\r\n ellipsoid\r\n) {\r\n var heightReference = Property.getValueOrDefault(\r\n ellipsoid.heightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n var options = this._options;\r\n options.vertexFormat =\r\n this._materialProperty instanceof ColorMaterialProperty\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.radii = ellipsoid.radii.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.radii\r\n );\r\n options.innerRadii = Property.getValueOrUndefined(\r\n ellipsoid.innerRadii,\r\n options.radii\r\n );\r\n options.minimumClock = Property.getValueOrUndefined(\r\n ellipsoid.minimumClock,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.maximumClock = Property.getValueOrUndefined(\r\n ellipsoid.maximumClock,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.minimumCone = Property.getValueOrUndefined(\r\n ellipsoid.minimumCone,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.maximumCone = Property.getValueOrUndefined(\r\n ellipsoid.maximumCone,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.stackPartitions = Property.getValueOrUndefined(\r\n ellipsoid.stackPartitions,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.slicePartitions = Property.getValueOrUndefined(\r\n ellipsoid.slicePartitions,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.subdivisions = Property.getValueOrUndefined(\r\n ellipsoid.subdivisions,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.offsetAttribute =\r\n heightReference !== HeightReference.NONE\r\n ? GeometryOffsetAttribute.ALL\r\n : undefined;\r\n};\r\n\r\nEllipsoidGeometryUpdater.prototype._onEntityPropertyChanged = heightReferenceOnEntityPropertyChanged;\r\n\r\nEllipsoidGeometryUpdater.DynamicGeometryUpdater = DynamicEllipsoidGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicEllipsoidGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n\r\n this._scene = geometryUpdater._scene;\r\n this._modelMatrix = new Matrix4();\r\n this._attributes = undefined;\r\n this._outlineAttributes = undefined;\r\n this._lastSceneMode = undefined;\r\n this._lastShow = undefined;\r\n this._lastOutlineShow = undefined;\r\n this._lastOutlineWidth = undefined;\r\n this._lastOutlineColor = undefined;\r\n this._lastOffset = new Cartesian3();\r\n this._material = {};\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicEllipsoidGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicEllipsoidGeometryUpdater.prototype.constructor = DynamicEllipsoidGeometryUpdater;\r\n}\r\n\r\nDynamicEllipsoidGeometryUpdater.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var ellipsoid = entity.ellipsoid;\r\n if (\r\n !entity.isShowing ||\r\n !entity.isAvailable(time) ||\r\n !Property.getValueOrDefault(ellipsoid.show, time, true)\r\n ) {\r\n if (defined(this._primitive)) {\r\n this._primitive.show = false;\r\n }\r\n\r\n if (defined(this._outlinePrimitive)) {\r\n this._outlinePrimitive.show = false;\r\n }\r\n return;\r\n }\r\n\r\n var radii = Property.getValueOrUndefined(ellipsoid.radii, time, radiiScratch);\r\n var modelMatrix = defined(radii)\r\n ? entity.computeModelMatrixForHeightReference(\r\n time,\r\n ellipsoid.heightReference,\r\n radii.z * 0.5,\r\n this._scene.mapProjection.ellipsoid,\r\n this._modelMatrix\r\n )\r\n : undefined;\r\n if (!defined(modelMatrix) || !defined(radii)) {\r\n if (defined(this._primitive)) {\r\n this._primitive.show = false;\r\n }\r\n\r\n if (defined(this._outlinePrimitive)) {\r\n this._outlinePrimitive.show = false;\r\n }\r\n return;\r\n }\r\n\r\n //Compute attributes and material.\r\n var showFill = Property.getValueOrDefault(ellipsoid.fill, time, true);\r\n var showOutline = Property.getValueOrDefault(ellipsoid.outline, time, false);\r\n var outlineColor = Property.getValueOrClonedDefault(\r\n ellipsoid.outlineColor,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var material = MaterialProperty.getValue(\r\n time,\r\n defaultValue(ellipsoid.material, defaultMaterial),\r\n this._material\r\n );\r\n\r\n // Check properties that could trigger a primitive rebuild.\r\n var innerRadii = Property.getValueOrUndefined(\r\n ellipsoid.innerRadii,\r\n time,\r\n innerRadiiScratch\r\n );\r\n var minimumClock = Property.getValueOrUndefined(ellipsoid.minimumClock, time);\r\n var maximumClock = Property.getValueOrUndefined(ellipsoid.maximumClock, time);\r\n var minimumCone = Property.getValueOrUndefined(ellipsoid.minimumCone, time);\r\n var maximumCone = Property.getValueOrUndefined(ellipsoid.maximumCone, time);\r\n var stackPartitions = Property.getValueOrUndefined(\r\n ellipsoid.stackPartitions,\r\n time\r\n );\r\n var slicePartitions = Property.getValueOrUndefined(\r\n ellipsoid.slicePartitions,\r\n time\r\n );\r\n var subdivisions = Property.getValueOrUndefined(ellipsoid.subdivisions, time);\r\n var outlineWidth = Property.getValueOrDefault(\r\n ellipsoid.outlineWidth,\r\n time,\r\n 1.0\r\n );\r\n var heightReference = Property.getValueOrDefault(\r\n ellipsoid.heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var offsetAttribute =\r\n heightReference !== HeightReference.NONE\r\n ? GeometryOffsetAttribute.ALL\r\n : undefined;\r\n\r\n //In 3D we use a fast path by modifying Primitive.modelMatrix instead of regenerating the primitive every frame.\r\n //Also check for height reference because this method doesn't work when the height is relative to terrain.\r\n var sceneMode = this._scene.mode;\r\n var in3D =\r\n sceneMode === SceneMode.SCENE3D && heightReference === HeightReference.NONE;\r\n\r\n var options = this._options;\r\n\r\n var shadows = this._geometryUpdater.shadowsProperty.getValue(time);\r\n\r\n var distanceDisplayConditionProperty = this._geometryUpdater\r\n .distanceDisplayConditionProperty;\r\n var distanceDisplayCondition = distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n var offset = Property.getValueOrDefault(\r\n this._geometryUpdater.terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n );\r\n\r\n //We only rebuild the primitive if something other than the radii has changed\r\n //For the radii, we use unit sphere and then deform it with a scale matrix.\r\n var rebuildPrimitives =\r\n !in3D ||\r\n this._lastSceneMode !== sceneMode ||\r\n !defined(this._primitive) || //\r\n options.stackPartitions !== stackPartitions ||\r\n options.slicePartitions !== slicePartitions || //\r\n (defined(innerRadii) &&\r\n !Cartesian3.equals(options.innerRadii !== innerRadii)) ||\r\n options.minimumClock !== minimumClock || //\r\n options.maximumClock !== maximumClock ||\r\n options.minimumCone !== minimumCone || //\r\n options.maximumCone !== maximumCone ||\r\n options.subdivisions !== subdivisions || //\r\n this._lastOutlineWidth !== outlineWidth ||\r\n options.offsetAttribute !== offsetAttribute;\r\n\r\n if (rebuildPrimitives) {\r\n var primitives = this._primitives;\r\n primitives.removeAndDestroy(this._primitive);\r\n primitives.removeAndDestroy(this._outlinePrimitive);\r\n this._primitive = undefined;\r\n this._outlinePrimitive = undefined;\r\n this._lastSceneMode = sceneMode;\r\n this._lastOutlineWidth = outlineWidth;\r\n\r\n options.stackPartitions = stackPartitions;\r\n options.slicePartitions = slicePartitions;\r\n options.subdivisions = subdivisions;\r\n options.offsetAttribute = offsetAttribute;\r\n options.radii = Cartesian3.clone(in3D ? unitSphere : radii, options.radii);\r\n if (defined(innerRadii)) {\r\n if (in3D) {\r\n var mag = Cartesian3.magnitude(radii);\r\n options.innerRadii = Cartesian3.fromElements(\r\n innerRadii.x / mag,\r\n innerRadii.y / mag,\r\n innerRadii.z / mag,\r\n options.innerRadii\r\n );\r\n } else {\r\n options.innerRadii = Cartesian3.clone(innerRadii, options.innerRadii);\r\n }\r\n } else {\r\n options.innerRadii = undefined;\r\n }\r\n options.minimumClock = minimumClock;\r\n options.maximumClock = maximumClock;\r\n options.minimumCone = minimumCone;\r\n options.maximumCone = maximumCone;\r\n\r\n var appearance = new MaterialAppearance({\r\n material: material,\r\n translucent: material.isTranslucent(),\r\n closed: true,\r\n });\r\n options.vertexFormat = appearance.vertexFormat;\r\n\r\n var fillInstance = this._geometryUpdater.createFillGeometryInstance(\r\n time,\r\n in3D,\r\n this._modelMatrix\r\n );\r\n\r\n this._primitive = primitives.add(\r\n new Primitive({\r\n geometryInstances: fillInstance,\r\n appearance: appearance,\r\n asynchronous: false,\r\n shadows: shadows,\r\n })\r\n );\r\n\r\n var outlineInstance = this._geometryUpdater.createOutlineGeometryInstance(\r\n time,\r\n in3D,\r\n this._modelMatrix\r\n );\r\n this._outlinePrimitive = primitives.add(\r\n new Primitive({\r\n geometryInstances: outlineInstance,\r\n appearance: new PerInstanceColorAppearance({\r\n flat: true,\r\n translucent: outlineInstance.attributes.color.value[3] !== 255,\r\n renderState: {\r\n lineWidth: this._geometryUpdater._scene.clampLineWidth(\r\n outlineWidth\r\n ),\r\n },\r\n }),\r\n asynchronous: false,\r\n shadows: shadows,\r\n })\r\n );\r\n\r\n this._lastShow = showFill;\r\n this._lastOutlineShow = showOutline;\r\n this._lastOutlineColor = Color.clone(outlineColor, this._lastOutlineColor);\r\n this._lastDistanceDisplayCondition = distanceDisplayCondition;\r\n this._lastOffset = Cartesian3.clone(offset, this._lastOffset);\r\n } else if (this._primitive.ready) {\r\n //Update attributes only.\r\n var primitive = this._primitive;\r\n var outlinePrimitive = this._outlinePrimitive;\r\n\r\n primitive.show = true;\r\n outlinePrimitive.show = true;\r\n primitive.appearance.material = material;\r\n\r\n var attributes = this._attributes;\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(entity);\r\n this._attributes = attributes;\r\n }\r\n if (showFill !== this._lastShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n showFill,\r\n attributes.show\r\n );\r\n this._lastShow = showFill;\r\n }\r\n\r\n var outlineAttributes = this._outlineAttributes;\r\n\r\n if (!defined(outlineAttributes)) {\r\n outlineAttributes = outlinePrimitive.getGeometryInstanceAttributes(\r\n entity\r\n );\r\n this._outlineAttributes = outlineAttributes;\r\n }\r\n\r\n if (showOutline !== this._lastOutlineShow) {\r\n outlineAttributes.show = ShowGeometryInstanceAttribute.toValue(\r\n showOutline,\r\n outlineAttributes.show\r\n );\r\n this._lastOutlineShow = showOutline;\r\n }\r\n\r\n if (!Color.equals(outlineColor, this._lastOutlineColor)) {\r\n outlineAttributes.color = ColorGeometryInstanceAttribute.toValue(\r\n outlineColor,\r\n outlineAttributes.color\r\n );\r\n Color.clone(outlineColor, this._lastOutlineColor);\r\n }\r\n\r\n if (\r\n !DistanceDisplayCondition.equals(\r\n distanceDisplayCondition,\r\n this._lastDistanceDisplayCondition\r\n )\r\n ) {\r\n attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(\r\n distanceDisplayCondition,\r\n attributes.distanceDisplayCondition\r\n );\r\n outlineAttributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(\r\n distanceDisplayCondition,\r\n outlineAttributes.distanceDisplayCondition\r\n );\r\n DistanceDisplayCondition.clone(\r\n distanceDisplayCondition,\r\n this._lastDistanceDisplayCondition\r\n );\r\n }\r\n\r\n if (!Cartesian3.equals(offset, this._lastOffset)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.toValue(\r\n offset,\r\n attributes.offset\r\n );\r\n outlineAttributes.offset = OffsetGeometryInstanceAttribute.toValue(\r\n offset,\r\n attributes.offset\r\n );\r\n Cartesian3.clone(offset, this._lastOffset);\r\n }\r\n }\r\n\r\n if (in3D) {\r\n //Since we are scaling a unit sphere, we can't let any of the values go to zero.\r\n //Instead we clamp them to a small value. To the naked eye, this produces the same results\r\n //that you get passing EllipsoidGeometry a radii with a zero component.\r\n radii.x = Math.max(radii.x, 0.001);\r\n radii.y = Math.max(radii.y, 0.001);\r\n radii.z = Math.max(radii.z, 0.001);\r\n\r\n modelMatrix = Matrix4.multiplyByScale(modelMatrix, radii, modelMatrix);\r\n this._primitive.modelMatrix = modelMatrix;\r\n this._outlinePrimitive.modelMatrix = modelMatrix;\r\n }\r\n};\r\nexport default EllipsoidGeometryUpdater;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport PlaneGeometry from \"../Core/PlaneGeometry.js\";\r\nimport PlaneOutlineGeometry from \"../Core/PlaneOutlineGeometry.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar positionScratch = new Cartesian3();\r\nvar scratchColor = new Color();\r\n\r\nfunction PlaneGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.plane = undefined;\r\n this.dimensions = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for planes.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias PlaneGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction PlaneGeometryUpdater(entity, scene) {\r\n GeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new PlaneGeometryOptions(entity),\r\n geometryPropertyName: \"plane\",\r\n observedPropertyNames: [\"availability\", \"position\", \"orientation\", \"plane\"],\r\n });\r\n\r\n this._onEntityPropertyChanged(entity, \"plane\", entity.plane, undefined);\r\n}\r\n\r\nif (defined(Object.create)) {\r\n PlaneGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);\r\n PlaneGeometryUpdater.prototype.constructor = PlaneGeometryUpdater;\r\n}\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nPlaneGeometryUpdater.prototype.createFillGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var attributes;\r\n\r\n var color;\r\n var show = new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n );\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n color: color,\r\n };\r\n } else {\r\n attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n };\r\n }\r\n\r\n var planeGraphics = entity.plane;\r\n var options = this._options;\r\n var modelMatrix = entity.computeModelMatrix(time);\r\n var plane = Property.getValueOrDefault(\r\n planeGraphics.plane,\r\n time,\r\n options.plane\r\n );\r\n var dimensions = Property.getValueOrUndefined(\r\n planeGraphics.dimensions,\r\n time,\r\n options.dimensions\r\n );\r\n\r\n options.plane = plane;\r\n options.dimensions = dimensions;\r\n\r\n modelMatrix = createPrimitiveMatrix(\r\n plane,\r\n dimensions,\r\n modelMatrix,\r\n modelMatrix\r\n );\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new PlaneGeometry(this._options),\r\n modelMatrix: modelMatrix,\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nPlaneGeometryUpdater.prototype.createOutlineGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n var planeGraphics = entity.plane;\r\n var options = this._options;\r\n var modelMatrix = entity.computeModelMatrix(time);\r\n var plane = Property.getValueOrDefault(\r\n planeGraphics.plane,\r\n time,\r\n options.plane\r\n );\r\n var dimensions = Property.getValueOrUndefined(\r\n planeGraphics.dimensions,\r\n time,\r\n options.dimensions\r\n );\r\n\r\n options.plane = plane;\r\n options.dimensions = dimensions;\r\n\r\n modelMatrix = createPrimitiveMatrix(\r\n plane,\r\n dimensions,\r\n modelMatrix,\r\n modelMatrix\r\n );\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new PlaneOutlineGeometry(),\r\n modelMatrix: modelMatrix,\r\n attributes: {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n },\r\n });\r\n};\r\n\r\nPlaneGeometryUpdater.prototype._isHidden = function (entity, plane) {\r\n return (\r\n !defined(plane.plane) ||\r\n !defined(plane.dimensions) ||\r\n !defined(entity.position) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, plane)\r\n );\r\n};\r\n\r\nPlaneGeometryUpdater.prototype._getIsClosed = function (options) {\r\n return false;\r\n};\r\n\r\nPlaneGeometryUpdater.prototype._isDynamic = function (entity, plane) {\r\n return (\r\n !entity.position.isConstant || //\r\n !Property.isConstant(entity.orientation) || //\r\n !plane.plane.isConstant || //\r\n !plane.dimensions.isConstant || //\r\n !Property.isConstant(plane.outlineWidth)\r\n );\r\n};\r\n\r\nPlaneGeometryUpdater.prototype._setStaticOptions = function (entity, plane) {\r\n var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;\r\n\r\n var options = this._options;\r\n options.vertexFormat = isColorMaterial\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.plane = plane.plane.getValue(Iso8601.MINIMUM_VALUE, options.plane);\r\n options.dimensions = plane.dimensions.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.dimensions\r\n );\r\n};\r\n\r\nPlaneGeometryUpdater.DynamicGeometryUpdater = DynamicPlaneGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicPlaneGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicPlaneGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicPlaneGeometryUpdater.prototype.constructor = DynamicPlaneGeometryUpdater;\r\n}\r\n\r\nDynamicPlaneGeometryUpdater.prototype._isHidden = function (\r\n entity,\r\n plane,\r\n time\r\n) {\r\n var options = this._options;\r\n var position = Property.getValueOrUndefined(\r\n entity.position,\r\n time,\r\n positionScratch\r\n );\r\n return (\r\n !defined(position) ||\r\n !defined(options.plane) ||\r\n !defined(options.dimensions) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(this, entity, plane, time)\r\n );\r\n};\r\n\r\nDynamicPlaneGeometryUpdater.prototype._setOptions = function (\r\n entity,\r\n plane,\r\n time\r\n) {\r\n var options = this._options;\r\n options.plane = Property.getValueOrDefault(plane.plane, time, options.plane);\r\n options.dimensions = Property.getValueOrUndefined(\r\n plane.dimensions,\r\n time,\r\n options.dimensions\r\n );\r\n};\r\n\r\nvar scratchAxis = new Cartesian3();\r\nvar scratchUp = new Cartesian3();\r\nvar scratchTranslation = new Cartesian3();\r\nvar scratchScale = new Cartesian3();\r\nvar scratchRotation = new Matrix3();\r\nvar scratchRotationScale = new Matrix3();\r\nvar scratchLocalTransform = new Matrix4();\r\nfunction createPrimitiveMatrix(plane, dimensions, transform, result) {\r\n var normal = plane.normal;\r\n var distance = plane.distance;\r\n\r\n var translation = Cartesian3.multiplyByScalar(\r\n normal,\r\n -distance,\r\n scratchTranslation\r\n );\r\n\r\n var up = Cartesian3.clone(Cartesian3.UNIT_Z, scratchUp);\r\n if (\r\n CesiumMath.equalsEpsilon(\r\n Math.abs(Cartesian3.dot(up, normal)),\r\n 1.0,\r\n CesiumMath.EPSILON8\r\n )\r\n ) {\r\n up = Cartesian3.clone(Cartesian3.UNIT_Y, up);\r\n }\r\n\r\n var left = Cartesian3.cross(up, normal, scratchAxis);\r\n up = Cartesian3.cross(normal, left, up);\r\n Cartesian3.normalize(left, left);\r\n Cartesian3.normalize(up, up);\r\n\r\n var rotationMatrix = scratchRotation;\r\n Matrix3.setColumn(rotationMatrix, 0, left, rotationMatrix);\r\n Matrix3.setColumn(rotationMatrix, 1, up, rotationMatrix);\r\n Matrix3.setColumn(rotationMatrix, 2, normal, rotationMatrix);\r\n\r\n var scale = Cartesian3.fromElements(\r\n dimensions.x,\r\n dimensions.y,\r\n 1.0,\r\n scratchScale\r\n );\r\n var rotationScaleMatrix = Matrix3.multiplyByScale(\r\n rotationMatrix,\r\n scale,\r\n scratchRotationScale\r\n );\r\n\r\n var localTransform = Matrix4.fromRotationTranslation(\r\n rotationScaleMatrix,\r\n translation,\r\n scratchLocalTransform\r\n );\r\n return Matrix4.multiplyTransformation(transform, localTransform, result);\r\n}\r\n\r\n/**\r\n * @private\r\n */\r\nPlaneGeometryUpdater.createPrimitiveMatrix = createPrimitiveMatrix;\r\nexport default PlaneGeometryUpdater;\r\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport ArcType from \"../Core/ArcType.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport CoplanarPolygonGeometry from \"../Core/CoplanarPolygonGeometry.js\";\r\nimport CoplanarPolygonOutlineGeometry from \"../Core/CoplanarPolygonOutlineGeometry.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport EllipsoidTangentPlane from \"../Core/EllipsoidTangentPlane.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport oneTimeWarning from \"../Core/oneTimeWarning.js\";\r\nimport PolygonGeometry from \"../Core/PolygonGeometry.js\";\r\nimport PolygonOutlineGeometry from \"../Core/PolygonOutlineGeometry.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport GroundGeometryUpdater from \"./GroundGeometryUpdater.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar heightAndPerPositionHeightWarning =\r\n \"Entity polygons cannot have both height and perPositionHeight. height will be ignored\";\r\nvar heightReferenceAndPerPositionHeightWarning =\r\n \"heightReference is not supported for entity polygons with perPositionHeight. heightReference will be ignored\";\r\n\r\nvar scratchColor = new Color();\r\nvar defaultOffset = Cartesian3.ZERO;\r\nvar offsetScratch = new Cartesian3();\r\nvar scratchRectangle = new Rectangle();\r\nvar scratch2DPositions = [];\r\nvar cart2Scratch = new Cartesian2();\r\n\r\nfunction PolygonGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.polygonHierarchy = undefined;\r\n this.perPositionHeight = undefined;\r\n this.closeTop = undefined;\r\n this.closeBottom = undefined;\r\n this.height = undefined;\r\n this.extrudedHeight = undefined;\r\n this.granularity = undefined;\r\n this.stRotation = undefined;\r\n this.offsetAttribute = undefined;\r\n this.arcType = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for polygons.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias PolygonGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction PolygonGeometryUpdater(entity, scene) {\r\n GroundGeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new PolygonGeometryOptions(entity),\r\n geometryPropertyName: \"polygon\",\r\n observedPropertyNames: [\"availability\", \"polygon\"],\r\n });\r\n\r\n this._onEntityPropertyChanged(entity, \"polygon\", entity.polygon, undefined);\r\n}\r\n\r\nif (defined(Object.create)) {\r\n PolygonGeometryUpdater.prototype = Object.create(\r\n GroundGeometryUpdater.prototype\r\n );\r\n PolygonGeometryUpdater.prototype.constructor = PolygonGeometryUpdater;\r\n}\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nPolygonGeometryUpdater.prototype.createFillGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var options = this._options;\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n ),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n this._distanceDisplayConditionProperty.getValue(time)\r\n ),\r\n offset: undefined,\r\n color: undefined,\r\n };\r\n\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n }\r\n if (defined(options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n var geometry;\r\n if (options.perPositionHeight && !defined(options.extrudedHeight)) {\r\n geometry = new CoplanarPolygonGeometry(options);\r\n } else {\r\n geometry = new PolygonGeometry(options);\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: geometry,\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nPolygonGeometryUpdater.prototype.createOutlineGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var options = this._options;\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n offset: undefined,\r\n };\r\n\r\n if (defined(options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n var geometry;\r\n if (options.perPositionHeight && !defined(options.extrudedHeight)) {\r\n geometry = new CoplanarPolygonOutlineGeometry(options);\r\n } else {\r\n geometry = new PolygonOutlineGeometry(options);\r\n }\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: geometry,\r\n attributes: attributes,\r\n });\r\n};\r\n\r\nPolygonGeometryUpdater.prototype._computeCenter = function (time, result) {\r\n var hierarchy = Property.getValueOrUndefined(\r\n this._entity.polygon.hierarchy,\r\n time\r\n );\r\n if (!defined(hierarchy)) {\r\n return;\r\n }\r\n var positions = hierarchy.positions;\r\n if (positions.length === 0) {\r\n return;\r\n }\r\n var ellipsoid = this._scene.mapProjection.ellipsoid;\r\n\r\n var tangentPlane = EllipsoidTangentPlane.fromPoints(positions, ellipsoid);\r\n var positions2D = tangentPlane.projectPointsOntoPlane(\r\n positions,\r\n scratch2DPositions\r\n );\r\n\r\n var length = positions2D.length;\r\n var area = 0;\r\n var j = length - 1;\r\n var centroid2D = new Cartesian2();\r\n for (var i = 0; i < length; j = i++) {\r\n var p1 = positions2D[i];\r\n var p2 = positions2D[j];\r\n var f = p1.x * p2.y - p2.x * p1.y;\r\n\r\n var sum = Cartesian2.add(p1, p2, cart2Scratch);\r\n sum = Cartesian2.multiplyByScalar(sum, f, sum);\r\n centroid2D = Cartesian2.add(centroid2D, sum, centroid2D);\r\n\r\n area += f;\r\n }\r\n\r\n var a = 1.0 / (area * 3.0);\r\n centroid2D = Cartesian2.multiplyByScalar(centroid2D, a, centroid2D);\r\n return tangentPlane.projectPointOntoEllipsoid(centroid2D, result);\r\n};\r\n\r\nPolygonGeometryUpdater.prototype._isHidden = function (entity, polygon) {\r\n return (\r\n !defined(polygon.hierarchy) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, polygon)\r\n );\r\n};\r\n\r\nPolygonGeometryUpdater.prototype._isOnTerrain = function (entity, polygon) {\r\n var onTerrain = GroundGeometryUpdater.prototype._isOnTerrain.call(\r\n this,\r\n entity,\r\n polygon\r\n );\r\n var perPositionHeightProperty = polygon.perPositionHeight;\r\n var perPositionHeightEnabled =\r\n defined(perPositionHeightProperty) &&\r\n (perPositionHeightProperty.isConstant\r\n ? perPositionHeightProperty.getValue(Iso8601.MINIMUM_VALUE)\r\n : true);\r\n return onTerrain && !perPositionHeightEnabled;\r\n};\r\n\r\nPolygonGeometryUpdater.prototype._isDynamic = function (entity, polygon) {\r\n return (\r\n !polygon.hierarchy.isConstant || //\r\n !Property.isConstant(polygon.height) || //\r\n !Property.isConstant(polygon.extrudedHeight) || //\r\n !Property.isConstant(polygon.granularity) || //\r\n !Property.isConstant(polygon.stRotation) || //\r\n !Property.isConstant(polygon.outlineWidth) || //\r\n !Property.isConstant(polygon.perPositionHeight) || //\r\n !Property.isConstant(polygon.closeTop) || //\r\n !Property.isConstant(polygon.closeBottom) || //\r\n !Property.isConstant(polygon.zIndex) || //\r\n !Property.isConstant(polygon.arcType) || //\r\n (this._onTerrain &&\r\n !Property.isConstant(this._materialProperty) &&\r\n !(this._materialProperty instanceof ColorMaterialProperty))\r\n );\r\n};\r\n\r\nPolygonGeometryUpdater.prototype._setStaticOptions = function (\r\n entity,\r\n polygon\r\n) {\r\n var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;\r\n\r\n var options = this._options;\r\n options.vertexFormat = isColorMaterial\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n\r\n var hierarchyValue = polygon.hierarchy.getValue(Iso8601.MINIMUM_VALUE);\r\n var heightValue = Property.getValueOrUndefined(\r\n polygon.height,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n var heightReferenceValue = Property.getValueOrDefault(\r\n polygon.heightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightValue = Property.getValueOrUndefined(\r\n polygon.extrudedHeight,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n var extrudedHeightReferenceValue = Property.getValueOrDefault(\r\n polygon.extrudedHeightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n var perPositionHeightValue = Property.getValueOrDefault(\r\n polygon.perPositionHeight,\r\n Iso8601.MINIMUM_VALUE,\r\n false\r\n );\r\n\r\n heightValue = GroundGeometryUpdater.getGeometryHeight(\r\n heightValue,\r\n heightReferenceValue\r\n );\r\n\r\n var offsetAttribute;\r\n if (perPositionHeightValue) {\r\n if (defined(heightValue)) {\r\n heightValue = undefined;\r\n oneTimeWarning(heightAndPerPositionHeightWarning);\r\n }\r\n if (\r\n heightReferenceValue !== HeightReference.NONE &&\r\n perPositionHeightValue\r\n ) {\r\n heightValue = undefined;\r\n oneTimeWarning(heightReferenceAndPerPositionHeightWarning);\r\n }\r\n } else {\r\n if (defined(extrudedHeightValue) && !defined(heightValue)) {\r\n heightValue = 0;\r\n }\r\n offsetAttribute = GroundGeometryUpdater.computeGeometryOffsetAttribute(\r\n heightValue,\r\n heightReferenceValue,\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n }\r\n\r\n options.polygonHierarchy = hierarchyValue;\r\n options.granularity = Property.getValueOrUndefined(\r\n polygon.granularity,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.stRotation = Property.getValueOrUndefined(\r\n polygon.stRotation,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.perPositionHeight = perPositionHeightValue;\r\n options.closeTop = Property.getValueOrDefault(\r\n polygon.closeTop,\r\n Iso8601.MINIMUM_VALUE,\r\n true\r\n );\r\n options.closeBottom = Property.getValueOrDefault(\r\n polygon.closeBottom,\r\n Iso8601.MINIMUM_VALUE,\r\n true\r\n );\r\n options.offsetAttribute = offsetAttribute;\r\n options.height = heightValue;\r\n options.arcType = Property.getValueOrDefault(\r\n polygon.arcType,\r\n Iso8601.MINIMUM_VALUE,\r\n ArcType.GEODESIC\r\n );\r\n\r\n extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {\r\n extrudedHeightValue = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n PolygonGeometry.computeRectangle(options, scratchRectangle)\r\n ).minimumTerrainHeight;\r\n }\r\n\r\n options.extrudedHeight = extrudedHeightValue;\r\n};\r\n\r\nPolygonGeometryUpdater.prototype._getIsClosed = function (options) {\r\n var height = options.height;\r\n var extrudedHeight = options.extrudedHeight;\r\n var isExtruded = defined(extrudedHeight) && extrudedHeight !== height;\r\n return (\r\n !options.perPositionHeight &&\r\n ((!isExtruded && height === 0) ||\r\n (isExtruded && options.closeTop && options.closeBottom))\r\n );\r\n};\r\n\r\nPolygonGeometryUpdater.DynamicGeometryUpdater = DyanmicPolygonGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DyanmicPolygonGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DyanmicPolygonGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DyanmicPolygonGeometryUpdater.prototype.constructor = DyanmicPolygonGeometryUpdater;\r\n}\r\n\r\nDyanmicPolygonGeometryUpdater.prototype._isHidden = function (\r\n entity,\r\n polygon,\r\n time\r\n) {\r\n return (\r\n !defined(this._options.polygonHierarchy) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(this, entity, polygon, time)\r\n );\r\n};\r\n\r\nDyanmicPolygonGeometryUpdater.prototype._setOptions = function (\r\n entity,\r\n polygon,\r\n time\r\n) {\r\n var options = this._options;\r\n\r\n options.polygonHierarchy = Property.getValueOrUndefined(\r\n polygon.hierarchy,\r\n time\r\n );\r\n\r\n var heightValue = Property.getValueOrUndefined(polygon.height, time);\r\n var heightReferenceValue = Property.getValueOrDefault(\r\n polygon.heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightReferenceValue = Property.getValueOrDefault(\r\n polygon.extrudedHeightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightValue = Property.getValueOrUndefined(\r\n polygon.extrudedHeight,\r\n time\r\n );\r\n var perPositionHeightValue = Property.getValueOrUndefined(\r\n polygon.perPositionHeight,\r\n time\r\n );\r\n\r\n heightValue = GroundGeometryUpdater.getGeometryHeight(\r\n heightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n\r\n var offsetAttribute;\r\n if (perPositionHeightValue) {\r\n if (defined(heightValue)) {\r\n heightValue = undefined;\r\n oneTimeWarning(heightAndPerPositionHeightWarning);\r\n }\r\n if (\r\n heightReferenceValue !== HeightReference.NONE &&\r\n perPositionHeightValue\r\n ) {\r\n heightValue = undefined;\r\n oneTimeWarning(heightReferenceAndPerPositionHeightWarning);\r\n }\r\n } else {\r\n if (defined(extrudedHeightValue) && !defined(heightValue)) {\r\n heightValue = 0;\r\n }\r\n\r\n offsetAttribute = GroundGeometryUpdater.computeGeometryOffsetAttribute(\r\n heightValue,\r\n heightReferenceValue,\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n }\r\n\r\n options.granularity = Property.getValueOrUndefined(polygon.granularity, time);\r\n options.stRotation = Property.getValueOrUndefined(polygon.stRotation, time);\r\n options.perPositionHeight = Property.getValueOrUndefined(\r\n polygon.perPositionHeight,\r\n time\r\n );\r\n options.closeTop = Property.getValueOrDefault(polygon.closeTop, time, true);\r\n options.closeBottom = Property.getValueOrDefault(\r\n polygon.closeBottom,\r\n time,\r\n true\r\n );\r\n options.offsetAttribute = offsetAttribute;\r\n options.height = heightValue;\r\n options.arcType = Property.getValueOrDefault(\r\n polygon.arcType,\r\n time,\r\n ArcType.GEODESIC\r\n );\r\n\r\n extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {\r\n extrudedHeightValue = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n PolygonGeometry.computeRectangle(options, scratchRectangle)\r\n ).minimumTerrainHeight;\r\n }\r\n\r\n options.extrudedHeight = extrudedHeightValue;\r\n};\r\nexport default PolygonGeometryUpdater;\r\n","import Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport PolylineVolumeGeometry from \"../Core/PolylineVolumeGeometry.js\";\r\nimport PolylineVolumeOutlineGeometry from \"../Core/PolylineVolumeOutlineGeometry.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar scratchColor = new Color();\r\n\r\nfunction PolylineVolumeGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.polylinePositions = undefined;\r\n this.shapePositions = undefined;\r\n this.cornerType = undefined;\r\n this.granularity = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for polyline volumes.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias PolylineVolumeGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction PolylineVolumeGeometryUpdater(entity, scene) {\r\n GeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new PolylineVolumeGeometryOptions(entity),\r\n geometryPropertyName: \"polylineVolume\",\r\n observedPropertyNames: [\"availability\", \"polylineVolume\"],\r\n });\r\n\r\n this._onEntityPropertyChanged(\r\n entity,\r\n \"polylineVolume\",\r\n entity.polylineVolume,\r\n undefined\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n PolylineVolumeGeometryUpdater.prototype = Object.create(\r\n GeometryUpdater.prototype\r\n );\r\n PolylineVolumeGeometryUpdater.prototype.constructor = PolylineVolumeGeometryUpdater;\r\n}\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nPolylineVolumeGeometryUpdater.prototype.createFillGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var attributes;\r\n\r\n var color;\r\n var show = new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n );\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n color: color,\r\n };\r\n } else {\r\n attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n };\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new PolylineVolumeGeometry(this._options),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nPolylineVolumeGeometryUpdater.prototype.createOutlineGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new PolylineVolumeOutlineGeometry(this._options),\r\n attributes: {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n },\r\n });\r\n};\r\n\r\nPolylineVolumeGeometryUpdater.prototype._isHidden = function (\r\n entity,\r\n polylineVolume\r\n) {\r\n return (\r\n !defined(polylineVolume.positions) ||\r\n !defined(polylineVolume.shape) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, polylineVolume)\r\n );\r\n};\r\n\r\nPolylineVolumeGeometryUpdater.prototype._isDynamic = function (\r\n entity,\r\n polylineVolume\r\n) {\r\n return (\r\n !polylineVolume.positions.isConstant || //\r\n !polylineVolume.shape.isConstant || //\r\n !Property.isConstant(polylineVolume.granularity) || //\r\n !Property.isConstant(polylineVolume.outlineWidth) || //\r\n !Property.isConstant(polylineVolume.cornerType)\r\n );\r\n};\r\n\r\nPolylineVolumeGeometryUpdater.prototype._setStaticOptions = function (\r\n entity,\r\n polylineVolume\r\n) {\r\n var granularity = polylineVolume.granularity;\r\n var cornerType = polylineVolume.cornerType;\r\n\r\n var options = this._options;\r\n var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;\r\n options.vertexFormat = isColorMaterial\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.polylinePositions = polylineVolume.positions.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.polylinePositions\r\n );\r\n options.shapePositions = polylineVolume.shape.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.shape\r\n );\r\n options.granularity = defined(granularity)\r\n ? granularity.getValue(Iso8601.MINIMUM_VALUE)\r\n : undefined;\r\n options.cornerType = defined(cornerType)\r\n ? cornerType.getValue(Iso8601.MINIMUM_VALUE)\r\n : undefined;\r\n};\r\n\r\nPolylineVolumeGeometryUpdater.DynamicGeometryUpdater = DynamicPolylineVolumeGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicPolylineVolumeGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicPolylineVolumeGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicPolylineVolumeGeometryUpdater.prototype.constructor = DynamicPolylineVolumeGeometryUpdater;\r\n}\r\n\r\nDynamicPolylineVolumeGeometryUpdater.prototype._isHidden = function (\r\n entity,\r\n polylineVolume,\r\n time\r\n) {\r\n var options = this._options;\r\n return (\r\n !defined(options.polylinePositions) ||\r\n !defined(options.shapePositions) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(\r\n this,\r\n entity,\r\n polylineVolume,\r\n time\r\n )\r\n );\r\n};\r\n\r\nDynamicPolylineVolumeGeometryUpdater.prototype._setOptions = function (\r\n entity,\r\n polylineVolume,\r\n time\r\n) {\r\n var options = this._options;\r\n options.polylinePositions = Property.getValueOrUndefined(\r\n polylineVolume.positions,\r\n time,\r\n options.polylinePositions\r\n );\r\n options.shapePositions = Property.getValueOrUndefined(\r\n polylineVolume.shape,\r\n time\r\n );\r\n options.granularity = Property.getValueOrUndefined(\r\n polylineVolume.granularity,\r\n time\r\n );\r\n options.cornerType = Property.getValueOrUndefined(\r\n polylineVolume.cornerType,\r\n time\r\n );\r\n};\r\nexport default PolylineVolumeGeometryUpdater;\r\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport RectangleGeometry from \"../Core/RectangleGeometry.js\";\r\nimport RectangleOutlineGeometry from \"../Core/RectangleOutlineGeometry.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport GroundGeometryUpdater from \"./GroundGeometryUpdater.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar scratchColor = new Color();\r\nvar defaultOffset = Cartesian3.ZERO;\r\nvar offsetScratch = new Cartesian3();\r\nvar scratchRectangle = new Rectangle();\r\nvar scratchCenterRect = new Rectangle();\r\nvar scratchCarto = new Cartographic();\r\n\r\nfunction RectangleGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.rectangle = undefined;\r\n this.height = undefined;\r\n this.extrudedHeight = undefined;\r\n this.granularity = undefined;\r\n this.stRotation = undefined;\r\n this.rotation = undefined;\r\n this.offsetAttribute = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for rectangles.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias RectangleGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction RectangleGeometryUpdater(entity, scene) {\r\n GroundGeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new RectangleGeometryOptions(entity),\r\n geometryPropertyName: \"rectangle\",\r\n observedPropertyNames: [\"availability\", \"rectangle\"],\r\n });\r\n\r\n this._onEntityPropertyChanged(\r\n entity,\r\n \"rectangle\",\r\n entity.rectangle,\r\n undefined\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n RectangleGeometryUpdater.prototype = Object.create(\r\n GroundGeometryUpdater.prototype\r\n );\r\n RectangleGeometryUpdater.prototype.constructor = RectangleGeometryUpdater;\r\n}\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nRectangleGeometryUpdater.prototype.createFillGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n ),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n this._distanceDisplayConditionProperty.getValue(time)\r\n ),\r\n offset: undefined,\r\n color: undefined,\r\n };\r\n\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n }\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new RectangleGeometry(this._options),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nRectangleGeometryUpdater.prototype.createOutlineGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n var attributes = {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n offset: undefined,\r\n };\r\n\r\n if (defined(this._options.offsetAttribute)) {\r\n attributes.offset = OffsetGeometryInstanceAttribute.fromCartesian3(\r\n Property.getValueOrDefault(\r\n this._terrainOffsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n )\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new RectangleOutlineGeometry(this._options),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\nRectangleGeometryUpdater.prototype._computeCenter = function (time, result) {\r\n var rect = Property.getValueOrUndefined(\r\n this._entity.rectangle.coordinates,\r\n time,\r\n scratchCenterRect\r\n );\r\n if (!defined(rect)) {\r\n return;\r\n }\r\n var center = Rectangle.center(rect, scratchCarto);\r\n return Cartographic.toCartesian(center, Ellipsoid.WGS84, result);\r\n};\r\n\r\nRectangleGeometryUpdater.prototype._isHidden = function (entity, rectangle) {\r\n return (\r\n !defined(rectangle.coordinates) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, rectangle)\r\n );\r\n};\r\n\r\nRectangleGeometryUpdater.prototype._isDynamic = function (entity, rectangle) {\r\n return (\r\n !rectangle.coordinates.isConstant || //\r\n !Property.isConstant(rectangle.height) || //\r\n !Property.isConstant(rectangle.extrudedHeight) || //\r\n !Property.isConstant(rectangle.granularity) || //\r\n !Property.isConstant(rectangle.stRotation) || //\r\n !Property.isConstant(rectangle.rotation) || //\r\n !Property.isConstant(rectangle.outlineWidth) || //\r\n !Property.isConstant(rectangle.zIndex) || //\r\n (this._onTerrain &&\r\n !Property.isConstant(this._materialProperty) &&\r\n !(this._materialProperty instanceof ColorMaterialProperty))\r\n );\r\n};\r\n\r\nRectangleGeometryUpdater.prototype._setStaticOptions = function (\r\n entity,\r\n rectangle\r\n) {\r\n var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;\r\n\r\n var heightValue = Property.getValueOrUndefined(\r\n rectangle.height,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n var heightReferenceValue = Property.getValueOrDefault(\r\n rectangle.heightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightValue = Property.getValueOrUndefined(\r\n rectangle.extrudedHeight,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n var extrudedHeightReferenceValue = Property.getValueOrDefault(\r\n rectangle.extrudedHeightReference,\r\n Iso8601.MINIMUM_VALUE,\r\n HeightReference.NONE\r\n );\r\n if (defined(extrudedHeightValue) && !defined(heightValue)) {\r\n heightValue = 0;\r\n }\r\n\r\n var options = this._options;\r\n options.vertexFormat = isColorMaterial\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.rectangle = rectangle.coordinates.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.rectangle\r\n );\r\n options.granularity = Property.getValueOrUndefined(\r\n rectangle.granularity,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.stRotation = Property.getValueOrUndefined(\r\n rectangle.stRotation,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.rotation = Property.getValueOrUndefined(\r\n rectangle.rotation,\r\n Iso8601.MINIMUM_VALUE\r\n );\r\n options.offsetAttribute = GroundGeometryUpdater.computeGeometryOffsetAttribute(\r\n heightValue,\r\n heightReferenceValue,\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n options.height = GroundGeometryUpdater.getGeometryHeight(\r\n heightValue,\r\n heightReferenceValue\r\n );\r\n\r\n extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {\r\n extrudedHeightValue = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n RectangleGeometry.computeRectangle(options, scratchRectangle)\r\n ).minimumTerrainHeight;\r\n }\r\n\r\n options.extrudedHeight = extrudedHeightValue;\r\n};\r\n\r\nRectangleGeometryUpdater.DynamicGeometryUpdater = DynamicRectangleGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicRectangleGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicRectangleGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicRectangleGeometryUpdater.prototype.constructor = DynamicRectangleGeometryUpdater;\r\n}\r\n\r\nDynamicRectangleGeometryUpdater.prototype._isHidden = function (\r\n entity,\r\n rectangle,\r\n time\r\n) {\r\n return (\r\n !defined(this._options.rectangle) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(\r\n this,\r\n entity,\r\n rectangle,\r\n time\r\n )\r\n );\r\n};\r\n\r\nDynamicRectangleGeometryUpdater.prototype._setOptions = function (\r\n entity,\r\n rectangle,\r\n time\r\n) {\r\n var options = this._options;\r\n var heightValue = Property.getValueOrUndefined(rectangle.height, time);\r\n var heightReferenceValue = Property.getValueOrDefault(\r\n rectangle.heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var extrudedHeightValue = Property.getValueOrUndefined(\r\n rectangle.extrudedHeight,\r\n time\r\n );\r\n var extrudedHeightReferenceValue = Property.getValueOrDefault(\r\n rectangle.extrudedHeightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n if (defined(extrudedHeightValue) && !defined(heightValue)) {\r\n heightValue = 0;\r\n }\r\n\r\n options.rectangle = Property.getValueOrUndefined(\r\n rectangle.coordinates,\r\n time,\r\n options.rectangle\r\n );\r\n options.granularity = Property.getValueOrUndefined(\r\n rectangle.granularity,\r\n time\r\n );\r\n options.stRotation = Property.getValueOrUndefined(rectangle.stRotation, time);\r\n options.rotation = Property.getValueOrUndefined(rectangle.rotation, time);\r\n options.offsetAttribute = GroundGeometryUpdater.computeGeometryOffsetAttribute(\r\n heightValue,\r\n heightReferenceValue,\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n options.height = GroundGeometryUpdater.getGeometryHeight(\r\n heightValue,\r\n heightReferenceValue\r\n );\r\n\r\n extrudedHeightValue = GroundGeometryUpdater.getGeometryExtrudedHeight(\r\n extrudedHeightValue,\r\n extrudedHeightReferenceValue\r\n );\r\n if (extrudedHeightValue === GroundGeometryUpdater.CLAMP_TO_GROUND) {\r\n extrudedHeightValue = ApproximateTerrainHeights.getMinimumMaximumHeights(\r\n RectangleGeometry.computeRectangle(options, scratchRectangle)\r\n ).minimumTerrainHeight;\r\n }\r\n\r\n options.extrudedHeight = extrudedHeightValue;\r\n};\r\nexport default RectangleGeometryUpdater;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport Primitive from \"../Scene/Primitive.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport MaterialProperty from \"./MaterialProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar colorScratch = new Color();\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\nvar defaultDistanceDisplayCondition = new DistanceDisplayCondition();\r\nvar defaultOffset = Cartesian3.ZERO;\r\nvar offsetScratch = new Cartesian3();\r\n\r\nfunction Batch(\r\n primitives,\r\n translucent,\r\n appearanceType,\r\n depthFailAppearanceType,\r\n depthFailMaterialProperty,\r\n closed,\r\n shadows\r\n) {\r\n this.translucent = translucent;\r\n this.appearanceType = appearanceType;\r\n this.depthFailAppearanceType = depthFailAppearanceType;\r\n this.depthFailMaterialProperty = depthFailMaterialProperty;\r\n this.depthFailMaterial = undefined;\r\n this.closed = closed;\r\n this.shadows = shadows;\r\n this.primitives = primitives;\r\n this.createPrimitive = false;\r\n this.waitingOnCreate = false;\r\n this.primitive = undefined;\r\n this.oldPrimitive = undefined;\r\n this.geometry = new AssociativeArray();\r\n this.updaters = new AssociativeArray();\r\n this.updatersWithAttributes = new AssociativeArray();\r\n this.attributes = new AssociativeArray();\r\n this.subscriptions = new AssociativeArray();\r\n this.showsUpdated = new AssociativeArray();\r\n this.itemsToRemove = [];\r\n this.invalidated = false;\r\n\r\n var removeMaterialSubscription;\r\n if (defined(depthFailMaterialProperty)) {\r\n removeMaterialSubscription = depthFailMaterialProperty.definitionChanged.addEventListener(\r\n Batch.prototype.onMaterialChanged,\r\n this\r\n );\r\n }\r\n this.removeMaterialSubscription = removeMaterialSubscription;\r\n}\r\n\r\nBatch.prototype.onMaterialChanged = function () {\r\n this.invalidated = true;\r\n};\r\n\r\nBatch.prototype.isMaterial = function (updater) {\r\n var material = this.depthFailMaterialProperty;\r\n var updaterMaterial = updater.depthFailMaterialProperty;\r\n if (updaterMaterial === material) {\r\n return true;\r\n }\r\n if (defined(material)) {\r\n return material.equals(updaterMaterial);\r\n }\r\n return false;\r\n};\r\n\r\nBatch.prototype.add = function (updater, instance) {\r\n var id = updater.id;\r\n this.createPrimitive = true;\r\n this.geometry.set(id, instance);\r\n this.updaters.set(id, updater);\r\n if (\r\n !updater.hasConstantFill ||\r\n !updater.fillMaterialProperty.isConstant ||\r\n !Property.isConstant(updater.distanceDisplayConditionProperty) ||\r\n !Property.isConstant(updater.terrainOffsetProperty)\r\n ) {\r\n this.updatersWithAttributes.set(id, updater);\r\n } else {\r\n var that = this;\r\n this.subscriptions.set(\r\n id,\r\n updater.entity.definitionChanged.addEventListener(function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n ) {\r\n if (propertyName === \"isShowing\") {\r\n that.showsUpdated.set(updater.id, updater);\r\n }\r\n })\r\n );\r\n }\r\n};\r\n\r\nBatch.prototype.remove = function (updater) {\r\n var id = updater.id;\r\n this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;\r\n if (this.updaters.remove(id)) {\r\n this.updatersWithAttributes.remove(id);\r\n var unsubscribe = this.subscriptions.get(id);\r\n if (defined(unsubscribe)) {\r\n unsubscribe();\r\n this.subscriptions.remove(id);\r\n this.showsUpdated.remove(id);\r\n }\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\nBatch.prototype.update = function (time) {\r\n var isUpdated = true;\r\n var removedCount = 0;\r\n var primitive = this.primitive;\r\n var primitives = this.primitives;\r\n var i;\r\n\r\n if (this.createPrimitive) {\r\n var geometries = this.geometry.values;\r\n var geometriesLength = geometries.length;\r\n if (geometriesLength > 0) {\r\n if (defined(primitive)) {\r\n if (!defined(this.oldPrimitive)) {\r\n this.oldPrimitive = primitive;\r\n } else {\r\n primitives.remove(primitive);\r\n }\r\n }\r\n\r\n var depthFailAppearance;\r\n if (defined(this.depthFailAppearanceType)) {\r\n if (defined(this.depthFailMaterialProperty)) {\r\n this.depthFailMaterial = MaterialProperty.getValue(\r\n time,\r\n this.depthFailMaterialProperty,\r\n this.depthFailMaterial\r\n );\r\n }\r\n depthFailAppearance = new this.depthFailAppearanceType({\r\n material: this.depthFailMaterial,\r\n translucent: this.translucent,\r\n closed: this.closed,\r\n });\r\n }\r\n\r\n primitive = new Primitive({\r\n show: false,\r\n asynchronous: true,\r\n geometryInstances: geometries.slice(),\r\n appearance: new this.appearanceType({\r\n translucent: this.translucent,\r\n closed: this.closed,\r\n }),\r\n depthFailAppearance: depthFailAppearance,\r\n shadows: this.shadows,\r\n });\r\n primitives.add(primitive);\r\n isUpdated = false;\r\n } else {\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n primitive = undefined;\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n }\r\n\r\n this.attributes.removeAll();\r\n this.primitive = primitive;\r\n this.createPrimitive = false;\r\n this.waitingOnCreate = true;\r\n } else if (defined(primitive) && primitive.ready) {\r\n primitive.show = true;\r\n if (defined(this.oldPrimitive)) {\r\n primitives.remove(this.oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n\r\n if (\r\n defined(this.depthFailAppearanceType) &&\r\n !(this.depthFailMaterialProperty instanceof ColorMaterialProperty)\r\n ) {\r\n this.depthFailMaterial = MaterialProperty.getValue(\r\n time,\r\n this.depthFailMaterialProperty,\r\n this.depthFailMaterial\r\n );\r\n this.primitive.depthFailAppearance.material = this.depthFailMaterial;\r\n }\r\n\r\n var updatersWithAttributes = this.updatersWithAttributes.values;\r\n var length = updatersWithAttributes.length;\r\n var waitingOnCreate = this.waitingOnCreate;\r\n for (i = 0; i < length; i++) {\r\n var updater = updatersWithAttributes[i];\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n if (!updater.fillMaterialProperty.isConstant || waitingOnCreate) {\r\n var colorProperty = updater.fillMaterialProperty.color;\r\n var resultColor = Property.getValueOrDefault(\r\n colorProperty,\r\n time,\r\n Color.WHITE,\r\n colorScratch\r\n );\r\n if (!Color.equals(attributes._lastColor, resultColor)) {\r\n attributes._lastColor = Color.clone(\r\n resultColor,\r\n attributes._lastColor\r\n );\r\n attributes.color = ColorGeometryInstanceAttribute.toValue(\r\n resultColor,\r\n attributes.color\r\n );\r\n if (\r\n (this.translucent && attributes.color[3] === 255) ||\r\n (!this.translucent && attributes.color[3] !== 255)\r\n ) {\r\n this.itemsToRemove[removedCount++] = updater;\r\n }\r\n }\r\n }\r\n\r\n if (\r\n defined(this.depthFailAppearanceType) &&\r\n updater.depthFailMaterialProperty instanceof ColorMaterialProperty &&\r\n (!updater.depthFailMaterialProperty.isConstant || waitingOnCreate)\r\n ) {\r\n var depthFailColorProperty = updater.depthFailMaterialProperty.color;\r\n var depthColor = Property.getValueOrDefault(\r\n depthFailColorProperty,\r\n time,\r\n Color.WHITE,\r\n colorScratch\r\n );\r\n if (!Color.equals(attributes._lastDepthFailColor, depthColor)) {\r\n attributes._lastDepthFailColor = Color.clone(\r\n depthColor,\r\n attributes._lastDepthFailColor\r\n );\r\n attributes.depthFailColor = ColorGeometryInstanceAttribute.toValue(\r\n depthColor,\r\n attributes.depthFailColor\r\n );\r\n }\r\n }\r\n\r\n var show =\r\n updater.entity.isShowing &&\r\n (updater.hasConstantFill || updater.isFilled(time));\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n }\r\n\r\n var distanceDisplayConditionProperty =\r\n updater.distanceDisplayConditionProperty;\r\n if (!Property.isConstant(distanceDisplayConditionProperty)) {\r\n var distanceDisplayCondition = Property.getValueOrDefault(\r\n distanceDisplayConditionProperty,\r\n time,\r\n defaultDistanceDisplayCondition,\r\n distanceDisplayConditionScratch\r\n );\r\n if (\r\n !DistanceDisplayCondition.equals(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n )\r\n ) {\r\n attributes._lastDistanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n );\r\n attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(\r\n distanceDisplayCondition,\r\n attributes.distanceDisplayCondition\r\n );\r\n }\r\n }\r\n\r\n var offsetProperty = updater.terrainOffsetProperty;\r\n if (!Property.isConstant(offsetProperty)) {\r\n var offset = Property.getValueOrDefault(\r\n offsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n );\r\n if (!Cartesian3.equals(offset, attributes._lastOffset)) {\r\n attributes._lastOffset = Cartesian3.clone(\r\n offset,\r\n attributes._lastOffset\r\n );\r\n attributes.offset = OffsetGeometryInstanceAttribute.toValue(\r\n offset,\r\n attributes.offset\r\n );\r\n }\r\n }\r\n }\r\n\r\n this.updateShows(primitive);\r\n this.waitingOnCreate = false;\r\n } else if (defined(primitive) && !primitive.ready) {\r\n isUpdated = false;\r\n }\r\n this.itemsToRemove.length = removedCount;\r\n return isUpdated;\r\n};\r\n\r\nBatch.prototype.updateShows = function (primitive) {\r\n var showsUpdated = this.showsUpdated.values;\r\n var length = showsUpdated.length;\r\n for (var i = 0; i < length; i++) {\r\n var updater = showsUpdated[i];\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n var show = updater.entity.isShowing;\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n instance.attributes.show.value[0] = attributes.show[0];\r\n }\r\n }\r\n this.showsUpdated.removeAll();\r\n};\r\n\r\nBatch.prototype.contains = function (updater) {\r\n return this.updaters.contains(updater.id);\r\n};\r\n\r\nBatch.prototype.getBoundingSphere = function (updater, result) {\r\n var primitive = this.primitive;\r\n if (!primitive.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n var attributes = primitive.getGeometryInstanceAttributes(updater.entity);\r\n if (\r\n !defined(attributes) ||\r\n !defined(attributes.boundingSphere) || //\r\n (defined(attributes.show) && attributes.show[0] === 0)\r\n ) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n attributes.boundingSphere.clone(result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\nBatch.prototype.destroy = function () {\r\n var primitive = this.primitive;\r\n var primitives = this.primitives;\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n }\r\n if (defined(this.removeMaterialSubscription)) {\r\n this.removeMaterialSubscription();\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nfunction StaticGeometryColorBatch(\r\n primitives,\r\n appearanceType,\r\n depthFailAppearanceType,\r\n closed,\r\n shadows\r\n) {\r\n this._solidItems = [];\r\n this._translucentItems = [];\r\n this._primitives = primitives;\r\n this._appearanceType = appearanceType;\r\n this._depthFailAppearanceType = depthFailAppearanceType;\r\n this._closed = closed;\r\n this._shadows = shadows;\r\n}\r\n\r\nStaticGeometryColorBatch.prototype.add = function (time, updater) {\r\n var items;\r\n var translucent;\r\n var instance = updater.createFillGeometryInstance(time);\r\n if (instance.attributes.color.value[3] === 255) {\r\n items = this._solidItems;\r\n translucent = false;\r\n } else {\r\n items = this._translucentItems;\r\n translucent = true;\r\n }\r\n\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n var item = items[i];\r\n if (item.isMaterial(updater)) {\r\n item.add(updater, instance);\r\n return;\r\n }\r\n }\r\n var batch = new Batch(\r\n this._primitives,\r\n translucent,\r\n this._appearanceType,\r\n this._depthFailAppearanceType,\r\n updater.depthFailMaterialProperty,\r\n this._closed,\r\n this._shadows\r\n );\r\n batch.add(updater, instance);\r\n items.push(batch);\r\n};\r\n\r\nfunction removeItem(items, updater) {\r\n var length = items.length;\r\n for (var i = length - 1; i >= 0; i--) {\r\n var item = items[i];\r\n if (item.remove(updater)) {\r\n if (item.updaters.length === 0) {\r\n items.splice(i, 1);\r\n item.destroy();\r\n }\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nStaticGeometryColorBatch.prototype.remove = function (updater) {\r\n if (!removeItem(this._solidItems, updater)) {\r\n removeItem(this._translucentItems, updater);\r\n }\r\n};\r\n\r\nfunction moveItems(batch, items, time) {\r\n var itemsMoved = false;\r\n var length = items.length;\r\n for (var i = 0; i < length; ++i) {\r\n var item = items[i];\r\n var itemsToRemove = item.itemsToRemove;\r\n var itemsToMoveLength = itemsToRemove.length;\r\n if (itemsToMoveLength > 0) {\r\n for (i = 0; i < itemsToMoveLength; i++) {\r\n var updater = itemsToRemove[i];\r\n item.remove(updater);\r\n batch.add(time, updater);\r\n itemsMoved = true;\r\n }\r\n }\r\n }\r\n return itemsMoved;\r\n}\r\n\r\nfunction updateItems(batch, items, time, isUpdated) {\r\n var length = items.length;\r\n var i;\r\n for (i = length - 1; i >= 0; i--) {\r\n var item = items[i];\r\n if (item.invalidated) {\r\n items.splice(i, 1);\r\n var updaters = item.updaters.values;\r\n var updatersLength = updaters.length;\r\n for (var h = 0; h < updatersLength; h++) {\r\n batch.add(time, updaters[h]);\r\n }\r\n item.destroy();\r\n }\r\n }\r\n\r\n length = items.length;\r\n for (i = 0; i < length; ++i) {\r\n isUpdated = items[i].update(time) && isUpdated;\r\n }\r\n return isUpdated;\r\n}\r\n\r\nStaticGeometryColorBatch.prototype.update = function (time) {\r\n //Perform initial update\r\n var isUpdated = updateItems(this, this._solidItems, time, true);\r\n isUpdated =\r\n updateItems(this, this._translucentItems, time, isUpdated) && isUpdated;\r\n\r\n //If any items swapped between solid/translucent, we need to\r\n //move them between batches\r\n var solidsMoved = moveItems(this, this._solidItems, time);\r\n var translucentsMoved = moveItems(this, this._translucentItems, time);\r\n\r\n //If we moved anything around, we need to re-build the primitive\r\n if (solidsMoved || translucentsMoved) {\r\n isUpdated =\r\n updateItems(this, this._solidItems, time, isUpdated) && isUpdated;\r\n isUpdated =\r\n updateItems(this, this._translucentItems, time, isUpdated) && isUpdated;\r\n }\r\n\r\n return isUpdated;\r\n};\r\n\r\nfunction getBoundingSphere(items, updater, result) {\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n var item = items[i];\r\n if (item.contains(updater)) {\r\n return item.getBoundingSphere(updater, result);\r\n }\r\n }\r\n return BoundingSphereState.FAILED;\r\n}\r\n\r\nStaticGeometryColorBatch.prototype.getBoundingSphere = function (\r\n updater,\r\n result\r\n) {\r\n var boundingSphere = getBoundingSphere(this._solidItems, updater, result);\r\n if (boundingSphere === BoundingSphereState.FAILED) {\r\n return getBoundingSphere(this._translucentItems, updater, result);\r\n }\r\n return boundingSphere;\r\n};\r\n\r\nfunction removeAllPrimitives(items) {\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n items[i].destroy();\r\n }\r\n items.length = 0;\r\n}\r\n\r\nStaticGeometryColorBatch.prototype.removeAllPrimitives = function () {\r\n removeAllPrimitives(this._solidItems);\r\n removeAllPrimitives(this._translucentItems);\r\n};\r\nexport default StaticGeometryColorBatch;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport Primitive from \"../Scene/Primitive.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport MaterialProperty from \"./MaterialProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\nvar defaultDistanceDisplayCondition = new DistanceDisplayCondition();\r\nvar defaultOffset = Cartesian3.ZERO;\r\nvar offsetScratch = new Cartesian3();\r\n\r\nfunction Batch(\r\n primitives,\r\n appearanceType,\r\n materialProperty,\r\n depthFailAppearanceType,\r\n depthFailMaterialProperty,\r\n closed,\r\n shadows\r\n) {\r\n this.primitives = primitives;\r\n this.appearanceType = appearanceType;\r\n this.materialProperty = materialProperty;\r\n this.depthFailAppearanceType = depthFailAppearanceType;\r\n this.depthFailMaterialProperty = depthFailMaterialProperty;\r\n this.closed = closed;\r\n this.shadows = shadows;\r\n this.updaters = new AssociativeArray();\r\n this.createPrimitive = true;\r\n this.primitive = undefined;\r\n this.oldPrimitive = undefined;\r\n this.geometry = new AssociativeArray();\r\n this.material = undefined;\r\n this.depthFailMaterial = undefined;\r\n this.updatersWithAttributes = new AssociativeArray();\r\n this.attributes = new AssociativeArray();\r\n this.invalidated = false;\r\n this.removeMaterialSubscription = materialProperty.definitionChanged.addEventListener(\r\n Batch.prototype.onMaterialChanged,\r\n this\r\n );\r\n this.subscriptions = new AssociativeArray();\r\n this.showsUpdated = new AssociativeArray();\r\n}\r\n\r\nBatch.prototype.onMaterialChanged = function () {\r\n this.invalidated = true;\r\n};\r\n\r\nBatch.prototype.isMaterial = function (updater) {\r\n var material = this.materialProperty;\r\n var updaterMaterial = updater.fillMaterialProperty;\r\n var depthFailMaterial = this.depthFailMaterialProperty;\r\n var updaterDepthFailMaterial = updater.depthFailMaterialProperty;\r\n\r\n if (\r\n updaterMaterial === material &&\r\n updaterDepthFailMaterial === depthFailMaterial\r\n ) {\r\n return true;\r\n }\r\n var equals = defined(material) && material.equals(updaterMaterial);\r\n equals =\r\n ((!defined(depthFailMaterial) && !defined(updaterDepthFailMaterial)) ||\r\n (defined(depthFailMaterial) &&\r\n depthFailMaterial.equals(updaterDepthFailMaterial))) &&\r\n equals;\r\n return equals;\r\n};\r\n\r\nBatch.prototype.add = function (time, updater) {\r\n var id = updater.id;\r\n this.updaters.set(id, updater);\r\n this.geometry.set(id, updater.createFillGeometryInstance(time));\r\n if (\r\n !updater.hasConstantFill ||\r\n !updater.fillMaterialProperty.isConstant ||\r\n !Property.isConstant(updater.distanceDisplayConditionProperty) ||\r\n !Property.isConstant(updater.terrainOffsetProperty)\r\n ) {\r\n this.updatersWithAttributes.set(id, updater);\r\n } else {\r\n var that = this;\r\n this.subscriptions.set(\r\n id,\r\n updater.entity.definitionChanged.addEventListener(function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n ) {\r\n if (propertyName === \"isShowing\") {\r\n that.showsUpdated.set(updater.id, updater);\r\n }\r\n })\r\n );\r\n }\r\n this.createPrimitive = true;\r\n};\r\n\r\nBatch.prototype.remove = function (updater) {\r\n var id = updater.id;\r\n this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;\r\n if (this.updaters.remove(id)) {\r\n this.updatersWithAttributes.remove(id);\r\n var unsubscribe = this.subscriptions.get(id);\r\n if (defined(unsubscribe)) {\r\n unsubscribe();\r\n this.subscriptions.remove(id);\r\n this.showsUpdated.remove(id);\r\n }\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\nvar colorScratch = new Color();\r\n\r\nBatch.prototype.update = function (time) {\r\n var isUpdated = true;\r\n var primitive = this.primitive;\r\n var primitives = this.primitives;\r\n var geometries = this.geometry.values;\r\n var i;\r\n\r\n if (this.createPrimitive) {\r\n var geometriesLength = geometries.length;\r\n if (geometriesLength > 0) {\r\n if (defined(primitive)) {\r\n if (!defined(this.oldPrimitive)) {\r\n this.oldPrimitive = primitive;\r\n } else {\r\n primitives.remove(primitive);\r\n }\r\n }\r\n\r\n this.material = MaterialProperty.getValue(\r\n time,\r\n this.materialProperty,\r\n this.material\r\n );\r\n\r\n var depthFailAppearance;\r\n if (defined(this.depthFailMaterialProperty)) {\r\n this.depthFailMaterial = MaterialProperty.getValue(\r\n time,\r\n this.depthFailMaterialProperty,\r\n this.depthFailMaterial\r\n );\r\n depthFailAppearance = new this.depthFailAppearanceType({\r\n material: this.depthFailMaterial,\r\n translucent: this.depthFailMaterial.isTranslucent(),\r\n closed: this.closed,\r\n });\r\n }\r\n\r\n primitive = new Primitive({\r\n show: false,\r\n asynchronous: true,\r\n geometryInstances: geometries.slice(),\r\n appearance: new this.appearanceType({\r\n material: this.material,\r\n translucent: this.material.isTranslucent(),\r\n closed: this.closed,\r\n }),\r\n depthFailAppearance: depthFailAppearance,\r\n shadows: this.shadows,\r\n });\r\n\r\n primitives.add(primitive);\r\n isUpdated = false;\r\n } else {\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n primitive = undefined;\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n }\r\n\r\n this.attributes.removeAll();\r\n this.primitive = primitive;\r\n this.createPrimitive = false;\r\n } else if (defined(primitive) && primitive.ready) {\r\n primitive.show = true;\r\n if (defined(this.oldPrimitive)) {\r\n primitives.remove(this.oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n\r\n this.material = MaterialProperty.getValue(\r\n time,\r\n this.materialProperty,\r\n this.material\r\n );\r\n this.primitive.appearance.material = this.material;\r\n\r\n if (\r\n defined(this.depthFailAppearanceType) &&\r\n !(this.depthFailMaterialProperty instanceof ColorMaterialProperty)\r\n ) {\r\n this.depthFailMaterial = MaterialProperty.getValue(\r\n time,\r\n this.depthFailMaterialProperty,\r\n this.depthFailMaterial\r\n );\r\n this.primitive.depthFailAppearance.material = this.depthFailMaterial;\r\n }\r\n\r\n var updatersWithAttributes = this.updatersWithAttributes.values;\r\n var length = updatersWithAttributes.length;\r\n for (i = 0; i < length; i++) {\r\n var updater = updatersWithAttributes[i];\r\n var entity = updater.entity;\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n if (\r\n defined(this.depthFailAppearanceType) &&\r\n this.depthFailMaterialProperty instanceof ColorMaterialProperty &&\r\n !updater.depthFailMaterialProperty.isConstant\r\n ) {\r\n var depthFailColorProperty = updater.depthFailMaterialProperty.color;\r\n var depthFailColor = Property.getValueOrDefault(\r\n depthFailColorProperty,\r\n time,\r\n Color.WHITE,\r\n colorScratch\r\n );\r\n if (!Color.equals(attributes._lastDepthFailColor, depthFailColor)) {\r\n attributes._lastDepthFailColor = Color.clone(\r\n depthFailColor,\r\n attributes._lastDepthFailColor\r\n );\r\n attributes.depthFailColor = ColorGeometryInstanceAttribute.toValue(\r\n depthFailColor,\r\n attributes.depthFailColor\r\n );\r\n }\r\n }\r\n\r\n var show =\r\n entity.isShowing && (updater.hasConstantFill || updater.isFilled(time));\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n }\r\n\r\n var distanceDisplayConditionProperty =\r\n updater.distanceDisplayConditionProperty;\r\n if (!Property.isConstant(distanceDisplayConditionProperty)) {\r\n var distanceDisplayCondition = Property.getValueOrDefault(\r\n distanceDisplayConditionProperty,\r\n time,\r\n defaultDistanceDisplayCondition,\r\n distanceDisplayConditionScratch\r\n );\r\n if (\r\n !DistanceDisplayCondition.equals(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n )\r\n ) {\r\n attributes._lastDistanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n );\r\n attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(\r\n distanceDisplayCondition,\r\n attributes.distanceDisplayCondition\r\n );\r\n }\r\n }\r\n\r\n var offsetProperty = updater.terrainOffsetProperty;\r\n if (!Property.isConstant(offsetProperty)) {\r\n var offset = Property.getValueOrDefault(\r\n offsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n );\r\n if (!Cartesian3.equals(offset, attributes._lastOffset)) {\r\n attributes._lastOffset = Cartesian3.clone(\r\n offset,\r\n attributes._lastOffset\r\n );\r\n attributes.offset = OffsetGeometryInstanceAttribute.toValue(\r\n offset,\r\n attributes.offset\r\n );\r\n }\r\n }\r\n }\r\n\r\n this.updateShows(primitive);\r\n } else if (defined(primitive) && !primitive.ready) {\r\n isUpdated = false;\r\n }\r\n return isUpdated;\r\n};\r\n\r\nBatch.prototype.updateShows = function (primitive) {\r\n var showsUpdated = this.showsUpdated.values;\r\n var length = showsUpdated.length;\r\n for (var i = 0; i < length; i++) {\r\n var updater = showsUpdated[i];\r\n var entity = updater.entity;\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n var show = entity.isShowing;\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n instance.attributes.show.value[0] = attributes.show[0];\r\n }\r\n }\r\n this.showsUpdated.removeAll();\r\n};\r\n\r\nBatch.prototype.contains = function (updater) {\r\n return this.updaters.contains(updater.id);\r\n};\r\n\r\nBatch.prototype.getBoundingSphere = function (updater, result) {\r\n var primitive = this.primitive;\r\n if (!primitive.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n var attributes = primitive.getGeometryInstanceAttributes(updater.entity);\r\n if (\r\n !defined(attributes) ||\r\n !defined(attributes.boundingSphere) ||\r\n (defined(attributes.show) && attributes.show[0] === 0)\r\n ) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n attributes.boundingSphere.clone(result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\nBatch.prototype.destroy = function () {\r\n var primitive = this.primitive;\r\n var primitives = this.primitives;\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n }\r\n this.removeMaterialSubscription();\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nfunction StaticGeometryPerMaterialBatch(\r\n primitives,\r\n appearanceType,\r\n depthFailAppearanceType,\r\n closed,\r\n shadows\r\n) {\r\n this._items = [];\r\n this._primitives = primitives;\r\n this._appearanceType = appearanceType;\r\n this._depthFailAppearanceType = depthFailAppearanceType;\r\n this._closed = closed;\r\n this._shadows = shadows;\r\n}\r\n\r\nStaticGeometryPerMaterialBatch.prototype.add = function (time, updater) {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n var item = items[i];\r\n if (item.isMaterial(updater)) {\r\n item.add(time, updater);\r\n return;\r\n }\r\n }\r\n var batch = new Batch(\r\n this._primitives,\r\n this._appearanceType,\r\n updater.fillMaterialProperty,\r\n this._depthFailAppearanceType,\r\n updater.depthFailMaterialProperty,\r\n this._closed,\r\n this._shadows\r\n );\r\n batch.add(time, updater);\r\n items.push(batch);\r\n};\r\n\r\nStaticGeometryPerMaterialBatch.prototype.remove = function (updater) {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = length - 1; i >= 0; i--) {\r\n var item = items[i];\r\n if (item.remove(updater)) {\r\n if (item.updaters.length === 0) {\r\n items.splice(i, 1);\r\n item.destroy();\r\n }\r\n break;\r\n }\r\n }\r\n};\r\n\r\nStaticGeometryPerMaterialBatch.prototype.update = function (time) {\r\n var i;\r\n var items = this._items;\r\n var length = items.length;\r\n\r\n for (i = length - 1; i >= 0; i--) {\r\n var item = items[i];\r\n if (item.invalidated) {\r\n items.splice(i, 1);\r\n var updaters = item.updaters.values;\r\n var updatersLength = updaters.length;\r\n for (var h = 0; h < updatersLength; h++) {\r\n this.add(time, updaters[h]);\r\n }\r\n item.destroy();\r\n }\r\n }\r\n\r\n var isUpdated = true;\r\n for (i = 0; i < items.length; i++) {\r\n isUpdated = items[i].update(time) && isUpdated;\r\n }\r\n return isUpdated;\r\n};\r\n\r\nStaticGeometryPerMaterialBatch.prototype.getBoundingSphere = function (\r\n updater,\r\n result\r\n) {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n var item = items[i];\r\n if (item.contains(updater)) {\r\n return item.getBoundingSphere(updater, result);\r\n }\r\n }\r\n return BoundingSphereState.FAILED;\r\n};\r\n\r\nStaticGeometryPerMaterialBatch.prototype.removeAllPrimitives = function () {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n items[i].destroy();\r\n }\r\n this._items.length = 0;\r\n};\r\nexport default StaticGeometryPerMaterialBatch;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport GroundPrimitive from \"../Scene/GroundPrimitive.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport Property from \"./Property.js\";\r\nimport RectangleCollisionChecker from \"../Core/RectangleCollisionChecker.js\";\r\n\r\nvar colorScratch = new Color();\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\nvar defaultDistanceDisplayCondition = new DistanceDisplayCondition();\r\n\r\nfunction Batch(primitives, classificationType, color, zIndex) {\r\n this.primitives = primitives;\r\n this.zIndex = zIndex;\r\n this.classificationType = classificationType;\r\n this.color = color;\r\n this.createPrimitive = false;\r\n this.waitingOnCreate = false;\r\n this.primitive = undefined;\r\n this.oldPrimitive = undefined;\r\n this.geometry = new AssociativeArray();\r\n this.updaters = new AssociativeArray();\r\n this.updatersWithAttributes = new AssociativeArray();\r\n this.attributes = new AssociativeArray();\r\n this.subscriptions = new AssociativeArray();\r\n this.showsUpdated = new AssociativeArray();\r\n this.itemsToRemove = [];\r\n this.isDirty = false;\r\n this.rectangleCollisionCheck = new RectangleCollisionChecker();\r\n}\r\n\r\nBatch.prototype.overlapping = function (rectangle) {\r\n return this.rectangleCollisionCheck.collides(rectangle);\r\n};\r\n\r\nBatch.prototype.add = function (updater, instance) {\r\n var id = updater.id;\r\n this.createPrimitive = true;\r\n this.geometry.set(id, instance);\r\n this.updaters.set(id, updater);\r\n this.rectangleCollisionCheck.insert(id, instance.geometry.rectangle);\r\n if (\r\n !updater.hasConstantFill ||\r\n !updater.fillMaterialProperty.isConstant ||\r\n !Property.isConstant(updater.distanceDisplayConditionProperty)\r\n ) {\r\n this.updatersWithAttributes.set(id, updater);\r\n } else {\r\n var that = this;\r\n this.subscriptions.set(\r\n id,\r\n updater.entity.definitionChanged.addEventListener(function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n ) {\r\n if (propertyName === \"isShowing\") {\r\n that.showsUpdated.set(updater.id, updater);\r\n }\r\n })\r\n );\r\n }\r\n};\r\n\r\nBatch.prototype.remove = function (updater) {\r\n var id = updater.id;\r\n var geometryInstance = this.geometry.get(id);\r\n this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;\r\n if (this.updaters.remove(id)) {\r\n this.rectangleCollisionCheck.remove(\r\n id,\r\n geometryInstance.geometry.rectangle\r\n );\r\n this.updatersWithAttributes.remove(id);\r\n var unsubscribe = this.subscriptions.get(id);\r\n if (defined(unsubscribe)) {\r\n unsubscribe();\r\n this.subscriptions.remove(id);\r\n this.showsUpdated.remove(id);\r\n }\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\nBatch.prototype.update = function (time) {\r\n var isUpdated = true;\r\n var removedCount = 0;\r\n var primitive = this.primitive;\r\n var primitives = this.primitives;\r\n var i;\r\n\r\n if (this.createPrimitive) {\r\n var geometries = this.geometry.values;\r\n var geometriesLength = geometries.length;\r\n if (geometriesLength > 0) {\r\n if (defined(primitive)) {\r\n if (!defined(this.oldPrimitive)) {\r\n this.oldPrimitive = primitive;\r\n } else {\r\n primitives.remove(primitive);\r\n }\r\n }\r\n\r\n primitive = new GroundPrimitive({\r\n show: false,\r\n asynchronous: true,\r\n geometryInstances: geometries.slice(),\r\n classificationType: this.classificationType,\r\n });\r\n primitives.add(primitive, this.zIndex);\r\n isUpdated = false;\r\n } else {\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n primitive = undefined;\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n }\r\n\r\n this.attributes.removeAll();\r\n this.primitive = primitive;\r\n this.createPrimitive = false;\r\n this.waitingOnCreate = true;\r\n } else if (defined(primitive) && primitive.ready) {\r\n primitive.show = true;\r\n if (defined(this.oldPrimitive)) {\r\n primitives.remove(this.oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n var updatersWithAttributes = this.updatersWithAttributes.values;\r\n var length = updatersWithAttributes.length;\r\n var waitingOnCreate = this.waitingOnCreate;\r\n for (i = 0; i < length; i++) {\r\n var updater = updatersWithAttributes[i];\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n if (!updater.fillMaterialProperty.isConstant || waitingOnCreate) {\r\n var colorProperty = updater.fillMaterialProperty.color;\r\n var fillColor = Property.getValueOrDefault(\r\n colorProperty,\r\n time,\r\n Color.WHITE,\r\n colorScratch\r\n );\r\n\r\n if (!Color.equals(attributes._lastColor, fillColor)) {\r\n attributes._lastColor = Color.clone(fillColor, attributes._lastColor);\r\n attributes.color = ColorGeometryInstanceAttribute.toValue(\r\n fillColor,\r\n attributes.color\r\n );\r\n }\r\n }\r\n\r\n var show =\r\n updater.entity.isShowing &&\r\n (updater.hasConstantFill || updater.isFilled(time));\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n }\r\n\r\n var distanceDisplayConditionProperty =\r\n updater.distanceDisplayConditionProperty;\r\n if (!Property.isConstant(distanceDisplayConditionProperty)) {\r\n var distanceDisplayCondition = Property.getValueOrDefault(\r\n distanceDisplayConditionProperty,\r\n time,\r\n defaultDistanceDisplayCondition,\r\n distanceDisplayConditionScratch\r\n );\r\n if (\r\n !DistanceDisplayCondition.equals(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n )\r\n ) {\r\n attributes._lastDistanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n );\r\n attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(\r\n distanceDisplayCondition,\r\n attributes.distanceDisplayCondition\r\n );\r\n }\r\n }\r\n }\r\n\r\n this.updateShows(primitive);\r\n this.waitingOnCreate = false;\r\n } else if (defined(primitive) && !primitive.ready) {\r\n isUpdated = false;\r\n }\r\n this.itemsToRemove.length = removedCount;\r\n return isUpdated;\r\n};\r\n\r\nBatch.prototype.updateShows = function (primitive) {\r\n var showsUpdated = this.showsUpdated.values;\r\n var length = showsUpdated.length;\r\n for (var i = 0; i < length; i++) {\r\n var updater = showsUpdated[i];\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n var show = updater.entity.isShowing;\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n instance.attributes.show.value[0] = attributes.show[0];\r\n }\r\n }\r\n this.showsUpdated.removeAll();\r\n};\r\n\r\nBatch.prototype.contains = function (updater) {\r\n return this.updaters.contains(updater.id);\r\n};\r\n\r\nBatch.prototype.getBoundingSphere = function (updater, result) {\r\n var primitive = this.primitive;\r\n if (!primitive.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n\r\n var bs = primitive.getBoundingSphere(updater.entity);\r\n if (!defined(bs)) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n bs.clone(result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\nBatch.prototype.removeAllPrimitives = function () {\r\n var primitives = this.primitives;\r\n\r\n var primitive = this.primitive;\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n this.primitive = undefined;\r\n this.geometry.removeAll();\r\n this.updaters.removeAll();\r\n }\r\n\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nfunction StaticGroundGeometryColorBatch(primitives, classificationType) {\r\n this._batches = [];\r\n this._primitives = primitives;\r\n this._classificationType = classificationType;\r\n}\r\n\r\nStaticGroundGeometryColorBatch.prototype.add = function (time, updater) {\r\n var instance = updater.createFillGeometryInstance(time);\r\n var batches = this._batches;\r\n var zIndex = Property.getValueOrDefault(updater.zIndex, 0);\r\n var batch;\r\n var length = batches.length;\r\n for (var i = 0; i < length; ++i) {\r\n var item = batches[i];\r\n if (\r\n item.zIndex === zIndex &&\r\n !item.overlapping(instance.geometry.rectangle)\r\n ) {\r\n batch = item;\r\n break;\r\n }\r\n }\r\n\r\n if (!defined(batch)) {\r\n batch = new Batch(\r\n this._primitives,\r\n this._classificationType,\r\n instance.attributes.color.value,\r\n zIndex\r\n );\r\n batches.push(batch);\r\n }\r\n batch.add(updater, instance);\r\n return batch;\r\n};\r\n\r\nStaticGroundGeometryColorBatch.prototype.remove = function (updater) {\r\n var batches = this._batches;\r\n var count = batches.length;\r\n for (var i = 0; i < count; ++i) {\r\n if (batches[i].remove(updater)) {\r\n return;\r\n }\r\n }\r\n};\r\n\r\nStaticGroundGeometryColorBatch.prototype.update = function (time) {\r\n var i;\r\n var updater;\r\n\r\n //Perform initial update\r\n var isUpdated = true;\r\n var batches = this._batches;\r\n var batchCount = batches.length;\r\n for (i = 0; i < batchCount; ++i) {\r\n isUpdated = batches[i].update(time) && isUpdated;\r\n }\r\n\r\n //If any items swapped between batches we need to move them\r\n for (i = 0; i < batchCount; ++i) {\r\n var oldBatch = batches[i];\r\n var itemsToRemove = oldBatch.itemsToRemove;\r\n var itemsToMoveLength = itemsToRemove.length;\r\n for (var j = 0; j < itemsToMoveLength; j++) {\r\n updater = itemsToRemove[j];\r\n oldBatch.remove(updater);\r\n var newBatch = this.add(time, updater);\r\n oldBatch.isDirty = true;\r\n newBatch.isDirty = true;\r\n }\r\n }\r\n\r\n //If we moved anything around, we need to re-build the primitive and remove empty batches\r\n for (i = batchCount - 1; i >= 0; --i) {\r\n var batch = batches[i];\r\n if (batch.isDirty) {\r\n isUpdated = batches[i].update(time) && isUpdated;\r\n batch.isDirty = false;\r\n }\r\n if (batch.geometry.length === 0) {\r\n batches.splice(i, 1);\r\n }\r\n }\r\n\r\n return isUpdated;\r\n};\r\n\r\nStaticGroundGeometryColorBatch.prototype.getBoundingSphere = function (\r\n updater,\r\n result\r\n) {\r\n var batches = this._batches;\r\n var batchCount = batches.length;\r\n for (var i = 0; i < batchCount; ++i) {\r\n var batch = batches[i];\r\n if (batch.contains(updater)) {\r\n return batch.getBoundingSphere(updater, result);\r\n }\r\n }\r\n\r\n return BoundingSphereState.FAILED;\r\n};\r\n\r\nStaticGroundGeometryColorBatch.prototype.removeAllPrimitives = function () {\r\n var batches = this._batches;\r\n var batchCount = batches.length;\r\n for (var i = 0; i < batchCount; ++i) {\r\n batches[i].removeAllPrimitives();\r\n }\r\n};\r\nexport default StaticGroundGeometryColorBatch;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport RectangleCollisionChecker from \"../Core/RectangleCollisionChecker.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport GroundPrimitive from \"../Scene/GroundPrimitive.js\";\r\nimport ShadowVolumeAppearance from \"../Scene/ShadowVolumeAppearance.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport MaterialProperty from \"./MaterialProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\nvar defaultDistanceDisplayCondition = new DistanceDisplayCondition();\r\n\r\n// Encapsulates a Primitive and all the entities that it represents.\r\nfunction Batch(\r\n primitives,\r\n classificationType,\r\n appearanceType,\r\n materialProperty,\r\n usingSphericalTextureCoordinates,\r\n zIndex\r\n) {\r\n this.primitives = primitives; // scene level primitive collection\r\n this.classificationType = classificationType;\r\n this.appearanceType = appearanceType;\r\n this.materialProperty = materialProperty;\r\n this.updaters = new AssociativeArray();\r\n this.createPrimitive = true;\r\n this.primitive = undefined; // a GroundPrimitive encapsulating all the entities\r\n this.oldPrimitive = undefined;\r\n this.geometry = new AssociativeArray();\r\n this.material = undefined;\r\n this.updatersWithAttributes = new AssociativeArray();\r\n this.attributes = new AssociativeArray();\r\n this.invalidated = false;\r\n this.removeMaterialSubscription = materialProperty.definitionChanged.addEventListener(\r\n Batch.prototype.onMaterialChanged,\r\n this\r\n );\r\n this.subscriptions = new AssociativeArray();\r\n this.showsUpdated = new AssociativeArray();\r\n this.usingSphericalTextureCoordinates = usingSphericalTextureCoordinates;\r\n this.zIndex = zIndex;\r\n this.rectangleCollisionCheck = new RectangleCollisionChecker();\r\n}\r\n\r\nBatch.prototype.onMaterialChanged = function () {\r\n this.invalidated = true;\r\n};\r\n\r\nBatch.prototype.overlapping = function (rectangle) {\r\n return this.rectangleCollisionCheck.collides(rectangle);\r\n};\r\n\r\n// Check if the given updater's material is compatible with this batch\r\nBatch.prototype.isMaterial = function (updater) {\r\n var material = this.materialProperty;\r\n var updaterMaterial = updater.fillMaterialProperty;\r\n\r\n if (\r\n updaterMaterial === material ||\r\n (updaterMaterial instanceof ColorMaterialProperty &&\r\n material instanceof ColorMaterialProperty)\r\n ) {\r\n return true;\r\n }\r\n return defined(material) && material.equals(updaterMaterial);\r\n};\r\n\r\nBatch.prototype.add = function (time, updater, geometryInstance) {\r\n var id = updater.id;\r\n this.updaters.set(id, updater);\r\n this.geometry.set(id, geometryInstance);\r\n this.rectangleCollisionCheck.insert(id, geometryInstance.geometry.rectangle);\r\n // Updaters with dynamic attributes must be tracked separately, may exit the batch\r\n if (\r\n !updater.hasConstantFill ||\r\n !updater.fillMaterialProperty.isConstant ||\r\n !Property.isConstant(updater.distanceDisplayConditionProperty)\r\n ) {\r\n this.updatersWithAttributes.set(id, updater);\r\n } else {\r\n var that = this;\r\n // Listen for show changes. These will be synchronized in updateShows.\r\n this.subscriptions.set(\r\n id,\r\n updater.entity.definitionChanged.addEventListener(function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n ) {\r\n if (propertyName === \"isShowing\") {\r\n that.showsUpdated.set(updater.id, updater);\r\n }\r\n })\r\n );\r\n }\r\n this.createPrimitive = true;\r\n};\r\n\r\nBatch.prototype.remove = function (updater) {\r\n var id = updater.id;\r\n var geometryInstance = this.geometry.get(id);\r\n this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;\r\n if (this.updaters.remove(id)) {\r\n this.rectangleCollisionCheck.remove(\r\n id,\r\n geometryInstance.geometry.rectangle\r\n );\r\n this.updatersWithAttributes.remove(id);\r\n var unsubscribe = this.subscriptions.get(id);\r\n if (defined(unsubscribe)) {\r\n unsubscribe();\r\n this.subscriptions.remove(id);\r\n }\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\nBatch.prototype.update = function (time) {\r\n var isUpdated = true;\r\n var primitive = this.primitive;\r\n var primitives = this.primitives;\r\n var geometries = this.geometry.values;\r\n var i;\r\n\r\n if (this.createPrimitive) {\r\n var geometriesLength = geometries.length;\r\n if (geometriesLength > 0) {\r\n if (defined(primitive)) {\r\n // Keep a handle to the old primitive so it can be removed when the updated version is ready.\r\n if (!defined(this.oldPrimitive)) {\r\n this.oldPrimitive = primitive;\r\n } else {\r\n // For if the new primitive changes again before it is ready.\r\n primitives.remove(primitive);\r\n }\r\n }\r\n\r\n this.material = MaterialProperty.getValue(\r\n time,\r\n this.materialProperty,\r\n this.material\r\n );\r\n\r\n primitive = new GroundPrimitive({\r\n show: false,\r\n asynchronous: true,\r\n geometryInstances: geometries.slice(),\r\n appearance: new this.appearanceType({\r\n material: this.material,\r\n // translucent and closed properties overridden\r\n }),\r\n classificationType: this.classificationType,\r\n });\r\n\r\n primitives.add(primitive, this.zIndex);\r\n isUpdated = false;\r\n } else {\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n primitive = undefined;\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n }\r\n\r\n this.attributes.removeAll();\r\n this.primitive = primitive;\r\n this.createPrimitive = false;\r\n } else if (defined(primitive) && primitive.ready) {\r\n primitive.show = true;\r\n if (defined(this.oldPrimitive)) {\r\n primitives.remove(this.oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n\r\n this.material = MaterialProperty.getValue(\r\n time,\r\n this.materialProperty,\r\n this.material\r\n );\r\n this.primitive.appearance.material = this.material;\r\n\r\n var updatersWithAttributes = this.updatersWithAttributes.values;\r\n var length = updatersWithAttributes.length;\r\n for (i = 0; i < length; i++) {\r\n var updater = updatersWithAttributes[i];\r\n var entity = updater.entity;\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n var show =\r\n entity.isShowing && (updater.hasConstantFill || updater.isFilled(time));\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n }\r\n\r\n var distanceDisplayConditionProperty =\r\n updater.distanceDisplayConditionProperty;\r\n if (!Property.isConstant(distanceDisplayConditionProperty)) {\r\n var distanceDisplayCondition = Property.getValueOrDefault(\r\n distanceDisplayConditionProperty,\r\n time,\r\n defaultDistanceDisplayCondition,\r\n distanceDisplayConditionScratch\r\n );\r\n if (\r\n !DistanceDisplayCondition.equals(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n )\r\n ) {\r\n attributes._lastDistanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n );\r\n attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(\r\n distanceDisplayCondition,\r\n attributes.distanceDisplayCondition\r\n );\r\n }\r\n }\r\n }\r\n\r\n this.updateShows(primitive);\r\n } else if (defined(primitive) && !primitive.ready) {\r\n isUpdated = false;\r\n }\r\n return isUpdated;\r\n};\r\n\r\nBatch.prototype.updateShows = function (primitive) {\r\n var showsUpdated = this.showsUpdated.values;\r\n var length = showsUpdated.length;\r\n for (var i = 0; i < length; i++) {\r\n var updater = showsUpdated[i];\r\n var entity = updater.entity;\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n var show = entity.isShowing;\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n instance.attributes.show.value[0] = attributes.show[0];\r\n }\r\n }\r\n this.showsUpdated.removeAll();\r\n};\r\n\r\nBatch.prototype.contains = function (updater) {\r\n return this.updaters.contains(updater.id);\r\n};\r\n\r\nBatch.prototype.getBoundingSphere = function (updater, result) {\r\n var primitive = this.primitive;\r\n if (!primitive.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n var attributes = primitive.getGeometryInstanceAttributes(updater.entity);\r\n if (\r\n !defined(attributes) ||\r\n !defined(attributes.boundingSphere) ||\r\n (defined(attributes.show) && attributes.show[0] === 0)\r\n ) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n attributes.boundingSphere.clone(result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\nBatch.prototype.destroy = function () {\r\n var primitive = this.primitive;\r\n var primitives = this.primitives;\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n }\r\n this.removeMaterialSubscription();\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nfunction StaticGroundGeometryPerMaterialBatch(\r\n primitives,\r\n classificationType,\r\n appearanceType\r\n) {\r\n this._items = [];\r\n this._primitives = primitives;\r\n this._classificationType = classificationType;\r\n this._appearanceType = appearanceType;\r\n}\r\n\r\nStaticGroundGeometryPerMaterialBatch.prototype.add = function (time, updater) {\r\n var items = this._items;\r\n var length = items.length;\r\n var geometryInstance = updater.createFillGeometryInstance(time);\r\n var usingSphericalTextureCoordinates = ShadowVolumeAppearance.shouldUseSphericalCoordinates(\r\n geometryInstance.geometry.rectangle\r\n );\r\n var zIndex = Property.getValueOrDefault(updater.zIndex, 0);\r\n // Check if the Entity represented by the updater can be placed in an existing batch. Requirements:\r\n // * compatible material (same material or same color)\r\n // * same type of texture coordinates (spherical vs. planar)\r\n // * conservatively non-overlapping with any entities in the existing batch\r\n for (var i = 0; i < length; ++i) {\r\n var item = items[i];\r\n if (\r\n item.isMaterial(updater) &&\r\n item.usingSphericalTextureCoordinates ===\r\n usingSphericalTextureCoordinates &&\r\n item.zIndex === zIndex &&\r\n !item.overlapping(geometryInstance.geometry.rectangle)\r\n ) {\r\n item.add(time, updater, geometryInstance);\r\n return;\r\n }\r\n }\r\n // If a compatible batch wasn't found, create a new batch.\r\n var batch = new Batch(\r\n this._primitives,\r\n this._classificationType,\r\n this._appearanceType,\r\n updater.fillMaterialProperty,\r\n usingSphericalTextureCoordinates,\r\n zIndex\r\n );\r\n batch.add(time, updater, geometryInstance);\r\n items.push(batch);\r\n};\r\n\r\nStaticGroundGeometryPerMaterialBatch.prototype.remove = function (updater) {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = length - 1; i >= 0; i--) {\r\n var item = items[i];\r\n if (item.remove(updater)) {\r\n if (item.updaters.length === 0) {\r\n items.splice(i, 1);\r\n item.destroy();\r\n }\r\n break;\r\n }\r\n }\r\n};\r\n\r\nStaticGroundGeometryPerMaterialBatch.prototype.update = function (time) {\r\n var i;\r\n var items = this._items;\r\n var length = items.length;\r\n\r\n for (i = length - 1; i >= 0; i--) {\r\n var item = items[i];\r\n if (item.invalidated) {\r\n items.splice(i, 1);\r\n var updaters = item.updaters.values;\r\n var updatersLength = updaters.length;\r\n for (var h = 0; h < updatersLength; h++) {\r\n this.add(time, updaters[h]);\r\n }\r\n item.destroy();\r\n }\r\n }\r\n\r\n var isUpdated = true;\r\n for (i = 0; i < items.length; i++) {\r\n isUpdated = items[i].update(time) && isUpdated;\r\n }\r\n return isUpdated;\r\n};\r\n\r\nStaticGroundGeometryPerMaterialBatch.prototype.getBoundingSphere = function (\r\n updater,\r\n result\r\n) {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n var item = items[i];\r\n if (item.contains(updater)) {\r\n return item.getBoundingSphere(updater, result);\r\n }\r\n }\r\n return BoundingSphereState.FAILED;\r\n};\r\n\r\nStaticGroundGeometryPerMaterialBatch.prototype.removeAllPrimitives = function () {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n items[i].destroy();\r\n }\r\n this._items.length = 0;\r\n};\r\nexport default StaticGroundGeometryPerMaterialBatch;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport OffsetGeometryInstanceAttribute from \"../Core/OffsetGeometryInstanceAttribute.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport Primitive from \"../Scene/Primitive.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar colorScratch = new Color();\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\nvar defaultDistanceDisplayCondition = new DistanceDisplayCondition();\r\nvar defaultOffset = Cartesian3.ZERO;\r\nvar offsetScratch = new Cartesian3();\r\n\r\nfunction Batch(primitives, translucent, width, shadows) {\r\n this.translucent = translucent;\r\n this.width = width;\r\n this.shadows = shadows;\r\n this.primitives = primitives;\r\n this.createPrimitive = false;\r\n this.waitingOnCreate = false;\r\n this.primitive = undefined;\r\n this.oldPrimitive = undefined;\r\n this.geometry = new AssociativeArray();\r\n this.updaters = new AssociativeArray();\r\n this.updatersWithAttributes = new AssociativeArray();\r\n this.attributes = new AssociativeArray();\r\n this.itemsToRemove = [];\r\n this.subscriptions = new AssociativeArray();\r\n this.showsUpdated = new AssociativeArray();\r\n}\r\nBatch.prototype.add = function (updater, instance) {\r\n var id = updater.id;\r\n this.createPrimitive = true;\r\n this.geometry.set(id, instance);\r\n this.updaters.set(id, updater);\r\n if (\r\n !updater.hasConstantOutline ||\r\n !updater.outlineColorProperty.isConstant ||\r\n !Property.isConstant(updater.distanceDisplayConditionProperty) ||\r\n !Property.isConstant(updater.terrainOffsetProperty)\r\n ) {\r\n this.updatersWithAttributes.set(id, updater);\r\n } else {\r\n var that = this;\r\n this.subscriptions.set(\r\n id,\r\n updater.entity.definitionChanged.addEventListener(function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n ) {\r\n if (propertyName === \"isShowing\") {\r\n that.showsUpdated.set(updater.id, updater);\r\n }\r\n })\r\n );\r\n }\r\n};\r\n\r\nBatch.prototype.remove = function (updater) {\r\n var id = updater.id;\r\n this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;\r\n if (this.updaters.remove(id)) {\r\n this.updatersWithAttributes.remove(id);\r\n var unsubscribe = this.subscriptions.get(id);\r\n if (defined(unsubscribe)) {\r\n unsubscribe();\r\n this.subscriptions.remove(id);\r\n this.showsUpdated.remove(id);\r\n }\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\nBatch.prototype.update = function (time) {\r\n var isUpdated = true;\r\n var removedCount = 0;\r\n var primitive = this.primitive;\r\n var primitives = this.primitives;\r\n var i;\r\n\r\n if (this.createPrimitive) {\r\n var geometries = this.geometry.values;\r\n var geometriesLength = geometries.length;\r\n if (geometriesLength > 0) {\r\n if (defined(primitive)) {\r\n if (!defined(this.oldPrimitive)) {\r\n this.oldPrimitive = primitive;\r\n } else {\r\n primitives.remove(primitive);\r\n }\r\n }\r\n\r\n primitive = new Primitive({\r\n show: false,\r\n asynchronous: true,\r\n geometryInstances: geometries.slice(),\r\n appearance: new PerInstanceColorAppearance({\r\n flat: true,\r\n translucent: this.translucent,\r\n renderState: {\r\n lineWidth: this.width,\r\n },\r\n }),\r\n shadows: this.shadows,\r\n });\r\n\r\n primitives.add(primitive);\r\n isUpdated = false;\r\n } else {\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n primitive = undefined;\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n }\r\n\r\n this.attributes.removeAll();\r\n this.primitive = primitive;\r\n this.createPrimitive = false;\r\n this.waitingOnCreate = true;\r\n } else if (defined(primitive) && primitive.ready) {\r\n primitive.show = true;\r\n if (defined(this.oldPrimitive)) {\r\n primitives.remove(this.oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n\r\n var updatersWithAttributes = this.updatersWithAttributes.values;\r\n var length = updatersWithAttributes.length;\r\n var waitingOnCreate = this.waitingOnCreate;\r\n for (i = 0; i < length; i++) {\r\n var updater = updatersWithAttributes[i];\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n if (!updater.outlineColorProperty.isConstant || waitingOnCreate) {\r\n var outlineColorProperty = updater.outlineColorProperty;\r\n var outlineColor = Property.getValueOrDefault(\r\n outlineColorProperty,\r\n time,\r\n Color.WHITE,\r\n colorScratch\r\n );\r\n if (!Color.equals(attributes._lastColor, outlineColor)) {\r\n attributes._lastColor = Color.clone(\r\n outlineColor,\r\n attributes._lastColor\r\n );\r\n attributes.color = ColorGeometryInstanceAttribute.toValue(\r\n outlineColor,\r\n attributes.color\r\n );\r\n if (\r\n (this.translucent && attributes.color[3] === 255) ||\r\n (!this.translucent && attributes.color[3] !== 255)\r\n ) {\r\n this.itemsToRemove[removedCount++] = updater;\r\n }\r\n }\r\n }\r\n\r\n var show =\r\n updater.entity.isShowing &&\r\n (updater.hasConstantOutline || updater.isOutlineVisible(time));\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n }\r\n\r\n var distanceDisplayConditionProperty =\r\n updater.distanceDisplayConditionProperty;\r\n if (!Property.isConstant(distanceDisplayConditionProperty)) {\r\n var distanceDisplayCondition = Property.getValueOrDefault(\r\n distanceDisplayConditionProperty,\r\n time,\r\n defaultDistanceDisplayCondition,\r\n distanceDisplayConditionScratch\r\n );\r\n if (\r\n !DistanceDisplayCondition.equals(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n )\r\n ) {\r\n attributes._lastDistanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n );\r\n attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(\r\n distanceDisplayCondition,\r\n attributes.distanceDisplayCondition\r\n );\r\n }\r\n }\r\n\r\n var offsetProperty = updater.terrainOffsetProperty;\r\n if (!Property.isConstant(offsetProperty)) {\r\n var offset = Property.getValueOrDefault(\r\n offsetProperty,\r\n time,\r\n defaultOffset,\r\n offsetScratch\r\n );\r\n if (!Cartesian3.equals(offset, attributes._lastOffset)) {\r\n attributes._lastOffset = Cartesian3.clone(\r\n offset,\r\n attributes._lastOffset\r\n );\r\n attributes.offset = OffsetGeometryInstanceAttribute.toValue(\r\n offset,\r\n attributes.offset\r\n );\r\n }\r\n }\r\n }\r\n\r\n this.updateShows(primitive);\r\n this.waitingOnCreate = false;\r\n } else if (defined(primitive) && !primitive.ready) {\r\n isUpdated = false;\r\n }\r\n\r\n this.itemsToRemove.length = removedCount;\r\n return isUpdated;\r\n};\r\n\r\nBatch.prototype.updateShows = function (primitive) {\r\n var showsUpdated = this.showsUpdated.values;\r\n var length = showsUpdated.length;\r\n for (var i = 0; i < length; i++) {\r\n var updater = showsUpdated[i];\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n var show = updater.entity.isShowing;\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n instance.attributes.show.value[0] = attributes.show[0];\r\n }\r\n }\r\n this.showsUpdated.removeAll();\r\n};\r\n\r\nBatch.prototype.contains = function (updater) {\r\n return this.updaters.contains(updater.id);\r\n};\r\n\r\nBatch.prototype.getBoundingSphere = function (updater, result) {\r\n var primitive = this.primitive;\r\n if (!primitive.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n var attributes = primitive.getGeometryInstanceAttributes(updater.entity);\r\n if (\r\n !defined(attributes) ||\r\n !defined(attributes.boundingSphere) || //\r\n (defined(attributes.show) && attributes.show[0] === 0)\r\n ) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n attributes.boundingSphere.clone(result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\nBatch.prototype.removeAllPrimitives = function () {\r\n var primitives = this.primitives;\r\n\r\n var primitive = this.primitive;\r\n if (defined(primitive)) {\r\n primitives.remove(primitive);\r\n this.primitive = undefined;\r\n this.geometry.removeAll();\r\n this.updaters.removeAll();\r\n }\r\n\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n primitives.remove(oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nfunction StaticOutlineGeometryBatch(primitives, scene, shadows) {\r\n this._primitives = primitives;\r\n this._scene = scene;\r\n this._shadows = shadows;\r\n this._solidBatches = new AssociativeArray();\r\n this._translucentBatches = new AssociativeArray();\r\n}\r\nStaticOutlineGeometryBatch.prototype.add = function (time, updater) {\r\n var instance = updater.createOutlineGeometryInstance(time);\r\n var width = this._scene.clampLineWidth(updater.outlineWidth);\r\n var batches;\r\n var batch;\r\n if (instance.attributes.color.value[3] === 255) {\r\n batches = this._solidBatches;\r\n batch = batches.get(width);\r\n if (!defined(batch)) {\r\n batch = new Batch(this._primitives, false, width, this._shadows);\r\n batches.set(width, batch);\r\n }\r\n batch.add(updater, instance);\r\n } else {\r\n batches = this._translucentBatches;\r\n batch = batches.get(width);\r\n if (!defined(batch)) {\r\n batch = new Batch(this._primitives, true, width, this._shadows);\r\n batches.set(width, batch);\r\n }\r\n batch.add(updater, instance);\r\n }\r\n};\r\n\r\nStaticOutlineGeometryBatch.prototype.remove = function (updater) {\r\n var i;\r\n\r\n var solidBatches = this._solidBatches.values;\r\n var solidBatchesLength = solidBatches.length;\r\n for (i = 0; i < solidBatchesLength; i++) {\r\n if (solidBatches[i].remove(updater)) {\r\n return;\r\n }\r\n }\r\n\r\n var translucentBatches = this._translucentBatches.values;\r\n var translucentBatchesLength = translucentBatches.length;\r\n for (i = 0; i < translucentBatchesLength; i++) {\r\n if (translucentBatches[i].remove(updater)) {\r\n return;\r\n }\r\n }\r\n};\r\n\r\nStaticOutlineGeometryBatch.prototype.update = function (time) {\r\n var i;\r\n var x;\r\n var updater;\r\n var batch;\r\n var solidBatches = this._solidBatches.values;\r\n var solidBatchesLength = solidBatches.length;\r\n var translucentBatches = this._translucentBatches.values;\r\n var translucentBatchesLength = translucentBatches.length;\r\n var itemsToRemove;\r\n var isUpdated = true;\r\n var needUpdate = false;\r\n\r\n do {\r\n needUpdate = false;\r\n for (x = 0; x < solidBatchesLength; x++) {\r\n batch = solidBatches[x];\r\n //Perform initial update\r\n isUpdated = batch.update(time);\r\n\r\n //If any items swapped between solid/translucent, we need to\r\n //move them between batches\r\n itemsToRemove = batch.itemsToRemove;\r\n var solidsToMoveLength = itemsToRemove.length;\r\n if (solidsToMoveLength > 0) {\r\n needUpdate = true;\r\n for (i = 0; i < solidsToMoveLength; i++) {\r\n updater = itemsToRemove[i];\r\n batch.remove(updater);\r\n this.add(time, updater);\r\n }\r\n }\r\n }\r\n for (x = 0; x < translucentBatchesLength; x++) {\r\n batch = translucentBatches[x];\r\n //Perform initial update\r\n isUpdated = batch.update(time);\r\n\r\n //If any items swapped between solid/translucent, we need to\r\n //move them between batches\r\n itemsToRemove = batch.itemsToRemove;\r\n var translucentToMoveLength = itemsToRemove.length;\r\n if (translucentToMoveLength > 0) {\r\n needUpdate = true;\r\n for (i = 0; i < translucentToMoveLength; i++) {\r\n updater = itemsToRemove[i];\r\n batch.remove(updater);\r\n this.add(time, updater);\r\n }\r\n }\r\n }\r\n } while (needUpdate);\r\n\r\n return isUpdated;\r\n};\r\n\r\nStaticOutlineGeometryBatch.prototype.getBoundingSphere = function (\r\n updater,\r\n result\r\n) {\r\n var i;\r\n\r\n var solidBatches = this._solidBatches.values;\r\n var solidBatchesLength = solidBatches.length;\r\n for (i = 0; i < solidBatchesLength; i++) {\r\n var solidBatch = solidBatches[i];\r\n if (solidBatch.contains(updater)) {\r\n return solidBatch.getBoundingSphere(updater, result);\r\n }\r\n }\r\n\r\n var translucentBatches = this._translucentBatches.values;\r\n var translucentBatchesLength = translucentBatches.length;\r\n for (i = 0; i < translucentBatchesLength; i++) {\r\n var translucentBatch = translucentBatches[i];\r\n if (translucentBatch.contains(updater)) {\r\n return translucentBatch.getBoundingSphere(updater, result);\r\n }\r\n }\r\n\r\n return BoundingSphereState.FAILED;\r\n};\r\n\r\nStaticOutlineGeometryBatch.prototype.removeAllPrimitives = function () {\r\n var i;\r\n\r\n var solidBatches = this._solidBatches.values;\r\n var solidBatchesLength = solidBatches.length;\r\n for (i = 0; i < solidBatchesLength; i++) {\r\n solidBatches[i].removeAllPrimitives();\r\n }\r\n\r\n var translucentBatches = this._translucentBatches.values;\r\n var translucentBatchesLength = translucentBatches.length;\r\n for (i = 0; i < translucentBatchesLength; i++) {\r\n translucentBatches[i].removeAllPrimitives();\r\n }\r\n};\r\nexport default StaticOutlineGeometryBatch;\r\n","import Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport WallGeometry from \"../Core/WallGeometry.js\";\r\nimport WallOutlineGeometry from \"../Core/WallOutlineGeometry.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryUpdater from \"./DynamicGeometryUpdater.js\";\r\nimport GeometryUpdater from \"./GeometryUpdater.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar scratchColor = new Color();\r\n\r\nfunction WallGeometryOptions(entity) {\r\n this.id = entity;\r\n this.vertexFormat = undefined;\r\n this.positions = undefined;\r\n this.minimumHeights = undefined;\r\n this.maximumHeights = undefined;\r\n this.granularity = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for walls.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias WallGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction WallGeometryUpdater(entity, scene) {\r\n GeometryUpdater.call(this, {\r\n entity: entity,\r\n scene: scene,\r\n geometryOptions: new WallGeometryOptions(entity),\r\n geometryPropertyName: \"wall\",\r\n observedPropertyNames: [\"availability\", \"wall\"],\r\n });\r\n\r\n this._onEntityPropertyChanged(entity, \"wall\", entity.wall, undefined);\r\n}\r\n\r\nif (defined(Object.create)) {\r\n WallGeometryUpdater.prototype = Object.create(GeometryUpdater.prototype);\r\n WallGeometryUpdater.prototype.constructor = WallGeometryUpdater;\r\n}\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nWallGeometryUpdater.prototype.createFillGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n\r\n var attributes;\r\n\r\n var color;\r\n var show = new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._fillProperty.getValue(time)\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n );\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n var currentColor;\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n color: color,\r\n };\r\n } else {\r\n attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n };\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new WallGeometry(this._options),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nWallGeometryUpdater.prototype.createOutlineGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n\r\n if (!this._outlineEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var outlineColor = Property.getValueOrDefault(\r\n this._outlineColorProperty,\r\n time,\r\n Color.BLACK,\r\n scratchColor\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new WallOutlineGeometry(this._options),\r\n attributes: {\r\n show: new ShowGeometryInstanceAttribute(\r\n isAvailable &&\r\n entity.isShowing &&\r\n this._showProperty.getValue(time) &&\r\n this._showOutlineProperty.getValue(time)\r\n ),\r\n color: ColorGeometryInstanceAttribute.fromColor(outlineColor),\r\n distanceDisplayCondition: DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n ),\r\n },\r\n });\r\n};\r\n\r\nWallGeometryUpdater.prototype._isHidden = function (entity, wall) {\r\n return (\r\n !defined(wall.positions) ||\r\n GeometryUpdater.prototype._isHidden.call(this, entity, wall)\r\n );\r\n};\r\n\r\nWallGeometryUpdater.prototype._getIsClosed = function (options) {\r\n return false;\r\n};\r\n\r\nWallGeometryUpdater.prototype._isDynamic = function (entity, wall) {\r\n return (\r\n !wall.positions.isConstant || //\r\n !Property.isConstant(wall.minimumHeights) || //\r\n !Property.isConstant(wall.maximumHeights) || //\r\n !Property.isConstant(wall.outlineWidth) || //\r\n !Property.isConstant(wall.granularity)\r\n );\r\n};\r\n\r\nWallGeometryUpdater.prototype._setStaticOptions = function (entity, wall) {\r\n var minimumHeights = wall.minimumHeights;\r\n var maximumHeights = wall.maximumHeights;\r\n var granularity = wall.granularity;\r\n var isColorMaterial = this._materialProperty instanceof ColorMaterialProperty;\r\n\r\n var options = this._options;\r\n options.vertexFormat = isColorMaterial\r\n ? PerInstanceColorAppearance.VERTEX_FORMAT\r\n : MaterialAppearance.MaterialSupport.TEXTURED.vertexFormat;\r\n options.positions = wall.positions.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n options.positions\r\n );\r\n options.minimumHeights = defined(minimumHeights)\r\n ? minimumHeights.getValue(Iso8601.MINIMUM_VALUE, options.minimumHeights)\r\n : undefined;\r\n options.maximumHeights = defined(maximumHeights)\r\n ? maximumHeights.getValue(Iso8601.MINIMUM_VALUE, options.maximumHeights)\r\n : undefined;\r\n options.granularity = defined(granularity)\r\n ? granularity.getValue(Iso8601.MINIMUM_VALUE)\r\n : undefined;\r\n};\r\n\r\nWallGeometryUpdater.DynamicGeometryUpdater = DynamicWallGeometryUpdater;\r\n\r\n/**\r\n * @private\r\n */\r\nfunction DynamicWallGeometryUpdater(\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n DynamicGeometryUpdater.call(\r\n this,\r\n geometryUpdater,\r\n primitives,\r\n groundPrimitives\r\n );\r\n}\r\n\r\nif (defined(Object.create)) {\r\n DynamicWallGeometryUpdater.prototype = Object.create(\r\n DynamicGeometryUpdater.prototype\r\n );\r\n DynamicWallGeometryUpdater.prototype.constructor = DynamicWallGeometryUpdater;\r\n}\r\n\r\nDynamicWallGeometryUpdater.prototype._isHidden = function (entity, wall, time) {\r\n return (\r\n !defined(this._options.positions) ||\r\n DynamicGeometryUpdater.prototype._isHidden.call(this, entity, wall, time)\r\n );\r\n};\r\n\r\nDynamicWallGeometryUpdater.prototype._setOptions = function (\r\n entity,\r\n wall,\r\n time\r\n) {\r\n var options = this._options;\r\n options.positions = Property.getValueOrUndefined(\r\n wall.positions,\r\n time,\r\n options.positions\r\n );\r\n options.minimumHeights = Property.getValueOrUndefined(\r\n wall.minimumHeights,\r\n time,\r\n options.minimumHeights\r\n );\r\n options.maximumHeights = Property.getValueOrUndefined(\r\n wall.maximumHeights,\r\n time,\r\n options.maximumHeights\r\n );\r\n options.granularity = Property.getValueOrUndefined(wall.granularity, time);\r\n};\r\nexport default WallGeometryUpdater;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport EventHelper from \"../Core/EventHelper.js\";\r\nimport ClassificationType from \"../Scene/ClassificationType.js\";\r\nimport MaterialAppearance from \"../Scene/MaterialAppearance.js\";\r\nimport PerInstanceColorAppearance from \"../Scene/PerInstanceColorAppearance.js\";\r\nimport ShadowMode from \"../Scene/ShadowMode.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport BoxGeometryUpdater from \"./BoxGeometryUpdater.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport CorridorGeometryUpdater from \"./CorridorGeometryUpdater.js\";\r\nimport CylinderGeometryUpdater from \"./CylinderGeometryUpdater.js\";\r\nimport DynamicGeometryBatch from \"./DynamicGeometryBatch.js\";\r\nimport EllipseGeometryUpdater from \"./EllipseGeometryUpdater.js\";\r\nimport EllipsoidGeometryUpdater from \"./EllipsoidGeometryUpdater.js\";\r\nimport Entity from \"./Entity.js\";\r\nimport PlaneGeometryUpdater from \"./PlaneGeometryUpdater.js\";\r\nimport PolygonGeometryUpdater from \"./PolygonGeometryUpdater.js\";\r\nimport PolylineVolumeGeometryUpdater from \"./PolylineVolumeGeometryUpdater.js\";\r\nimport RectangleGeometryUpdater from \"./RectangleGeometryUpdater.js\";\r\nimport StaticGeometryColorBatch from \"./StaticGeometryColorBatch.js\";\r\nimport StaticGeometryPerMaterialBatch from \"./StaticGeometryPerMaterialBatch.js\";\r\nimport StaticGroundGeometryColorBatch from \"./StaticGroundGeometryColorBatch.js\";\r\nimport StaticGroundGeometryPerMaterialBatch from \"./StaticGroundGeometryPerMaterialBatch.js\";\r\nimport StaticOutlineGeometryBatch from \"./StaticOutlineGeometryBatch.js\";\r\nimport WallGeometryUpdater from \"./WallGeometryUpdater.js\";\r\n\r\nvar emptyArray = [];\r\n\r\nvar geometryUpdaters = [\r\n BoxGeometryUpdater,\r\n CylinderGeometryUpdater,\r\n CorridorGeometryUpdater,\r\n EllipseGeometryUpdater,\r\n EllipsoidGeometryUpdater,\r\n PlaneGeometryUpdater,\r\n PolygonGeometryUpdater,\r\n PolylineVolumeGeometryUpdater,\r\n RectangleGeometryUpdater,\r\n WallGeometryUpdater,\r\n];\r\n\r\nfunction GeometryUpdaterSet(entity, scene) {\r\n this.entity = entity;\r\n this.scene = scene;\r\n var updaters = new Array(geometryUpdaters.length);\r\n var geometryChanged = new Event();\r\n function raiseEvent(geometry) {\r\n geometryChanged.raiseEvent(geometry);\r\n }\r\n var eventHelper = new EventHelper();\r\n for (var i = 0; i < updaters.length; i++) {\r\n var updater = new geometryUpdaters[i](entity, scene);\r\n eventHelper.add(updater.geometryChanged, raiseEvent);\r\n updaters[i] = updater;\r\n }\r\n this.updaters = updaters;\r\n this.geometryChanged = geometryChanged;\r\n this.eventHelper = eventHelper;\r\n\r\n this._removeEntitySubscription = entity.definitionChanged.addEventListener(\r\n GeometryUpdaterSet.prototype._onEntityPropertyChanged,\r\n this\r\n );\r\n}\r\n\r\nGeometryUpdaterSet.prototype._onEntityPropertyChanged = function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n) {\r\n var updaters = this.updaters;\r\n for (var i = 0; i < updaters.length; i++) {\r\n updaters[i]._onEntityPropertyChanged(\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n );\r\n }\r\n};\r\n\r\nGeometryUpdaterSet.prototype.forEach = function (callback) {\r\n var updaters = this.updaters;\r\n for (var i = 0; i < updaters.length; i++) {\r\n callback(updaters[i]);\r\n }\r\n};\r\n\r\nGeometryUpdaterSet.prototype.destroy = function () {\r\n this.eventHelper.removeAll();\r\n var updaters = this.updaters;\r\n for (var i = 0; i < updaters.length; i++) {\r\n updaters[i].destroy();\r\n }\r\n this._removeEntitySubscription();\r\n destroyObject(this);\r\n};\r\n\r\n/**\r\n * A general purpose visualizer for geometry represented by {@link Primitive} instances.\r\n * @alias GeometryVisualizer\r\n * @constructor\r\n *\r\n * @param {Scene} scene The scene the primitives will be rendered in.\r\n * @param {EntityCollection} entityCollection The entityCollection to visualize.\r\n * @param {PrimitiveCollection} [primitives=scene.primitives] A collection to add primitives related to the entities\r\n * @param {PrimitiveCollection} [groundPrimitives=scene.groundPrimitives] A collection to add ground primitives related to the entities\r\n */\r\nfunction GeometryVisualizer(\r\n scene,\r\n entityCollection,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"scene\", scene);\r\n Check.defined(\"entityCollection\", entityCollection);\r\n //>>includeEnd('debug');\r\n\r\n primitives = defaultValue(primitives, scene.primitives);\r\n groundPrimitives = defaultValue(groundPrimitives, scene.groundPrimitives);\r\n\r\n this._scene = scene;\r\n this._primitives = primitives;\r\n this._groundPrimitives = groundPrimitives;\r\n this._entityCollection = undefined;\r\n this._addedObjects = new AssociativeArray();\r\n this._removedObjects = new AssociativeArray();\r\n this._changedObjects = new AssociativeArray();\r\n\r\n var numberOfShadowModes = ShadowMode.NUMBER_OF_SHADOW_MODES;\r\n this._outlineBatches = new Array(numberOfShadowModes * 2);\r\n this._closedColorBatches = new Array(numberOfShadowModes * 2);\r\n this._closedMaterialBatches = new Array(numberOfShadowModes * 2);\r\n this._openColorBatches = new Array(numberOfShadowModes * 2);\r\n this._openMaterialBatches = new Array(numberOfShadowModes * 2);\r\n\r\n var supportsMaterialsforEntitiesOnTerrain = Entity.supportsMaterialsforEntitiesOnTerrain(\r\n scene\r\n );\r\n this._supportsMaterialsforEntitiesOnTerrain = supportsMaterialsforEntitiesOnTerrain;\r\n\r\n var i;\r\n for (i = 0; i < numberOfShadowModes; ++i) {\r\n this._outlineBatches[i] = new StaticOutlineGeometryBatch(\r\n primitives,\r\n scene,\r\n i,\r\n false\r\n );\r\n this._outlineBatches[\r\n numberOfShadowModes + i\r\n ] = new StaticOutlineGeometryBatch(primitives, scene, i, true);\r\n\r\n this._closedColorBatches[i] = new StaticGeometryColorBatch(\r\n primitives,\r\n PerInstanceColorAppearance,\r\n undefined,\r\n true,\r\n i,\r\n true\r\n );\r\n this._closedColorBatches[\r\n numberOfShadowModes + i\r\n ] = new StaticGeometryColorBatch(\r\n primitives,\r\n PerInstanceColorAppearance,\r\n undefined,\r\n true,\r\n i,\r\n false\r\n );\r\n\r\n this._closedMaterialBatches[i] = new StaticGeometryPerMaterialBatch(\r\n primitives,\r\n MaterialAppearance,\r\n undefined,\r\n true,\r\n i,\r\n true\r\n );\r\n this._closedMaterialBatches[\r\n numberOfShadowModes + i\r\n ] = new StaticGeometryPerMaterialBatch(\r\n primitives,\r\n MaterialAppearance,\r\n undefined,\r\n true,\r\n i,\r\n false\r\n );\r\n\r\n this._openColorBatches[i] = new StaticGeometryColorBatch(\r\n primitives,\r\n PerInstanceColorAppearance,\r\n undefined,\r\n false,\r\n i,\r\n true\r\n );\r\n this._openColorBatches[\r\n numberOfShadowModes + i\r\n ] = new StaticGeometryColorBatch(\r\n primitives,\r\n PerInstanceColorAppearance,\r\n undefined,\r\n false,\r\n i,\r\n false\r\n );\r\n\r\n this._openMaterialBatches[i] = new StaticGeometryPerMaterialBatch(\r\n primitives,\r\n MaterialAppearance,\r\n undefined,\r\n false,\r\n i,\r\n true\r\n );\r\n this._openMaterialBatches[\r\n numberOfShadowModes + i\r\n ] = new StaticGeometryPerMaterialBatch(\r\n primitives,\r\n MaterialAppearance,\r\n undefined,\r\n false,\r\n i,\r\n false\r\n );\r\n }\r\n\r\n var numberOfClassificationTypes =\r\n ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES;\r\n var groundColorBatches = new Array(numberOfClassificationTypes);\r\n var groundMaterialBatches = [];\r\n if (supportsMaterialsforEntitiesOnTerrain) {\r\n for (i = 0; i < numberOfClassificationTypes; ++i) {\r\n groundMaterialBatches.push(\r\n new StaticGroundGeometryPerMaterialBatch(\r\n groundPrimitives,\r\n i,\r\n MaterialAppearance\r\n )\r\n );\r\n groundColorBatches[i] = new StaticGroundGeometryColorBatch(\r\n groundPrimitives,\r\n i\r\n );\r\n }\r\n } else {\r\n for (i = 0; i < numberOfClassificationTypes; ++i) {\r\n groundColorBatches[i] = new StaticGroundGeometryColorBatch(\r\n groundPrimitives,\r\n i\r\n );\r\n }\r\n }\r\n\r\n this._groundColorBatches = groundColorBatches;\r\n this._groundMaterialBatches = groundMaterialBatches;\r\n\r\n this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives);\r\n\r\n this._batches = this._outlineBatches.concat(\r\n this._closedColorBatches,\r\n this._closedMaterialBatches,\r\n this._openColorBatches,\r\n this._openMaterialBatches,\r\n this._groundColorBatches,\r\n this._groundMaterialBatches,\r\n this._dynamicBatch\r\n );\r\n\r\n this._subscriptions = new AssociativeArray();\r\n this._updaterSets = new AssociativeArray();\r\n\r\n this._entityCollection = entityCollection;\r\n entityCollection.collectionChanged.addEventListener(\r\n GeometryVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n this._onCollectionChanged(\r\n entityCollection,\r\n entityCollection.values,\r\n emptyArray\r\n );\r\n}\r\n\r\n/**\r\n * Updates all of the primitives created by this visualizer to match their\r\n * Entity counterpart at the given time.\r\n *\r\n * @param {JulianDate} time The time to update to.\r\n * @returns {Boolean} True if the visualizer successfully updated to the provided time,\r\n * false if the visualizer is waiting for asynchronous primitives to be created.\r\n */\r\nGeometryVisualizer.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var addedObjects = this._addedObjects;\r\n var added = addedObjects.values;\r\n var removedObjects = this._removedObjects;\r\n var removed = removedObjects.values;\r\n var changedObjects = this._changedObjects;\r\n var changed = changedObjects.values;\r\n\r\n var i;\r\n var entity;\r\n var id;\r\n var updaterSet;\r\n var that = this;\r\n\r\n for (i = changed.length - 1; i > -1; i--) {\r\n entity = changed[i];\r\n id = entity.id;\r\n updaterSet = this._updaterSets.get(id);\r\n\r\n //If in a single update, an entity gets removed and a new instance\r\n //re-added with the same id, the updater no longer tracks the\r\n //correct entity, we need to both remove the old one and\r\n //add the new one, which is done by pushing the entity\r\n //onto the removed/added lists.\r\n if (updaterSet.entity === entity) {\r\n updaterSet.forEach(function (updater) {\r\n that._removeUpdater(updater);\r\n that._insertUpdaterIntoBatch(time, updater);\r\n });\r\n } else {\r\n removed.push(entity);\r\n added.push(entity);\r\n }\r\n }\r\n\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n id = entity.id;\r\n updaterSet = this._updaterSets.get(id);\r\n updaterSet.forEach(this._removeUpdater.bind(this));\r\n updaterSet.destroy();\r\n this._updaterSets.remove(id);\r\n this._subscriptions.get(id)();\r\n this._subscriptions.remove(id);\r\n }\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n id = entity.id;\r\n updaterSet = new GeometryUpdaterSet(entity, this._scene);\r\n this._updaterSets.set(id, updaterSet);\r\n updaterSet.forEach(function (updater) {\r\n that._insertUpdaterIntoBatch(time, updater);\r\n });\r\n this._subscriptions.set(\r\n id,\r\n updaterSet.geometryChanged.addEventListener(\r\n GeometryVisualizer._onGeometryChanged,\r\n this\r\n )\r\n );\r\n }\r\n\r\n addedObjects.removeAll();\r\n removedObjects.removeAll();\r\n changedObjects.removeAll();\r\n\r\n var isUpdated = true;\r\n var batches = this._batches;\r\n var length = batches.length;\r\n for (i = 0; i < length; i++) {\r\n isUpdated = batches[i].update(time) && isUpdated;\r\n }\r\n\r\n return isUpdated;\r\n};\r\n\r\nvar getBoundingSphereArrayScratch = [];\r\nvar getBoundingSphereBoundingSphereScratch = new BoundingSphere();\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n *\r\n * @param {Entity} entity The entity whose bounding sphere to compute.\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nGeometryVisualizer.prototype.getBoundingSphere = function (entity, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"entity\", entity);\r\n Check.defined(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var boundingSpheres = getBoundingSphereArrayScratch;\r\n var tmp = getBoundingSphereBoundingSphereScratch;\r\n\r\n var count = 0;\r\n var state = BoundingSphereState.DONE;\r\n var batches = this._batches;\r\n var batchesLength = batches.length;\r\n\r\n var id = entity.id;\r\n var updaters = this._updaterSets.get(id).updaters;\r\n\r\n for (var j = 0; j < updaters.length; j++) {\r\n var updater = updaters[j];\r\n for (var i = 0; i < batchesLength; i++) {\r\n state = batches[i].getBoundingSphere(updater, tmp);\r\n if (state === BoundingSphereState.PENDING) {\r\n return BoundingSphereState.PENDING;\r\n } else if (state === BoundingSphereState.DONE) {\r\n boundingSpheres[count] = BoundingSphere.clone(\r\n tmp,\r\n boundingSpheres[count]\r\n );\r\n count++;\r\n }\r\n }\r\n }\r\n\r\n if (count === 0) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n boundingSpheres.length = count;\r\n BoundingSphere.fromBoundingSpheres(boundingSpheres, result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nGeometryVisualizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys all primitives created by this instance.\r\n */\r\nGeometryVisualizer.prototype.destroy = function () {\r\n this._entityCollection.collectionChanged.removeEventListener(\r\n GeometryVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n this._addedObjects.removeAll();\r\n this._removedObjects.removeAll();\r\n\r\n var i;\r\n var batches = this._batches;\r\n var length = batches.length;\r\n for (i = 0; i < length; i++) {\r\n batches[i].removeAllPrimitives();\r\n }\r\n\r\n var subscriptions = this._subscriptions.values;\r\n length = subscriptions.length;\r\n for (i = 0; i < length; i++) {\r\n subscriptions[i]();\r\n }\r\n this._subscriptions.removeAll();\r\n\r\n var updaterSets = this._updaterSets.values;\r\n length = updaterSets.length;\r\n for (i = 0; i < length; i++) {\r\n updaterSets[i].destroy();\r\n }\r\n this._updaterSets.removeAll();\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nGeometryVisualizer.prototype._removeUpdater = function (updater) {\r\n //We don't keep track of which batch an updater is in, so just remove it from all of them.\r\n var batches = this._batches;\r\n var length = batches.length;\r\n for (var i = 0; i < length; i++) {\r\n batches[i].remove(updater);\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nGeometryVisualizer.prototype._insertUpdaterIntoBatch = function (\r\n time,\r\n updater\r\n) {\r\n if (updater.isDynamic) {\r\n this._dynamicBatch.add(time, updater);\r\n return;\r\n }\r\n\r\n var shadows;\r\n if (updater.outlineEnabled || updater.fillEnabled) {\r\n shadows = updater.shadowsProperty.getValue(time);\r\n }\r\n\r\n var numberOfShadowModes = ShadowMode.NUMBER_OF_SHADOW_MODES;\r\n if (updater.outlineEnabled) {\r\n if (defined(updater.terrainOffsetProperty)) {\r\n this._outlineBatches[numberOfShadowModes + shadows].add(time, updater);\r\n } else {\r\n this._outlineBatches[shadows].add(time, updater);\r\n }\r\n }\r\n\r\n if (updater.fillEnabled) {\r\n if (updater.onTerrain) {\r\n var classificationType = updater.classificationTypeProperty.getValue(\r\n time\r\n );\r\n if (updater.fillMaterialProperty instanceof ColorMaterialProperty) {\r\n this._groundColorBatches[classificationType].add(time, updater);\r\n } else {\r\n // If unsupported, updater will not be on terrain.\r\n this._groundMaterialBatches[classificationType].add(time, updater);\r\n }\r\n } else if (updater.isClosed) {\r\n if (updater.fillMaterialProperty instanceof ColorMaterialProperty) {\r\n if (defined(updater.terrainOffsetProperty)) {\r\n this._closedColorBatches[numberOfShadowModes + shadows].add(\r\n time,\r\n updater\r\n );\r\n } else {\r\n this._closedColorBatches[shadows].add(time, updater);\r\n }\r\n } else if (defined(updater.terrainOffsetProperty)) {\r\n this._closedMaterialBatches[numberOfShadowModes + shadows].add(\r\n time,\r\n updater\r\n );\r\n } else {\r\n this._closedMaterialBatches[shadows].add(time, updater);\r\n }\r\n } else if (updater.fillMaterialProperty instanceof ColorMaterialProperty) {\r\n if (defined(updater.terrainOffsetProperty)) {\r\n this._openColorBatches[numberOfShadowModes + shadows].add(\r\n time,\r\n updater\r\n );\r\n } else {\r\n this._openColorBatches[shadows].add(time, updater);\r\n }\r\n } else if (defined(updater.terrainOffsetProperty)) {\r\n this._openMaterialBatches[numberOfShadowModes + shadows].add(\r\n time,\r\n updater\r\n );\r\n } else {\r\n this._openMaterialBatches[shadows].add(time, updater);\r\n }\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nGeometryVisualizer._onGeometryChanged = function (updater) {\r\n var removedObjects = this._removedObjects;\r\n var changedObjects = this._changedObjects;\r\n\r\n var entity = updater.entity;\r\n var id = entity.id;\r\n\r\n if (!defined(removedObjects.get(id)) && !defined(changedObjects.get(id))) {\r\n changedObjects.set(id, entity);\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nGeometryVisualizer.prototype._onCollectionChanged = function (\r\n entityCollection,\r\n added,\r\n removed\r\n) {\r\n var addedObjects = this._addedObjects;\r\n var removedObjects = this._removedObjects;\r\n var changedObjects = this._changedObjects;\r\n\r\n var i;\r\n var id;\r\n var entity;\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n id = entity.id;\r\n if (!addedObjects.remove(id)) {\r\n removedObjects.set(id, entity);\r\n changedObjects.remove(id);\r\n }\r\n }\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n id = entity.id;\r\n if (removedObjects.remove(id)) {\r\n changedObjects.set(id, entity);\r\n } else {\r\n addedObjects.set(id, entity);\r\n }\r\n }\r\n};\r\nexport default GeometryVisualizer;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport NearFarScalar from \"../Core/NearFarScalar.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport HorizontalOrigin from \"../Scene/HorizontalOrigin.js\";\r\nimport LabelStyle from \"../Scene/LabelStyle.js\";\r\nimport VerticalOrigin from \"../Scene/VerticalOrigin.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultScale = 1.0;\r\nvar defaultFont = \"30px sans-serif\";\r\nvar defaultStyle = LabelStyle.FILL;\r\nvar defaultFillColor = Color.WHITE;\r\nvar defaultOutlineColor = Color.BLACK;\r\nvar defaultOutlineWidth = 1.0;\r\nvar defaultShowBackground = false;\r\nvar defaultBackgroundColor = new Color(0.165, 0.165, 0.165, 0.8);\r\nvar defaultBackgroundPadding = new Cartesian2(7, 5);\r\nvar defaultPixelOffset = Cartesian2.ZERO;\r\nvar defaultEyeOffset = Cartesian3.ZERO;\r\nvar defaultHeightReference = HeightReference.NONE;\r\nvar defaultHorizontalOrigin = HorizontalOrigin.CENTER;\r\nvar defaultVerticalOrigin = VerticalOrigin.CENTER;\r\n\r\nvar positionScratch = new Cartesian3();\r\nvar fillColorScratch = new Color();\r\nvar outlineColorScratch = new Color();\r\nvar backgroundColorScratch = new Color();\r\nvar backgroundPaddingScratch = new Cartesian2();\r\nvar eyeOffsetScratch = new Cartesian3();\r\nvar pixelOffsetScratch = new Cartesian2();\r\nvar translucencyByDistanceScratch = new NearFarScalar();\r\nvar pixelOffsetScaleByDistanceScratch = new NearFarScalar();\r\nvar scaleByDistanceScratch = new NearFarScalar();\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\n\r\nfunction EntityData(entity) {\r\n this.entity = entity;\r\n this.label = undefined;\r\n this.index = undefined;\r\n}\r\n\r\n/**\r\n * A {@link Visualizer} which maps the {@link LabelGraphics} instance\r\n * in {@link Entity#label} to a {@link Label}.\r\n * @alias LabelVisualizer\r\n * @constructor\r\n *\r\n * @param {EntityCluster} entityCluster The entity cluster to manage the collection of billboards and optionally cluster with other entities.\r\n * @param {EntityCollection} entityCollection The entityCollection to visualize.\r\n */\r\nfunction LabelVisualizer(entityCluster, entityCollection) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entityCluster)) {\r\n throw new DeveloperError(\"entityCluster is required.\");\r\n }\r\n if (!defined(entityCollection)) {\r\n throw new DeveloperError(\"entityCollection is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n entityCollection.collectionChanged.addEventListener(\r\n LabelVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n\r\n this._cluster = entityCluster;\r\n this._entityCollection = entityCollection;\r\n this._items = new AssociativeArray();\r\n\r\n this._onCollectionChanged(entityCollection, entityCollection.values, [], []);\r\n}\r\n\r\n/**\r\n * Updates the primitives created by this visualizer to match their\r\n * Entity counterpart at the given time.\r\n *\r\n * @param {JulianDate} time The time to update to.\r\n * @returns {Boolean} This function always returns true.\r\n */\r\nLabelVisualizer.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var items = this._items.values;\r\n var cluster = this._cluster;\r\n\r\n for (var i = 0, len = items.length; i < len; i++) {\r\n var item = items[i];\r\n var entity = item.entity;\r\n var labelGraphics = entity._label;\r\n var text;\r\n var label = item.label;\r\n var show =\r\n entity.isShowing &&\r\n entity.isAvailable(time) &&\r\n Property.getValueOrDefault(labelGraphics._show, time, true);\r\n var position;\r\n if (show) {\r\n position = Property.getValueOrUndefined(\r\n entity._position,\r\n time,\r\n positionScratch\r\n );\r\n text = Property.getValueOrUndefined(labelGraphics._text, time);\r\n show = defined(position) && defined(text);\r\n }\r\n\r\n if (!show) {\r\n //don't bother creating or updating anything else\r\n returnPrimitive(item, entity, cluster);\r\n continue;\r\n }\r\n\r\n if (!Property.isConstant(entity._position)) {\r\n cluster._clusterDirty = true;\r\n }\r\n\r\n var updateClamping = false;\r\n var heightReference = Property.getValueOrDefault(\r\n labelGraphics._heightReference,\r\n time,\r\n defaultHeightReference\r\n );\r\n\r\n if (!defined(label)) {\r\n label = cluster.getLabel(entity);\r\n label.id = entity;\r\n item.label = label;\r\n\r\n // If this new label happens to have a position and height reference that match our new values,\r\n // label._updateClamping will not be called automatically. That's a problem because the clamped\r\n // height may be based on different terrain than is now loaded. So we'll manually call\r\n // _updateClamping below.\r\n updateClamping =\r\n Cartesian3.equals(label.position, position) &&\r\n label.heightReference === heightReference;\r\n }\r\n\r\n label.show = true;\r\n label.position = position;\r\n label.text = text;\r\n label.scale = Property.getValueOrDefault(\r\n labelGraphics._scale,\r\n time,\r\n defaultScale\r\n );\r\n label.font = Property.getValueOrDefault(\r\n labelGraphics._font,\r\n time,\r\n defaultFont\r\n );\r\n label.style = Property.getValueOrDefault(\r\n labelGraphics._style,\r\n time,\r\n defaultStyle\r\n );\r\n label.fillColor = Property.getValueOrDefault(\r\n labelGraphics._fillColor,\r\n time,\r\n defaultFillColor,\r\n fillColorScratch\r\n );\r\n label.outlineColor = Property.getValueOrDefault(\r\n labelGraphics._outlineColor,\r\n time,\r\n defaultOutlineColor,\r\n outlineColorScratch\r\n );\r\n label.outlineWidth = Property.getValueOrDefault(\r\n labelGraphics._outlineWidth,\r\n time,\r\n defaultOutlineWidth\r\n );\r\n label.showBackground = Property.getValueOrDefault(\r\n labelGraphics._showBackground,\r\n time,\r\n defaultShowBackground\r\n );\r\n label.backgroundColor = Property.getValueOrDefault(\r\n labelGraphics._backgroundColor,\r\n time,\r\n defaultBackgroundColor,\r\n backgroundColorScratch\r\n );\r\n label.backgroundPadding = Property.getValueOrDefault(\r\n labelGraphics._backgroundPadding,\r\n time,\r\n defaultBackgroundPadding,\r\n backgroundPaddingScratch\r\n );\r\n label.pixelOffset = Property.getValueOrDefault(\r\n labelGraphics._pixelOffset,\r\n time,\r\n defaultPixelOffset,\r\n pixelOffsetScratch\r\n );\r\n label.eyeOffset = Property.getValueOrDefault(\r\n labelGraphics._eyeOffset,\r\n time,\r\n defaultEyeOffset,\r\n eyeOffsetScratch\r\n );\r\n label.heightReference = heightReference;\r\n label.horizontalOrigin = Property.getValueOrDefault(\r\n labelGraphics._horizontalOrigin,\r\n time,\r\n defaultHorizontalOrigin\r\n );\r\n label.verticalOrigin = Property.getValueOrDefault(\r\n labelGraphics._verticalOrigin,\r\n time,\r\n defaultVerticalOrigin\r\n );\r\n label.translucencyByDistance = Property.getValueOrUndefined(\r\n labelGraphics._translucencyByDistance,\r\n time,\r\n translucencyByDistanceScratch\r\n );\r\n label.pixelOffsetScaleByDistance = Property.getValueOrUndefined(\r\n labelGraphics._pixelOffsetScaleByDistance,\r\n time,\r\n pixelOffsetScaleByDistanceScratch\r\n );\r\n label.scaleByDistance = Property.getValueOrUndefined(\r\n labelGraphics._scaleByDistance,\r\n time,\r\n scaleByDistanceScratch\r\n );\r\n label.distanceDisplayCondition = Property.getValueOrUndefined(\r\n labelGraphics._distanceDisplayCondition,\r\n time,\r\n distanceDisplayConditionScratch\r\n );\r\n label.disableDepthTestDistance = Property.getValueOrUndefined(\r\n labelGraphics._disableDepthTestDistance,\r\n time\r\n );\r\n\r\n if (updateClamping) {\r\n label._updateClamping();\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n *\r\n * @param {Entity} entity The entity whose bounding sphere to compute.\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nLabelVisualizer.prototype.getBoundingSphere = function (entity, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entity)) {\r\n throw new DeveloperError(\"entity is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var item = this._items.get(entity.id);\r\n if (!defined(item) || !defined(item.label)) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n var label = item.label;\r\n result.center = Cartesian3.clone(\r\n defaultValue(label._clampedPosition, label.position),\r\n result.center\r\n );\r\n result.radius = 0;\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nLabelVisualizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys all primitives created by this instance.\r\n */\r\nLabelVisualizer.prototype.destroy = function () {\r\n this._entityCollection.collectionChanged.removeEventListener(\r\n LabelVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n var entities = this._entityCollection.values;\r\n for (var i = 0; i < entities.length; i++) {\r\n this._cluster.removeLabel(entities[i]);\r\n }\r\n return destroyObject(this);\r\n};\r\n\r\nLabelVisualizer.prototype._onCollectionChanged = function (\r\n entityCollection,\r\n added,\r\n removed,\r\n changed\r\n) {\r\n var i;\r\n var entity;\r\n var items = this._items;\r\n var cluster = this._cluster;\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n if (defined(entity._label) && defined(entity._position)) {\r\n items.set(entity.id, new EntityData(entity));\r\n }\r\n }\r\n\r\n for (i = changed.length - 1; i > -1; i--) {\r\n entity = changed[i];\r\n if (defined(entity._label) && defined(entity._position)) {\r\n if (!items.contains(entity.id)) {\r\n items.set(entity.id, new EntityData(entity));\r\n }\r\n } else {\r\n returnPrimitive(items.get(entity.id), entity, cluster);\r\n items.remove(entity.id);\r\n }\r\n }\r\n\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n returnPrimitive(items.get(entity.id), entity, cluster);\r\n items.remove(entity.id);\r\n }\r\n};\r\n\r\nfunction returnPrimitive(item, entity, cluster) {\r\n if (defined(item)) {\r\n item.label = undefined;\r\n cluster.removeLabel(entity);\r\n }\r\n}\r\nexport default LabelVisualizer;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport ColorBlendMode from \"../Scene/ColorBlendMode.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport Model from \"../Scene/Model.js\";\r\nimport ModelAnimationLoop from \"../Scene/ModelAnimationLoop.js\";\r\nimport ShadowMode from \"../Scene/ShadowMode.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultScale = 1.0;\r\nvar defaultMinimumPixelSize = 0.0;\r\nvar defaultIncrementallyLoadTextures = true;\r\nvar defaultClampAnimations = true;\r\nvar defaultShadows = ShadowMode.ENABLED;\r\nvar defaultHeightReference = HeightReference.NONE;\r\nvar defaultSilhouetteColor = Color.RED;\r\nvar defaultSilhouetteSize = 0.0;\r\nvar defaultColor = Color.WHITE;\r\nvar defaultColorBlendMode = ColorBlendMode.HIGHLIGHT;\r\nvar defaultColorBlendAmount = 0.5;\r\nvar defaultImageBasedLightingFactor = new Cartesian2(1.0, 1.0);\r\n\r\nvar modelMatrixScratch = new Matrix4();\r\nvar nodeMatrixScratch = new Matrix4();\r\n\r\n/**\r\n * A {@link Visualizer} which maps {@link Entity#model} to a {@link Model}.\r\n * @alias ModelVisualizer\r\n * @constructor\r\n *\r\n * @param {Scene} scene The scene the primitives will be rendered in.\r\n * @param {EntityCollection} entityCollection The entityCollection to visualize.\r\n */\r\nfunction ModelVisualizer(scene, entityCollection) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(scene)) {\r\n throw new DeveloperError(\"scene is required.\");\r\n }\r\n if (!defined(entityCollection)) {\r\n throw new DeveloperError(\"entityCollection is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n entityCollection.collectionChanged.addEventListener(\r\n ModelVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n\r\n this._scene = scene;\r\n this._primitives = scene.primitives;\r\n this._entityCollection = entityCollection;\r\n this._modelHash = {};\r\n this._entitiesToVisualize = new AssociativeArray();\r\n this._onCollectionChanged(entityCollection, entityCollection.values, [], []);\r\n}\r\n\r\n/**\r\n * Updates models created this visualizer to match their\r\n * Entity counterpart at the given time.\r\n *\r\n * @param {JulianDate} time The time to update to.\r\n * @returns {Boolean} This function always returns true.\r\n */\r\nModelVisualizer.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entities = this._entitiesToVisualize.values;\r\n var modelHash = this._modelHash;\r\n var primitives = this._primitives;\r\n\r\n for (var i = 0, len = entities.length; i < len; i++) {\r\n var entity = entities[i];\r\n var modelGraphics = entity._model;\r\n\r\n var resource;\r\n var modelData = modelHash[entity.id];\r\n var show =\r\n entity.isShowing &&\r\n entity.isAvailable(time) &&\r\n Property.getValueOrDefault(modelGraphics._show, time, true);\r\n\r\n var modelMatrix;\r\n if (show) {\r\n modelMatrix = entity.computeModelMatrix(time, modelMatrixScratch);\r\n resource = Resource.createIfNeeded(\r\n Property.getValueOrUndefined(modelGraphics._uri, time)\r\n );\r\n show = defined(modelMatrix) && defined(resource);\r\n }\r\n\r\n if (!show) {\r\n if (defined(modelData)) {\r\n modelData.modelPrimitive.show = false;\r\n }\r\n continue;\r\n }\r\n\r\n var model = defined(modelData) ? modelData.modelPrimitive : undefined;\r\n if (!defined(model) || resource.url !== modelData.url) {\r\n if (defined(model)) {\r\n primitives.removeAndDestroy(model);\r\n delete modelHash[entity.id];\r\n }\r\n model = Model.fromGltf({\r\n url: resource,\r\n incrementallyLoadTextures: Property.getValueOrDefault(\r\n modelGraphics._incrementallyLoadTextures,\r\n time,\r\n defaultIncrementallyLoadTextures\r\n ),\r\n scene: this._scene,\r\n });\r\n model.id = entity;\r\n primitives.add(model);\r\n\r\n modelData = {\r\n modelPrimitive: model,\r\n url: resource.url,\r\n animationsRunning: false,\r\n nodeTransformationsScratch: {},\r\n articulationsScratch: {},\r\n loadFail: false,\r\n };\r\n modelHash[entity.id] = modelData;\r\n\r\n checkModelLoad(model, entity, modelHash);\r\n }\r\n\r\n model.show = true;\r\n model.scale = Property.getValueOrDefault(\r\n modelGraphics._scale,\r\n time,\r\n defaultScale\r\n );\r\n model.minimumPixelSize = Property.getValueOrDefault(\r\n modelGraphics._minimumPixelSize,\r\n time,\r\n defaultMinimumPixelSize\r\n );\r\n model.maximumScale = Property.getValueOrUndefined(\r\n modelGraphics._maximumScale,\r\n time\r\n );\r\n model.modelMatrix = Matrix4.clone(modelMatrix, model.modelMatrix);\r\n model.shadows = Property.getValueOrDefault(\r\n modelGraphics._shadows,\r\n time,\r\n defaultShadows\r\n );\r\n model.heightReference = Property.getValueOrDefault(\r\n modelGraphics._heightReference,\r\n time,\r\n defaultHeightReference\r\n );\r\n model.distanceDisplayCondition = Property.getValueOrUndefined(\r\n modelGraphics._distanceDisplayCondition,\r\n time\r\n );\r\n model.silhouetteColor = Property.getValueOrDefault(\r\n modelGraphics._silhouetteColor,\r\n time,\r\n defaultSilhouetteColor,\r\n model._silhouetteColor\r\n );\r\n model.silhouetteSize = Property.getValueOrDefault(\r\n modelGraphics._silhouetteSize,\r\n time,\r\n defaultSilhouetteSize\r\n );\r\n model.color = Property.getValueOrDefault(\r\n modelGraphics._color,\r\n time,\r\n defaultColor,\r\n model._color\r\n );\r\n model.colorBlendMode = Property.getValueOrDefault(\r\n modelGraphics._colorBlendMode,\r\n time,\r\n defaultColorBlendMode\r\n );\r\n model.colorBlendAmount = Property.getValueOrDefault(\r\n modelGraphics._colorBlendAmount,\r\n time,\r\n defaultColorBlendAmount\r\n );\r\n model.clippingPlanes = Property.getValueOrUndefined(\r\n modelGraphics._clippingPlanes,\r\n time\r\n );\r\n model.clampAnimations = Property.getValueOrDefault(\r\n modelGraphics._clampAnimations,\r\n time,\r\n defaultClampAnimations\r\n );\r\n model.imageBasedLightingFactor = Property.getValueOrDefault(\r\n modelGraphics._imageBasedLightingFactor,\r\n time,\r\n defaultImageBasedLightingFactor\r\n );\r\n model.lightColor = Property.getValueOrUndefined(\r\n modelGraphics._lightColor,\r\n time\r\n );\r\n\r\n if (model.ready) {\r\n var runAnimations = Property.getValueOrDefault(\r\n modelGraphics._runAnimations,\r\n time,\r\n true\r\n );\r\n if (modelData.animationsRunning !== runAnimations) {\r\n if (runAnimations) {\r\n model.activeAnimations.addAll({\r\n loop: ModelAnimationLoop.REPEAT,\r\n });\r\n } else {\r\n model.activeAnimations.removeAll();\r\n }\r\n modelData.animationsRunning = runAnimations;\r\n }\r\n\r\n // Apply node transformations\r\n var nodeTransformations = Property.getValueOrUndefined(\r\n modelGraphics._nodeTransformations,\r\n time,\r\n modelData.nodeTransformationsScratch\r\n );\r\n if (defined(nodeTransformations)) {\r\n var nodeNames = Object.keys(nodeTransformations);\r\n for (\r\n var nodeIndex = 0, nodeLength = nodeNames.length;\r\n nodeIndex < nodeLength;\r\n ++nodeIndex\r\n ) {\r\n var nodeName = nodeNames[nodeIndex];\r\n\r\n var nodeTransformation = nodeTransformations[nodeName];\r\n if (!defined(nodeTransformation)) {\r\n continue;\r\n }\r\n\r\n var modelNode = model.getNode(nodeName);\r\n if (!defined(modelNode)) {\r\n continue;\r\n }\r\n\r\n var transformationMatrix = Matrix4.fromTranslationRotationScale(\r\n nodeTransformation,\r\n nodeMatrixScratch\r\n );\r\n modelNode.matrix = Matrix4.multiply(\r\n modelNode.originalMatrix,\r\n transformationMatrix,\r\n transformationMatrix\r\n );\r\n }\r\n }\r\n\r\n // Apply articulations\r\n var anyArticulationUpdated = false;\r\n var articulations = Property.getValueOrUndefined(\r\n modelGraphics._articulations,\r\n time,\r\n modelData.articulationsScratch\r\n );\r\n if (defined(articulations)) {\r\n var articulationStageKeys = Object.keys(articulations);\r\n for (\r\n var s = 0, numKeys = articulationStageKeys.length;\r\n s < numKeys;\r\n ++s\r\n ) {\r\n var key = articulationStageKeys[s];\r\n\r\n var articulationStageValue = articulations[key];\r\n if (!defined(articulationStageValue)) {\r\n continue;\r\n }\r\n\r\n anyArticulationUpdated = true;\r\n model.setArticulationStage(key, articulationStageValue);\r\n }\r\n }\r\n\r\n if (anyArticulationUpdated) {\r\n model.applyArticulations();\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nModelVisualizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys all primitives created by this instance.\r\n */\r\nModelVisualizer.prototype.destroy = function () {\r\n this._entityCollection.collectionChanged.removeEventListener(\r\n ModelVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n var entities = this._entitiesToVisualize.values;\r\n var modelHash = this._modelHash;\r\n var primitives = this._primitives;\r\n for (var i = entities.length - 1; i > -1; i--) {\r\n removeModel(this, entities[i], modelHash, primitives);\r\n }\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n *\r\n * @param {Entity} entity The entity whose bounding sphere to compute.\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nModelVisualizer.prototype.getBoundingSphere = function (entity, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entity)) {\r\n throw new DeveloperError(\"entity is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var modelData = this._modelHash[entity.id];\r\n if (!defined(modelData) || modelData.loadFail) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n var model = modelData.modelPrimitive;\r\n if (!defined(model) || !model.show) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n if (!model.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n\r\n if (model.heightReference === HeightReference.NONE) {\r\n BoundingSphere.transform(model.boundingSphere, model.modelMatrix, result);\r\n } else {\r\n if (!defined(model._clampedModelMatrix)) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n BoundingSphere.transform(\r\n model.boundingSphere,\r\n model._clampedModelMatrix,\r\n result\r\n );\r\n }\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nModelVisualizer.prototype._onCollectionChanged = function (\r\n entityCollection,\r\n added,\r\n removed,\r\n changed\r\n) {\r\n var i;\r\n var entity;\r\n var entities = this._entitiesToVisualize;\r\n var modelHash = this._modelHash;\r\n var primitives = this._primitives;\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n if (defined(entity._model) && defined(entity._position)) {\r\n entities.set(entity.id, entity);\r\n }\r\n }\r\n\r\n for (i = changed.length - 1; i > -1; i--) {\r\n entity = changed[i];\r\n if (defined(entity._model) && defined(entity._position)) {\r\n clearNodeTransformationsArticulationsScratch(entity, modelHash);\r\n entities.set(entity.id, entity);\r\n } else {\r\n removeModel(this, entity, modelHash, primitives);\r\n entities.remove(entity.id);\r\n }\r\n }\r\n\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n removeModel(this, entity, modelHash, primitives);\r\n entities.remove(entity.id);\r\n }\r\n};\r\n\r\nfunction removeModel(visualizer, entity, modelHash, primitives) {\r\n var modelData = modelHash[entity.id];\r\n if (defined(modelData)) {\r\n primitives.removeAndDestroy(modelData.modelPrimitive);\r\n delete modelHash[entity.id];\r\n }\r\n}\r\n\r\nfunction clearNodeTransformationsArticulationsScratch(entity, modelHash) {\r\n var modelData = modelHash[entity.id];\r\n if (defined(modelData)) {\r\n modelData.nodeTransformationsScratch = {};\r\n modelData.articulationsScratch = {};\r\n }\r\n}\r\n\r\nfunction checkModelLoad(model, entity, modelHash) {\r\n model.readyPromise.otherwise(function (error) {\r\n console.error(error);\r\n modelHash[entity.id].loadFail = true;\r\n });\r\n}\r\nexport default ModelVisualizer;\r\n","import defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport Property from \"./Property.js\";\r\n\r\n/**\r\n * This is a temporary class for scaling position properties to the WGS84 surface.\r\n * It will go away or be refactored to support data with arbitrary height references.\r\n * @private\r\n */\r\nfunction ScaledPositionProperty(value) {\r\n this._definitionChanged = new Event();\r\n this._value = undefined;\r\n this._removeSubscription = undefined;\r\n this.setValue(value);\r\n}\r\n\r\nObject.defineProperties(ScaledPositionProperty.prototype, {\r\n isConstant: {\r\n get: function () {\r\n return Property.isConstant(this._value);\r\n },\r\n },\r\n definitionChanged: {\r\n get: function () {\r\n return this._definitionChanged;\r\n },\r\n },\r\n referenceFrame: {\r\n get: function () {\r\n return defined(this._value)\r\n ? this._value.referenceFrame\r\n : ReferenceFrame.FIXED;\r\n },\r\n },\r\n});\r\n\r\nScaledPositionProperty.prototype.getValue = function (time, result) {\r\n return this.getValueInReferenceFrame(time, ReferenceFrame.FIXED, result);\r\n};\r\n\r\nScaledPositionProperty.prototype.setValue = function (value) {\r\n if (this._value !== value) {\r\n this._value = value;\r\n\r\n if (defined(this._removeSubscription)) {\r\n this._removeSubscription();\r\n this._removeSubscription = undefined;\r\n }\r\n\r\n if (defined(value)) {\r\n this._removeSubscription = value.definitionChanged.addEventListener(\r\n this._raiseDefinitionChanged,\r\n this\r\n );\r\n }\r\n this._definitionChanged.raiseEvent(this);\r\n }\r\n};\r\n\r\nScaledPositionProperty.prototype.getValueInReferenceFrame = function (\r\n time,\r\n referenceFrame,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n if (!defined(referenceFrame)) {\r\n throw new DeveloperError(\"referenceFrame is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n if (!defined(this._value)) {\r\n return undefined;\r\n }\r\n\r\n result = this._value.getValueInReferenceFrame(time, referenceFrame, result);\r\n return defined(result)\r\n ? Ellipsoid.WGS84.scaleToGeodeticSurface(result, result)\r\n : undefined;\r\n};\r\n\r\nScaledPositionProperty.prototype.equals = function (other) {\r\n return (\r\n this === other ||\r\n (other instanceof ScaledPositionProperty && this._value === other._value)\r\n );\r\n};\r\n\r\nScaledPositionProperty.prototype._raiseDefinitionChanged = function () {\r\n this._definitionChanged.raiseEvent(this);\r\n};\r\nexport default ScaledPositionProperty;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport TimeInterval from \"../Core/TimeInterval.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport PolylineCollection from \"../Scene/PolylineCollection.js\";\r\nimport SceneMode from \"../Scene/SceneMode.js\";\r\nimport CompositePositionProperty from \"./CompositePositionProperty.js\";\r\nimport ConstantPositionProperty from \"./ConstantPositionProperty.js\";\r\nimport MaterialProperty from \"./MaterialProperty.js\";\r\nimport Property from \"./Property.js\";\r\nimport ReferenceProperty from \"./ReferenceProperty.js\";\r\nimport SampledPositionProperty from \"./SampledPositionProperty.js\";\r\nimport ScaledPositionProperty from \"./ScaledPositionProperty.js\";\r\nimport TimeIntervalCollectionPositionProperty from \"./TimeIntervalCollectionPositionProperty.js\";\r\n\r\nvar defaultResolution = 60.0;\r\nvar defaultWidth = 1.0;\r\n\r\nvar scratchTimeInterval = new TimeInterval();\r\nvar subSampleCompositePropertyScratch = new TimeInterval();\r\nvar subSampleIntervalPropertyScratch = new TimeInterval();\r\n\r\nfunction EntityData(entity) {\r\n this.entity = entity;\r\n this.polyline = undefined;\r\n this.index = undefined;\r\n this.updater = undefined;\r\n}\r\n\r\nfunction subSampleSampledProperty(\r\n property,\r\n start,\r\n stop,\r\n times,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n startingIndex,\r\n result\r\n) {\r\n var r = startingIndex;\r\n //Always step exactly on start (but only use it if it exists.)\r\n var tmp;\r\n tmp = property.getValueInReferenceFrame(start, referenceFrame, result[r]);\r\n if (defined(tmp)) {\r\n result[r++] = tmp;\r\n }\r\n\r\n var steppedOnNow =\r\n !defined(updateTime) ||\r\n JulianDate.lessThanOrEquals(updateTime, start) ||\r\n JulianDate.greaterThanOrEquals(updateTime, stop);\r\n\r\n //Iterate over all interval times and add the ones that fall in our\r\n //time range. Note that times can contain data outside of\r\n //the intervals range. This is by design for use with interpolation.\r\n var t = 0;\r\n var len = times.length;\r\n var current = times[t];\r\n var loopStop = stop;\r\n var sampling = false;\r\n var sampleStepsToTake;\r\n var sampleStepsTaken;\r\n var sampleStepSize;\r\n\r\n while (t < len) {\r\n if (!steppedOnNow && JulianDate.greaterThanOrEquals(current, updateTime)) {\r\n tmp = property.getValueInReferenceFrame(\r\n updateTime,\r\n referenceFrame,\r\n result[r]\r\n );\r\n if (defined(tmp)) {\r\n result[r++] = tmp;\r\n }\r\n steppedOnNow = true;\r\n }\r\n if (\r\n JulianDate.greaterThan(current, start) &&\r\n JulianDate.lessThan(current, loopStop) &&\r\n !current.equals(updateTime)\r\n ) {\r\n tmp = property.getValueInReferenceFrame(\r\n current,\r\n referenceFrame,\r\n result[r]\r\n );\r\n if (defined(tmp)) {\r\n result[r++] = tmp;\r\n }\r\n }\r\n\r\n if (t < len - 1) {\r\n if (maximumStep > 0 && !sampling) {\r\n var next = times[t + 1];\r\n var secondsUntilNext = JulianDate.secondsDifference(next, current);\r\n sampling = secondsUntilNext > maximumStep;\r\n\r\n if (sampling) {\r\n sampleStepsToTake = Math.ceil(secondsUntilNext / maximumStep);\r\n sampleStepsTaken = 0;\r\n sampleStepSize = secondsUntilNext / Math.max(sampleStepsToTake, 2);\r\n sampleStepsToTake = Math.max(sampleStepsToTake - 1, 1);\r\n }\r\n }\r\n\r\n if (sampling && sampleStepsTaken < sampleStepsToTake) {\r\n current = JulianDate.addSeconds(\r\n current,\r\n sampleStepSize,\r\n new JulianDate()\r\n );\r\n sampleStepsTaken++;\r\n continue;\r\n }\r\n }\r\n sampling = false;\r\n t++;\r\n current = times[t];\r\n }\r\n\r\n //Always step exactly on stop (but only use it if it exists.)\r\n tmp = property.getValueInReferenceFrame(stop, referenceFrame, result[r]);\r\n if (defined(tmp)) {\r\n result[r++] = tmp;\r\n }\r\n\r\n return r;\r\n}\r\n\r\nfunction subSampleGenericProperty(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n startingIndex,\r\n result\r\n) {\r\n var tmp;\r\n var i = 0;\r\n var index = startingIndex;\r\n var time = start;\r\n var stepSize = Math.max(maximumStep, 60);\r\n var steppedOnNow =\r\n !defined(updateTime) ||\r\n JulianDate.lessThanOrEquals(updateTime, start) ||\r\n JulianDate.greaterThanOrEquals(updateTime, stop);\r\n while (JulianDate.lessThan(time, stop)) {\r\n if (!steppedOnNow && JulianDate.greaterThanOrEquals(time, updateTime)) {\r\n steppedOnNow = true;\r\n tmp = property.getValueInReferenceFrame(\r\n updateTime,\r\n referenceFrame,\r\n result[index]\r\n );\r\n if (defined(tmp)) {\r\n result[index] = tmp;\r\n index++;\r\n }\r\n }\r\n tmp = property.getValueInReferenceFrame(\r\n time,\r\n referenceFrame,\r\n result[index]\r\n );\r\n if (defined(tmp)) {\r\n result[index] = tmp;\r\n index++;\r\n }\r\n i++;\r\n time = JulianDate.addSeconds(start, stepSize * i, new JulianDate());\r\n }\r\n //Always sample stop.\r\n tmp = property.getValueInReferenceFrame(stop, referenceFrame, result[index]);\r\n if (defined(tmp)) {\r\n result[index] = tmp;\r\n index++;\r\n }\r\n return index;\r\n}\r\n\r\nfunction subSampleIntervalProperty(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n startingIndex,\r\n result\r\n) {\r\n subSampleIntervalPropertyScratch.start = start;\r\n subSampleIntervalPropertyScratch.stop = stop;\r\n\r\n var index = startingIndex;\r\n var intervals = property.intervals;\r\n for (var i = 0; i < intervals.length; i++) {\r\n var interval = intervals.get(i);\r\n if (\r\n !TimeInterval.intersect(\r\n interval,\r\n subSampleIntervalPropertyScratch,\r\n scratchTimeInterval\r\n ).isEmpty\r\n ) {\r\n var time = interval.start;\r\n if (!interval.isStartIncluded) {\r\n if (interval.isStopIncluded) {\r\n time = interval.stop;\r\n } else {\r\n time = JulianDate.addSeconds(\r\n interval.start,\r\n JulianDate.secondsDifference(interval.stop, interval.start) / 2,\r\n new JulianDate()\r\n );\r\n }\r\n }\r\n var tmp = property.getValueInReferenceFrame(\r\n time,\r\n referenceFrame,\r\n result[index]\r\n );\r\n if (defined(tmp)) {\r\n result[index] = tmp;\r\n index++;\r\n }\r\n }\r\n }\r\n return index;\r\n}\r\n\r\nfunction subSampleConstantProperty(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n startingIndex,\r\n result\r\n) {\r\n var tmp = property.getValueInReferenceFrame(\r\n start,\r\n referenceFrame,\r\n result[startingIndex]\r\n );\r\n if (defined(tmp)) {\r\n result[startingIndex++] = tmp;\r\n }\r\n return startingIndex;\r\n}\r\n\r\nfunction subSampleCompositeProperty(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n startingIndex,\r\n result\r\n) {\r\n subSampleCompositePropertyScratch.start = start;\r\n subSampleCompositePropertyScratch.stop = stop;\r\n\r\n var index = startingIndex;\r\n var intervals = property.intervals;\r\n for (var i = 0; i < intervals.length; i++) {\r\n var interval = intervals.get(i);\r\n if (\r\n !TimeInterval.intersect(\r\n interval,\r\n subSampleCompositePropertyScratch,\r\n scratchTimeInterval\r\n ).isEmpty\r\n ) {\r\n var intervalStart = interval.start;\r\n var intervalStop = interval.stop;\r\n\r\n var sampleStart = start;\r\n if (JulianDate.greaterThan(intervalStart, sampleStart)) {\r\n sampleStart = intervalStart;\r\n }\r\n\r\n var sampleStop = stop;\r\n if (JulianDate.lessThan(intervalStop, sampleStop)) {\r\n sampleStop = intervalStop;\r\n }\r\n\r\n index = reallySubSample(\r\n interval.data,\r\n sampleStart,\r\n sampleStop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n index,\r\n result\r\n );\r\n }\r\n }\r\n return index;\r\n}\r\n\r\nfunction reallySubSample(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n index,\r\n result\r\n) {\r\n //Unwrap any references until we have the actual property.\r\n while (property instanceof ReferenceProperty) {\r\n property = property.resolvedProperty;\r\n }\r\n\r\n if (property instanceof SampledPositionProperty) {\r\n var times = property._property._times;\r\n index = subSampleSampledProperty(\r\n property,\r\n start,\r\n stop,\r\n times,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n index,\r\n result\r\n );\r\n } else if (property instanceof CompositePositionProperty) {\r\n index = subSampleCompositeProperty(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n index,\r\n result\r\n );\r\n } else if (property instanceof TimeIntervalCollectionPositionProperty) {\r\n index = subSampleIntervalProperty(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n index,\r\n result\r\n );\r\n } else if (\r\n property instanceof ConstantPositionProperty ||\r\n (property instanceof ScaledPositionProperty &&\r\n Property.isConstant(property))\r\n ) {\r\n index = subSampleConstantProperty(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n index,\r\n result\r\n );\r\n } else {\r\n //Fallback to generic sampling.\r\n index = subSampleGenericProperty(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n index,\r\n result\r\n );\r\n }\r\n return index;\r\n}\r\n\r\nfunction subSample(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n result\r\n) {\r\n if (!defined(result)) {\r\n result = [];\r\n }\r\n\r\n var length = reallySubSample(\r\n property,\r\n start,\r\n stop,\r\n updateTime,\r\n referenceFrame,\r\n maximumStep,\r\n 0,\r\n result\r\n );\r\n result.length = length;\r\n return result;\r\n}\r\n\r\nvar toFixedScratch = new Matrix3();\r\nfunction PolylineUpdater(scene, referenceFrame) {\r\n this._unusedIndexes = [];\r\n this._polylineCollection = new PolylineCollection();\r\n this._scene = scene;\r\n this._referenceFrame = referenceFrame;\r\n scene.primitives.add(this._polylineCollection);\r\n}\r\n\r\nPolylineUpdater.prototype.update = function (time) {\r\n if (this._referenceFrame === ReferenceFrame.INERTIAL) {\r\n var toFixed = Transforms.computeIcrfToFixedMatrix(time, toFixedScratch);\r\n if (!defined(toFixed)) {\r\n toFixed = Transforms.computeTemeToPseudoFixedMatrix(time, toFixedScratch);\r\n }\r\n Matrix4.fromRotationTranslation(\r\n toFixed,\r\n Cartesian3.ZERO,\r\n this._polylineCollection.modelMatrix\r\n );\r\n }\r\n};\r\n\r\nPolylineUpdater.prototype.updateObject = function (time, item) {\r\n var entity = item.entity;\r\n var pathGraphics = entity._path;\r\n var positionProperty = entity._position;\r\n\r\n var sampleStart;\r\n var sampleStop;\r\n var showProperty = pathGraphics._show;\r\n var polyline = item.polyline;\r\n var show =\r\n entity.isShowing && (!defined(showProperty) || showProperty.getValue(time));\r\n\r\n //While we want to show the path, there may not actually be anything to show\r\n //depending on lead/trail settings. Compute the interval of the path to\r\n //show and check against actual availability.\r\n if (show) {\r\n var leadTime = Property.getValueOrUndefined(pathGraphics._leadTime, time);\r\n var trailTime = Property.getValueOrUndefined(pathGraphics._trailTime, time);\r\n var availability = entity._availability;\r\n var hasAvailability = defined(availability);\r\n var hasLeadTime = defined(leadTime);\r\n var hasTrailTime = defined(trailTime);\r\n\r\n //Objects need to have either defined availability or both a lead and trail time in order to\r\n //draw a path (since we can't draw \"infinite\" paths.\r\n show = hasAvailability || (hasLeadTime && hasTrailTime);\r\n\r\n //The final step is to compute the actual start/stop times of the path to show.\r\n //If current time is outside of the availability interval, there's a chance that\r\n //we won't have to draw anything anyway.\r\n if (show) {\r\n if (hasTrailTime) {\r\n sampleStart = JulianDate.addSeconds(time, -trailTime, new JulianDate());\r\n }\r\n if (hasLeadTime) {\r\n sampleStop = JulianDate.addSeconds(time, leadTime, new JulianDate());\r\n }\r\n\r\n if (hasAvailability) {\r\n var start = availability.start;\r\n var stop = availability.stop;\r\n\r\n if (!hasTrailTime || JulianDate.greaterThan(start, sampleStart)) {\r\n sampleStart = start;\r\n }\r\n\r\n if (!hasLeadTime || JulianDate.lessThan(stop, sampleStop)) {\r\n sampleStop = stop;\r\n }\r\n }\r\n show = JulianDate.lessThan(sampleStart, sampleStop);\r\n }\r\n }\r\n\r\n if (!show) {\r\n //don't bother creating or updating anything else\r\n if (defined(polyline)) {\r\n this._unusedIndexes.push(item.index);\r\n item.polyline = undefined;\r\n polyline.show = false;\r\n item.index = undefined;\r\n }\r\n return;\r\n }\r\n\r\n if (!defined(polyline)) {\r\n var unusedIndexes = this._unusedIndexes;\r\n var length = unusedIndexes.length;\r\n if (length > 0) {\r\n var index = unusedIndexes.pop();\r\n polyline = this._polylineCollection.get(index);\r\n item.index = index;\r\n } else {\r\n item.index = this._polylineCollection.length;\r\n polyline = this._polylineCollection.add();\r\n }\r\n polyline.id = entity;\r\n item.polyline = polyline;\r\n }\r\n\r\n var resolution = Property.getValueOrDefault(\r\n pathGraphics._resolution,\r\n time,\r\n defaultResolution\r\n );\r\n\r\n polyline.show = true;\r\n polyline.positions = subSample(\r\n positionProperty,\r\n sampleStart,\r\n sampleStop,\r\n time,\r\n this._referenceFrame,\r\n resolution,\r\n polyline.positions.slice()\r\n );\r\n polyline.material = MaterialProperty.getValue(\r\n time,\r\n pathGraphics._material,\r\n polyline.material\r\n );\r\n polyline.width = Property.getValueOrDefault(\r\n pathGraphics._width,\r\n time,\r\n defaultWidth\r\n );\r\n polyline.distanceDisplayCondition = Property.getValueOrUndefined(\r\n pathGraphics._distanceDisplayCondition,\r\n time,\r\n polyline.distanceDisplayCondition\r\n );\r\n};\r\n\r\nPolylineUpdater.prototype.removeObject = function (item) {\r\n var polyline = item.polyline;\r\n if (defined(polyline)) {\r\n this._unusedIndexes.push(item.index);\r\n item.polyline = undefined;\r\n polyline.show = false;\r\n polyline.id = undefined;\r\n item.index = undefined;\r\n }\r\n};\r\n\r\nPolylineUpdater.prototype.destroy = function () {\r\n this._scene.primitives.remove(this._polylineCollection);\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * A {@link Visualizer} which maps {@link Entity#path} to a {@link Polyline}.\r\n * @alias PathVisualizer\r\n * @constructor\r\n *\r\n * @param {Scene} scene The scene the primitives will be rendered in.\r\n * @param {EntityCollection} entityCollection The entityCollection to visualize.\r\n */\r\nfunction PathVisualizer(scene, entityCollection) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(scene)) {\r\n throw new DeveloperError(\"scene is required.\");\r\n }\r\n if (!defined(entityCollection)) {\r\n throw new DeveloperError(\"entityCollection is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n entityCollection.collectionChanged.addEventListener(\r\n PathVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n\r\n this._scene = scene;\r\n this._updaters = {};\r\n this._entityCollection = entityCollection;\r\n this._items = new AssociativeArray();\r\n\r\n this._onCollectionChanged(entityCollection, entityCollection.values, [], []);\r\n}\r\n\r\n/**\r\n * Updates all of the primitives created by this visualizer to match their\r\n * Entity counterpart at the given time.\r\n *\r\n * @param {JulianDate} time The time to update to.\r\n * @returns {Boolean} This function always returns true.\r\n */\r\nPathVisualizer.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var updaters = this._updaters;\r\n for (var key in updaters) {\r\n if (updaters.hasOwnProperty(key)) {\r\n updaters[key].update(time);\r\n }\r\n }\r\n\r\n var items = this._items.values;\r\n if (\r\n items.length === 0 &&\r\n defined(this._updaters) &&\r\n Object.keys(this._updaters).length > 0\r\n ) {\r\n for (var u in updaters) {\r\n if (updaters.hasOwnProperty(u)) {\r\n updaters[u].destroy();\r\n }\r\n }\r\n this._updaters = {};\r\n }\r\n\r\n for (var i = 0, len = items.length; i < len; i++) {\r\n var item = items[i];\r\n var entity = item.entity;\r\n var positionProperty = entity._position;\r\n\r\n var lastUpdater = item.updater;\r\n\r\n var frameToVisualize = ReferenceFrame.FIXED;\r\n if (this._scene.mode === SceneMode.SCENE3D) {\r\n frameToVisualize = positionProperty.referenceFrame;\r\n }\r\n\r\n var currentUpdater = this._updaters[frameToVisualize];\r\n\r\n if (lastUpdater === currentUpdater && defined(currentUpdater)) {\r\n currentUpdater.updateObject(time, item);\r\n continue;\r\n }\r\n\r\n if (defined(lastUpdater)) {\r\n lastUpdater.removeObject(item);\r\n }\r\n\r\n if (!defined(currentUpdater)) {\r\n currentUpdater = new PolylineUpdater(this._scene, frameToVisualize);\r\n currentUpdater.update(time);\r\n this._updaters[frameToVisualize] = currentUpdater;\r\n }\r\n\r\n item.updater = currentUpdater;\r\n if (defined(currentUpdater)) {\r\n currentUpdater.updateObject(time, item);\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nPathVisualizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys all primitives created by this instance.\r\n */\r\nPathVisualizer.prototype.destroy = function () {\r\n this._entityCollection.collectionChanged.removeEventListener(\r\n PathVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n\r\n var updaters = this._updaters;\r\n for (var key in updaters) {\r\n if (updaters.hasOwnProperty(key)) {\r\n updaters[key].destroy();\r\n }\r\n }\r\n\r\n return destroyObject(this);\r\n};\r\n\r\nPathVisualizer.prototype._onCollectionChanged = function (\r\n entityCollection,\r\n added,\r\n removed,\r\n changed\r\n) {\r\n var i;\r\n var entity;\r\n var item;\r\n var items = this._items;\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n if (defined(entity._path) && defined(entity._position)) {\r\n items.set(entity.id, new EntityData(entity));\r\n }\r\n }\r\n\r\n for (i = changed.length - 1; i > -1; i--) {\r\n entity = changed[i];\r\n if (defined(entity._path) && defined(entity._position)) {\r\n if (!items.contains(entity.id)) {\r\n items.set(entity.id, new EntityData(entity));\r\n }\r\n } else {\r\n item = items.get(entity.id);\r\n if (defined(item)) {\r\n if (defined(item.updater)) {\r\n item.updater.removeObject(item);\r\n }\r\n items.remove(entity.id);\r\n }\r\n }\r\n }\r\n\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n item = items.get(entity.id);\r\n if (defined(item)) {\r\n if (defined(item.updater)) {\r\n item.updater.removeObject(item);\r\n }\r\n items.remove(entity.id);\r\n }\r\n }\r\n};\r\n\r\n//for testing\r\nPathVisualizer._subSample = subSample;\r\nexport default PathVisualizer;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport NearFarScalar from \"../Core/NearFarScalar.js\";\r\nimport createBillboardPointCallback from \"../Scene/createBillboardPointCallback.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultColor = Color.WHITE;\r\nvar defaultOutlineColor = Color.BLACK;\r\nvar defaultOutlineWidth = 0.0;\r\nvar defaultPixelSize = 1.0;\r\nvar defaultDisableDepthTestDistance = 0.0;\r\n\r\nvar colorScratch = new Color();\r\nvar positionScratch = new Cartesian3();\r\nvar outlineColorScratch = new Color();\r\nvar scaleByDistanceScratch = new NearFarScalar();\r\nvar translucencyByDistanceScratch = new NearFarScalar();\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\n\r\nfunction EntityData(entity) {\r\n this.entity = entity;\r\n this.pointPrimitive = undefined;\r\n this.billboard = undefined;\r\n this.color = undefined;\r\n this.outlineColor = undefined;\r\n this.pixelSize = undefined;\r\n this.outlineWidth = undefined;\r\n}\r\n\r\n/**\r\n * A {@link Visualizer} which maps {@link Entity#point} to a {@link PointPrimitive}.\r\n * @alias PointVisualizer\r\n * @constructor\r\n *\r\n * @param {EntityCluster} entityCluster The entity cluster to manage the collection of billboards and optionally cluster with other entities.\r\n * @param {EntityCollection} entityCollection The entityCollection to visualize.\r\n */\r\nfunction PointVisualizer(entityCluster, entityCollection) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entityCluster)) {\r\n throw new DeveloperError(\"entityCluster is required.\");\r\n }\r\n if (!defined(entityCollection)) {\r\n throw new DeveloperError(\"entityCollection is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n entityCollection.collectionChanged.addEventListener(\r\n PointVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n\r\n this._cluster = entityCluster;\r\n this._entityCollection = entityCollection;\r\n this._items = new AssociativeArray();\r\n this._onCollectionChanged(entityCollection, entityCollection.values, [], []);\r\n}\r\n\r\n/**\r\n * Updates the primitives created by this visualizer to match their\r\n * Entity counterpart at the given time.\r\n *\r\n * @param {JulianDate} time The time to update to.\r\n * @returns {Boolean} This function always returns true.\r\n */\r\nPointVisualizer.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var items = this._items.values;\r\n var cluster = this._cluster;\r\n for (var i = 0, len = items.length; i < len; i++) {\r\n var item = items[i];\r\n var entity = item.entity;\r\n var pointGraphics = entity._point;\r\n var pointPrimitive = item.pointPrimitive;\r\n var billboard = item.billboard;\r\n var heightReference = Property.getValueOrDefault(\r\n pointGraphics._heightReference,\r\n time,\r\n HeightReference.NONE\r\n );\r\n var show =\r\n entity.isShowing &&\r\n entity.isAvailable(time) &&\r\n Property.getValueOrDefault(pointGraphics._show, time, true);\r\n var position;\r\n if (show) {\r\n position = Property.getValueOrUndefined(\r\n entity._position,\r\n time,\r\n positionScratch\r\n );\r\n show = defined(position);\r\n }\r\n if (!show) {\r\n returnPrimitive(item, entity, cluster);\r\n continue;\r\n }\r\n\r\n if (!Property.isConstant(entity._position)) {\r\n cluster._clusterDirty = true;\r\n }\r\n\r\n var needsRedraw = false;\r\n var updateClamping = false;\r\n if (heightReference !== HeightReference.NONE && !defined(billboard)) {\r\n if (defined(pointPrimitive)) {\r\n returnPrimitive(item, entity, cluster);\r\n pointPrimitive = undefined;\r\n }\r\n\r\n billboard = cluster.getBillboard(entity);\r\n billboard.id = entity;\r\n billboard.image = undefined;\r\n item.billboard = billboard;\r\n needsRedraw = true;\r\n\r\n // If this new billboard happens to have a position and height reference that match our new values,\r\n // billboard._updateClamping will not be called automatically. That's a problem because the clamped\r\n // height may be based on different terrain than is now loaded. So we'll manually call\r\n // _updateClamping below.\r\n updateClamping =\r\n Cartesian3.equals(billboard.position, position) &&\r\n billboard.heightReference === heightReference;\r\n } else if (\r\n heightReference === HeightReference.NONE &&\r\n !defined(pointPrimitive)\r\n ) {\r\n if (defined(billboard)) {\r\n returnPrimitive(item, entity, cluster);\r\n billboard = undefined;\r\n }\r\n\r\n pointPrimitive = cluster.getPoint(entity);\r\n pointPrimitive.id = entity;\r\n item.pointPrimitive = pointPrimitive;\r\n }\r\n\r\n if (defined(pointPrimitive)) {\r\n pointPrimitive.show = true;\r\n pointPrimitive.position = position;\r\n pointPrimitive.scaleByDistance = Property.getValueOrUndefined(\r\n pointGraphics._scaleByDistance,\r\n time,\r\n scaleByDistanceScratch\r\n );\r\n pointPrimitive.translucencyByDistance = Property.getValueOrUndefined(\r\n pointGraphics._translucencyByDistance,\r\n time,\r\n translucencyByDistanceScratch\r\n );\r\n pointPrimitive.color = Property.getValueOrDefault(\r\n pointGraphics._color,\r\n time,\r\n defaultColor,\r\n colorScratch\r\n );\r\n pointPrimitive.outlineColor = Property.getValueOrDefault(\r\n pointGraphics._outlineColor,\r\n time,\r\n defaultOutlineColor,\r\n outlineColorScratch\r\n );\r\n pointPrimitive.outlineWidth = Property.getValueOrDefault(\r\n pointGraphics._outlineWidth,\r\n time,\r\n defaultOutlineWidth\r\n );\r\n pointPrimitive.pixelSize = Property.getValueOrDefault(\r\n pointGraphics._pixelSize,\r\n time,\r\n defaultPixelSize\r\n );\r\n pointPrimitive.distanceDisplayCondition = Property.getValueOrUndefined(\r\n pointGraphics._distanceDisplayCondition,\r\n time,\r\n distanceDisplayConditionScratch\r\n );\r\n pointPrimitive.disableDepthTestDistance = Property.getValueOrDefault(\r\n pointGraphics._disableDepthTestDistance,\r\n time,\r\n defaultDisableDepthTestDistance\r\n );\r\n } else if (defined(billboard)) {\r\n billboard.show = true;\r\n billboard.position = position;\r\n billboard.scaleByDistance = Property.getValueOrUndefined(\r\n pointGraphics._scaleByDistance,\r\n time,\r\n scaleByDistanceScratch\r\n );\r\n billboard.translucencyByDistance = Property.getValueOrUndefined(\r\n pointGraphics._translucencyByDistance,\r\n time,\r\n translucencyByDistanceScratch\r\n );\r\n billboard.distanceDisplayCondition = Property.getValueOrUndefined(\r\n pointGraphics._distanceDisplayCondition,\r\n time,\r\n distanceDisplayConditionScratch\r\n );\r\n billboard.disableDepthTestDistance = Property.getValueOrDefault(\r\n pointGraphics._disableDepthTestDistance,\r\n time,\r\n defaultDisableDepthTestDistance\r\n );\r\n billboard.heightReference = heightReference;\r\n\r\n var newColor = Property.getValueOrDefault(\r\n pointGraphics._color,\r\n time,\r\n defaultColor,\r\n colorScratch\r\n );\r\n var newOutlineColor = Property.getValueOrDefault(\r\n pointGraphics._outlineColor,\r\n time,\r\n defaultOutlineColor,\r\n outlineColorScratch\r\n );\r\n var newOutlineWidth = Math.round(\r\n Property.getValueOrDefault(\r\n pointGraphics._outlineWidth,\r\n time,\r\n defaultOutlineWidth\r\n )\r\n );\r\n var newPixelSize = Math.max(\r\n 1,\r\n Math.round(\r\n Property.getValueOrDefault(\r\n pointGraphics._pixelSize,\r\n time,\r\n defaultPixelSize\r\n )\r\n )\r\n );\r\n\r\n if (newOutlineWidth > 0) {\r\n billboard.scale = 1.0;\r\n needsRedraw =\r\n needsRedraw || //\r\n newOutlineWidth !== item.outlineWidth || //\r\n newPixelSize !== item.pixelSize || //\r\n !Color.equals(newColor, item.color) || //\r\n !Color.equals(newOutlineColor, item.outlineColor);\r\n } else {\r\n billboard.scale = newPixelSize / 50.0;\r\n newPixelSize = 50.0;\r\n needsRedraw =\r\n needsRedraw || //\r\n newOutlineWidth !== item.outlineWidth || //\r\n !Color.equals(newColor, item.color) || //\r\n !Color.equals(newOutlineColor, item.outlineColor);\r\n }\r\n\r\n if (needsRedraw) {\r\n item.color = Color.clone(newColor, item.color);\r\n item.outlineColor = Color.clone(newOutlineColor, item.outlineColor);\r\n item.pixelSize = newPixelSize;\r\n item.outlineWidth = newOutlineWidth;\r\n\r\n var centerAlpha = newColor.alpha;\r\n var cssColor = newColor.toCssColorString();\r\n var cssOutlineColor = newOutlineColor.toCssColorString();\r\n var textureId = JSON.stringify([\r\n cssColor,\r\n newPixelSize,\r\n cssOutlineColor,\r\n newOutlineWidth,\r\n ]);\r\n\r\n billboard.setImage(\r\n textureId,\r\n createBillboardPointCallback(\r\n centerAlpha,\r\n cssColor,\r\n cssOutlineColor,\r\n newOutlineWidth,\r\n newPixelSize\r\n )\r\n );\r\n }\r\n\r\n if (updateClamping) {\r\n billboard._updateClamping();\r\n }\r\n }\r\n }\r\n return true;\r\n};\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n *\r\n * @param {Entity} entity The entity whose bounding sphere to compute.\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nPointVisualizer.prototype.getBoundingSphere = function (entity, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entity)) {\r\n throw new DeveloperError(\"entity is required.\");\r\n }\r\n if (!defined(result)) {\r\n throw new DeveloperError(\"result is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var item = this._items.get(entity.id);\r\n if (\r\n !defined(item) ||\r\n !(defined(item.pointPrimitive) || defined(item.billboard))\r\n ) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n if (defined(item.pointPrimitive)) {\r\n result.center = Cartesian3.clone(\r\n item.pointPrimitive.position,\r\n result.center\r\n );\r\n } else {\r\n var billboard = item.billboard;\r\n if (!defined(billboard._clampedPosition)) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n result.center = Cartesian3.clone(billboard._clampedPosition, result.center);\r\n }\r\n\r\n result.radius = 0;\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nPointVisualizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys all primitives created by this instance.\r\n */\r\nPointVisualizer.prototype.destroy = function () {\r\n this._entityCollection.collectionChanged.removeEventListener(\r\n PointVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n var entities = this._entityCollection.values;\r\n for (var i = 0; i < entities.length; i++) {\r\n this._cluster.removePoint(entities[i]);\r\n }\r\n return destroyObject(this);\r\n};\r\n\r\nPointVisualizer.prototype._onCollectionChanged = function (\r\n entityCollection,\r\n added,\r\n removed,\r\n changed\r\n) {\r\n var i;\r\n var entity;\r\n var items = this._items;\r\n var cluster = this._cluster;\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n if (defined(entity._point) && defined(entity._position)) {\r\n items.set(entity.id, new EntityData(entity));\r\n }\r\n }\r\n\r\n for (i = changed.length - 1; i > -1; i--) {\r\n entity = changed[i];\r\n if (defined(entity._point) && defined(entity._position)) {\r\n if (!items.contains(entity.id)) {\r\n items.set(entity.id, new EntityData(entity));\r\n }\r\n } else {\r\n returnPrimitive(items.get(entity.id), entity, cluster);\r\n items.remove(entity.id);\r\n }\r\n }\r\n\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n returnPrimitive(items.get(entity.id), entity, cluster);\r\n items.remove(entity.id);\r\n }\r\n};\r\n\r\nfunction returnPrimitive(item, entity, cluster) {\r\n if (defined(item)) {\r\n var pointPrimitive = item.pointPrimitive;\r\n if (defined(pointPrimitive)) {\r\n item.pointPrimitive = undefined;\r\n cluster.removePoint(entity);\r\n return;\r\n }\r\n var billboard = item.billboard;\r\n if (defined(billboard)) {\r\n item.billboard = undefined;\r\n cluster.removeBillboard(entity);\r\n }\r\n }\r\n}\r\nexport default PointVisualizer;\r\n","import ArcType from \"../Core/ArcType.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport Event from \"../Core/Event.js\";\r\nimport GeometryInstance from \"../Core/GeometryInstance.js\";\r\nimport GroundPolylineGeometry from \"../Core/GroundPolylineGeometry.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport oneTimeWarning from \"../Core/oneTimeWarning.js\";\r\nimport PolylineGeometry from \"../Core/PolylineGeometry.js\";\r\nimport PolylinePipeline from \"../Core/PolylinePipeline.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport Entity from \"../DataSources/Entity.js\";\r\nimport ClassificationType from \"../Scene/ClassificationType.js\";\r\nimport GroundPolylinePrimitive from \"../Scene/GroundPolylinePrimitive.js\";\r\nimport PolylineCollection from \"../Scene/PolylineCollection.js\";\r\nimport PolylineColorAppearance from \"../Scene/PolylineColorAppearance.js\";\r\nimport PolylineMaterialAppearance from \"../Scene/PolylineMaterialAppearance.js\";\r\nimport ShadowMode from \"../Scene/ShadowMode.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport ConstantProperty from \"./ConstantProperty.js\";\r\nimport MaterialProperty from \"./MaterialProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar defaultZIndex = new ConstantProperty(0);\r\n\r\n//We use this object to create one polyline collection per-scene.\r\nvar polylineCollections = {};\r\n\r\nvar scratchColor = new Color();\r\nvar defaultMaterial = new ColorMaterialProperty(Color.WHITE);\r\nvar defaultShow = new ConstantProperty(true);\r\nvar defaultShadows = new ConstantProperty(ShadowMode.DISABLED);\r\nvar defaultDistanceDisplayCondition = new ConstantProperty(\r\n new DistanceDisplayCondition()\r\n);\r\nvar defaultClassificationType = new ConstantProperty(ClassificationType.BOTH);\r\n\r\nfunction GeometryOptions() {\r\n this.vertexFormat = undefined;\r\n this.positions = undefined;\r\n this.width = undefined;\r\n this.arcType = undefined;\r\n this.granularity = undefined;\r\n}\r\n\r\nfunction GroundGeometryOptions() {\r\n this.positions = undefined;\r\n this.width = undefined;\r\n this.arcType = undefined;\r\n this.granularity = undefined;\r\n}\r\n\r\n/**\r\n * A {@link GeometryUpdater} for polylines.\r\n * Clients do not normally create this class directly, but instead rely on {@link DataSourceDisplay}.\r\n * @alias PolylineGeometryUpdater\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity containing the geometry to be visualized.\r\n * @param {Scene} scene The scene where visualization is taking place.\r\n */\r\nfunction PolylineGeometryUpdater(entity, scene) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entity)) {\r\n throw new DeveloperError(\"entity is required\");\r\n }\r\n if (!defined(scene)) {\r\n throw new DeveloperError(\"scene is required\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n this._entity = entity;\r\n this._scene = scene;\r\n this._entitySubscription = entity.definitionChanged.addEventListener(\r\n PolylineGeometryUpdater.prototype._onEntityPropertyChanged,\r\n this\r\n );\r\n this._fillEnabled = false;\r\n this._dynamic = false;\r\n this._geometryChanged = new Event();\r\n this._showProperty = undefined;\r\n this._materialProperty = undefined;\r\n this._shadowsProperty = undefined;\r\n this._distanceDisplayConditionProperty = undefined;\r\n this._classificationTypeProperty = undefined;\r\n this._depthFailMaterialProperty = undefined;\r\n this._geometryOptions = new GeometryOptions();\r\n this._groundGeometryOptions = new GroundGeometryOptions();\r\n this._id = \"polyline-\" + entity.id;\r\n this._clampToGround = false;\r\n this._supportsPolylinesOnTerrain = Entity.supportsPolylinesOnTerrain(scene);\r\n\r\n this._zIndex = 0;\r\n\r\n this._onEntityPropertyChanged(entity, \"polyline\", entity.polyline, undefined);\r\n}\r\n\r\nObject.defineProperties(PolylineGeometryUpdater.prototype, {\r\n /**\r\n * Gets the unique ID associated with this updater\r\n * @memberof PolylineGeometryUpdater.prototype\r\n * @type {String}\r\n * @readonly\r\n */\r\n id: {\r\n get: function () {\r\n return this._id;\r\n },\r\n },\r\n /**\r\n * Gets the entity associated with this geometry.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Entity}\r\n * @readonly\r\n */\r\n entity: {\r\n get: function () {\r\n return this._entity;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry has a fill component.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n fillEnabled: {\r\n get: function () {\r\n return this._fillEnabled;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if fill visibility varies with simulation time.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n hasConstantFill: {\r\n get: function () {\r\n return (\r\n !this._fillEnabled ||\r\n (!defined(this._entity.availability) &&\r\n Property.isConstant(this._showProperty))\r\n );\r\n },\r\n },\r\n /**\r\n * Gets the material property used to fill the geometry.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {MaterialProperty}\r\n * @readonly\r\n */\r\n fillMaterialProperty: {\r\n get: function () {\r\n return this._materialProperty;\r\n },\r\n },\r\n /**\r\n * Gets the material property used to fill the geometry when it fails the depth test.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {MaterialProperty}\r\n * @readonly\r\n */\r\n depthFailMaterialProperty: {\r\n get: function () {\r\n return this._depthFailMaterialProperty;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry has an outline component.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n outlineEnabled: {\r\n value: false,\r\n },\r\n /**\r\n * Gets a value indicating if outline visibility varies with simulation time.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n hasConstantOutline: {\r\n value: true,\r\n },\r\n /**\r\n * Gets the {@link Color} property for the geometry outline.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Property}\r\n * @readonly\r\n */\r\n outlineColorProperty: {\r\n value: undefined,\r\n },\r\n /**\r\n * Gets the property specifying whether the geometry\r\n * casts or receives shadows from light sources.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Property}\r\n * @readonly\r\n */\r\n shadowsProperty: {\r\n get: function () {\r\n return this._shadowsProperty;\r\n },\r\n },\r\n /**\r\n * Gets or sets the {@link DistanceDisplayCondition} Property specifying at what distance from the camera that this geometry will be displayed.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Property}\r\n * @readonly\r\n */\r\n distanceDisplayConditionProperty: {\r\n get: function () {\r\n return this._distanceDisplayConditionProperty;\r\n },\r\n },\r\n /**\r\n * Gets or sets the {@link ClassificationType} Property specifying if this geometry will classify terrain, 3D Tiles, or both when on the ground.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Property}\r\n * @readonly\r\n */\r\n classificationTypeProperty: {\r\n get: function () {\r\n return this._classificationTypeProperty;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry is time-varying.\r\n * If true, all visualization is delegated to the {@link DynamicGeometryUpdater}\r\n * returned by GeometryUpdater#createDynamicUpdater.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isDynamic: {\r\n get: function () {\r\n return this._dynamic;\r\n },\r\n },\r\n /**\r\n * Gets a value indicating if the geometry is closed.\r\n * This property is only valid for static geometry.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n isClosed: {\r\n value: false,\r\n },\r\n /**\r\n * Gets an event that is raised whenever the public properties\r\n * of this updater change.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n geometryChanged: {\r\n get: function () {\r\n return this._geometryChanged;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating if the path of the line.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {ArcType}\r\n * @readonly\r\n */\r\n arcType: {\r\n get: function () {\r\n return this._arcType;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating if the geometry is clamped to the ground.\r\n * Returns false if polylines on terrain is not supported.\r\n * @memberof PolylineGeometryUpdater.prototype\r\n *\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n clampToGround: {\r\n get: function () {\r\n return this._clampToGround && this._supportsPolylinesOnTerrain;\r\n },\r\n },\r\n\r\n /**\r\n * Gets the zindex\r\n * @type {Number}\r\n * @memberof PolylineGeometryUpdater.prototype\r\n * @readonly\r\n */\r\n zIndex: {\r\n get: function () {\r\n return this._zIndex;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Checks if the geometry is outlined at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve visibility.\r\n * @returns {Boolean} true if geometry is outlined at the provided time, false otherwise.\r\n */\r\nPolylineGeometryUpdater.prototype.isOutlineVisible = function (time) {\r\n return false;\r\n};\r\n\r\n/**\r\n * Checks if the geometry is filled at the provided time.\r\n *\r\n * @param {JulianDate} time The time for which to retrieve visibility.\r\n * @returns {Boolean} true if geometry is filled at the provided time, false otherwise.\r\n */\r\nPolylineGeometryUpdater.prototype.isFilled = function (time) {\r\n var entity = this._entity;\r\n var visible =\r\n this._fillEnabled &&\r\n entity.isAvailable(time) &&\r\n this._showProperty.getValue(time);\r\n return defaultValue(visible, false);\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the fill of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the filled portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent a filled geometry.\r\n */\r\nPolylineGeometryUpdater.prototype.createFillGeometryInstance = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(time)) {\r\n throw new DeveloperError(\"time is required.\");\r\n }\r\n\r\n if (!this._fillEnabled) {\r\n throw new DeveloperError(\r\n \"This instance does not represent a filled geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n var entity = this._entity;\r\n var isAvailable = entity.isAvailable(time);\r\n var show = new ShowGeometryInstanceAttribute(\r\n isAvailable && entity.isShowing && this._showProperty.getValue(time)\r\n );\r\n var distanceDisplayCondition = this._distanceDisplayConditionProperty.getValue(\r\n time\r\n );\r\n var distanceDisplayConditionAttribute = DistanceDisplayConditionGeometryInstanceAttribute.fromDistanceDisplayCondition(\r\n distanceDisplayCondition\r\n );\r\n\r\n var attributes = {\r\n show: show,\r\n distanceDisplayCondition: distanceDisplayConditionAttribute,\r\n };\r\n\r\n var currentColor;\r\n if (this._materialProperty instanceof ColorMaterialProperty) {\r\n if (\r\n defined(this._materialProperty.color) &&\r\n (this._materialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._materialProperty.color.getValue(time, scratchColor);\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n attributes.color = ColorGeometryInstanceAttribute.fromColor(currentColor);\r\n }\r\n\r\n if (this.clampToGround) {\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new GroundPolylineGeometry(this._groundGeometryOptions),\r\n attributes: attributes,\r\n });\r\n }\r\n\r\n if (\r\n defined(this._depthFailMaterialProperty) &&\r\n this._depthFailMaterialProperty instanceof ColorMaterialProperty\r\n ) {\r\n if (\r\n defined(this._depthFailMaterialProperty.color) &&\r\n (this._depthFailMaterialProperty.color.isConstant || isAvailable)\r\n ) {\r\n currentColor = this._depthFailMaterialProperty.color.getValue(\r\n time,\r\n scratchColor\r\n );\r\n }\r\n if (!defined(currentColor)) {\r\n currentColor = Color.WHITE;\r\n }\r\n attributes.depthFailColor = ColorGeometryInstanceAttribute.fromColor(\r\n currentColor\r\n );\r\n }\r\n\r\n return new GeometryInstance({\r\n id: entity,\r\n geometry: new PolylineGeometry(this._geometryOptions),\r\n attributes: attributes,\r\n });\r\n};\r\n\r\n/**\r\n * Creates the geometry instance which represents the outline of the geometry.\r\n *\r\n * @param {JulianDate} time The time to use when retrieving initial attribute values.\r\n * @returns {GeometryInstance} The geometry instance representing the outline portion of the geometry.\r\n *\r\n * @exception {DeveloperError} This instance does not represent an outlined geometry.\r\n */\r\nPolylineGeometryUpdater.prototype.createOutlineGeometryInstance = function (\r\n time\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n throw new DeveloperError(\r\n \"This instance does not represent an outlined geometry.\"\r\n );\r\n //>>includeEnd('debug');\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nPolylineGeometryUpdater.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys and resources used by the object. Once an object is destroyed, it should not be used.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n */\r\nPolylineGeometryUpdater.prototype.destroy = function () {\r\n this._entitySubscription();\r\n destroyObject(this);\r\n};\r\n\r\nPolylineGeometryUpdater.prototype._onEntityPropertyChanged = function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n) {\r\n if (!(propertyName === \"availability\" || propertyName === \"polyline\")) {\r\n return;\r\n }\r\n\r\n var polyline = this._entity.polyline;\r\n\r\n if (!defined(polyline)) {\r\n if (this._fillEnabled) {\r\n this._fillEnabled = false;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n return;\r\n }\r\n\r\n var positionsProperty = polyline.positions;\r\n\r\n var show = polyline.show;\r\n if (\r\n (defined(show) &&\r\n show.isConstant &&\r\n !show.getValue(Iso8601.MINIMUM_VALUE)) || //\r\n !defined(positionsProperty)\r\n ) {\r\n if (this._fillEnabled) {\r\n this._fillEnabled = false;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n return;\r\n }\r\n\r\n var zIndex = polyline.zIndex;\r\n var material = defaultValue(polyline.material, defaultMaterial);\r\n var isColorMaterial = material instanceof ColorMaterialProperty;\r\n this._materialProperty = material;\r\n this._depthFailMaterialProperty = polyline.depthFailMaterial;\r\n this._showProperty = defaultValue(show, defaultShow);\r\n this._shadowsProperty = defaultValue(polyline.shadows, defaultShadows);\r\n this._distanceDisplayConditionProperty = defaultValue(\r\n polyline.distanceDisplayCondition,\r\n defaultDistanceDisplayCondition\r\n );\r\n this._classificationTypeProperty = defaultValue(\r\n polyline.classificationType,\r\n defaultClassificationType\r\n );\r\n this._fillEnabled = true;\r\n this._zIndex = defaultValue(zIndex, defaultZIndex);\r\n\r\n var width = polyline.width;\r\n var arcType = polyline.arcType;\r\n var clampToGround = polyline.clampToGround;\r\n var granularity = polyline.granularity;\r\n\r\n if (\r\n !positionsProperty.isConstant ||\r\n !Property.isConstant(width) ||\r\n !Property.isConstant(arcType) ||\r\n !Property.isConstant(granularity) ||\r\n !Property.isConstant(clampToGround) ||\r\n !Property.isConstant(zIndex)\r\n ) {\r\n if (!this._dynamic) {\r\n this._dynamic = true;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n } else {\r\n var geometryOptions = this._geometryOptions;\r\n var positions = positionsProperty.getValue(\r\n Iso8601.MINIMUM_VALUE,\r\n geometryOptions.positions\r\n );\r\n\r\n //Because of the way we currently handle reference properties,\r\n //we can't automatically assume the positions are always valid.\r\n if (!defined(positions) || positions.length < 2) {\r\n if (this._fillEnabled) {\r\n this._fillEnabled = false;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n return;\r\n }\r\n\r\n var vertexFormat;\r\n if (\r\n isColorMaterial &&\r\n (!defined(this._depthFailMaterialProperty) ||\r\n this._depthFailMaterialProperty instanceof ColorMaterialProperty)\r\n ) {\r\n vertexFormat = PolylineColorAppearance.VERTEX_FORMAT;\r\n } else {\r\n vertexFormat = PolylineMaterialAppearance.VERTEX_FORMAT;\r\n }\r\n\r\n geometryOptions.vertexFormat = vertexFormat;\r\n geometryOptions.positions = positions;\r\n geometryOptions.width = defined(width)\r\n ? width.getValue(Iso8601.MINIMUM_VALUE)\r\n : undefined;\r\n geometryOptions.arcType = defined(arcType)\r\n ? arcType.getValue(Iso8601.MINIMUM_VALUE)\r\n : undefined;\r\n geometryOptions.granularity = defined(granularity)\r\n ? granularity.getValue(Iso8601.MINIMUM_VALUE)\r\n : undefined;\r\n\r\n var groundGeometryOptions = this._groundGeometryOptions;\r\n groundGeometryOptions.positions = positions;\r\n groundGeometryOptions.width = geometryOptions.width;\r\n groundGeometryOptions.arcType = geometryOptions.arcType;\r\n groundGeometryOptions.granularity = geometryOptions.granularity;\r\n\r\n this._clampToGround = defined(clampToGround)\r\n ? clampToGround.getValue(Iso8601.MINIMUM_VALUE)\r\n : false;\r\n\r\n if (!this._clampToGround && defined(zIndex)) {\r\n oneTimeWarning(\r\n \"Entity polylines must have clampToGround: true when using zIndex. zIndex will be ignored.\"\r\n );\r\n }\r\n\r\n this._dynamic = false;\r\n this._geometryChanged.raiseEvent(this);\r\n }\r\n};\r\n\r\n/**\r\n * Creates the dynamic updater to be used when GeometryUpdater#isDynamic is true.\r\n *\r\n * @param {PrimitiveCollection} primitives The primitive collection to use.\r\n * @param {PrimitiveCollection|OrderedGroundPrimitiveCollection} groundPrimitives The primitive collection to use for ordered ground primitives.\r\n * @returns {DynamicGeometryUpdater} The dynamic updater used to update the geometry each frame.\r\n *\r\n * @exception {DeveloperError} This instance does not represent dynamic geometry.\r\n * @private\r\n */\r\nPolylineGeometryUpdater.prototype.createDynamicUpdater = function (\r\n primitives,\r\n groundPrimitives\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"primitives\", primitives);\r\n Check.defined(\"groundPrimitives\", groundPrimitives);\r\n\r\n if (!this._dynamic) {\r\n throw new DeveloperError(\r\n \"This instance does not represent dynamic geometry.\"\r\n );\r\n }\r\n //>>includeEnd('debug');\r\n\r\n return new DynamicGeometryUpdater(primitives, groundPrimitives, this);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nvar generateCartesianArcOptions = {\r\n positions: undefined,\r\n granularity: undefined,\r\n height: undefined,\r\n ellipsoid: undefined,\r\n};\r\n\r\nfunction DynamicGeometryUpdater(primitives, groundPrimitives, geometryUpdater) {\r\n this._line = undefined;\r\n this._primitives = primitives;\r\n this._groundPrimitives = groundPrimitives;\r\n this._groundPolylinePrimitive = undefined;\r\n this._material = undefined;\r\n this._geometryUpdater = geometryUpdater;\r\n this._positions = [];\r\n}\r\n\r\nfunction getLine(dynamicGeometryUpdater) {\r\n if (defined(dynamicGeometryUpdater._line)) {\r\n return dynamicGeometryUpdater._line;\r\n }\r\n\r\n var sceneId = dynamicGeometryUpdater._geometryUpdater._scene.id;\r\n var polylineCollection = polylineCollections[sceneId];\r\n var primitives = dynamicGeometryUpdater._primitives;\r\n if (!defined(polylineCollection) || polylineCollection.isDestroyed()) {\r\n polylineCollection = new PolylineCollection();\r\n polylineCollections[sceneId] = polylineCollection;\r\n primitives.add(polylineCollection);\r\n } else if (!primitives.contains(polylineCollection)) {\r\n primitives.add(polylineCollection);\r\n }\r\n\r\n var line = polylineCollection.add();\r\n line.id = dynamicGeometryUpdater._geometryUpdater._entity;\r\n dynamicGeometryUpdater._line = line;\r\n return line;\r\n}\r\n\r\nDynamicGeometryUpdater.prototype.update = function (time) {\r\n var geometryUpdater = this._geometryUpdater;\r\n var entity = geometryUpdater._entity;\r\n var polyline = entity.polyline;\r\n\r\n var positionsProperty = polyline.positions;\r\n var positions = Property.getValueOrUndefined(\r\n positionsProperty,\r\n time,\r\n this._positions\r\n );\r\n\r\n // Synchronize with geometryUpdater for GroundPolylinePrimitive\r\n geometryUpdater._clampToGround = Property.getValueOrDefault(\r\n polyline._clampToGround,\r\n time,\r\n false\r\n );\r\n geometryUpdater._groundGeometryOptions.positions = positions;\r\n geometryUpdater._groundGeometryOptions.width = Property.getValueOrDefault(\r\n polyline._width,\r\n time,\r\n 1\r\n );\r\n geometryUpdater._groundGeometryOptions.arcType = Property.getValueOrDefault(\r\n polyline._arcType,\r\n time,\r\n ArcType.GEODESIC\r\n );\r\n geometryUpdater._groundGeometryOptions.granularity = Property.getValueOrDefault(\r\n polyline._granularity,\r\n time,\r\n 9999\r\n );\r\n\r\n var groundPrimitives = this._groundPrimitives;\r\n\r\n if (defined(this._groundPolylinePrimitive)) {\r\n groundPrimitives.remove(this._groundPolylinePrimitive); // destroys by default\r\n this._groundPolylinePrimitive = undefined;\r\n }\r\n\r\n if (geometryUpdater.clampToGround) {\r\n if (\r\n !entity.isShowing ||\r\n !entity.isAvailable(time) ||\r\n !Property.getValueOrDefault(polyline._show, time, true)\r\n ) {\r\n return;\r\n }\r\n\r\n if (!defined(positions) || positions.length < 2) {\r\n return;\r\n }\r\n\r\n var fillMaterialProperty = geometryUpdater.fillMaterialProperty;\r\n var appearance;\r\n if (fillMaterialProperty instanceof ColorMaterialProperty) {\r\n appearance = new PolylineColorAppearance();\r\n } else {\r\n var material = MaterialProperty.getValue(\r\n time,\r\n fillMaterialProperty,\r\n this._material\r\n );\r\n appearance = new PolylineMaterialAppearance({\r\n material: material,\r\n translucent: material.isTranslucent(),\r\n });\r\n this._material = material;\r\n }\r\n\r\n this._groundPolylinePrimitive = groundPrimitives.add(\r\n new GroundPolylinePrimitive({\r\n geometryInstances: geometryUpdater.createFillGeometryInstance(time),\r\n appearance: appearance,\r\n classificationType: geometryUpdater.classificationTypeProperty.getValue(\r\n time\r\n ),\r\n asynchronous: false,\r\n }),\r\n Property.getValueOrUndefined(geometryUpdater.zIndex, time)\r\n );\r\n\r\n // Hide the polyline in the collection, if any\r\n if (defined(this._line)) {\r\n this._line.show = false;\r\n }\r\n return;\r\n }\r\n\r\n var line = getLine(this);\r\n\r\n if (\r\n !entity.isShowing ||\r\n !entity.isAvailable(time) ||\r\n !Property.getValueOrDefault(polyline._show, time, true)\r\n ) {\r\n line.show = false;\r\n return;\r\n }\r\n\r\n if (!defined(positions) || positions.length < 2) {\r\n line.show = false;\r\n return;\r\n }\r\n\r\n var arcType = ArcType.GEODESIC;\r\n arcType = Property.getValueOrDefault(polyline._arcType, time, arcType);\r\n\r\n var globe = geometryUpdater._scene.globe;\r\n if (arcType !== ArcType.NONE && defined(globe)) {\r\n generateCartesianArcOptions.ellipsoid = globe.ellipsoid;\r\n generateCartesianArcOptions.positions = positions;\r\n generateCartesianArcOptions.granularity = Property.getValueOrUndefined(\r\n polyline._granularity,\r\n time\r\n );\r\n generateCartesianArcOptions.height = PolylinePipeline.extractHeights(\r\n positions,\r\n globe.ellipsoid\r\n );\r\n if (arcType === ArcType.GEODESIC) {\r\n positions = PolylinePipeline.generateCartesianArc(\r\n generateCartesianArcOptions\r\n );\r\n } else {\r\n positions = PolylinePipeline.generateCartesianRhumbArc(\r\n generateCartesianArcOptions\r\n );\r\n }\r\n }\r\n\r\n line.show = true;\r\n line.positions = positions.slice();\r\n line.material = MaterialProperty.getValue(\r\n time,\r\n geometryUpdater.fillMaterialProperty,\r\n line.material\r\n );\r\n line.width = Property.getValueOrDefault(polyline._width, time, 1);\r\n line.distanceDisplayCondition = Property.getValueOrUndefined(\r\n polyline._distanceDisplayCondition,\r\n time,\r\n line.distanceDisplayCondition\r\n );\r\n};\r\n\r\nDynamicGeometryUpdater.prototype.getBoundingSphere = function (result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n if (!this._geometryUpdater.clampToGround) {\r\n var line = getLine(this);\r\n if (line.show && line.positions.length > 0) {\r\n BoundingSphere.fromPoints(line.positions, result);\r\n return BoundingSphereState.DONE;\r\n }\r\n } else {\r\n var groundPolylinePrimitive = this._groundPolylinePrimitive;\r\n if (\r\n defined(groundPolylinePrimitive) &&\r\n groundPolylinePrimitive.show &&\r\n groundPolylinePrimitive.ready\r\n ) {\r\n var attributes = groundPolylinePrimitive.getGeometryInstanceAttributes(\r\n this._geometryUpdater._entity\r\n );\r\n if (defined(attributes) && defined(attributes.boundingSphere)) {\r\n BoundingSphere.clone(attributes.boundingSphere, result);\r\n return BoundingSphereState.DONE;\r\n }\r\n }\r\n\r\n if (defined(groundPolylinePrimitive) && !groundPolylinePrimitive.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n\r\n return BoundingSphereState.DONE;\r\n }\r\n\r\n return BoundingSphereState.FAILED;\r\n};\r\n\r\nDynamicGeometryUpdater.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\nDynamicGeometryUpdater.prototype.destroy = function () {\r\n var geometryUpdater = this._geometryUpdater;\r\n var sceneId = geometryUpdater._scene.id;\r\n var polylineCollection = polylineCollections[sceneId];\r\n if (defined(polylineCollection)) {\r\n polylineCollection.remove(this._line);\r\n if (polylineCollection.length === 0) {\r\n this._primitives.removeAndDestroy(polylineCollection);\r\n delete polylineCollections[sceneId];\r\n }\r\n }\r\n if (defined(this._groundPolylinePrimitive)) {\r\n this._groundPrimitives.remove(this._groundPolylinePrimitive);\r\n }\r\n destroyObject(this);\r\n};\r\nexport default PolylineGeometryUpdater;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport ColorGeometryInstanceAttribute from \"../Core/ColorGeometryInstanceAttribute.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DistanceDisplayCondition from \"../Core/DistanceDisplayCondition.js\";\r\nimport DistanceDisplayConditionGeometryInstanceAttribute from \"../Core/DistanceDisplayConditionGeometryInstanceAttribute.js\";\r\nimport ShowGeometryInstanceAttribute from \"../Core/ShowGeometryInstanceAttribute.js\";\r\nimport GroundPolylinePrimitive from \"../Scene/GroundPolylinePrimitive.js\";\r\nimport PolylineColorAppearance from \"../Scene/PolylineColorAppearance.js\";\r\nimport PolylineMaterialAppearance from \"../Scene/PolylineMaterialAppearance.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport MaterialProperty from \"./MaterialProperty.js\";\r\nimport Property from \"./Property.js\";\r\n\r\nvar scratchColor = new Color();\r\nvar distanceDisplayConditionScratch = new DistanceDisplayCondition();\r\nvar defaultDistanceDisplayCondition = new DistanceDisplayCondition();\r\n\r\n// Encapsulates a Primitive and all the entities that it represents.\r\nfunction Batch(\r\n orderedGroundPrimitives,\r\n classificationType,\r\n materialProperty,\r\n zIndex,\r\n asynchronous\r\n) {\r\n var appearanceType;\r\n if (materialProperty instanceof ColorMaterialProperty) {\r\n appearanceType = PolylineColorAppearance;\r\n } else {\r\n appearanceType = PolylineMaterialAppearance;\r\n }\r\n\r\n this.orderedGroundPrimitives = orderedGroundPrimitives; // scene level primitive collection\r\n this.classificationType = classificationType;\r\n this.appearanceType = appearanceType;\r\n this.materialProperty = materialProperty;\r\n this.updaters = new AssociativeArray();\r\n this.createPrimitive = true;\r\n this.primitive = undefined; // a GroundPolylinePrimitive encapsulating all the entities\r\n this.oldPrimitive = undefined;\r\n this.geometry = new AssociativeArray();\r\n this.material = undefined;\r\n this.updatersWithAttributes = new AssociativeArray();\r\n this.attributes = new AssociativeArray();\r\n this.invalidated = false;\r\n this.removeMaterialSubscription = materialProperty.definitionChanged.addEventListener(\r\n Batch.prototype.onMaterialChanged,\r\n this\r\n );\r\n this.subscriptions = new AssociativeArray();\r\n this.showsUpdated = new AssociativeArray();\r\n this.zIndex = zIndex;\r\n\r\n this._asynchronous = asynchronous;\r\n}\r\n\r\nBatch.prototype.onMaterialChanged = function () {\r\n this.invalidated = true;\r\n};\r\n\r\n// Check if the given updater's material is compatible with this batch\r\nBatch.prototype.isMaterial = function (updater) {\r\n var material = this.materialProperty;\r\n var updaterMaterial = updater.fillMaterialProperty;\r\n\r\n if (\r\n updaterMaterial === material ||\r\n (updaterMaterial instanceof ColorMaterialProperty &&\r\n material instanceof ColorMaterialProperty)\r\n ) {\r\n return true;\r\n }\r\n return defined(material) && material.equals(updaterMaterial);\r\n};\r\n\r\nBatch.prototype.add = function (time, updater, geometryInstance) {\r\n var id = updater.id;\r\n this.updaters.set(id, updater);\r\n this.geometry.set(id, geometryInstance);\r\n // Updaters with dynamic attributes must be tracked separately, may exit the batch\r\n if (\r\n !updater.hasConstantFill ||\r\n !updater.fillMaterialProperty.isConstant ||\r\n !Property.isConstant(updater.distanceDisplayConditionProperty)\r\n ) {\r\n this.updatersWithAttributes.set(id, updater);\r\n } else {\r\n var that = this;\r\n // Listen for show changes. These will be synchronized in updateShows.\r\n this.subscriptions.set(\r\n id,\r\n updater.entity.definitionChanged.addEventListener(function (\r\n entity,\r\n propertyName,\r\n newValue,\r\n oldValue\r\n ) {\r\n if (propertyName === \"isShowing\") {\r\n that.showsUpdated.set(updater.id, updater);\r\n }\r\n })\r\n );\r\n }\r\n this.createPrimitive = true;\r\n};\r\n\r\nBatch.prototype.remove = function (updater) {\r\n var id = updater.id;\r\n this.createPrimitive = this.geometry.remove(id) || this.createPrimitive;\r\n if (this.updaters.remove(id)) {\r\n this.updatersWithAttributes.remove(id);\r\n var unsubscribe = this.subscriptions.get(id);\r\n if (defined(unsubscribe)) {\r\n unsubscribe();\r\n this.subscriptions.remove(id);\r\n }\r\n return true;\r\n }\r\n return false;\r\n};\r\n\r\nBatch.prototype.update = function (time) {\r\n var isUpdated = true;\r\n var primitive = this.primitive;\r\n var orderedGroundPrimitives = this.orderedGroundPrimitives;\r\n var geometries = this.geometry.values;\r\n var i;\r\n\r\n if (this.createPrimitive) {\r\n var geometriesLength = geometries.length;\r\n if (geometriesLength > 0) {\r\n if (defined(primitive)) {\r\n // Keep a handle to the old primitive so it can be removed when the updated version is ready.\r\n if (!defined(this.oldPrimitive)) {\r\n this.oldPrimitive = primitive;\r\n } else {\r\n // For if the new primitive changes again before it is ready.\r\n orderedGroundPrimitives.remove(primitive);\r\n }\r\n }\r\n\r\n primitive = new GroundPolylinePrimitive({\r\n show: false,\r\n asynchronous: this._asynchronous,\r\n geometryInstances: geometries.slice(),\r\n appearance: new this.appearanceType(),\r\n classificationType: this.classificationType,\r\n });\r\n\r\n if (this.appearanceType === PolylineMaterialAppearance) {\r\n this.material = MaterialProperty.getValue(\r\n time,\r\n this.materialProperty,\r\n this.material\r\n );\r\n primitive.appearance.material = this.material;\r\n }\r\n\r\n orderedGroundPrimitives.add(primitive, this.zIndex);\r\n isUpdated = false;\r\n } else {\r\n if (defined(primitive)) {\r\n orderedGroundPrimitives.remove(primitive);\r\n primitive = undefined;\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n orderedGroundPrimitives.remove(oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n }\r\n\r\n this.attributes.removeAll();\r\n this.primitive = primitive;\r\n this.createPrimitive = false;\r\n } else if (defined(primitive) && primitive.ready) {\r\n primitive.show = true;\r\n if (defined(this.oldPrimitive)) {\r\n orderedGroundPrimitives.remove(this.oldPrimitive);\r\n this.oldPrimitive = undefined;\r\n }\r\n\r\n if (this.appearanceType === PolylineMaterialAppearance) {\r\n this.material = MaterialProperty.getValue(\r\n time,\r\n this.materialProperty,\r\n this.material\r\n );\r\n this.primitive.appearance.material = this.material;\r\n }\r\n var updatersWithAttributes = this.updatersWithAttributes.values;\r\n var length = updatersWithAttributes.length;\r\n for (i = 0; i < length; i++) {\r\n var updater = updatersWithAttributes[i];\r\n var entity = updater.entity;\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n if (!updater.fillMaterialProperty.isConstant) {\r\n var colorProperty = updater.fillMaterialProperty.color;\r\n var resultColor = Property.getValueOrDefault(\r\n colorProperty,\r\n time,\r\n Color.WHITE,\r\n scratchColor\r\n );\r\n if (!Color.equals(attributes._lastColor, resultColor)) {\r\n attributes._lastColor = Color.clone(\r\n resultColor,\r\n attributes._lastColor\r\n );\r\n attributes.color = ColorGeometryInstanceAttribute.toValue(\r\n resultColor,\r\n attributes.color\r\n );\r\n }\r\n }\r\n\r\n var show =\r\n entity.isShowing && (updater.hasConstantFill || updater.isFilled(time));\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n }\r\n\r\n var distanceDisplayConditionProperty =\r\n updater.distanceDisplayConditionProperty;\r\n if (!Property.isConstant(distanceDisplayConditionProperty)) {\r\n var distanceDisplayCondition = Property.getValueOrDefault(\r\n distanceDisplayConditionProperty,\r\n time,\r\n defaultDistanceDisplayCondition,\r\n distanceDisplayConditionScratch\r\n );\r\n if (\r\n !DistanceDisplayCondition.equals(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n )\r\n ) {\r\n attributes._lastDistanceDisplayCondition = DistanceDisplayCondition.clone(\r\n distanceDisplayCondition,\r\n attributes._lastDistanceDisplayCondition\r\n );\r\n attributes.distanceDisplayCondition = DistanceDisplayConditionGeometryInstanceAttribute.toValue(\r\n distanceDisplayCondition,\r\n attributes.distanceDisplayCondition\r\n );\r\n }\r\n }\r\n }\r\n\r\n this.updateShows(primitive);\r\n } else if (defined(primitive) && !primitive.ready) {\r\n isUpdated = false;\r\n }\r\n return isUpdated;\r\n};\r\n\r\nBatch.prototype.updateShows = function (primitive) {\r\n var showsUpdated = this.showsUpdated.values;\r\n var length = showsUpdated.length;\r\n for (var i = 0; i < length; i++) {\r\n var updater = showsUpdated[i];\r\n var entity = updater.entity;\r\n var instance = this.geometry.get(updater.id);\r\n\r\n var attributes = this.attributes.get(instance.id.id);\r\n if (!defined(attributes)) {\r\n attributes = primitive.getGeometryInstanceAttributes(instance.id);\r\n this.attributes.set(instance.id.id, attributes);\r\n }\r\n\r\n var show = entity.isShowing;\r\n var currentShow = attributes.show[0] === 1;\r\n if (show !== currentShow) {\r\n attributes.show = ShowGeometryInstanceAttribute.toValue(\r\n show,\r\n attributes.show\r\n );\r\n instance.attributes.show.value[0] = attributes.show[0];\r\n }\r\n }\r\n this.showsUpdated.removeAll();\r\n};\r\n\r\nBatch.prototype.contains = function (updater) {\r\n return this.updaters.contains(updater.id);\r\n};\r\n\r\nBatch.prototype.getBoundingSphere = function (updater, result) {\r\n var primitive = this.primitive;\r\n if (!primitive.ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n var attributes = primitive.getGeometryInstanceAttributes(updater.entity);\r\n if (\r\n !defined(attributes) ||\r\n !defined(attributes.boundingSphere) ||\r\n (defined(attributes.show) && attributes.show[0] === 0)\r\n ) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n attributes.boundingSphere.clone(result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\nBatch.prototype.destroy = function () {\r\n var primitive = this.primitive;\r\n var orderedGroundPrimitives = this.orderedGroundPrimitives;\r\n if (defined(primitive)) {\r\n orderedGroundPrimitives.remove(primitive);\r\n }\r\n var oldPrimitive = this.oldPrimitive;\r\n if (defined(oldPrimitive)) {\r\n orderedGroundPrimitives.remove(oldPrimitive);\r\n }\r\n this.removeMaterialSubscription();\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nfunction StaticGroundPolylinePerMaterialBatch(\r\n orderedGroundPrimitives,\r\n classificationType,\r\n asynchronous\r\n) {\r\n this._items = [];\r\n this._orderedGroundPrimitives = orderedGroundPrimitives;\r\n this._classificationType = classificationType;\r\n this._asynchronous = defaultValue(asynchronous, true);\r\n}\r\n\r\nStaticGroundPolylinePerMaterialBatch.prototype.add = function (time, updater) {\r\n var items = this._items;\r\n var length = items.length;\r\n var geometryInstance = updater.createFillGeometryInstance(time);\r\n var zIndex = Property.getValueOrDefault(updater.zIndex, 0);\r\n // Check if the Entity represented by the updater has the same material or a material representable with per-instance color.\r\n for (var i = 0; i < length; ++i) {\r\n var item = items[i];\r\n if (item.isMaterial(updater) && item.zIndex === zIndex) {\r\n item.add(time, updater, geometryInstance);\r\n return;\r\n }\r\n }\r\n // If a compatible batch wasn't found, create a new batch.\r\n var batch = new Batch(\r\n this._orderedGroundPrimitives,\r\n this._classificationType,\r\n updater.fillMaterialProperty,\r\n zIndex,\r\n this._asynchronous\r\n );\r\n batch.add(time, updater, geometryInstance);\r\n items.push(batch);\r\n};\r\n\r\nStaticGroundPolylinePerMaterialBatch.prototype.remove = function (updater) {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = length - 1; i >= 0; i--) {\r\n var item = items[i];\r\n if (item.remove(updater)) {\r\n if (item.updaters.length === 0) {\r\n items.splice(i, 1);\r\n item.destroy();\r\n }\r\n break;\r\n }\r\n }\r\n};\r\n\r\nStaticGroundPolylinePerMaterialBatch.prototype.update = function (time) {\r\n var i;\r\n var items = this._items;\r\n var length = items.length;\r\n\r\n for (i = length - 1; i >= 0; i--) {\r\n var item = items[i];\r\n if (item.invalidated) {\r\n items.splice(i, 1);\r\n var updaters = item.updaters.values;\r\n var updatersLength = updaters.length;\r\n for (var h = 0; h < updatersLength; h++) {\r\n this.add(time, updaters[h]);\r\n }\r\n item.destroy();\r\n }\r\n }\r\n\r\n var isUpdated = true;\r\n for (i = 0; i < items.length; i++) {\r\n isUpdated = items[i].update(time) && isUpdated;\r\n }\r\n return isUpdated;\r\n};\r\n\r\nStaticGroundPolylinePerMaterialBatch.prototype.getBoundingSphere = function (\r\n updater,\r\n result\r\n) {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n var item = items[i];\r\n if (item.contains(updater)) {\r\n return item.getBoundingSphere(updater, result);\r\n }\r\n }\r\n return BoundingSphereState.FAILED;\r\n};\r\n\r\nStaticGroundPolylinePerMaterialBatch.prototype.removeAllPrimitives = function () {\r\n var items = this._items;\r\n var length = items.length;\r\n for (var i = 0; i < length; i++) {\r\n items[i].destroy();\r\n }\r\n this._items.length = 0;\r\n};\r\nexport default StaticGroundPolylinePerMaterialBatch;\r\n","import AssociativeArray from \"../Core/AssociativeArray.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport ClassificationType from \"../Scene/ClassificationType.js\";\r\nimport PolylineColorAppearance from \"../Scene/PolylineColorAppearance.js\";\r\nimport PolylineMaterialAppearance from \"../Scene/PolylineMaterialAppearance.js\";\r\nimport ShadowMode from \"../Scene/ShadowMode.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport ColorMaterialProperty from \"./ColorMaterialProperty.js\";\r\nimport DynamicGeometryBatch from \"./DynamicGeometryBatch.js\";\r\nimport PolylineGeometryUpdater from \"./PolylineGeometryUpdater.js\";\r\nimport StaticGeometryColorBatch from \"./StaticGeometryColorBatch.js\";\r\nimport StaticGeometryPerMaterialBatch from \"./StaticGeometryPerMaterialBatch.js\";\r\nimport StaticGroundPolylinePerMaterialBatch from \"./StaticGroundPolylinePerMaterialBatch.js\";\r\n\r\nvar emptyArray = [];\r\n\r\nfunction removeUpdater(that, updater) {\r\n //We don't keep track of which batch an updater is in, so just remove it from all of them.\r\n var batches = that._batches;\r\n var length = batches.length;\r\n for (var i = 0; i < length; i++) {\r\n batches[i].remove(updater);\r\n }\r\n}\r\n\r\nfunction insertUpdaterIntoBatch(that, time, updater) {\r\n if (updater.isDynamic) {\r\n that._dynamicBatch.add(time, updater);\r\n return;\r\n }\r\n\r\n if (updater.clampToGround && updater.fillEnabled) {\r\n // Also checks for support\r\n var classificationType = updater.classificationTypeProperty.getValue(time);\r\n that._groundBatches[classificationType].add(time, updater);\r\n return;\r\n }\r\n\r\n var shadows;\r\n if (updater.fillEnabled) {\r\n shadows = updater.shadowsProperty.getValue(time);\r\n }\r\n\r\n var multiplier = 0;\r\n if (defined(updater.depthFailMaterialProperty)) {\r\n multiplier =\r\n updater.depthFailMaterialProperty instanceof ColorMaterialProperty\r\n ? 1\r\n : 2;\r\n }\r\n\r\n var index;\r\n if (defined(shadows)) {\r\n index = shadows + multiplier * ShadowMode.NUMBER_OF_SHADOW_MODES;\r\n }\r\n\r\n if (updater.fillEnabled) {\r\n if (updater.fillMaterialProperty instanceof ColorMaterialProperty) {\r\n that._colorBatches[index].add(time, updater);\r\n } else {\r\n that._materialBatches[index].add(time, updater);\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * A visualizer for polylines represented by {@link Primitive} instances.\r\n * @alias PolylineVisualizer\r\n * @constructor\r\n *\r\n * @param {Scene} scene The scene the primitives will be rendered in.\r\n * @param {EntityCollection} entityCollection The entityCollection to visualize.\r\n * @param {PrimitiveCollection} [primitives=scene.primitives] A collection to add primitives related to the entities\r\n * @param {PrimitiveCollection} [groundPrimitives=scene.groundPrimitives] A collection to add ground primitives related to the entities\r\n */\r\nfunction PolylineVisualizer(\r\n scene,\r\n entityCollection,\r\n primitives,\r\n groundPrimitives\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"scene\", scene);\r\n Check.defined(\"entityCollection\", entityCollection);\r\n //>>includeEnd('debug');\r\n\r\n groundPrimitives = defaultValue(groundPrimitives, scene.groundPrimitives);\r\n primitives = defaultValue(primitives, scene.primitives);\r\n\r\n this._scene = scene;\r\n this._primitives = primitives;\r\n this._entityCollection = undefined;\r\n this._addedObjects = new AssociativeArray();\r\n this._removedObjects = new AssociativeArray();\r\n this._changedObjects = new AssociativeArray();\r\n\r\n var i;\r\n var numberOfShadowModes = ShadowMode.NUMBER_OF_SHADOW_MODES;\r\n this._colorBatches = new Array(numberOfShadowModes * 3);\r\n this._materialBatches = new Array(numberOfShadowModes * 3);\r\n\r\n for (i = 0; i < numberOfShadowModes; ++i) {\r\n this._colorBatches[i] = new StaticGeometryColorBatch(\r\n primitives,\r\n PolylineColorAppearance,\r\n undefined,\r\n false,\r\n i\r\n ); // no depth fail appearance\r\n this._materialBatches[i] = new StaticGeometryPerMaterialBatch(\r\n primitives,\r\n PolylineMaterialAppearance,\r\n undefined,\r\n false,\r\n i\r\n );\r\n\r\n this._colorBatches[i + numberOfShadowModes] = new StaticGeometryColorBatch(\r\n primitives,\r\n PolylineColorAppearance,\r\n PolylineColorAppearance,\r\n false,\r\n i\r\n ); //depth fail appearance variations\r\n this._materialBatches[\r\n i + numberOfShadowModes\r\n ] = new StaticGeometryPerMaterialBatch(\r\n primitives,\r\n PolylineMaterialAppearance,\r\n PolylineColorAppearance,\r\n false,\r\n i\r\n );\r\n\r\n this._colorBatches[\r\n i + numberOfShadowModes * 2\r\n ] = new StaticGeometryColorBatch(\r\n primitives,\r\n PolylineColorAppearance,\r\n PolylineMaterialAppearance,\r\n false,\r\n i\r\n );\r\n this._materialBatches[\r\n i + numberOfShadowModes * 2\r\n ] = new StaticGeometryPerMaterialBatch(\r\n primitives,\r\n PolylineMaterialAppearance,\r\n PolylineMaterialAppearance,\r\n false,\r\n i\r\n );\r\n }\r\n\r\n this._dynamicBatch = new DynamicGeometryBatch(primitives, groundPrimitives);\r\n\r\n var numberOfClassificationTypes =\r\n ClassificationType.NUMBER_OF_CLASSIFICATION_TYPES;\r\n this._groundBatches = new Array(numberOfClassificationTypes);\r\n\r\n for (i = 0; i < numberOfClassificationTypes; ++i) {\r\n this._groundBatches[i] = new StaticGroundPolylinePerMaterialBatch(\r\n groundPrimitives,\r\n i\r\n );\r\n }\r\n\r\n this._batches = this._colorBatches.concat(\r\n this._materialBatches,\r\n this._dynamicBatch,\r\n this._groundBatches\r\n );\r\n\r\n this._subscriptions = new AssociativeArray();\r\n this._updaters = new AssociativeArray();\r\n\r\n this._entityCollection = entityCollection;\r\n entityCollection.collectionChanged.addEventListener(\r\n PolylineVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n this._onCollectionChanged(\r\n entityCollection,\r\n entityCollection.values,\r\n emptyArray\r\n );\r\n}\r\n\r\n/**\r\n * Updates all of the primitives created by this visualizer to match their\r\n * Entity counterpart at the given time.\r\n *\r\n * @param {JulianDate} time The time to update to.\r\n * @returns {Boolean} True if the visualizer successfully updated to the provided time,\r\n * false if the visualizer is waiting for asynchronous primitives to be created.\r\n */\r\nPolylineVisualizer.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var addedObjects = this._addedObjects;\r\n var added = addedObjects.values;\r\n var removedObjects = this._removedObjects;\r\n var removed = removedObjects.values;\r\n var changedObjects = this._changedObjects;\r\n var changed = changedObjects.values;\r\n\r\n var i;\r\n var entity;\r\n var id;\r\n var updater;\r\n\r\n for (i = changed.length - 1; i > -1; i--) {\r\n entity = changed[i];\r\n id = entity.id;\r\n updater = this._updaters.get(id);\r\n\r\n //If in a single update, an entity gets removed and a new instance\r\n //re-added with the same id, the updater no longer tracks the\r\n //correct entity, we need to both remove the old one and\r\n //add the new one, which is done by pushing the entity\r\n //onto the removed/added lists.\r\n if (updater.entity === entity) {\r\n removeUpdater(this, updater);\r\n insertUpdaterIntoBatch(this, time, updater);\r\n } else {\r\n removed.push(entity);\r\n added.push(entity);\r\n }\r\n }\r\n\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n id = entity.id;\r\n updater = this._updaters.get(id);\r\n removeUpdater(this, updater);\r\n updater.destroy();\r\n this._updaters.remove(id);\r\n this._subscriptions.get(id)();\r\n this._subscriptions.remove(id);\r\n }\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n id = entity.id;\r\n updater = new PolylineGeometryUpdater(entity, this._scene);\r\n this._updaters.set(id, updater);\r\n insertUpdaterIntoBatch(this, time, updater);\r\n this._subscriptions.set(\r\n id,\r\n updater.geometryChanged.addEventListener(\r\n PolylineVisualizer._onGeometryChanged,\r\n this\r\n )\r\n );\r\n }\r\n\r\n addedObjects.removeAll();\r\n removedObjects.removeAll();\r\n changedObjects.removeAll();\r\n\r\n var isUpdated = true;\r\n var batches = this._batches;\r\n var length = batches.length;\r\n for (i = 0; i < length; i++) {\r\n isUpdated = batches[i].update(time) && isUpdated;\r\n }\r\n\r\n return isUpdated;\r\n};\r\n\r\nvar getBoundingSphereArrayScratch = [];\r\nvar getBoundingSphereBoundingSphereScratch = new BoundingSphere();\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n *\r\n * @param {Entity} entity The entity whose bounding sphere to compute.\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nPolylineVisualizer.prototype.getBoundingSphere = function (entity, result) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"entity\", entity);\r\n Check.defined(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n var boundingSpheres = getBoundingSphereArrayScratch;\r\n var tmp = getBoundingSphereBoundingSphereScratch;\r\n\r\n var count = 0;\r\n var state = BoundingSphereState.DONE;\r\n var batches = this._batches;\r\n var batchesLength = batches.length;\r\n var updater = this._updaters.get(entity.id);\r\n for (var i = 0; i < batchesLength; i++) {\r\n state = batches[i].getBoundingSphere(updater, tmp);\r\n if (state === BoundingSphereState.PENDING) {\r\n return BoundingSphereState.PENDING;\r\n } else if (state === BoundingSphereState.DONE) {\r\n boundingSpheres[count] = BoundingSphere.clone(\r\n tmp,\r\n boundingSpheres[count]\r\n );\r\n count++;\r\n }\r\n }\r\n\r\n if (count === 0) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n boundingSpheres.length = count;\r\n BoundingSphere.fromBoundingSpheres(boundingSpheres, result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n */\r\nPolylineVisualizer.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Removes and destroys all primitives created by this instance.\r\n */\r\nPolylineVisualizer.prototype.destroy = function () {\r\n this._entityCollection.collectionChanged.removeEventListener(\r\n PolylineVisualizer.prototype._onCollectionChanged,\r\n this\r\n );\r\n this._addedObjects.removeAll();\r\n this._removedObjects.removeAll();\r\n\r\n var i;\r\n var batches = this._batches;\r\n var length = batches.length;\r\n for (i = 0; i < length; i++) {\r\n batches[i].removeAllPrimitives();\r\n }\r\n\r\n var subscriptions = this._subscriptions.values;\r\n length = subscriptions.length;\r\n for (i = 0; i < length; i++) {\r\n subscriptions[i]();\r\n }\r\n this._subscriptions.removeAll();\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPolylineVisualizer._onGeometryChanged = function (updater) {\r\n var removedObjects = this._removedObjects;\r\n var changedObjects = this._changedObjects;\r\n\r\n var entity = updater.entity;\r\n var id = entity.id;\r\n\r\n if (!defined(removedObjects.get(id)) && !defined(changedObjects.get(id))) {\r\n changedObjects.set(id, entity);\r\n }\r\n};\r\n\r\n/**\r\n * @private\r\n */\r\nPolylineVisualizer.prototype._onCollectionChanged = function (\r\n entityCollection,\r\n added,\r\n removed\r\n) {\r\n var addedObjects = this._addedObjects;\r\n var removedObjects = this._removedObjects;\r\n var changedObjects = this._changedObjects;\r\n\r\n var i;\r\n var id;\r\n var entity;\r\n for (i = removed.length - 1; i > -1; i--) {\r\n entity = removed[i];\r\n id = entity.id;\r\n if (!addedObjects.remove(id)) {\r\n removedObjects.set(id, entity);\r\n changedObjects.remove(id);\r\n }\r\n }\r\n\r\n for (i = added.length - 1; i > -1; i--) {\r\n entity = added[i];\r\n id = entity.id;\r\n if (removedObjects.remove(id)) {\r\n changedObjects.set(id, entity);\r\n } else {\r\n addedObjects.set(id, entity);\r\n }\r\n }\r\n};\r\nexport default PolylineVisualizer;\r\n","import ApproximateTerrainHeights from \"../Core/ApproximateTerrainHeights.js\";\r\nimport BoundingSphere from \"../Core/BoundingSphere.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport destroyObject from \"../Core/destroyObject.js\";\r\nimport EventHelper from \"../Core/EventHelper.js\";\r\nimport GroundPolylinePrimitive from \"../Scene/GroundPolylinePrimitive.js\";\r\nimport GroundPrimitive from \"../Scene/GroundPrimitive.js\";\r\nimport OrderedGroundPrimitiveCollection from \"../Scene/OrderedGroundPrimitiveCollection.js\";\r\nimport PrimitiveCollection from \"../Scene/PrimitiveCollection.js\";\r\nimport BillboardVisualizer from \"./BillboardVisualizer.js\";\r\nimport BoundingSphereState from \"./BoundingSphereState.js\";\r\nimport CustomDataSource from \"./CustomDataSource.js\";\r\nimport GeometryVisualizer from \"./GeometryVisualizer.js\";\r\nimport LabelVisualizer from \"./LabelVisualizer.js\";\r\nimport ModelVisualizer from \"./ModelVisualizer.js\";\r\nimport Cesium3DTilesetVisualizer from \"./Cesium3DTilesetVisualizer.js\";\r\nimport PathVisualizer from \"./PathVisualizer.js\";\r\nimport PointVisualizer from \"./PointVisualizer.js\";\r\nimport PolylineVisualizer from \"./PolylineVisualizer.js\";\r\n\r\n/**\r\n * Visualizes a collection of {@link DataSource} instances.\r\n * @alias DataSourceDisplay\r\n * @constructor\r\n *\r\n * @param {Object} options Object with the following properties:\r\n * @param {Scene} options.scene The scene in which to display the data.\r\n * @param {DataSourceCollection} options.dataSourceCollection The data sources to display.\r\n * @param {DataSourceDisplay.VisualizersCallback} [options.visualizersCallback=DataSourceDisplay.defaultVisualizersCallback]\r\n * A function which creates an array of visualizers used for visualization.\r\n * If undefined, all standard visualizers are used.\r\n */\r\nfunction DataSourceDisplay(options) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.typeOf.object(\"options\", options);\r\n Check.typeOf.object(\"options.scene\", options.scene);\r\n Check.typeOf.object(\r\n \"options.dataSourceCollection\",\r\n options.dataSourceCollection\r\n );\r\n //>>includeEnd('debug');\r\n\r\n GroundPrimitive.initializeTerrainHeights();\r\n GroundPolylinePrimitive.initializeTerrainHeights();\r\n\r\n var scene = options.scene;\r\n var dataSourceCollection = options.dataSourceCollection;\r\n\r\n this._eventHelper = new EventHelper();\r\n this._eventHelper.add(\r\n dataSourceCollection.dataSourceAdded,\r\n this._onDataSourceAdded,\r\n this\r\n );\r\n this._eventHelper.add(\r\n dataSourceCollection.dataSourceRemoved,\r\n this._onDataSourceRemoved,\r\n this\r\n );\r\n this._eventHelper.add(\r\n dataSourceCollection.dataSourceMoved,\r\n this._onDataSourceMoved,\r\n this\r\n );\r\n this._eventHelper.add(scene.postRender, this._postRender, this);\r\n\r\n this._dataSourceCollection = dataSourceCollection;\r\n this._scene = scene;\r\n this._visualizersCallback = defaultValue(\r\n options.visualizersCallback,\r\n DataSourceDisplay.defaultVisualizersCallback\r\n );\r\n\r\n var primitivesAdded = false;\r\n var primitives = new PrimitiveCollection();\r\n var groundPrimitives = new PrimitiveCollection();\r\n\r\n if (dataSourceCollection.length > 0) {\r\n scene.primitives.add(primitives);\r\n scene.groundPrimitives.add(groundPrimitives);\r\n primitivesAdded = true;\r\n }\r\n\r\n this._primitives = primitives;\r\n this._groundPrimitives = groundPrimitives;\r\n\r\n for (var i = 0, len = dataSourceCollection.length; i < len; i++) {\r\n this._onDataSourceAdded(dataSourceCollection, dataSourceCollection.get(i));\r\n }\r\n\r\n var defaultDataSource = new CustomDataSource();\r\n this._onDataSourceAdded(undefined, defaultDataSource);\r\n this._defaultDataSource = defaultDataSource;\r\n\r\n var removeDefaultDataSourceListener;\r\n var removeDataSourceCollectionListener;\r\n if (!primitivesAdded) {\r\n var that = this;\r\n var addPrimitives = function () {\r\n scene.primitives.add(primitives);\r\n scene.groundPrimitives.add(groundPrimitives);\r\n removeDefaultDataSourceListener();\r\n removeDataSourceCollectionListener();\r\n that._removeDefaultDataSourceListener = undefined;\r\n that._removeDataSourceCollectionListener = undefined;\r\n };\r\n removeDefaultDataSourceListener = defaultDataSource.entities.collectionChanged.addEventListener(\r\n addPrimitives\r\n );\r\n removeDataSourceCollectionListener = dataSourceCollection.dataSourceAdded.addEventListener(\r\n addPrimitives\r\n );\r\n }\r\n\r\n this._removeDefaultDataSourceListener = removeDefaultDataSourceListener;\r\n this._removeDataSourceCollectionListener = removeDataSourceCollectionListener;\r\n\r\n this._ready = false;\r\n}\r\n\r\n/**\r\n * Gets or sets the default function which creates an array of visualizers used for visualization.\r\n * By default, this function uses all standard visualizers.\r\n *\r\n * @type {DataSourceDisplay.VisualizersCallback}\r\n */\r\nDataSourceDisplay.defaultVisualizersCallback = function (\r\n scene,\r\n entityCluster,\r\n dataSource\r\n) {\r\n var entities = dataSource.entities;\r\n return [\r\n new BillboardVisualizer(entityCluster, entities),\r\n new GeometryVisualizer(\r\n scene,\r\n entities,\r\n dataSource._primitives,\r\n dataSource._groundPrimitives\r\n ),\r\n new LabelVisualizer(entityCluster, entities),\r\n new ModelVisualizer(scene, entities),\r\n new Cesium3DTilesetVisualizer(scene, entities),\r\n new PointVisualizer(entityCluster, entities),\r\n new PathVisualizer(scene, entities),\r\n new PolylineVisualizer(\r\n scene,\r\n entities,\r\n dataSource._primitives,\r\n dataSource._groundPrimitives\r\n ),\r\n ];\r\n};\r\n\r\nObject.defineProperties(DataSourceDisplay.prototype, {\r\n /**\r\n * Gets the scene associated with this display.\r\n * @memberof DataSourceDisplay.prototype\r\n * @type {Scene}\r\n */\r\n scene: {\r\n get: function () {\r\n return this._scene;\r\n },\r\n },\r\n /**\r\n * Gets the collection of data sources to display.\r\n * @memberof DataSourceDisplay.prototype\r\n * @type {DataSourceCollection}\r\n */\r\n dataSources: {\r\n get: function () {\r\n return this._dataSourceCollection;\r\n },\r\n },\r\n /**\r\n * Gets the default data source instance which can be used to\r\n * manually create and visualize entities not tied to\r\n * a specific data source. This instance is always available\r\n * and does not appear in the list dataSources collection.\r\n * @memberof DataSourceDisplay.prototype\r\n * @type {CustomDataSource}\r\n */\r\n defaultDataSource: {\r\n get: function () {\r\n return this._defaultDataSource;\r\n },\r\n },\r\n\r\n /**\r\n * Gets a value indicating whether or not all entities in the data source are ready\r\n * @memberof DataSourceDisplay.prototype\r\n * @type {Boolean}\r\n * @readonly\r\n */\r\n ready: {\r\n get: function () {\r\n return this._ready;\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * Returns true if this object was destroyed; otherwise, false.\r\n *

\r\n * If this object was destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception.\r\n *\r\n * @returns {Boolean} True if this object was destroyed; otherwise, false.\r\n *\r\n * @see DataSourceDisplay#destroy\r\n */\r\nDataSourceDisplay.prototype.isDestroyed = function () {\r\n return false;\r\n};\r\n\r\n/**\r\n * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic\r\n * release of WebGL resources, instead of relying on the garbage collector to destroy this object.\r\n *

\r\n * Once an object is destroyed, it should not be used; calling any function other than\r\n * isDestroyed will result in a {@link DeveloperError} exception. Therefore,\r\n * assign the return value (undefined) to the object as done in the example.\r\n *\r\n * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.\r\n *\r\n *\r\n * @example\r\n * dataSourceDisplay = dataSourceDisplay.destroy();\r\n *\r\n * @see DataSourceDisplay#isDestroyed\r\n */\r\nDataSourceDisplay.prototype.destroy = function () {\r\n this._eventHelper.removeAll();\r\n\r\n var dataSourceCollection = this._dataSourceCollection;\r\n for (var i = 0, length = dataSourceCollection.length; i < length; ++i) {\r\n this._onDataSourceRemoved(\r\n this._dataSourceCollection,\r\n dataSourceCollection.get(i)\r\n );\r\n }\r\n this._onDataSourceRemoved(undefined, this._defaultDataSource);\r\n\r\n if (defined(this._removeDefaultDataSourceListener)) {\r\n this._removeDefaultDataSourceListener();\r\n this._removeDataSourceCollectionListener();\r\n } else {\r\n this._scene.primitives.remove(this._primitives);\r\n this._scene.groundPrimitives.remove(this._groundPrimitives);\r\n }\r\n\r\n return destroyObject(this);\r\n};\r\n\r\n/**\r\n * Updates the display to the provided time.\r\n *\r\n * @param {JulianDate} time The simulation time.\r\n * @returns {Boolean} True if all data sources are ready to be displayed, false otherwise.\r\n */\r\nDataSourceDisplay.prototype.update = function (time) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n if (!ApproximateTerrainHeights.initialized) {\r\n this._ready = false;\r\n return false;\r\n }\r\n\r\n var result = true;\r\n\r\n var i;\r\n var x;\r\n var visualizers;\r\n var vLength;\r\n var dataSources = this._dataSourceCollection;\r\n var length = dataSources.length;\r\n for (i = 0; i < length; i++) {\r\n var dataSource = dataSources.get(i);\r\n if (defined(dataSource.update)) {\r\n result = dataSource.update(time) && result;\r\n }\r\n\r\n visualizers = dataSource._visualizers;\r\n vLength = visualizers.length;\r\n for (x = 0; x < vLength; x++) {\r\n result = visualizers[x].update(time) && result;\r\n }\r\n }\r\n\r\n visualizers = this._defaultDataSource._visualizers;\r\n vLength = visualizers.length;\r\n for (x = 0; x < vLength; x++) {\r\n result = visualizers[x].update(time) && result;\r\n }\r\n\r\n this._ready = result;\r\n\r\n return result;\r\n};\r\n\r\nDataSourceDisplay.prototype._postRender = function () {\r\n // Adds credits for all datasources\r\n var frameState = this._scene.frameState;\r\n var dataSources = this._dataSourceCollection;\r\n var length = dataSources.length;\r\n for (var i = 0; i < length; i++) {\r\n var dataSource = dataSources.get(i);\r\n\r\n var credit = dataSource.credit;\r\n if (defined(credit)) {\r\n frameState.creditDisplay.addCredit(credit);\r\n }\r\n\r\n // Credits from the resource that the user can't remove\r\n var credits = dataSource._resourceCredits;\r\n if (defined(credits)) {\r\n var creditCount = credits.length;\r\n for (var c = 0; c < creditCount; c++) {\r\n frameState.creditDisplay.addCredit(credits[c]);\r\n }\r\n }\r\n }\r\n};\r\n\r\nvar getBoundingSphereArrayScratch = [];\r\nvar getBoundingSphereBoundingSphereScratch = new BoundingSphere();\r\n\r\n/**\r\n * Computes a bounding sphere which encloses the visualization produced for the specified entity.\r\n * The bounding sphere is in the fixed frame of the scene's globe.\r\n *\r\n * @param {Entity} entity The entity whose bounding sphere to compute.\r\n * @param {Boolean} allowPartial If true, pending bounding spheres are ignored and an answer will be returned from the currently available data.\r\n * If false, the the function will halt and return pending if any of the bounding spheres are pending.\r\n * @param {BoundingSphere} result The bounding sphere onto which to store the result.\r\n * @returns {BoundingSphereState} BoundingSphereState.DONE if the result contains the bounding sphere,\r\n * BoundingSphereState.PENDING if the result is still being computed, or\r\n * BoundingSphereState.FAILED if the entity has no visualization in the current scene.\r\n * @private\r\n */\r\nDataSourceDisplay.prototype.getBoundingSphere = function (\r\n entity,\r\n allowPartial,\r\n result\r\n) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"entity\", entity);\r\n Check.typeOf.bool(\"allowPartial\", allowPartial);\r\n Check.defined(\"result\", result);\r\n //>>includeEnd('debug');\r\n\r\n if (!this._ready) {\r\n return BoundingSphereState.PENDING;\r\n }\r\n\r\n var i;\r\n var length;\r\n var dataSource = this._defaultDataSource;\r\n if (!dataSource.entities.contains(entity)) {\r\n dataSource = undefined;\r\n\r\n var dataSources = this._dataSourceCollection;\r\n length = dataSources.length;\r\n for (i = 0; i < length; i++) {\r\n var d = dataSources.get(i);\r\n if (d.entities.contains(entity)) {\r\n dataSource = d;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!defined(dataSource)) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n var boundingSpheres = getBoundingSphereArrayScratch;\r\n var tmp = getBoundingSphereBoundingSphereScratch;\r\n\r\n var count = 0;\r\n var state = BoundingSphereState.DONE;\r\n var visualizers = dataSource._visualizers;\r\n var visualizersLength = visualizers.length;\r\n\r\n for (i = 0; i < visualizersLength; i++) {\r\n var visualizer = visualizers[i];\r\n if (defined(visualizer.getBoundingSphere)) {\r\n state = visualizers[i].getBoundingSphere(entity, tmp);\r\n if (!allowPartial && state === BoundingSphereState.PENDING) {\r\n return BoundingSphereState.PENDING;\r\n } else if (state === BoundingSphereState.DONE) {\r\n boundingSpheres[count] = BoundingSphere.clone(\r\n tmp,\r\n boundingSpheres[count]\r\n );\r\n count++;\r\n }\r\n }\r\n }\r\n\r\n if (count === 0) {\r\n return BoundingSphereState.FAILED;\r\n }\r\n\r\n boundingSpheres.length = count;\r\n BoundingSphere.fromBoundingSpheres(boundingSpheres, result);\r\n return BoundingSphereState.DONE;\r\n};\r\n\r\nDataSourceDisplay.prototype._onDataSourceAdded = function (\r\n dataSourceCollection,\r\n dataSource\r\n) {\r\n var scene = this._scene;\r\n\r\n var displayPrimitives = this._primitives;\r\n var displayGroundPrimitives = this._groundPrimitives;\r\n\r\n var primitives = displayPrimitives.add(new PrimitiveCollection());\r\n var groundPrimitives = displayGroundPrimitives.add(\r\n new OrderedGroundPrimitiveCollection()\r\n );\r\n\r\n dataSource._primitives = primitives;\r\n dataSource._groundPrimitives = groundPrimitives;\r\n\r\n var entityCluster = dataSource.clustering;\r\n entityCluster._initialize(scene);\r\n\r\n primitives.add(entityCluster);\r\n\r\n dataSource._visualizers = this._visualizersCallback(\r\n scene,\r\n entityCluster,\r\n dataSource\r\n );\r\n};\r\n\r\nDataSourceDisplay.prototype._onDataSourceRemoved = function (\r\n dataSourceCollection,\r\n dataSource\r\n) {\r\n var displayPrimitives = this._primitives;\r\n var displayGroundPrimitives = this._groundPrimitives;\r\n\r\n var primitives = dataSource._primitives;\r\n var groundPrimitives = dataSource._groundPrimitives;\r\n\r\n var entityCluster = dataSource.clustering;\r\n primitives.remove(entityCluster);\r\n\r\n var visualizers = dataSource._visualizers;\r\n var length = visualizers.length;\r\n for (var i = 0; i < length; i++) {\r\n visualizers[i].destroy();\r\n }\r\n\r\n displayPrimitives.remove(primitives);\r\n displayGroundPrimitives.remove(groundPrimitives);\r\n\r\n dataSource._visualizers = undefined;\r\n};\r\n\r\nDataSourceDisplay.prototype._onDataSourceMoved = function (\r\n dataSource,\r\n newIndex,\r\n oldIndex\r\n) {\r\n var displayPrimitives = this._primitives;\r\n var displayGroundPrimitives = this._groundPrimitives;\r\n\r\n var primitives = dataSource._primitives;\r\n var groundPrimitives = dataSource._groundPrimitives;\r\n\r\n if (newIndex === oldIndex + 1) {\r\n displayPrimitives.raise(primitives);\r\n displayGroundPrimitives.raise(groundPrimitives);\r\n } else if (newIndex === oldIndex - 1) {\r\n displayPrimitives.lower(primitives);\r\n displayGroundPrimitives.lower(groundPrimitives);\r\n } else if (newIndex === 0) {\r\n displayPrimitives.lowerToBottom(primitives);\r\n displayGroundPrimitives.lowerToBottom(groundPrimitives);\r\n displayPrimitives.raise(primitives); // keep defaultDataSource primitives at index 0 since it's not in the collection\r\n displayGroundPrimitives.raise(groundPrimitives);\r\n } else {\r\n displayPrimitives.raiseToTop(primitives);\r\n displayGroundPrimitives.raiseToTop(groundPrimitives);\r\n }\r\n};\r\n\r\n/**\r\n * A function which creates an array of visualizers used for visualization.\r\n * @callback DataSourceDisplay.VisualizersCallback\r\n *\r\n * @param {Scene} scene The scene to create visualizers for.\r\n * @param {DataSource} dataSource The data source to create visualizers for.\r\n * @returns {Visualizer[]} An array of visualizers used for visualization.\r\n *\r\n * @example\r\n * function createVisualizers(scene, dataSource) {\r\n * return [new Cesium.BillboardVisualizer(scene, dataSource.entities)];\r\n * }\r\n */\r\nexport default DataSourceDisplay;\r\n","import Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Check from \"../Core/Check.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport HeadingPitchRange from \"../Core/HeadingPitchRange.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Matrix3 from \"../Core/Matrix3.js\";\r\nimport Matrix4 from \"../Core/Matrix4.js\";\r\nimport Transforms from \"../Core/Transforms.js\";\r\nimport SceneMode from \"../Scene/SceneMode.js\";\r\n\r\nvar updateTransformMatrix3Scratch1 = new Matrix3();\r\nvar updateTransformMatrix3Scratch2 = new Matrix3();\r\nvar updateTransformMatrix3Scratch3 = new Matrix3();\r\nvar updateTransformMatrix4Scratch = new Matrix4();\r\nvar updateTransformCartesian3Scratch1 = new Cartesian3();\r\nvar updateTransformCartesian3Scratch2 = new Cartesian3();\r\nvar updateTransformCartesian3Scratch3 = new Cartesian3();\r\nvar updateTransformCartesian3Scratch4 = new Cartesian3();\r\nvar updateTransformCartesian3Scratch5 = new Cartesian3();\r\nvar updateTransformCartesian3Scratch6 = new Cartesian3();\r\nvar deltaTime = new JulianDate();\r\nvar northUpAxisFactor = 1.25; // times ellipsoid's maximum radius\r\n\r\nfunction updateTransform(\r\n that,\r\n camera,\r\n updateLookAt,\r\n saveCamera,\r\n positionProperty,\r\n time,\r\n ellipsoid\r\n) {\r\n var mode = that.scene.mode;\r\n var cartesian = positionProperty.getValue(time, that._lastCartesian);\r\n if (defined(cartesian)) {\r\n var hasBasis = false;\r\n var invertVelocity = false;\r\n var xBasis;\r\n var yBasis;\r\n var zBasis;\r\n\r\n if (mode === SceneMode.SCENE3D) {\r\n // The time delta was determined based on how fast satellites move compared to vehicles near the surface.\r\n // Slower moving vehicles will most likely default to east-north-up, while faster ones will be VVLH.\r\n JulianDate.addSeconds(time, 0.001, deltaTime);\r\n var deltaCartesian = positionProperty.getValue(\r\n deltaTime,\r\n updateTransformCartesian3Scratch1\r\n );\r\n\r\n // If no valid position at (time + 0.001), sample at (time - 0.001) and invert the vector\r\n if (!defined(deltaCartesian)) {\r\n JulianDate.addSeconds(time, -0.001, deltaTime);\r\n deltaCartesian = positionProperty.getValue(\r\n deltaTime,\r\n updateTransformCartesian3Scratch1\r\n );\r\n invertVelocity = true;\r\n }\r\n\r\n if (defined(deltaCartesian)) {\r\n var toInertial = Transforms.computeFixedToIcrfMatrix(\r\n time,\r\n updateTransformMatrix3Scratch1\r\n );\r\n var toInertialDelta = Transforms.computeFixedToIcrfMatrix(\r\n deltaTime,\r\n updateTransformMatrix3Scratch2\r\n );\r\n var toFixed;\r\n\r\n if (!defined(toInertial) || !defined(toInertialDelta)) {\r\n toFixed = Transforms.computeTemeToPseudoFixedMatrix(\r\n time,\r\n updateTransformMatrix3Scratch3\r\n );\r\n toInertial = Matrix3.transpose(\r\n toFixed,\r\n updateTransformMatrix3Scratch1\r\n );\r\n toInertialDelta = Transforms.computeTemeToPseudoFixedMatrix(\r\n deltaTime,\r\n updateTransformMatrix3Scratch2\r\n );\r\n Matrix3.transpose(toInertialDelta, toInertialDelta);\r\n } else {\r\n toFixed = Matrix3.transpose(\r\n toInertial,\r\n updateTransformMatrix3Scratch3\r\n );\r\n }\r\n\r\n var inertialCartesian = Matrix3.multiplyByVector(\r\n toInertial,\r\n cartesian,\r\n updateTransformCartesian3Scratch5\r\n );\r\n var inertialDeltaCartesian = Matrix3.multiplyByVector(\r\n toInertialDelta,\r\n deltaCartesian,\r\n updateTransformCartesian3Scratch6\r\n );\r\n\r\n Cartesian3.subtract(\r\n inertialCartesian,\r\n inertialDeltaCartesian,\r\n updateTransformCartesian3Scratch4\r\n );\r\n var inertialVelocity =\r\n Cartesian3.magnitude(updateTransformCartesian3Scratch4) * 1000.0; // meters/sec\r\n\r\n var mu = CesiumMath.GRAVITATIONALPARAMETER; // m^3 / sec^2\r\n var semiMajorAxis =\r\n -mu /\r\n (inertialVelocity * inertialVelocity -\r\n (2 * mu) / Cartesian3.magnitude(inertialCartesian));\r\n\r\n if (\r\n semiMajorAxis < 0 ||\r\n semiMajorAxis > northUpAxisFactor * ellipsoid.maximumRadius\r\n ) {\r\n // North-up viewing from deep space.\r\n\r\n // X along the nadir\r\n xBasis = updateTransformCartesian3Scratch2;\r\n Cartesian3.normalize(cartesian, xBasis);\r\n Cartesian3.negate(xBasis, xBasis);\r\n\r\n // Z is North\r\n zBasis = Cartesian3.clone(\r\n Cartesian3.UNIT_Z,\r\n updateTransformCartesian3Scratch3\r\n );\r\n\r\n // Y is along the cross of z and x (right handed basis / in the direction of motion)\r\n yBasis = Cartesian3.cross(\r\n zBasis,\r\n xBasis,\r\n updateTransformCartesian3Scratch1\r\n );\r\n if (Cartesian3.magnitude(yBasis) > CesiumMath.EPSILON7) {\r\n Cartesian3.normalize(xBasis, xBasis);\r\n Cartesian3.normalize(yBasis, yBasis);\r\n\r\n zBasis = Cartesian3.cross(\r\n xBasis,\r\n yBasis,\r\n updateTransformCartesian3Scratch3\r\n );\r\n Cartesian3.normalize(zBasis, zBasis);\r\n\r\n hasBasis = true;\r\n }\r\n } else if (\r\n !Cartesian3.equalsEpsilon(\r\n cartesian,\r\n deltaCartesian,\r\n CesiumMath.EPSILON7\r\n )\r\n ) {\r\n // Approximation of VVLH (Vehicle Velocity Local Horizontal) with the Z-axis flipped.\r\n\r\n // Z along the position\r\n zBasis = updateTransformCartesian3Scratch2;\r\n Cartesian3.normalize(inertialCartesian, zBasis);\r\n Cartesian3.normalize(inertialDeltaCartesian, inertialDeltaCartesian);\r\n\r\n // Y is along the angular momentum vector (e.g. \"orbit normal\")\r\n yBasis = Cartesian3.cross(\r\n zBasis,\r\n inertialDeltaCartesian,\r\n updateTransformCartesian3Scratch3\r\n );\r\n\r\n if (invertVelocity) {\r\n yBasis = Cartesian3.multiplyByScalar(yBasis, -1, yBasis);\r\n }\r\n\r\n if (\r\n !Cartesian3.equalsEpsilon(\r\n yBasis,\r\n Cartesian3.ZERO,\r\n CesiumMath.EPSILON7\r\n )\r\n ) {\r\n // X is along the cross of y and z (right handed basis / in the direction of motion)\r\n xBasis = Cartesian3.cross(\r\n yBasis,\r\n zBasis,\r\n updateTransformCartesian3Scratch1\r\n );\r\n\r\n Matrix3.multiplyByVector(toFixed, xBasis, xBasis);\r\n Matrix3.multiplyByVector(toFixed, yBasis, yBasis);\r\n Matrix3.multiplyByVector(toFixed, zBasis, zBasis);\r\n\r\n Cartesian3.normalize(xBasis, xBasis);\r\n Cartesian3.normalize(yBasis, yBasis);\r\n Cartesian3.normalize(zBasis, zBasis);\r\n\r\n hasBasis = true;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (defined(that.boundingSphere)) {\r\n cartesian = that.boundingSphere.center;\r\n }\r\n\r\n var position;\r\n var direction;\r\n var up;\r\n\r\n if (saveCamera) {\r\n position = Cartesian3.clone(\r\n camera.position,\r\n updateTransformCartesian3Scratch4\r\n );\r\n direction = Cartesian3.clone(\r\n camera.direction,\r\n updateTransformCartesian3Scratch5\r\n );\r\n up = Cartesian3.clone(camera.up, updateTransformCartesian3Scratch6);\r\n }\r\n\r\n var transform = updateTransformMatrix4Scratch;\r\n if (hasBasis) {\r\n transform[0] = xBasis.x;\r\n transform[1] = xBasis.y;\r\n transform[2] = xBasis.z;\r\n transform[3] = 0.0;\r\n transform[4] = yBasis.x;\r\n transform[5] = yBasis.y;\r\n transform[6] = yBasis.z;\r\n transform[7] = 0.0;\r\n transform[8] = zBasis.x;\r\n transform[9] = zBasis.y;\r\n transform[10] = zBasis.z;\r\n transform[11] = 0.0;\r\n transform[12] = cartesian.x;\r\n transform[13] = cartesian.y;\r\n transform[14] = cartesian.z;\r\n transform[15] = 0.0;\r\n } else {\r\n // Stationary or slow-moving, low-altitude objects use East-North-Up.\r\n Transforms.eastNorthUpToFixedFrame(cartesian, ellipsoid, transform);\r\n }\r\n\r\n camera._setTransform(transform);\r\n\r\n if (saveCamera) {\r\n Cartesian3.clone(position, camera.position);\r\n Cartesian3.clone(direction, camera.direction);\r\n Cartesian3.clone(up, camera.up);\r\n Cartesian3.cross(direction, up, camera.right);\r\n }\r\n }\r\n\r\n if (updateLookAt) {\r\n var offset =\r\n mode === SceneMode.SCENE2D ||\r\n Cartesian3.equals(that._offset3D, Cartesian3.ZERO)\r\n ? undefined\r\n : that._offset3D;\r\n camera.lookAtTransform(camera.transform, offset);\r\n }\r\n}\r\n\r\n/**\r\n * A utility object for tracking an entity with the camera.\r\n * @alias EntityView\r\n * @constructor\r\n *\r\n * @param {Entity} entity The entity to track with the camera.\r\n * @param {Scene} scene The scene to use.\r\n * @param {Ellipsoid} [ellipsoid=Ellipsoid.WGS84] The ellipsoid to use for orienting the camera.\r\n */\r\nfunction EntityView(entity, scene, ellipsoid) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"entity\", entity);\r\n Check.defined(\"scene\", scene);\r\n //>>includeEnd('debug');\r\n\r\n /**\r\n * The entity to track with the camera.\r\n * @type {Entity}\r\n */\r\n this.entity = entity;\r\n\r\n /**\r\n * The scene in which to track the object.\r\n * @type {Scene}\r\n */\r\n this.scene = scene;\r\n\r\n /**\r\n * The ellipsoid to use for orienting the camera.\r\n * @type {Ellipsoid}\r\n */\r\n this.ellipsoid = defaultValue(ellipsoid, Ellipsoid.WGS84);\r\n\r\n /**\r\n * The bounding sphere of the object.\r\n * @type {BoundingSphere}\r\n */\r\n this.boundingSphere = undefined;\r\n\r\n // Shadow copies of the objects so we can detect changes.\r\n this._lastEntity = undefined;\r\n this._mode = undefined;\r\n\r\n this._lastCartesian = new Cartesian3();\r\n this._defaultOffset3D = undefined;\r\n\r\n this._offset3D = new Cartesian3();\r\n}\r\n\r\n// STATIC properties defined here, not per-instance.\r\nObject.defineProperties(EntityView, {\r\n /**\r\n * Gets or sets a camera offset that will be used to\r\n * initialize subsequent EntityViews.\r\n * @memberof EntityView\r\n * @type {Cartesian3}\r\n */\r\n defaultOffset3D: {\r\n get: function () {\r\n return this._defaultOffset3D;\r\n },\r\n set: function (vector) {\r\n this._defaultOffset3D = Cartesian3.clone(vector, new Cartesian3());\r\n },\r\n },\r\n});\r\n\r\n// Initialize the static property.\r\nEntityView.defaultOffset3D = new Cartesian3(-14000, 3500, 3500);\r\n\r\nvar scratchHeadingPitchRange = new HeadingPitchRange();\r\nvar scratchCartesian = new Cartesian3();\r\n\r\n/**\r\n * Should be called each animation frame to update the camera\r\n * to the latest settings.\r\n * @param {JulianDate} time The current animation time.\r\n * @param {BoundingSphere} [boundingSphere] bounding sphere of the object.\r\n */\r\nEntityView.prototype.update = function (time, boundingSphere) {\r\n //>>includeStart('debug', pragmas.debug);\r\n Check.defined(\"time\", time);\r\n //>>includeEnd('debug');\r\n\r\n var scene = this.scene;\r\n var ellipsoid = this.ellipsoid;\r\n var sceneMode = scene.mode;\r\n if (sceneMode === SceneMode.MORPHING) {\r\n return;\r\n }\r\n\r\n var entity = this.entity;\r\n var positionProperty = entity.position;\r\n if (!defined(positionProperty)) {\r\n return;\r\n }\r\n var objectChanged = entity !== this._lastEntity;\r\n var sceneModeChanged = sceneMode !== this._mode;\r\n\r\n var camera = scene.camera;\r\n\r\n var updateLookAt = objectChanged || sceneModeChanged;\r\n var saveCamera = true;\r\n\r\n if (objectChanged) {\r\n var viewFromProperty = entity.viewFrom;\r\n var hasViewFrom = defined(viewFromProperty);\r\n\r\n if (!hasViewFrom && defined(boundingSphere)) {\r\n // The default HPR is not ideal for high altitude objects so\r\n // we scale the pitch as we get further from the earth for a more\r\n // downward view.\r\n scratchHeadingPitchRange.pitch = -CesiumMath.PI_OVER_FOUR;\r\n scratchHeadingPitchRange.range = 0;\r\n var position = positionProperty.getValue(time, scratchCartesian);\r\n if (defined(position)) {\r\n var factor =\r\n 2 -\r\n 1 /\r\n Math.max(\r\n 1,\r\n Cartesian3.magnitude(position) / ellipsoid.maximumRadius\r\n );\r\n scratchHeadingPitchRange.pitch *= factor;\r\n }\r\n\r\n camera.viewBoundingSphere(boundingSphere, scratchHeadingPitchRange);\r\n this.boundingSphere = boundingSphere;\r\n updateLookAt = false;\r\n saveCamera = false;\r\n } else if (\r\n !hasViewFrom ||\r\n !defined(viewFromProperty.getValue(time, this._offset3D))\r\n ) {\r\n Cartesian3.clone(EntityView._defaultOffset3D, this._offset3D);\r\n }\r\n } else if (!sceneModeChanged && this._mode !== SceneMode.SCENE2D) {\r\n Cartesian3.clone(camera.position, this._offset3D);\r\n }\r\n\r\n this._lastEntity = entity;\r\n this._mode = sceneMode;\r\n\r\n updateTransform(\r\n this,\r\n camera,\r\n updateLookAt,\r\n saveCamera,\r\n positionProperty,\r\n time,\r\n ellipsoid\r\n );\r\n};\r\nexport default EntityView;\r\n","/**\r\n@license\r\n Copyright (c) 2013 Gildas Lormeau. All rights reserved.\r\n\r\n Redistribution and use in source and binary forms, with or without\r\n modification, are permitted provided that the following conditions are met:\r\n\r\n 1. Redistributions of source code must retain the above copyright notice,\r\n this list of conditions and the following disclaimer.\r\n\r\n 2. Redistributions in binary form must reproduce the above copyright\r\n notice, this list of conditions and the following disclaimer in\r\n the documentation and/or other materials provided with the distribution.\r\n\r\n 3. The names of the authors may not be used to endorse or promote products\r\n derived from this software without specific prior written permission.\r\n\r\n THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,\r\n INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\r\n FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,\r\n INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,\r\n INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r\n LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r\n OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r\n EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n**/\r\n\r\nimport buildModuleUrl from '../Core/buildModuleUrl.js';\r\n\r\nvar tmp = {};\r\n\r\n(function(obj) {\r\n\r\n\tvar ERR_BAD_FORMAT = \"File format is not recognized.\";\r\n\tvar ERR_ENCRYPTED = \"File contains encrypted entry.\";\r\n\tvar ERR_ZIP64 = \"File is using Zip64 (4gb+ file size).\";\r\n\tvar ERR_READ = \"Error while reading zip file.\";\r\n\tvar ERR_WRITE = \"Error while writing zip file.\";\r\n\tvar ERR_WRITE_DATA = \"Error while writing file data.\";\r\n\tvar ERR_READ_DATA = \"Error while reading file data.\";\r\n\tvar ERR_DUPLICATED_NAME = \"File already exists.\";\r\n\tvar CHUNK_SIZE = 512 * 1024;\r\n\r\n\tvar INFLATE_JS = \"inflate.js\";\r\n\tvar DEFLATE_JS = \"deflate.js\";\r\n\r\n\tvar TEXT_PLAIN = \"text/plain\";\r\n\r\n\tvar MESSAGE_EVENT = \"message\";\r\n\r\n\tvar appendABViewSupported;\r\n\ttry {\r\n\t\tappendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;\r\n\t} catch (e) {\r\n\t}\r\n\r\n\tfunction Crc32() {\r\n\t\tvar crc = -1, that = this;\r\n\t\tthat.append = function(data) {\r\n\t\t\tvar offset, table = that.table;\r\n\t\t\tfor (offset = 0; offset < data.length; offset++)\r\n\t\t\t\tcrc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];\r\n\t\t};\r\n\t\tthat.get = function() {\r\n\t\t\treturn ~crc;\r\n\t\t};\r\n\t}\r\n\tCrc32.prototype.table = (function() {\r\n\t\tvar i, j, t, table = [];\r\n\t\tfor (i = 0; i < 256; i++) {\r\n\t\t\tt = i;\r\n\t\t\tfor (j = 0; j < 8; j++)\r\n\t\t\t\tif (t & 1)\r\n\t\t\t\t\tt = (t >>> 1) ^ 0xEDB88320;\r\n\t\t\t\telse\r\n\t\t\t\t\tt = t >>> 1;\r\n\t\t\ttable[i] = t;\r\n\t\t}\r\n\t\treturn table;\r\n\t})();\r\n\r\n\tfunction blobSlice(blob, index, length) {\r\n\t\tif (blob.slice)\r\n\t\t\treturn blob.slice(index, index + length);\r\n\t\telse if (blob.webkitSlice)\r\n\t\t\treturn blob.webkitSlice(index, index + length);\r\n\t\telse if (blob.mozSlice)\r\n\t\t\treturn blob.mozSlice(index, index + length);\r\n\t\telse if (blob.msSlice)\r\n\t\t\treturn blob.msSlice(index, index + length);\r\n\t}\r\n\r\n\tfunction getDataHelper(byteLength, bytes) {\r\n\t\tvar dataBuffer, dataArray;\r\n\t\tdataBuffer = new ArrayBuffer(byteLength);\r\n\t\tdataArray = new Uint8Array(dataBuffer);\r\n\t\tif (bytes)\r\n\t\t\tdataArray.set(bytes, 0);\r\n\t\treturn {\r\n\t\t\tbuffer : dataBuffer,\r\n\t\t\tarray : dataArray,\r\n\t\t\tview : new DataView(dataBuffer)\r\n\t\t};\r\n\t}\r\n\r\n\t// Readers\r\n\tfunction Reader() {\r\n\t}\r\n\r\n\tfunction TextReader(text) {\r\n\t\tvar that = this, blobReader;\r\n\r\n\t\tfunction init(callback, onerror) {\r\n\t\t\tvar blob = new Blob([ text ], {\r\n\t\t\t\ttype : TEXT_PLAIN\r\n\t\t\t});\r\n\t\t\tblobReader = new BlobReader(blob);\r\n\t\t\tblobReader.init(function() {\r\n\t\t\t\tthat.size = blobReader.size;\r\n\t\t\t\tcallback();\r\n\t\t\t}, onerror);\r\n\t\t}\r\n\r\n\t\tfunction readUint8Array(index, length, callback, onerror) {\r\n\t\t\tblobReader.readUint8Array(index, length, callback, onerror);\r\n\t\t}\r\n\r\n\t\tthat.size = 0;\r\n\t\tthat.init = init;\r\n\t\tthat.readUint8Array = readUint8Array;\r\n\t}\r\n\tTextReader.prototype = new Reader();\r\n\tTextReader.prototype.constructor = TextReader;\r\n\r\n\tfunction Data64URIReader(dataURI) {\r\n\t\tvar that = this, dataStart;\r\n\r\n\t\tfunction init(callback) {\r\n\t\t\tvar dataEnd = dataURI.length;\r\n\t\t\twhile (dataURI.charAt(dataEnd - 1) == \"=\")\r\n\t\t\t\tdataEnd--;\r\n\t\t\tdataStart = dataURI.indexOf(\",\") + 1;\r\n\t\t\tthat.size = Math.floor((dataEnd - dataStart) * 0.75);\r\n\t\t\tcallback();\r\n\t\t}\r\n\r\n\t\tfunction readUint8Array(index, length, callback) {\r\n\t\t\tvar i, data = getDataHelper(length);\r\n\t\t\tvar start = Math.floor(index / 3) * 4;\r\n\t\t\tvar end = Math.ceil((index + length) / 3) * 4;\r\n\t\t\tvar bytes = window.atob(dataURI.substring(start + dataStart, end + dataStart));\r\n\t\t\tvar delta = index - Math.floor(start / 4) * 3;\r\n\t\t\tfor (i = delta; i < delta + length; i++)\r\n\t\t\t\tdata.array[i - delta] = bytes.charCodeAt(i);\r\n\t\t\tcallback(data.array);\r\n\t\t}\r\n\r\n\t\tthat.size = 0;\r\n\t\tthat.init = init;\r\n\t\tthat.readUint8Array = readUint8Array;\r\n\t}\r\n\tData64URIReader.prototype = new Reader();\r\n\tData64URIReader.prototype.constructor = Data64URIReader;\r\n\r\n\tfunction BlobReader(blob) {\r\n\t\tvar that = this;\r\n\r\n\t\tfunction init(callback) {\r\n\t\t\tthis.size = blob.size;\r\n\t\t\tcallback();\r\n\t\t}\r\n\r\n\t\tfunction readUint8Array(index, length, callback, onerror) {\r\n\t\t\tvar reader = new FileReader();\r\n\t\t\treader.onload = function(e) {\r\n\t\t\t\tcallback(new Uint8Array(e.target.result));\r\n\t\t\t};\r\n\t\t\treader.onerror = onerror;\r\n\t\t\treader.readAsArrayBuffer(blobSlice(blob, index, length));\r\n\t\t}\r\n\r\n\t\tthat.size = 0;\r\n\t\tthat.init = init;\r\n\t\tthat.readUint8Array = readUint8Array;\r\n\t}\r\n\tBlobReader.prototype = new Reader();\r\n\tBlobReader.prototype.constructor = BlobReader;\r\n\r\n\t// Writers\r\n\r\n\tfunction Writer() {\r\n\t}\r\n\tWriter.prototype.getData = function(callback) {\r\n\t\tcallback(this.data);\r\n\t};\r\n\r\n\tfunction TextWriter(encoding) {\r\n\t\tvar that = this, blob;\r\n\r\n\t\tfunction init(callback) {\r\n\t\t\tblob = new Blob([], {\r\n\t\t\t\ttype : TEXT_PLAIN\r\n\t\t\t});\r\n\t\t\tcallback();\r\n\t\t}\r\n\r\n\t\tfunction writeUint8Array(array, callback) {\r\n\t\t\tblob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {\r\n\t\t\t\ttype : TEXT_PLAIN\r\n\t\t\t});\r\n\t\t\tcallback();\r\n\t\t}\r\n\r\n\t\tfunction getData(callback, onerror) {\r\n\t\t\tvar reader = new FileReader();\r\n\t\t\treader.onload = function(e) {\r\n\t\t\t\tcallback(e.target.result);\r\n\t\t\t};\r\n\t\t\treader.onerror = onerror;\r\n\t\t\treader.readAsText(blob, encoding);\r\n\t\t}\r\n\r\n\t\tthat.init = init;\r\n\t\tthat.writeUint8Array = writeUint8Array;\r\n\t\tthat.getData = getData;\r\n\t}\r\n\tTextWriter.prototype = new Writer();\r\n\tTextWriter.prototype.constructor = TextWriter;\r\n\r\n\tfunction Data64URIWriter(contentType) {\r\n\t\tvar that = this, data = \"\", pending = \"\";\r\n\r\n\t\tfunction init(callback) {\r\n\t\t\tdata += \"data:\" + (contentType || \"\") + \";base64,\";\r\n\t\t\tcallback();\r\n\t\t}\r\n\r\n\t\tfunction writeUint8Array(array, callback) {\r\n\t\t\tvar i, delta = pending.length, dataString = pending;\r\n\t\t\tpending = \"\";\r\n\t\t\tfor (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)\r\n\t\t\t\tdataString += String.fromCharCode(array[i]);\r\n\t\t\tfor (; i < array.length; i++)\r\n\t\t\t\tpending += String.fromCharCode(array[i]);\r\n\t\t\tif (dataString.length > 2)\r\n\t\t\t\tdata += window.btoa(dataString);\r\n\t\t\telse\r\n\t\t\t\tpending = dataString;\r\n\t\t\tcallback();\r\n\t\t}\r\n\r\n\t\tfunction getData(callback) {\r\n\t\t\tcallback(data + window.btoa(pending));\r\n\t\t}\r\n\r\n\t\tthat.init = init;\r\n\t\tthat.writeUint8Array = writeUint8Array;\r\n\t\tthat.getData = getData;\r\n\t}\r\n\tData64URIWriter.prototype = new Writer();\r\n\tData64URIWriter.prototype.constructor = Data64URIWriter;\r\n\r\n\tfunction BlobWriter(contentType) {\r\n\t\tvar blob, that = this;\r\n\r\n\t\tfunction init(callback) {\r\n\t\t\tblob = new Blob([], {\r\n\t\t\t\ttype : contentType\r\n\t\t\t});\r\n\t\t\tcallback();\r\n\t\t}\r\n\r\n\t\tfunction writeUint8Array(array, callback) {\r\n\t\t\tblob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {\r\n\t\t\t\ttype : contentType\r\n\t\t\t});\r\n\t\t\tcallback();\r\n\t\t}\r\n\r\n\t\tfunction getData(callback) {\r\n\t\t\tcallback(blob);\r\n\t\t}\r\n\r\n\t\tthat.init = init;\r\n\t\tthat.writeUint8Array = writeUint8Array;\r\n\t\tthat.getData = getData;\r\n\t}\r\n\tBlobWriter.prototype = new Writer();\r\n\tBlobWriter.prototype.constructor = BlobWriter;\r\n\r\n\t// inflate/deflate core functions\r\n\r\n\tfunction launchWorkerProcess(worker, reader, writer, offset, size, onappend, onprogress, onend, onreaderror, onwriteerror) {\r\n\t\tvar chunkIndex = 0, index, outputSize;\r\n\r\n\t\tfunction onflush() {\r\n\t\t\tworker.removeEventListener(MESSAGE_EVENT, onmessage, false);\r\n\t\t\tonend(outputSize);\r\n\t\t}\r\n\r\n\t\tfunction onmessage(event) {\r\n\t\t\tvar message = event.data, data = message.data;\r\n\r\n\t\t\tif (message.onappend) {\r\n\t\t\t\toutputSize += data.length;\r\n\t\t\t\twriter.writeUint8Array(data, function() {\r\n\t\t\t\t\tonappend(false, data);\r\n\t\t\t\t\tstep();\r\n\t\t\t\t}, onwriteerror);\r\n\t\t\t}\r\n\t\t\tif (message.onflush)\r\n\t\t\t\tif (data) {\r\n\t\t\t\t\toutputSize += data.length;\r\n\t\t\t\t\twriter.writeUint8Array(data, function() {\r\n\t\t\t\t\t\tonappend(false, data);\r\n\t\t\t\t\t\tonflush();\r\n\t\t\t\t\t}, onwriteerror);\r\n\t\t\t\t} else\r\n\t\t\t\t\tonflush();\r\n\t\t\tif (message.progress && onprogress)\r\n\t\t\t\tonprogress(index + message.current, size);\r\n\t\t}\r\n\r\n\t\tfunction step() {\r\n\t\t\tindex = chunkIndex * CHUNK_SIZE;\r\n\t\t\tif (index < size)\r\n\t\t\t\treader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {\r\n\t\t\t\t\tworker.postMessage({\r\n\t\t\t\t\t\tappend : true,\r\n\t\t\t\t\t\tdata : array\r\n\t\t\t\t\t});\r\n\t\t\t\t\tchunkIndex++;\r\n\t\t\t\t\tif (onprogress)\r\n\t\t\t\t\t\tonprogress(index, size);\r\n\t\t\t\t\tonappend(true, array);\r\n\t\t\t\t}, onreaderror);\r\n\t\t\telse\r\n\t\t\t\tworker.postMessage({\r\n\t\t\t\t\tflush : true\r\n\t\t\t\t});\r\n\t\t}\r\n\r\n\t\toutputSize = 0;\r\n\t\tworker.addEventListener(MESSAGE_EVENT, onmessage, false);\r\n\t\tstep();\r\n\t}\r\n\r\n\tfunction launchProcess(process, reader, writer, offset, size, onappend, onprogress, onend, onreaderror, onwriteerror) {\r\n\t\tvar chunkIndex = 0, index, outputSize = 0;\r\n\r\n\t\tfunction step() {\r\n\t\t\tvar outputData;\r\n\t\t\tindex = chunkIndex * CHUNK_SIZE;\r\n\t\t\tif (index < size)\r\n\t\t\t\treader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(inputData) {\r\n\t\t\t\t\tvar outputData = process.append(inputData, function() {\r\n\t\t\t\t\t\tif (onprogress)\r\n\t\t\t\t\t\t\tonprogress(offset + index, size);\r\n\t\t\t\t\t});\r\n\t\t\t\t\toutputSize += outputData.length;\r\n\t\t\t\t\tonappend(true, inputData);\r\n\t\t\t\t\twriter.writeUint8Array(outputData, function() {\r\n\t\t\t\t\t\tonappend(false, outputData);\r\n\t\t\t\t\t\tchunkIndex++;\r\n\t\t\t\t\t\tsetTimeout(step, 1);\r\n\t\t\t\t\t}, onwriteerror);\r\n\t\t\t\t\tif (onprogress)\r\n\t\t\t\t\t\tonprogress(index, size);\r\n\t\t\t\t}, onreaderror);\r\n\t\t\telse {\r\n\t\t\t\toutputData = process.flush();\r\n\t\t\t\tif (outputData) {\r\n\t\t\t\t\toutputSize += outputData.length;\r\n\t\t\t\t\twriter.writeUint8Array(outputData, function() {\r\n\t\t\t\t\t\tonappend(false, outputData);\r\n\t\t\t\t\t\tonend(outputSize);\r\n\t\t\t\t\t}, onwriteerror);\r\n\t\t\t\t} else\r\n\t\t\t\t\tonend(outputSize);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tstep();\r\n\t}\r\n\r\n\tfunction inflate(reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {\r\n\t\tvar worker, crc32 = new Crc32();\r\n\r\n\t\tfunction oninflateappend(sending, array) {\r\n\t\t\tif (computeCrc32 && !sending)\r\n\t\t\t\tcrc32.append(array);\r\n\t\t}\r\n\r\n\t\tfunction oninflateend(outputSize) {\r\n\t\t\tonend(outputSize, crc32.get());\r\n\t\t}\r\n\r\n\t\tif (obj.zip.useWebWorkers) {\r\n\t\t\tworker = new Worker(obj.zip.workerScriptsPath + INFLATE_JS);\r\n\t\t\tlaunchWorkerProcess(worker, reader, writer, offset, size, oninflateappend, onprogress, oninflateend, onreaderror, onwriteerror);\r\n\t\t} else\r\n\t\t\tlaunchProcess(new obj.zip.Inflater(), reader, writer, offset, size, oninflateappend, onprogress, oninflateend, onreaderror, onwriteerror);\r\n\t\treturn worker;\r\n\t}\r\n\r\n\tfunction deflate(reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {\r\n\t\tvar worker, crc32 = new Crc32();\r\n\r\n\t\tfunction ondeflateappend(sending, array) {\r\n\t\t\tif (sending)\r\n\t\t\t\tcrc32.append(array);\r\n\t\t}\r\n\r\n\t\tfunction ondeflateend(outputSize) {\r\n\t\t\tonend(outputSize, crc32.get());\r\n\t\t}\r\n\r\n\t\tfunction onmessage() {\r\n\t\t\tworker.removeEventListener(MESSAGE_EVENT, onmessage, false);\r\n\t\t\tlaunchWorkerProcess(worker, reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);\r\n\t\t}\r\n\r\n\t\tif (obj.zip.useWebWorkers) {\r\n\t\t\tworker = new Worker(obj.zip.workerScriptsPath + DEFLATE_JS);\r\n\t\t\tworker.addEventListener(MESSAGE_EVENT, onmessage, false);\r\n\t\t\tworker.postMessage({\r\n\t\t\t\tinit : true,\r\n\t\t\t\tlevel : level\r\n\t\t\t});\r\n\t\t} else\r\n\t\t\tlaunchProcess(new obj.zip.Deflater(), reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);\r\n\t\treturn worker;\r\n\t}\r\n\r\n\tfunction copy(reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {\r\n\t\tvar chunkIndex = 0, crc32 = new Crc32();\r\n\r\n\t\tfunction step() {\r\n\t\t\tvar index = chunkIndex * CHUNK_SIZE;\r\n\t\t\tif (index < size)\r\n\t\t\t\treader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {\r\n\t\t\t\t\tif (computeCrc32)\r\n\t\t\t\t\t\tcrc32.append(array);\r\n\t\t\t\t\tif (onprogress)\r\n\t\t\t\t\t\tonprogress(index, size, array);\r\n\t\t\t\t\twriter.writeUint8Array(array, function() {\r\n\t\t\t\t\t\tchunkIndex++;\r\n\t\t\t\t\t\tstep();\r\n\t\t\t\t\t}, onwriteerror);\r\n\t\t\t\t}, onreaderror);\r\n\t\t\telse\r\n\t\t\t\tonend(size, crc32.get());\r\n\t\t}\r\n\r\n\t\tstep();\r\n\t}\r\n\r\n\t// ZipReader\r\n\r\n\tfunction decodeASCII(str) {\r\n\t\tvar i, out = \"\", charCode, extendedASCII = [ '\\u00C7', '\\u00FC', '\\u00E9', '\\u00E2', '\\u00E4', '\\u00E0', '\\u00E5', '\\u00E7', '\\u00EA', '\\u00EB',\r\n\t\t\t\t'\\u00E8', '\\u00EF', '\\u00EE', '\\u00EC', '\\u00C4', '\\u00C5', '\\u00C9', '\\u00E6', '\\u00C6', '\\u00F4', '\\u00F6', '\\u00F2', '\\u00FB', '\\u00F9',\r\n\t\t\t\t'\\u00FF', '\\u00D6', '\\u00DC', '\\u00F8', '\\u00A3', '\\u00D8', '\\u00D7', '\\u0192', '\\u00E1', '\\u00ED', '\\u00F3', '\\u00FA', '\\u00F1', '\\u00D1',\r\n\t\t\t\t'\\u00AA', '\\u00BA', '\\u00BF', '\\u00AE', '\\u00AC', '\\u00BD', '\\u00BC', '\\u00A1', '\\u00AB', '\\u00BB', '_', '_', '_', '\\u00A6', '\\u00A6',\r\n\t\t\t\t'\\u00C1', '\\u00C2', '\\u00C0', '\\u00A9', '\\u00A6', '\\u00A6', '+', '+', '\\u00A2', '\\u00A5', '+', '+', '-', '-', '+', '-', '+', '\\u00E3',\r\n\t\t\t\t'\\u00C3', '+', '+', '-', '-', '\\u00A6', '-', '+', '\\u00A4', '\\u00F0', '\\u00D0', '\\u00CA', '\\u00CB', '\\u00C8', 'i', '\\u00CD', '\\u00CE',\r\n\t\t\t\t'\\u00CF', '+', '+', '_', '_', '\\u00A6', '\\u00CC', '_', '\\u00D3', '\\u00DF', '\\u00D4', '\\u00D2', '\\u00F5', '\\u00D5', '\\u00B5', '\\u00FE',\r\n\t\t\t\t'\\u00DE', '\\u00DA', '\\u00DB', '\\u00D9', '\\u00FD', '\\u00DD', '\\u00AF', '\\u00B4', '\\u00AD', '\\u00B1', '_', '\\u00BE', '\\u00B6', '\\u00A7',\r\n\t\t\t\t'\\u00F7', '\\u00B8', '\\u00B0', '\\u00A8', '\\u00B7', '\\u00B9', '\\u00B3', '\\u00B2', '_', ' ' ];\r\n\t\tfor (i = 0; i < str.length; i++) {\r\n\t\t\tcharCode = str.charCodeAt(i) & 0xFF;\r\n\t\t\tif (charCode > 127)\r\n\t\t\t\tout += extendedASCII[charCode - 128];\r\n\t\t\telse\r\n\t\t\t\tout += String.fromCharCode(charCode);\r\n\t\t}\r\n\t\treturn out;\r\n\t}\r\n\r\n\tfunction decodeUTF8(string) {\r\n\t\treturn decodeURIComponent(escape(string));\r\n\t}\r\n\r\n\tfunction getString(bytes) {\r\n\t\tvar i, str = \"\";\r\n\t\tfor (i = 0; i < bytes.length; i++)\r\n\t\t\tstr += String.fromCharCode(bytes[i]);\r\n\t\treturn str;\r\n\t}\r\n\r\n\tfunction getDate(timeRaw) {\r\n\t\tvar date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;\r\n\t\ttry {\r\n\t\t\treturn new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5,\r\n\t\t\t\t\t(time & 0x001F) * 2, 0);\r\n\t\t} catch (e) {\r\n\t\t}\r\n\t}\r\n\r\n\tfunction readCommonHeader(entry, data, index, centralDirectory, onerror) {\r\n\t\tentry.version = data.view.getUint16(index, true);\r\n\t\tentry.bitFlag = data.view.getUint16(index + 2, true);\r\n\t\tentry.compressionMethod = data.view.getUint16(index + 4, true);\r\n\t\tentry.lastModDateRaw = data.view.getUint32(index + 6, true);\r\n\t\tentry.lastModDate = getDate(entry.lastModDateRaw);\r\n\t\tif ((entry.bitFlag & 0x01) === 0x01) {\r\n\t\t\tonerror(ERR_ENCRYPTED);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (centralDirectory || (entry.bitFlag & 0x0008) != 0x0008) {\r\n\t\t\tentry.crc32 = data.view.getUint32(index + 10, true);\r\n\t\t\tentry.compressedSize = data.view.getUint32(index + 14, true);\r\n\t\t\tentry.uncompressedSize = data.view.getUint32(index + 18, true);\r\n\t\t}\r\n\t\tif (entry.compressedSize === 0xFFFFFFFF || entry.uncompressedSize === 0xFFFFFFFF) {\r\n\t\t\tonerror(ERR_ZIP64);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tentry.filenameLength = data.view.getUint16(index + 22, true);\r\n\t\tentry.extraFieldLength = data.view.getUint16(index + 24, true);\r\n\t}\r\n\r\n\tfunction createZipReader(reader, onerror) {\r\n\t\tfunction Entry() {\r\n\t\t}\r\n\r\n\t\tEntry.prototype.getData = function(writer, onend, onprogress, checkCrc32) {\r\n\t\t\tvar that = this, worker;\r\n\r\n\t\t\tfunction terminate(callback, param) {\r\n\t\t\t\tif (worker)\r\n\t\t\t\t\tworker.terminate();\r\n\t\t\t\tworker = null;\r\n\t\t\t\tif (callback)\r\n\t\t\t\t\tcallback(param);\r\n\t\t\t}\r\n\r\n\t\t\tfunction testCrc32(crc32) {\r\n\t\t\t\tvar dataCrc32 = getDataHelper(4);\r\n\t\t\t\tdataCrc32.view.setUint32(0, crc32);\r\n\t\t\t\treturn that.crc32 == dataCrc32.view.getUint32(0);\r\n\t\t\t}\r\n\r\n\t\t\tfunction getWriterData(uncompressedSize, crc32) {\r\n\t\t\t\tif (checkCrc32 && !testCrc32(crc32))\r\n\t\t\t\t\tonreaderror();\r\n\t\t\t\telse\r\n\t\t\t\t\twriter.getData(function(data) {\r\n\t\t\t\t\t\tterminate(onend, data);\r\n\t\t\t\t\t});\r\n\t\t\t}\r\n\r\n\t\t\tfunction onreaderror() {\r\n\t\t\t\tterminate(onerror, ERR_READ_DATA);\r\n\t\t\t}\r\n\r\n\t\t\tfunction onwriteerror() {\r\n\t\t\t\tterminate(onerror, ERR_WRITE_DATA);\r\n\t\t\t}\r\n\r\n\t\t\treader.readUint8Array(that.offset, 30, function(bytes) {\r\n\t\t\t\tvar data = getDataHelper(bytes.length, bytes), dataOffset;\r\n\t\t\t\tif (data.view.getUint32(0) != 0x504b0304) {\r\n\t\t\t\t\tonerror(ERR_BAD_FORMAT);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\treadCommonHeader(that, data, 4, false, onerror);\r\n\t\t\t\tdataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;\r\n\t\t\t\twriter.init(function() {\r\n\t\t\t\t\tif (that.compressionMethod === 0)\r\n\t\t\t\t\t\tcopy(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);\r\n\t\t\t\t\telse\r\n\t\t\t\t\t\tworker = inflate(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);\r\n\t\t\t\t}, onwriteerror);\r\n\t\t\t}, onreaderror);\r\n\t\t};\r\n\r\n\t\tfunction seekEOCDR(offset, entriesCallback) {\r\n\t\t\treader.readUint8Array(reader.size - offset, offset, function(bytes) {\r\n\t\t\t\tvar dataView = getDataHelper(bytes.length, bytes).view;\r\n\t\t\t\tif (dataView.getUint32(0) != 0x504b0506) {\r\n\t\t\t\t\tseekEOCDR(offset + 1, entriesCallback);\r\n\t\t\t\t} else {\r\n\t\t\t\t\tentriesCallback(dataView);\r\n\t\t\t\t}\r\n\t\t\t}, function() {\r\n\t\t\t\tonerror(ERR_READ);\r\n\t\t\t});\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tgetEntries : function(callback) {\r\n\t\t\t\tif (reader.size < 22) {\r\n\t\t\t\t\tonerror(ERR_BAD_FORMAT);\r\n\t\t\t\t\treturn;\r\n\t\t\t\t}\r\n\t\t\t\t// look for End of central directory record\r\n\t\t\t\tseekEOCDR(22, function(dataView) {\r\n\t\t\t\t\tvar datalength, fileslength;\r\n\t\t\t\t\tdatalength = dataView.getUint32(16, true);\r\n\t\t\t\t\tfileslength = dataView.getUint16(8, true);\r\n\t\t\t\t\treader.readUint8Array(datalength, reader.size - datalength, function(bytes) {\r\n\t\t\t\t\t\tvar i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);\r\n\t\t\t\t\t\tfor (i = 0; i < fileslength; i++) {\r\n\t\t\t\t\t\t\tentry = new Entry();\r\n\t\t\t\t\t\t\tif (data.view.getUint32(index) != 0x504b0102) {\r\n\t\t\t\t\t\t\t\tonerror(ERR_BAD_FORMAT);\r\n\t\t\t\t\t\t\t\treturn;\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t\treadCommonHeader(entry, data, index + 6, true, onerror);\r\n\t\t\t\t\t\t\tentry.commentLength = data.view.getUint16(index + 32, true);\r\n\t\t\t\t\t\t\tentry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);\r\n\t\t\t\t\t\t\tentry.offset = data.view.getUint32(index + 42, true);\r\n\t\t\t\t\t\t\tfilename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));\r\n\t\t\t\t\t\t\tentry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);\r\n\t\t\t\t\t\t\tif (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == \"/\")\r\n\t\t\t\t\t\t\t\tentry.directory = true;\r\n\t\t\t\t\t\t\tcomment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46\r\n\t\t\t\t\t\t\t\t\t+ entry.filenameLength + entry.extraFieldLength + entry.commentLength));\r\n\t\t\t\t\t\t\tentry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);\r\n\t\t\t\t\t\t\tentries.push(entry);\r\n\t\t\t\t\t\t\tindex += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t\tcallback(entries);\r\n\t\t\t\t\t}, function() {\r\n\t\t\t\t\t\tonerror(ERR_READ);\r\n\t\t\t\t\t});\r\n\t\t\t\t});\r\n\t\t\t},\r\n\t\t\tclose : function(callback) {\r\n\t\t\t\tif (callback)\r\n\t\t\t\t\tcallback();\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\t// ZipWriter\r\n\r\n\tfunction encodeUTF8(string) {\r\n\t\treturn unescape(encodeURIComponent(string));\r\n\t}\r\n\r\n\tfunction getBytes(str) {\r\n\t\tvar i, array = [];\r\n\t\tfor (i = 0; i < str.length; i++)\r\n\t\t\tarray.push(str.charCodeAt(i));\r\n\t\treturn array;\r\n\t}\r\n\r\n\tfunction createZipWriter(writer, onerror, dontDeflate) {\r\n\t\tvar worker, files = {}, filenames = [], datalength = 0;\r\n\r\n\t\tfunction terminate(callback, message) {\r\n\t\t\tif (worker)\r\n\t\t\t\tworker.terminate();\r\n\t\t\tworker = null;\r\n\t\t\tif (callback)\r\n\t\t\t\tcallback(message);\r\n\t\t}\r\n\r\n\t\tfunction onwriteerror() {\r\n\t\t\tterminate(onerror, ERR_WRITE);\r\n\t\t}\r\n\r\n\t\tfunction onreaderror() {\r\n\t\t\tterminate(onerror, ERR_READ_DATA);\r\n\t\t}\r\n\r\n\t\treturn {\r\n\t\t\tadd : function(name, reader, onend, onprogress, options) {\r\n\t\t\t\tvar header, filename, date;\r\n\r\n\t\t\t\tfunction writeHeader(callback) {\r\n\t\t\t\t\tvar data;\r\n\t\t\t\t\tdate = options.lastModDate || new Date();\r\n\t\t\t\t\theader = getDataHelper(26);\r\n\t\t\t\t\tfiles[name] = {\r\n\t\t\t\t\t\theaderArray : header.array,\r\n\t\t\t\t\t\tdirectory : options.directory,\r\n\t\t\t\t\t\tfilename : filename,\r\n\t\t\t\t\t\toffset : datalength,\r\n\t\t\t\t\t\tcomment : getBytes(encodeUTF8(options.comment || \"\"))\r\n\t\t\t\t\t};\r\n\t\t\t\t\theader.view.setUint32(0, 0x14000808);\r\n\t\t\t\t\tif (options.version)\r\n\t\t\t\t\t\theader.view.setUint8(0, options.version);\r\n\t\t\t\t\tif (!dontDeflate && options.level !== 0 && !options.directory)\r\n\t\t\t\t\t\theader.view.setUint16(4, 0x0800);\r\n\t\t\t\t\theader.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);\r\n\t\t\t\t\theader.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);\r\n\t\t\t\t\theader.view.setUint16(22, filename.length, true);\r\n\t\t\t\t\tdata = getDataHelper(30 + filename.length);\r\n\t\t\t\t\tdata.view.setUint32(0, 0x504b0304);\r\n\t\t\t\t\tdata.array.set(header.array, 4);\r\n\t\t\t\t\tdata.array.set(filename, 30);\r\n\t\t\t\t\tdatalength += data.array.length;\r\n\t\t\t\t\twriter.writeUint8Array(data.array, callback, onwriteerror);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfunction writeFooter(compressedLength, crc32) {\r\n\t\t\t\t\tvar footer = getDataHelper(16);\r\n\t\t\t\t\tdatalength += compressedLength || 0;\r\n\t\t\t\t\tfooter.view.setUint32(0, 0x504b0708);\r\n\t\t\t\t\tif (typeof crc32 != \"undefined\") {\r\n\t\t\t\t\t\theader.view.setUint32(10, crc32, true);\r\n\t\t\t\t\t\tfooter.view.setUint32(4, crc32, true);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (reader) {\r\n\t\t\t\t\t\tfooter.view.setUint32(8, compressedLength, true);\r\n\t\t\t\t\t\theader.view.setUint32(14, compressedLength, true);\r\n\t\t\t\t\t\tfooter.view.setUint32(12, reader.size, true);\r\n\t\t\t\t\t\theader.view.setUint32(18, reader.size, true);\r\n\t\t\t\t\t}\r\n\t\t\t\t\twriter.writeUint8Array(footer.array, function() {\r\n\t\t\t\t\t\tdatalength += 16;\r\n\t\t\t\t\t\tterminate(onend);\r\n\t\t\t\t\t}, onwriteerror);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tfunction writeFile() {\r\n\t\t\t\t\toptions = options || {};\r\n\t\t\t\t\tname = name.trim();\r\n\t\t\t\t\tif (options.directory && name.charAt(name.length - 1) != \"/\")\r\n\t\t\t\t\t\tname += \"/\";\r\n\t\t\t\t\tif (files.hasOwnProperty(name)) {\r\n\t\t\t\t\t\tonerror(ERR_DUPLICATED_NAME);\r\n\t\t\t\t\t\treturn;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tfilename = getBytes(encodeUTF8(name));\r\n\t\t\t\t\tfilenames.push(name);\r\n\t\t\t\t\twriteHeader(function() {\r\n\t\t\t\t\t\tif (reader)\r\n\t\t\t\t\t\t\tif (dontDeflate || options.level === 0)\r\n\t\t\t\t\t\t\t\tcopy(reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);\r\n\t\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\t\tworker = deflate(reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);\r\n\t\t\t\t\t\telse\r\n\t\t\t\t\t\t\twriteFooter();\r\n\t\t\t\t\t}, onwriteerror);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tif (reader)\r\n\t\t\t\t\treader.init(writeFile, onreaderror);\r\n\t\t\t\telse\r\n\t\t\t\t\twriteFile();\r\n\t\t\t},\r\n\t\t\tclose : function(callback) {\r\n\t\t\t\tvar data, length = 0, index = 0, indexFilename, file;\r\n\t\t\t\tfor (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {\r\n\t\t\t\t\tfile = files[filenames[indexFilename]];\r\n\t\t\t\t\tlength += 46 + file.filename.length + file.comment.length;\r\n\t\t\t\t}\r\n\t\t\t\tdata = getDataHelper(length + 22);\r\n\t\t\t\tfor (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {\r\n\t\t\t\t\tfile = files[filenames[indexFilename]];\r\n\t\t\t\t\tdata.view.setUint32(index, 0x504b0102);\r\n\t\t\t\t\tdata.view.setUint16(index + 4, 0x1400);\r\n\t\t\t\t\tdata.array.set(file.headerArray, index + 6);\r\n\t\t\t\t\tdata.view.setUint16(index + 32, file.comment.length, true);\r\n\t\t\t\t\tif (file.directory)\r\n\t\t\t\t\t\tdata.view.setUint8(index + 38, 0x10);\r\n\t\t\t\t\tdata.view.setUint32(index + 42, file.offset, true);\r\n\t\t\t\t\tdata.array.set(file.filename, index + 46);\r\n\t\t\t\t\tdata.array.set(file.comment, index + 46 + file.filename.length);\r\n\t\t\t\t\tindex += 46 + file.filename.length + file.comment.length;\r\n\t\t\t\t}\r\n\t\t\t\tdata.view.setUint32(index, 0x504b0506);\r\n\t\t\t\tdata.view.setUint16(index + 8, filenames.length, true);\r\n\t\t\t\tdata.view.setUint16(index + 10, filenames.length, true);\r\n\t\t\t\tdata.view.setUint32(index + 12, length, true);\r\n\t\t\t\tdata.view.setUint32(index + 16, datalength, true);\r\n\t\t\t\twriter.writeUint8Array(data.array, function() {\r\n\t\t\t\t\tterminate(function() {\r\n\t\t\t\t\t\twriter.getData(callback);\r\n\t\t\t\t\t});\r\n\t\t\t\t}, onwriteerror);\r\n\t\t\t}\r\n\t\t};\r\n\t}\r\n\r\n\tobj.zip = {\r\n\t\tReader : Reader,\r\n\t\tWriter : Writer,\r\n\t\tBlobReader : BlobReader,\r\n\t\tData64URIReader : Data64URIReader,\r\n\t\tTextReader : TextReader,\r\n\t\tBlobWriter : BlobWriter,\r\n\t\tData64URIWriter : Data64URIWriter,\r\n\t\tTextWriter : TextWriter,\r\n\t\tcreateReader : function(reader, callback, onerror) {\r\n\t\t\treader.init(function() {\r\n\t\t\t\tcallback(createZipReader(reader, onerror));\r\n\t\t\t}, onerror);\r\n\t\t},\r\n\t\tcreateWriter : function(writer, callback, onerror, dontDeflate) {\r\n\t\t\twriter.init(function() {\r\n\t\t\t\tcallback(createZipWriter(writer, onerror, dontDeflate));\r\n\t\t\t}, onerror);\r\n\t\t},\r\n\t\tuseWebWorkers : true\r\n\t};\r\n\r\n\tvar workerScriptsPath;\r\n\r\n\tObject.defineProperties(obj.zip, {\r\n 'workerScriptsPath' : {\r\n get : function() {\r\n if (typeof workerScriptsPath === 'undefined') {\r\n workerScriptsPath = buildModuleUrl('ThirdParty/Workers/');\r\n }\r\n return workerScriptsPath;\r\n }\r\n }\r\n });\r\n\r\n})(tmp);\r\n\r\n export default tmp.zip;\r\n","import Cartesian2 from \"../Core/Cartesian2.js\";\r\nimport Cartesian3 from \"../Core/Cartesian3.js\";\r\nimport Cartographic from \"../Core/Cartographic.js\";\r\nimport Color from \"../Core/Color.js\";\r\nimport createGuid from \"../Core/createGuid.js\";\r\nimport defaultValue from \"../Core/defaultValue.js\";\r\nimport defined from \"../Core/defined.js\";\r\nimport DeveloperError from \"../Core/DeveloperError.js\";\r\nimport Ellipsoid from \"../Core/Ellipsoid.js\";\r\nimport Iso8601 from \"../Core/Iso8601.js\";\r\nimport JulianDate from \"../Core/JulianDate.js\";\r\nimport CesiumMath from \"../Core/Math.js\";\r\nimport Rectangle from \"../Core/Rectangle.js\";\r\nimport ReferenceFrame from \"../Core/ReferenceFrame.js\";\r\nimport Resource from \"../Core/Resource.js\";\r\nimport RuntimeError from \"../Core/RuntimeError.js\";\r\nimport TimeInterval from \"../Core/TimeInterval.js\";\r\nimport TimeIntervalCollection from \"../Core/TimeIntervalCollection.js\";\r\nimport HeightReference from \"../Scene/HeightReference.js\";\r\nimport HorizontalOrigin from \"../Scene/HorizontalOrigin.js\";\r\nimport VerticalOrigin from \"../Scene/VerticalOrigin.js\";\r\nimport when from \"../ThirdParty/when.js\";\r\nimport zip from \"../ThirdParty/zip.js\";\r\nimport BillboardGraphics from \"./BillboardGraphics.js\";\r\nimport CompositePositionProperty from \"./CompositePositionProperty.js\";\r\nimport ModelGraphics from \"./ModelGraphics.js\";\r\nimport RectangleGraphics from \"./RectangleGraphics.js\";\r\nimport SampledPositionProperty from \"./SampledPositionProperty.js\";\r\nimport SampledProperty from \"./SampledProperty.js\";\r\nimport ScaledPositionProperty from \"./ScaledPositionProperty.js\";\r\n\r\nvar BILLBOARD_SIZE = 32;\r\nvar kmlNamespace = \"http://www.opengis.net/kml/2.2\";\r\nvar gxNamespace = \"http://www.google.com/kml/ext/2.2\";\r\nvar xmlnsNamespace = \"http://www.w3.org/2000/xmlns/\";\r\n\r\n//\r\n// Handles files external to the KML (eg. textures and models)\r\n//\r\nfunction ExternalFileHandler(modelCallback) {\r\n this._files = {};\r\n this._promises = [];\r\n this._count = 0;\r\n this._modelCallback = modelCallback;\r\n}\r\n\r\nvar imageTypeRegex = /^data:image\\/([^,;]+)/;\r\nExternalFileHandler.prototype.texture = function (texture) {\r\n var that = this;\r\n var filename;\r\n\r\n if (typeof texture === \"string\" || texture instanceof Resource) {\r\n texture = Resource.createIfNeeded(texture);\r\n if (!texture.isDataUri) {\r\n return texture.url;\r\n }\r\n\r\n // If its a data URI try and get the correct extension and then fetch the blob\r\n var regexResult = texture.url.match(imageTypeRegex);\r\n filename = \"texture_\" + ++this._count;\r\n if (defined(regexResult)) {\r\n filename += \".\" + regexResult[1];\r\n }\r\n\r\n var promise = texture.fetchBlob().then(function (blob) {\r\n that._files[filename] = blob;\r\n });\r\n\r\n this._promises.push(promise);\r\n\r\n return filename;\r\n }\r\n\r\n if (texture instanceof HTMLCanvasElement) {\r\n var deferred = when.defer();\r\n this._promises.push(deferred.promise);\r\n\r\n filename = \"texture_\" + ++this._count + \".png\";\r\n texture.toBlob(function (blob) {\r\n that._files[filename] = blob;\r\n deferred.resolve();\r\n });\r\n\r\n return filename;\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nfunction getModelBlobHander(that, filename) {\r\n return function (blob) {\r\n that._files[filename] = blob;\r\n };\r\n}\r\n\r\nExternalFileHandler.prototype.model = function (model, time) {\r\n var modelCallback = this._modelCallback;\r\n if (!defined(modelCallback)) {\r\n throw new RuntimeError(\r\n \"Encountered a model entity while exporting to KML, but no model callback was supplied.\"\r\n );\r\n }\r\n\r\n var externalFiles = {};\r\n var url = modelCallback(model, time, externalFiles);\r\n\r\n // Iterate through external files and add them to our list once the promise resolves\r\n for (var filename in externalFiles) {\r\n if (externalFiles.hasOwnProperty(filename)) {\r\n var promise = when(externalFiles[filename]);\r\n this._promises.push(promise);\r\n\r\n promise.then(getModelBlobHander(this, filename));\r\n }\r\n }\r\n\r\n return url;\r\n};\r\n\r\nObject.defineProperties(ExternalFileHandler.prototype, {\r\n promise: {\r\n get: function () {\r\n return when.all(this._promises);\r\n },\r\n },\r\n files: {\r\n get: function () {\r\n return this._files;\r\n },\r\n },\r\n});\r\n\r\n//\r\n// Handles getting values from properties taking the desired time and default values into account\r\n//\r\nfunction ValueGetter(time) {\r\n this._time = time;\r\n}\r\n\r\nValueGetter.prototype.get = function (property, defaultVal, result) {\r\n var value;\r\n if (defined(property)) {\r\n value = defined(property.getValue)\r\n ? property.getValue(this._time, result)\r\n : property;\r\n }\r\n\r\n return defaultValue(value, defaultVal);\r\n};\r\n\r\nValueGetter.prototype.getColor = function (property, defaultVal) {\r\n var result = this.get(property, defaultVal);\r\n if (defined(result)) {\r\n return colorToString(result);\r\n }\r\n};\r\n\r\nValueGetter.prototype.getMaterialType = function (property) {\r\n if (!defined(property)) {\r\n return;\r\n }\r\n\r\n return property.getType(this._time);\r\n};\r\n\r\n//\r\n// Caches styles so we don't generate a ton of duplicate styles\r\n//\r\nfunction StyleCache() {\r\n this._ids = {};\r\n this._styles = {};\r\n this._count = 0;\r\n}\r\n\r\nStyleCache.prototype.get = function (element) {\r\n var ids = this._ids;\r\n var key = element.innerHTML;\r\n if (defined(ids[key])) {\r\n return ids[key];\r\n }\r\n\r\n var styleId = \"style-\" + ++this._count;\r\n element.setAttribute(\"id\", styleId);\r\n\r\n // Store with #\r\n styleId = \"#\" + styleId;\r\n ids[key] = styleId;\r\n this._styles[key] = element;\r\n\r\n return styleId;\r\n};\r\n\r\nStyleCache.prototype.save = function (parentElement) {\r\n var styles = this._styles;\r\n\r\n var firstElement = parentElement.childNodes[0];\r\n for (var key in styles) {\r\n if (styles.hasOwnProperty(key)) {\r\n parentElement.insertBefore(styles[key], firstElement);\r\n }\r\n }\r\n};\r\n\r\n//\r\n// Manages the generation of IDs because an entity may have geometry and a Folder for children\r\n//\r\nfunction IdManager() {\r\n this._ids = {};\r\n}\r\n\r\nIdManager.prototype.get = function (id) {\r\n if (!defined(id)) {\r\n return this.get(createGuid());\r\n }\r\n\r\n var ids = this._ids;\r\n if (!defined(ids[id])) {\r\n ids[id] = 0;\r\n return id;\r\n }\r\n\r\n return id.toString() + \"-\" + ++ids[id];\r\n};\r\n\r\n/**\r\n * @typedef exportKmlResultKml\r\n * @type {Object}\r\n * @property {String} kml The generated KML.\r\n * @property {Object.} externalFiles An object dictionary of external files\r\n */\r\n\r\n/**\r\n * @typedef exportKmlResultKmz\r\n * @type {Object}\r\n * @property {Blob} kmz The generated kmz file.\r\n */\r\n\r\n/**\r\n * Exports an EntityCollection as a KML document. Only Point, Billboard, Model, Path, Polygon, Polyline geometries\r\n * will be exported. Note that there is not a 1 to 1 mapping of Entity properties to KML Feature properties. For\r\n * example, entity properties that are time dynamic but cannot be dynamic in KML are exported with their values at\r\n * options.time or the beginning of the EntityCollection's time interval if not specified. For time-dynamic properties\r\n * that are supported in KML, we use the samples if it is a {@link SampledProperty} otherwise we sample the value using\r\n * the options.sampleDuration. Point, Billboard, Model and Path geometries with time-dynamic positions will be exported\r\n * as gx:Track Features. Not all Materials are representable in KML, so for more advanced Materials just the primary\r\n * color is used. Canvas objects are exported as PNG images.\r\n *\r\n * @function exportKml\r\n *\r\n * @param {Object} options An object with the following properties:\r\n * @param {EntityCollection} options.entities The EntityCollection to export as KML.\r\n * @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid for the output file.\r\n * @param {exportKmlModelCallback} [options.modelCallback] A callback that will be called with a {@link ModelGraphics} instance and should return the URI to use in the KML. Required if a model exists in the entity collection.\r\n * @param {JulianDate} [options.time=entities.computeAvailability().start] The time value to use to get properties that are not time varying in KML.\r\n * @param {TimeInterval} [options.defaultAvailability=entities.computeAvailability()] The interval that will be sampled if an entity doesn't have an availability.\r\n * @param {Number} [options.sampleDuration=60] The number of seconds to sample properties that are varying in KML.\r\n * @param {Boolean} [options.kmz=false] If true KML and external files will be compressed into a kmz file.\r\n *\r\n * @returns {Promise} A promise that resolved to an object containing the KML string and a dictionary of external file blobs, or a kmz file as a blob if options.kmz is true.\r\n * @demo {@link https://sandcastle.cesium.com/index.html?src=Export%20KML.html|Cesium Sandcastle KML Export Demo}\r\n * @example\r\n * Cesium.exportKml({\r\n * entities: entityCollection\r\n * })\r\n * .then(function(result) {\r\n * // The XML string is in result.kml\r\n *\r\n * var externalFiles = result.externalFiles\r\n * for(var file in externalFiles) {\r\n * // file is the name of the file used in the KML document as the href\r\n * // externalFiles[file] is a blob with the contents of the file\r\n * }\r\n * });\r\n *\r\n */\r\nfunction exportKml(options) {\r\n options = defaultValue(options, defaultValue.EMPTY_OBJECT);\r\n var entities = options.entities;\r\n var kmz = defaultValue(options.kmz, false);\r\n\r\n //>>includeStart('debug', pragmas.debug);\r\n if (!defined(entities)) {\r\n throw new DeveloperError(\"entities is required.\");\r\n }\r\n //>>includeEnd('debug');\r\n\r\n // Get the state that is passed around during the recursion\r\n // This is separated out for testing.\r\n var state = exportKml._createState(options);\r\n\r\n // Filter EntityCollection so we only have top level entities\r\n var rootEntities = entities.values.filter(function (entity) {\r\n return !defined(entity.parent);\r\n });\r\n\r\n // Add the \r\n var kmlDoc = state.kmlDoc;\r\n var kmlElement = kmlDoc.documentElement;\r\n kmlElement.setAttributeNS(xmlnsNamespace, \"xmlns:gx\", gxNamespace);\r\n var kmlDocumentElement = kmlDoc.createElement(\"Document\");\r\n kmlElement.appendChild(kmlDocumentElement);\r\n\r\n // Create the KML Hierarchy\r\n recurseEntities(state, kmlDocumentElement, rootEntities);\r\n\r\n // Write out the